Merge "Add event log when keyguard status changed."
diff --git a/Android.bp b/Android.bp
index ee3b396..7219ef5 100644
--- a/Android.bp
+++ b/Android.bp
@@ -136,7 +136,6 @@
         "core/java/android/content/pm/IDexModuleRegisterCallback.aidl",
         "core/java/android/content/pm/ILauncherApps.aidl",
         "core/java/android/content/pm/IOnAppsChangedListener.aidl",
-        "core/java/android/content/pm/IOnPermissionsChangeListener.aidl",
         "core/java/android/content/pm/IOtaDexopt.aidl",
         "core/java/android/content/pm/IPackageDataObserver.aidl",
         "core/java/android/content/pm/IPackageDeleteObserver.aidl",
@@ -278,6 +277,7 @@
         "core/java/android/os/storage/IStorageEventListener.aidl",
         "core/java/android/os/storage/IStorageShutdownObserver.aidl",
         "core/java/android/os/storage/IObbActionListener.aidl",
+        "core/java/android/permission/IOnPermissionsChangeListener.aidl",
         "core/java/android/permission/IPermissionController.aidl",
         "core/java/android/permission/IPermissionManager.aidl",
         ":keystore_aidl",
@@ -565,7 +565,7 @@
         "telephony/java/android/telephony/ims/aidl/IImsServiceController.aidl",
         "telephony/java/android/telephony/ims/aidl/IImsServiceControllerListener.aidl",
         "telephony/java/android/telephony/ims/aidl/IImsSmsListener.aidl",
-        "telephony/java/android/telephony/ims/aidl/IRcs.aidl",
+        "telephony/java/android/telephony/ims/aidl/IRcsMessage.aidl",
         "telephony/java/android/telephony/mbms/IMbmsDownloadSessionCallback.aidl",
         "telephony/java/android/telephony/mbms/IMbmsStreamingSessionCallback.aidl",
         "telephony/java/android/telephony/mbms/IMbmsGroupCallSessionCallback.aidl",
diff --git a/api/current.txt b/api/current.txt
index 25801ca..7c13dc1 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5842,12 +5842,19 @@
     method public boolean updateAutomaticZenRule(String, android.app.AutomaticZenRule);
     field public static final String ACTION_APP_BLOCK_STATE_CHANGED = "android.app.action.APP_BLOCK_STATE_CHANGED";
     field public static final String ACTION_AUTOMATIC_ZEN_RULE = "android.app.action.AUTOMATIC_ZEN_RULE";
+    field public static final String ACTION_AUTOMATIC_ZEN_RULE_STATUS_CHANGED = "android.app.action.AUTOMATIC_ZEN_RULE_STATUS_CHANGED";
     field public static final String ACTION_INTERRUPTION_FILTER_CHANGED = "android.app.action.INTERRUPTION_FILTER_CHANGED";
     field public static final String ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED = "android.app.action.NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED";
     field public static final String ACTION_NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED = "android.app.action.NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED";
     field public static final String ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED = "android.app.action.NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED";
     field public static final String ACTION_NOTIFICATION_POLICY_CHANGED = "android.app.action.NOTIFICATION_POLICY_CHANGED";
+    field public static final int AUTOMATIC_RULE_STATUS_DISABLED = 2; // 0x2
+    field public static final int AUTOMATIC_RULE_STATUS_ENABLED = 1; // 0x1
+    field public static final int AUTOMATIC_RULE_STATUS_REMOVED = 3; // 0x3
+    field public static final int AUTOMATIC_RULE_STATUS_UNKNOWN = -1; // 0xffffffff
     field public static final String EXTRA_AUTOMATIC_RULE_ID = "android.app.extra.AUTOMATIC_RULE_ID";
+    field public static final String EXTRA_AUTOMATIC_ZEN_RULE_ID = "android.app.extra.AUTOMATIC_ZEN_RULE_ID";
+    field public static final String EXTRA_AUTOMATIC_ZEN_RULE_STATUS = "android.app.extra.AUTOMATIC_ZEN_RULE_STATUS";
     field public static final String EXTRA_BLOCKED_STATE = "android.app.extra.BLOCKED_STATE";
     field public static final String EXTRA_NOTIFICATION_CHANNEL_GROUP_ID = "android.app.extra.NOTIFICATION_CHANNEL_GROUP_ID";
     field public static final String EXTRA_NOTIFICATION_CHANNEL_ID = "android.app.extra.NOTIFICATION_CHANNEL_ID";
diff --git a/api/system-current.txt b/api/system-current.txt
index ce7df5e..48804b6 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -3693,8 +3693,18 @@
 package android.media.session {
 
   public final class MediaSessionManager {
+    method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void registerCallback(@NonNull android.media.session.MediaSessionManager.Callback, @Nullable android.os.Handler);
     method @RequiresPermission(android.Manifest.permission.SET_MEDIA_KEY_LISTENER) public void setOnMediaKeyListener(android.media.session.MediaSessionManager.OnMediaKeyListener, @Nullable android.os.Handler);
     method @RequiresPermission(android.Manifest.permission.SET_VOLUME_KEY_LONG_PRESS_LISTENER) public void setOnVolumeKeyLongPressListener(android.media.session.MediaSessionManager.OnVolumeKeyLongPressListener, @Nullable android.os.Handler);
+    method @RequiresPermission(android.Manifest.permission.MEDIA_CONTENT_CONTROL) public void unregisterCallback(@NonNull android.media.session.MediaSessionManager.Callback);
+  }
+
+  public abstract static class MediaSessionManager.Callback {
+    ctor public MediaSessionManager.Callback();
+    method public abstract void onAddressedPlayerChanged(android.media.session.MediaSession.Token);
+    method public abstract void onAddressedPlayerChanged(android.content.ComponentName);
+    method public abstract void onMediaKeyEventDispatched(android.view.KeyEvent, android.media.session.MediaSession.Token);
+    method public abstract void onMediaKeyEventDispatched(android.view.KeyEvent, android.content.ComponentName);
   }
 
   public static interface MediaSessionManager.OnMediaKeyListener {
@@ -5473,6 +5483,7 @@
   public class UpdateEngine {
     ctor public UpdateEngine();
     method public void applyPayload(String, long, long, String[]);
+    method public void applyPayload(java.io.FileDescriptor, long, long, String[]);
     method public boolean bind(android.os.UpdateEngineCallback, android.os.Handler);
     method public boolean bind(android.os.UpdateEngineCallback);
     method public void cancel();
diff --git a/api/test-current.txt b/api/test-current.txt
index 874c216..050ec52 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -700,6 +700,7 @@
   }
 
   public abstract class PackageManager {
+    method @RequiresPermission("android.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS") public abstract void addOnPermissionsChangeListener(@NonNull android.content.pm.PackageManager.OnPermissionsChangedListener);
     method public abstract boolean arePermissionsIndividuallyControlled();
     method @Nullable @RequiresPermission("android.permission.INTERACT_ACROSS_USERS_FULL") public abstract String getDefaultBrowserPackageNameAsUser(int);
     method @Nullable public String getIncidentReportApproverPackageName();
@@ -713,6 +714,7 @@
     method @NonNull public abstract String getSharedSystemSharedLibraryPackageName();
     method @Nullable public String getWellbeingPackageName();
     method @RequiresPermission("android.permission.GRANT_RUNTIME_PERMISSIONS") public abstract void grantRuntimePermission(@NonNull String, @NonNull String, @NonNull android.os.UserHandle);
+    method @RequiresPermission("android.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS") public abstract void removeOnPermissionsChangeListener(@NonNull android.content.pm.PackageManager.OnPermissionsChangedListener);
     method @RequiresPermission("android.permission.REVOKE_RUNTIME_PERMISSIONS") public abstract void revokeRuntimePermission(@NonNull String, @NonNull String, @NonNull android.os.UserHandle);
     method @RequiresPermission(anyOf={"android.permission.GRANT_RUNTIME_PERMISSIONS", "android.permission.REVOKE_RUNTIME_PERMISSIONS"}) public abstract void updatePermissionFlags(@NonNull String, @NonNull String, int, int, @NonNull android.os.UserHandle);
     field public static final String FEATURE_ADOPTABLE_STORAGE = "android.software.adoptable_storage";
@@ -735,6 +737,10 @@
     field public static final String SYSTEM_SHARED_LIBRARY_SHARED = "android.ext.shared";
   }
 
+  public static interface PackageManager.OnPermissionsChangedListener {
+    method public void onPermissionsChanged(int);
+  }
+
   public class PermissionInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
     field public static final int FLAG_REMOVED = 2; // 0x2
     field public static final int PROTECTION_FLAG_APP_PREDICTOR = 2097152; // 0x200000
diff --git a/cmds/statsd/Android.bp b/cmds/statsd/Android.bp
index 2f0dc3c..6df0a8e 100644
--- a/cmds/statsd/Android.bp
+++ b/cmds/statsd/Android.bp
@@ -71,7 +71,6 @@
         "src/config/ConfigManager.cpp",
         "src/external/GpuStatsPuller.cpp",
         "src/external/Perfetto.cpp",
-        "src/external/Perfprofd.cpp",
         "src/external/StatsPuller.cpp",
         "src/external/StatsCallbackPuller.cpp",
         "src/external/StatsCompanionServicePuller.cpp",
@@ -109,8 +108,6 @@
         "src/socket/StatsSocketListener.cpp",
         "src/shell/ShellSubscriber.cpp",
         "src/shell/shell_config.proto",
-
-        ":perfprofd_aidl",
     ],
 
     local_include_dirs: [
diff --git a/cmds/statsd/src/anomaly/subscriber_util.cpp b/cmds/statsd/src/anomaly/subscriber_util.cpp
index 548a686..e09d575 100644
--- a/cmds/statsd/src/anomaly/subscriber_util.cpp
+++ b/cmds/statsd/src/anomaly/subscriber_util.cpp
@@ -22,7 +22,6 @@
 #include <binder/IServiceManager.h>
 
 #include "external/Perfetto.h"
-#include "external/Perfprofd.h"
 #include "subscriber/IncidentdReporter.h"
 #include "subscriber/SubscriberReporter.h"
 
@@ -64,12 +63,6 @@
                 SubscriberReporter::getInstance().alertBroadcastSubscriber(configKey, subscription,
                                                                            dimensionKey);
                 break;
-            case Subscription::SubscriberInformationCase::kPerfprofdDetails:
-                if (!CollectPerfprofdTraceAndUploadToDropbox(subscription.perfprofd_details(),
-                                                             ruleId, configKey)) {
-                    ALOGW("Failed to generate perfprofd traces.");
-                }
-                break;
             default:
                 break;
         }
diff --git a/cmds/statsd/src/external/Perfprofd.cpp b/cmds/statsd/src/external/Perfprofd.cpp
deleted file mode 100644
index 1678f10..0000000
--- a/cmds/statsd/src/external/Perfprofd.cpp
+++ /dev/null
@@ -1,74 +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.
- */
-
-#include "Perfprofd.h"
-
-#define DEBUG false  // STOPSHIP if true
-#include "config/ConfigKey.h"
-#include "Log.h"
-
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-#include <string>
-
-#include <binder/IServiceManager.h>
-
-#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"  // Alert
-
-#include "android/os/IPerfProfd.h"
-
-namespace android {
-namespace os {
-namespace statsd {
-
-bool CollectPerfprofdTraceAndUploadToDropbox(const PerfprofdDetails& config,
-                                             int64_t alert_id,
-                                             const ConfigKey& configKey) {
-    VLOG("Starting trace collection through perfprofd");
-
-    if (!config.has_perfprofd_config()) {
-      ALOGE("The perfprofd trace config is empty, aborting");
-      return false;
-    }
-
-    sp<IPerfProfd> service = interface_cast<IPerfProfd>(
-        defaultServiceManager()->getService(android::String16("perfprofd")));
-    if (service == NULL) {
-      ALOGE("Could not find perfprofd service");
-      return false;
-    }
-
-    auto* data = reinterpret_cast<const uint8_t*>(config.perfprofd_config().data());
-    std::vector<uint8_t> proto_serialized(data, data + config.perfprofd_config().size());
-
-    // TODO: alert-id etc?
-
-    binder::Status status = service->startProfilingProtobuf(proto_serialized);
-    if (status.isOk()) {
-      return true;
-    }
-
-    ALOGE("Error starting perfprofd profiling: %s", status.toString8().c_str());
-    return false;
-}
-
-}  // namespace statsd
-}  // namespace os
-}  // namespace android
diff --git a/cmds/statsd/src/external/Perfprofd.h b/cmds/statsd/src/external/Perfprofd.h
deleted file mode 100644
index b93fdf8..0000000
--- a/cmds/statsd/src/external/Perfprofd.h
+++ /dev/null
@@ -1,38 +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.
- */
-
-#pragma once
-
-#include <inttypes.h>
-
-namespace android {
-namespace os {
-namespace statsd {
-
-class ConfigKey;
-class PerfprofdDetails;  // Declared in statsd_config.pb.h
-
-// Starts the collection of a Perfprofd trace with the given |config|.
-// The trace is uploaded to Dropbox by the perfprofd service once done.
-// This method returns immediately after passing the config and does NOT wait
-// for the full duration of the trace.
-bool CollectPerfprofdTraceAndUploadToDropbox(const PerfprofdDetails& config,
-                                             int64_t alert_id,
-                                             const ConfigKey& configKey);
-
-}  // namespace statsd
-}  // namespace os
-}  // namespace android
diff --git a/cmds/statsd/src/statsd_config.proto b/cmds/statsd/src/statsd_config.proto
index a2fd9d4..79c06b9 100644
--- a/cmds/statsd/src/statsd_config.proto
+++ b/cmds/statsd/src/statsd_config.proto
@@ -343,15 +343,6 @@
   optional bytes trace_config = 1;
 }
 
-message PerfprofdDetails {
-  // The |perfprofd_config| field is a proto-encoded message of type
-  // android.perfprofd.ProfilingConfig defined in
-  // //system/extras/perfprofd/. On device, statsd doesn't need to
-  // deserialize the message as it's just passed binary-encoded to
-  // the perfprofd service.
-  optional bytes perfprofd_config = 1;
-}
-
 message BroadcastSubscriberDetails {
   optional int64 subscriber_id = 1;
   repeated string cookie = 2;
@@ -373,10 +364,12 @@
     IncidentdDetails incidentd_details = 4;
     PerfettoDetails perfetto_details = 5;
     BroadcastSubscriberDetails broadcast_subscriber_details = 6;
-    PerfprofdDetails perfprofd_details = 8;
   }
 
   optional float probability_of_informing = 7 [default = 1.1];
+
+  // This was used for perfprofd historically.
+  reserved 8;
 }
 
 enum ActivationType {
diff --git a/config/hiddenapi-greylist-max-p.txt b/config/hiddenapi-greylist-max-p.txt
index 141e8e6..25d45b0 100644
--- a/config/hiddenapi-greylist-max-p.txt
+++ b/config/hiddenapi-greylist-max-p.txt
@@ -70,6 +70,8 @@
 Lcom/android/internal/R$styleable;->Searchable:[I
 Lcom/android/internal/R$styleable;->SearchableActionKey:[I
 Lcom/android/internal/telephony/IPhoneSubInfo$Stub;-><init>()V
+Lcom/android/internal/telephony/ITelephony;->getDataActivity()I
+Lcom/android/internal/telephony/ITelephony;->getDataState()I
 Lcom/android/internal/telephony/ITelephonyRegistry;->notifyCallForwardingChanged(Z)V
 Lcom/android/internal/telephony/ITelephonyRegistry;->notifyCellLocation(Landroid/os/Bundle;)V
 Lcom/android/internal/telephony/ITelephonyRegistry;->notifyDataActivity(I)V
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 1641afb..416aaa3 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -34,7 +34,6 @@
 import android.content.pm.ChangedPackages;
 import android.content.pm.ComponentInfo;
 import android.content.pm.FeatureInfo;
-import android.content.pm.IOnPermissionsChangeListener;
 import android.content.pm.IPackageDataObserver;
 import android.content.pm.IPackageDeleteObserver;
 import android.content.pm.IPackageManager;
@@ -82,6 +81,7 @@
 import android.os.UserManager;
 import android.os.storage.StorageManager;
 import android.os.storage.VolumeInfo;
+import android.permission.IOnPermissionsChangeListener;
 import android.permission.IPermissionManager;
 import android.provider.Settings;
 import android.system.ErrnoException;
@@ -626,7 +626,7 @@
     @Override
     public int checkPermission(String permName, String pkgName) {
         try {
-            return mPM.checkPermission(permName, pkgName, getUserId());
+            return mPermissionManager.checkPermission(permName, pkgName, getUserId());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -707,46 +707,47 @@
     }
 
     @Override
-    public void revokeRuntimePermission(String packageName, String permissionName,
-            UserHandle user) {
+    public void revokeRuntimePermission(String packageName, String permName, UserHandle user) {
         if (DEBUG_TRACE_GRANTS
-                && shouldTraceGrant(packageName, permissionName, user.getIdentifier())) {
+                && shouldTraceGrant(packageName, permName, user.getIdentifier())) {
             Log.i(TAG, "App " + mContext.getPackageName() + " is revoking "
-                    + permissionName + " for user " + user.getIdentifier(), new RuntimeException());
+                    + permName + " for user " + user.getIdentifier(), new RuntimeException());
         }
         try {
-            mPM.revokeRuntimePermission(packageName, permissionName, user.getIdentifier());
+            mPermissionManager
+                    .revokeRuntimePermission(packageName, permName, user.getIdentifier());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
     }
 
     @Override
-    public int getPermissionFlags(String permissionName, String packageName, UserHandle user) {
+    public int getPermissionFlags(String permName, String packageName, UserHandle user) {
         try {
-            return mPM.getPermissionFlags(permissionName, packageName, user.getIdentifier());
+            return mPermissionManager
+                    .getPermissionFlags(permName, packageName, user.getIdentifier());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
     }
 
     @Override
-    public void updatePermissionFlags(String permissionName, String packageName,
+    public void updatePermissionFlags(String permName, String packageName,
             int flagMask, int flagValues, UserHandle user) {
         if (DEBUG_TRACE_GRANTS
-                && shouldTraceGrant(packageName, permissionName, user.getIdentifier())) {
+                && shouldTraceGrant(packageName, permName, user.getIdentifier())) {
             Log.i(TAG, "App " + mContext.getPackageName() + " is updating flags for "
-                    + permissionName + " for user " + user.getIdentifier() + ": "
+                    + permName + " for user " + user.getIdentifier() + ": "
                     + DebugUtils.flagsToString(PackageManager.class, "FLAG_PERMISSION_", flagMask)
                     + " := " + DebugUtils.flagsToString(
                             PackageManager.class, "FLAG_PERMISSION_", flagValues),
                     new RuntimeException());
         }
         try {
-            mPM.updatePermissionFlags(permissionName, packageName, flagMask,
-                    flagValues,
-                    mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.Q,
-                    user.getIdentifier());
+            final boolean checkAdjustPolicyFlagPermission =
+                    mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.Q;
+            mPermissionManager.updatePermissionFlags(permName, packageName, flagMask,
+                    flagValues, checkAdjustPolicyFlagPermission, user.getIdentifier());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -754,10 +755,11 @@
 
     @Override
     public @NonNull Set<String> getWhitelistedRestrictedPermissions(
-            @NonNull String packageName, @PermissionWhitelistFlags int whitelistFlags) {
+            @NonNull String packageName, @PermissionWhitelistFlags int flags) {
         try {
-            final List<String> whitelist = mPM.getWhitelistedRestrictedPermissions(
-                    packageName, whitelistFlags, getUserId());
+            final int userId = getUserId();
+            final List<String> whitelist = mPermissionManager
+                    .getWhitelistedRestrictedPermissions(packageName, flags, userId);
             if (whitelist != null) {
                 return new ArraySet<>(whitelist);
             }
@@ -769,10 +771,11 @@
 
     @Override
     public boolean addWhitelistedRestrictedPermission(@NonNull String packageName,
-            @NonNull String permission, @PermissionWhitelistFlags int whitelistFlags) {
+            @NonNull String permName, @PermissionWhitelistFlags int flags) {
         try {
-            return mPM.addWhitelistedRestrictedPermission(packageName, permission,
-                    whitelistFlags, getUserId());
+            final int userId = getUserId();
+            return mPermissionManager
+                    .addWhitelistedRestrictedPermission(packageName, permName, flags, userId);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -780,10 +783,11 @@
 
     @Override
     public boolean removeWhitelistedRestrictedPermission(@NonNull String packageName,
-            @NonNull String permission, @PermissionWhitelistFlags int whitelistFlags) {
+            @NonNull String permName, @PermissionWhitelistFlags int flags) {
         try {
-            return mPM.removeWhitelistedRestrictedPermission(packageName, permission,
-                    whitelistFlags, getUserId());
+            final int userId = getUserId();
+            return mPermissionManager
+                    .removeWhitelistedRestrictedPermission(packageName, permName, flags, userId);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -1623,7 +1627,7 @@
             OnPermissionsChangeListenerDelegate delegate =
                     new OnPermissionsChangeListenerDelegate(listener, Looper.getMainLooper());
             try {
-                mPM.addOnPermissionsChangeListener(delegate);
+                mPermissionManager.addOnPermissionsChangeListener(delegate);
                 mPermissionListeners.put(listener, delegate);
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
@@ -1637,7 +1641,7 @@
             IOnPermissionsChangeListener delegate = mPermissionListeners.get(listener);
             if (delegate != null) {
                 try {
-                    mPM.removeOnPermissionsChangeListener(delegate);
+                    mPermissionManager.removeOnPermissionsChangeListener(delegate);
                     mPermissionListeners.remove(listener);
                 } catch (RemoteException e) {
                     throw e.rethrowFromSystemServer();
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index c1cee77..316cab8 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -171,6 +171,78 @@
             "android.app.action.NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED";
 
     /**
+     * Intent that is broadcast when the status of an {@link AutomaticZenRule} has changed.
+     *
+     * <p>Use this to know whether you need to continue monitor to device state in order to
+     * provide up-to-date states (with {@link #setAutomaticZenRuleState(String, Condition)}) for
+     * this rule.</p>
+     *
+     * Input: nothing
+     * Output: {@link #EXTRA_AUTOMATIC_ZEN_RULE_ID}
+     * Output: {@link #EXTRA_AUTOMATIC_ZEN_RULE_STATUS}
+     */
+    @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_AUTOMATIC_ZEN_RULE_STATUS_CHANGED =
+            "android.app.action.AUTOMATIC_ZEN_RULE_STATUS_CHANGED";
+
+    /**
+     * Integer extra for {@link #ACTION_AUTOMATIC_ZEN_RULE_STATUS_CHANGED} containing the state of
+     * the {@link AutomaticZenRule}.
+     *
+     * <p>
+     *     The value will be one of {@link #AUTOMATIC_RULE_STATUS_ENABLED},
+     *     {@link #AUTOMATIC_RULE_STATUS_DISABLED}, {@link #AUTOMATIC_RULE_STATUS_REMOVED},
+     *     {@link #AUTOMATIC_RULE_STATUS_UNKNOWN}.
+     * </p>
+     */
+    public static final String EXTRA_AUTOMATIC_ZEN_RULE_STATUS =
+            "android.app.extra.AUTOMATIC_ZEN_RULE_STATUS";
+
+    /**
+     * String extra for {@link #ACTION_AUTOMATIC_ZEN_RULE_STATUS_CHANGED} containing the id of the
+     * {@link AutomaticZenRule} (see {@link #addAutomaticZenRule(AutomaticZenRule)}) that has
+     * changed.
+     */
+    public static final String EXTRA_AUTOMATIC_ZEN_RULE_ID =
+            "android.app.extra.AUTOMATIC_ZEN_RULE_ID";
+
+    /** @hide */
+    @IntDef(prefix = { "AUTOMATIC_RULE_STATUS" }, value = {
+            AUTOMATIC_RULE_STATUS_ENABLED, AUTOMATIC_RULE_STATUS_DISABLED,
+            AUTOMATIC_RULE_STATUS_REMOVED, AUTOMATIC_RULE_STATUS_UNKNOWN
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface AutomaticZenRuleStatus {}
+
+    /**
+     * Constant value for {@link #EXTRA_AUTOMATIC_ZEN_RULE_STATUS} - the current status of the
+     * rule is unknown at your target sdk version, and you should continue to provide state changes
+     * via {@link #setAutomaticZenRuleState(String, Condition)}.
+     */
+    public static final int AUTOMATIC_RULE_STATUS_UNKNOWN = -1;
+
+    /**
+     * Constant value for {@link #EXTRA_AUTOMATIC_ZEN_RULE_STATUS} - the given rule currently
+     * exists and is enabled. You should continue to provide state changes via
+     * {@link #setAutomaticZenRuleState(String, Condition)}.
+     */
+    public static final int AUTOMATIC_RULE_STATUS_ENABLED = 1;
+
+    /**
+     * Constant value for {@link #EXTRA_AUTOMATIC_ZEN_RULE_STATUS} - the given rule currently
+     * exists but is disabled. You do not need to continue to provide state changes via
+     * {@link #setAutomaticZenRuleState(String, Condition)} until the rule is reenabled.
+     */
+    public static final int AUTOMATIC_RULE_STATUS_DISABLED = 2;
+
+    /**
+     * Constant value for {@link #EXTRA_AUTOMATIC_ZEN_RULE_STATUS} - the given rule has been
+     * deleted. Further calls to {@link #setAutomaticZenRuleState(String, Condition)} will be
+     * ignored.
+     */
+    public static final int AUTOMATIC_RULE_STATUS_REMOVED = 3;
+
+    /**
      * Intent that is broadcast when the state of {@link #getEffectsSuppressor()} changes.
      * This broadcast is only sent to registered receivers.
      *
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index d32b6b5..cfe2cf0 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -172,7 +172,7 @@
 import android.telephony.TelephonyManager;
 import android.telephony.euicc.EuiccCardManager;
 import android.telephony.euicc.EuiccManager;
-import android.telephony.ims.RcsManager;
+import android.telephony.ims.RcsMessageManager;
 import android.util.ArrayMap;
 import android.util.Log;
 import android.view.ContextThemeWrapper;
@@ -614,11 +614,11 @@
                 return new SubscriptionManager(ctx.getOuterContext());
             }});
 
-        registerService(Context.TELEPHONY_RCS_SERVICE, RcsManager.class,
-                new CachedServiceFetcher<RcsManager>() {
+        registerService(Context.TELEPHONY_RCS_MESSAGE_SERVICE, RcsMessageManager.class,
+                new CachedServiceFetcher<RcsMessageManager>() {
                     @Override
-                    public RcsManager createService(ContextImpl ctx) {
-                        return new RcsManager(ctx.getOuterContext());
+                    public RcsMessageManager createService(ContextImpl ctx) {
+                        return new RcsMessageManager(ctx.getOuterContext());
                     }
                 });
 
diff --git a/core/java/android/app/UiAutomationConnection.java b/core/java/android/app/UiAutomationConnection.java
index dc07df8..4f8b60b 100644
--- a/core/java/android/app/UiAutomationConnection.java
+++ b/core/java/android/app/UiAutomationConnection.java
@@ -20,7 +20,6 @@
 import android.accessibilityservice.IAccessibilityServiceClient;
 import android.annotation.Nullable;
 import android.content.Context;
-import android.content.pm.IPackageManager;
 import android.graphics.Bitmap;
 import android.graphics.Rect;
 import android.hardware.input.InputManager;
@@ -31,6 +30,7 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.UserHandle;
+import android.permission.IPermissionManager;
 import android.util.Log;
 import android.view.IWindowManager;
 import android.view.InputEvent;
@@ -69,8 +69,8 @@
     private final IAccessibilityManager mAccessibilityManager = IAccessibilityManager.Stub
             .asInterface(ServiceManager.getService(Service.ACCESSIBILITY_SERVICE));
 
-    private final IPackageManager mPackageManager = IPackageManager.Stub
-            .asInterface(ServiceManager.getService("package"));
+    private final IPermissionManager mPermissionManager = IPermissionManager.Stub
+            .asInterface(ServiceManager.getService("permissionmgr"));
 
     private final IActivityManager mActivityManager = IActivityManager.Stub
             .asInterface(ServiceManager.getService("activity"));
@@ -273,7 +273,7 @@
         }
         final long identity = Binder.clearCallingIdentity();
         try {
-            mPackageManager.grantRuntimePermission(packageName, permission, userId);
+            mPermissionManager.grantRuntimePermission(packageName, permission, userId);
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
@@ -289,7 +289,7 @@
         }
         final long identity = Binder.clearCallingIdentity();
         try {
-            mPackageManager.revokeRuntimePermission(packageName, permission, userId);
+            mPermissionManager.revokeRuntimePermission(packageName, permission, userId);
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index c3dd827..7a013f1 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3067,7 +3067,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(trackingBug = 136728678)
     public boolean bindServiceAsUser(Intent service, ServiceConnection conn, int flags,
             Handler handler, UserHandle user) {
         throw new RuntimeException("Not implemented. Must override in a subclass.");
@@ -4665,10 +4665,10 @@
 
     /**
      * Use with {@link #getSystemService(String)} to retrieve an
-     * {@link android.telephony.ims.RcsManager}.
+     * {@link android.telephony.ims.RcsMessageManager}.
      * @hide
      */
-    public static final String TELEPHONY_RCS_SERVICE = "ircs";
+    public static final String TELEPHONY_RCS_MESSAGE_SERVICE = "ircsmessage";
 
      /**
      * Use with {@link #getSystemService(String)} to retrieve an
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 277e41d..904bd16 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -32,7 +32,6 @@
 import android.content.pm.IPackageDataObserver;
 import android.content.pm.IPackageMoveObserver;
 import android.content.pm.IPackageStatsObserver;
-import android.content.pm.IOnPermissionsChangeListener;
 import android.content.pm.IntentFilterVerificationInfo;
 import android.content.pm.InstrumentationInfo;
 import android.content.pm.KeySet;
@@ -95,36 +94,7 @@
 
     @UnsupportedAppUsage
     ProviderInfo getProviderInfo(in ComponentName className, int flags, int userId);
-
-    @UnsupportedAppUsage
-    int checkPermission(String permName, String pkgName, int userId);
-
-    int checkUidPermission(String permName, int uid);
-
-    @UnsupportedAppUsage
-    void grantRuntimePermission(String packageName, String permissionName, int userId);
-
-    void revokeRuntimePermission(String packageName, String permissionName, int userId);
-
-    void resetRuntimePermissions();
-
-    int getPermissionFlags(String permissionName, String packageName, int userId);
-
-    void updatePermissionFlags(String permissionName, String packageName, int flagMask,
-            int flagValues, boolean checkAdjustPolicyFlagPermission, int userId);
-
-    void updatePermissionFlagsForAllApps(int flagMask, int flagValues, int userId);
-
-    List<String> getWhitelistedRestrictedPermissions(String packageName, int flags,
-            int userId);
-
-    boolean addWhitelistedRestrictedPermission(String packageName, String permission,
-            int whitelistFlags, int userId);
-
-    boolean removeWhitelistedRestrictedPermission(String packageName, String permission,
-            int whitelistFlags, int userId);
-
-    boolean shouldShowRequestPermissionRationale(String permissionName,
+    boolean shouldShowRequestPermissionRationale(String permName,
             String packageName, int userId);
 
     boolean isProtectedBroadcast(String actionName);
@@ -659,8 +629,6 @@
     boolean isPackageSignedByKeySet(String packageName, in KeySet ks);
     boolean isPackageSignedByKeySetExactly(String packageName, in KeySet ks);
 
-    void addOnPermissionsChangeListener(in IOnPermissionsChangeListener listener);
-    void removeOnPermissionsChangeListener(in IOnPermissionsChangeListener listener);
     void grantDefaultPermissionsToEnabledCarrierApps(in String[] packageNames, int userId);
     void grantDefaultPermissionsToEnabledImsServices(in String[] packageNames, int userId);
     void grantDefaultPermissionsToEnabledTelephonyDataServices(
@@ -757,6 +725,10 @@
     // The following binder interfaces have been moved to IPermissionManager
     //
     //------------------------------------------------------------------------
+
+    //------------------------------------------------------------------------
+    // We need to keep these in IPackageManager for app compatibility
+    //------------------------------------------------------------------------
     @UnsupportedAppUsage
     String[] getAppOpPermissionPackages(String permissionName);
 
@@ -771,4 +743,17 @@
 
     @UnsupportedAppUsage
     void removePermission(String name);
+
+    @UnsupportedAppUsage
+    int checkPermission(String permName, String pkgName, int userId);
+
+    @UnsupportedAppUsage
+    void grantRuntimePermission(String packageName, String permissionName, int userId);
+
+    //------------------------------------------------------------------------
+    // We need to keep these in IPackageManager for convenience in splitting
+    // out the permission manager. This should be cleaned up, but, will require
+    // a large change that modifies many repos.
+    //------------------------------------------------------------------------
+    int checkUidPermission(String permName, int uid);
 }
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index e08f4a2..b845a37 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -105,6 +105,7 @@
      * @hide
      */
     @SystemApi
+    @TestApi
     public interface OnPermissionsChangedListener {
 
         /**
@@ -6413,6 +6414,7 @@
      * @hide
      */
     @SystemApi
+    @TestApi
     @RequiresPermission(Manifest.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS)
     public abstract void addOnPermissionsChangeListener(
             @NonNull OnPermissionsChangedListener listener);
@@ -6425,6 +6427,7 @@
      * @hide
      */
     @SystemApi
+    @TestApi
     @RequiresPermission(Manifest.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS)
     public abstract void removeOnPermissionsChangeListener(
             @NonNull OnPermissionsChangedListener listener);
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index 1c1d709..e21d4c41 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -32,13 +32,10 @@
 import android.util.ArraySet;
 import android.util.SparseArray;
 
-import com.android.internal.util.function.TriFunction;
-
 import java.io.IOException;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.List;
-import java.util.function.BiFunction;
 import java.util.function.Consumer;
 
 /**
@@ -86,32 +83,6 @@
         void onPackageRemoved(@NonNull String packageName, int uid);
     }
 
-    /** Interface to override permission checks via composition */
-    public interface CheckPermissionDelegate {
-        /**
-         * Allows overriding check permission behavior.
-         *
-         * @param permName The permission to check.
-         * @param pkgName The package for which to check.
-         * @param userId The user for which to check.
-         * @param superImpl The super implementation.
-         * @return The check permission result.
-         */
-        int checkPermission(String permName, String pkgName, int userId,
-                TriFunction<String, String, Integer, Integer> superImpl);
-
-        /**
-         * Allows overriding check UID permission behavior.
-         *
-         * @param permName The permission to check.
-         * @param uid The UID for which to check.
-         * @param superImpl The super implementation.
-         * @return The check permission result.
-         */
-        int checkUidPermission(String permName, int uid,
-                BiFunction<String, Integer, Integer> superImpl);
-    }
-
     /**
      * Provider for package names.
      */
@@ -464,26 +435,6 @@
     public abstract boolean wasPackageEverLaunched(String packageName, int userId);
 
     /**
-     * Grants a runtime permission
-     * @param packageName The package name.
-     * @param name The name of the permission.
-     * @param userId The userId for which to grant the permission.
-     * @param overridePolicy If true, grant this permission even if it is fixed by policy.
-     */
-    public abstract void grantRuntimePermission(String packageName, String name, int userId,
-            boolean overridePolicy);
-
-    /**
-     * Revokes a runtime permission
-     * @param packageName The package name.
-     * @param name The name of the permission.
-     * @param userId The userId for which to revoke the permission.
-     * @param overridePolicy If true, revoke this permission even if it is fixed by policy.
-     */
-    public abstract void revokeRuntimePermission(String packageName, String name, int userId,
-            boolean overridePolicy);
-
-    /**
      * Retrieve the official name associated with a uid. This name is
      * guaranteed to never change, though it is possible for the underlying
      * uid to be changed. That is, if you are storing information about
@@ -668,6 +619,12 @@
     public abstract @Nullable PackageParser.Package getPackage(@NonNull String packageName);
 
     /**
+     * Returns a package for the given UID. If the UID is part of a shared user ID, one
+     * of the packages will be chosen to be returned.
+     */
+    public abstract @Nullable PackageParser.Package getPackage(int uid);
+
+    /**
      * Returns a list without a change observer.
      *
      * @see #getPackageList(PackageListObserver)
@@ -742,17 +699,6 @@
     public abstract boolean filterAppAccess(
             @Nullable PackageParser.Package pkg, int callingUid, int userId);
 
-    /*
-     * NOTE: The following methods are temporary until permissions are extracted from
-     * the package manager into a component specifically for handling permissions.
-     */
-    /** Returns the flags for the given permission. */
-    public abstract @Nullable int getPermissionFlagsTEMP(@NonNull String permName,
-            @NonNull String packageName, int userId);
-    /** Updates the flags for the given permission. */
-    public abstract void updatePermissionFlagsTEMP(@NonNull String permName,
-            @NonNull String packageName, int flagMask, int flagValues, int userId);
-
     /** Returns whether the given package was signed by the platform */
     public abstract boolean isPlatformSigned(String pkg);
 
@@ -782,20 +728,6 @@
             @PackageParser.SigningDetails.CertCapabilities int capability);
 
     /**
-     * Get the delegate to influence permission checking.
-     *
-     * @return The delegate instance or null to clear.
-     */
-    public abstract @Nullable CheckPermissionDelegate getCheckPermissionDelegate();
-
-    /**
-     * Set a delegate to influence permission checking.
-     *
-     * @param delegate A delegate instance or null to clear.
-     */
-    public abstract void setCheckPermissionDelegate(@Nullable CheckPermissionDelegate delegate);
-
-    /**
      * Get appIds of all available apps which specified android:sharedUserId in the manifest.
      *
      * @return a SparseArray mapping from appId to it's sharedUserId.
@@ -1006,4 +938,26 @@
      * the settings have been written.
      */
     public abstract void writeSettings(boolean async);
+
+    /**
+     * Writes all permission settings for the given set of users to disk. If {@code async}
+     * is {@code true}, the settings are written at some point in the future. Otherwise,
+     * the call blocks until the settings have been written.
+     */
+    public abstract void writePermissionSettings(@NonNull @UserIdInt int[] userIds, boolean async);
+
+    /**
+     * Returns the target SDK for the given UID. Will return {@code 0} if there is no
+     * package associated with the UID or if the package has not been installed for
+     * the user. Will return the highest target SDK if the UID references packages with
+     * a shared user id.
+     */
+    public abstract int getTargetSdk(int uid);
+
+    /**
+     * Returns {@code true} if the caller is the installer of record for the given package.
+     * Otherwise, {@code false}.
+     */
+    public abstract boolean isCallerInstallerOfRecord(
+            @NonNull PackageParser.Package pkg, int callingUid);
 }
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index e5ef67b..2420a61 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -1157,8 +1157,11 @@
             }
         }
 
-        if (mObject != 0) {
-            nativeDestroy(mObject);
+        synchronized (this) {
+            if (mObject != 0) {
+                nativeDestroy(mObject);
+                mObject = 0;
+            }
         }
     }
 
diff --git a/core/java/android/content/res/ResourcesImpl.java b/core/java/android/content/res/ResourcesImpl.java
index 794be9e..b72544c 100644
--- a/core/java/android/content/res/ResourcesImpl.java
+++ b/core/java/android/content/res/ResourcesImpl.java
@@ -856,7 +856,8 @@
             stack.push(id);
             try {
                 if (file.endsWith(".xml")) {
-                    if (file.startsWith("res/color/")) {
+                    final String typeName = getResourceTypeName(id);
+                    if (typeName != null && typeName.equals("color")) {
                         dr = loadColorOrXmlDrawable(wrapper, value, id, density, file);
                     } else {
                         dr = loadXmlDrawable(wrapper, value, id, density, file);
diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java
index ae421a4..87c7118 100644
--- a/core/java/android/net/NetworkTemplate.java
+++ b/core/java/android/net/NetworkTemplate.java
@@ -48,6 +48,7 @@
 import java.io.DataOutputStream;
 import java.io.IOException;
 import java.util.Arrays;
+import java.util.List;
 import java.util.Objects;
 
 /**
@@ -481,17 +482,39 @@
      * For example, given an incoming template matching B, and the currently
      * active merge set [A,B], we'd return a new template that primarily matches
      * A, but also matches B.
+     * TODO: remove and use {@link #normalize(NetworkTemplate, List)}.
      */
     @UnsupportedAppUsage
     public static NetworkTemplate normalize(NetworkTemplate template, String[] merged) {
-        if (template.isMatchRuleMobile() && ArrayUtils.contains(merged, template.mSubscriberId)) {
-            // Requested template subscriber is part of the merge group; return
-            // a template that matches all merged subscribers.
-            return new NetworkTemplate(template.mMatchRule, merged[0], merged,
-                    template.mNetworkId);
-        } else {
-            return template;
+        return normalize(template, Arrays.<String[]>asList(merged));
+    }
+
+    /**
+     * Examine the given template and normalize if it refers to a "merged"
+     * mobile subscriber. We pick the "lowest" merged subscriber as the primary
+     * for key purposes, and expand the template to match all other merged
+     * subscribers.
+     *
+     * There can be multiple merged subscriberIds for multi-SIM devices.
+     *
+     * <p>
+     * For example, given an incoming template matching B, and the currently
+     * active merge set [A,B], we'd return a new template that primarily matches
+     * A, but also matches B.
+     */
+    public static NetworkTemplate normalize(NetworkTemplate template, List<String[]> mergedList) {
+        if (!template.isMatchRuleMobile()) return template;
+
+        for (String[] merged : mergedList) {
+            if (ArrayUtils.contains(merged, template.mSubscriberId)) {
+                // Requested template subscriber is part of the merge group; return
+                // a template that matches all merged subscribers.
+                return new NetworkTemplate(template.mMatchRule, merged[0], merged,
+                        template.mNetworkId);
+            }
         }
+
+        return template;
     }
 
     @UnsupportedAppUsage
diff --git a/core/java/android/os/RedactingFileDescriptor.java b/core/java/android/os/RedactingFileDescriptor.java
index 4e5eaac..a1ed214 100644
--- a/core/java/android/os/RedactingFileDescriptor.java
+++ b/core/java/android/os/RedactingFileDescriptor.java
@@ -35,7 +35,7 @@
 
 /**
  * Variant of {@link FileDescriptor} that allows its creator to specify regions
- * that should be redacted (appearing as zeros to the reader).
+ * that should be redacted.
  *
  * @hide
  */
@@ -44,13 +44,16 @@
     private static final boolean DEBUG = true;
 
     private volatile long[] mRedactRanges;
+    private volatile long[] mFreeOffsets;
 
     private FileDescriptor mInner = null;
     private ParcelFileDescriptor mOuter = null;
 
-    private RedactingFileDescriptor(Context context, File file, int mode, long[] redactRanges)
+    private RedactingFileDescriptor(
+            Context context, File file, int mode, long[] redactRanges, long[] freeOffsets)
             throws IOException {
         mRedactRanges = checkRangesArgument(redactRanges);
+        mFreeOffsets = freeOffsets;
 
         try {
             try {
@@ -88,13 +91,17 @@
      *
      * @param file The underlying file to open.
      * @param mode The {@link ParcelFileDescriptor} mode to open with.
-     * @param redactRanges List of file offsets that should be redacted, stored
+     * @param redactRanges List of file ranges that should be redacted, stored
      *            as {@code [start1, end1, start2, end2, ...]}. Start values are
      *            inclusive and end values are exclusive.
+     * @param freePositions List of file offsets at which the four byte value 'free' should be
+     *            written instead of zeros within parts of the file covered by {@code redactRanges}.
+     *            Non-redacted bytes will not be modified even if covered by a 'free'. This is
+     *            useful for overwriting boxes in ISOBMFF files with padding data.
      */
     public static ParcelFileDescriptor open(Context context, File file, int mode,
-            long[] redactRanges) throws IOException {
-        return new RedactingFileDescriptor(context, file, mode, redactRanges).mOuter;
+            long[] redactRanges, long[] freePositions) throws IOException {
+        return new RedactingFileDescriptor(context, file, mode, redactRanges, freePositions).mOuter;
     }
 
     /**
@@ -169,6 +176,15 @@
                 for (long j = start; j < end; j++) {
                     data[(int) (j - offset)] = 0;
                 }
+                // Overwrite data at 'free' offsets within the redaction ranges.
+                for (long freeOffset : mFreeOffsets) {
+                    final long freeEnd = freeOffset + 4;
+                    final long redactFreeStart = Math.max(freeOffset, start);
+                    final long redactFreeEnd = Math.min(freeEnd, end);
+                    for (long j = redactFreeStart; j < redactFreeEnd; j++) {
+                        data[(int) (j - offset)] = (byte) "free".charAt((int) (j - freeOffset));
+                    }
+                }
             }
             return n;
         }
diff --git a/core/java/android/os/UpdateEngine.java b/core/java/android/os/UpdateEngine.java
index 5cf3b97..29af17a 100644
--- a/core/java/android/os/UpdateEngine.java
+++ b/core/java/android/os/UpdateEngine.java
@@ -21,6 +21,8 @@
 import android.os.IUpdateEngineCallback;
 import android.os.RemoteException;
 
+import java.io.FileDescriptor;
+
 /**
  * UpdateEngine handles calls to the update engine which takes care of A/B OTA
  * updates. It wraps up the update engine Binder APIs and exposes them as
@@ -312,6 +314,22 @@
     }
 
     /**
+     * Applies the payload passed as file descriptor {@code fd} instead of
+     * using the {@code file://} scheme.
+     *
+     * <p>See {@link #applyPayload(String)} for {@code offset}, {@code size} and
+     * {@code headerKeyValuePairs} parameters.
+     */
+    public void applyPayload(FileDescriptor fd, long offset, long size,
+            String[] headerKeyValuePairs) {
+        try {
+            mUpdateEngine.applyPayloadFd(fd, offset, size, headerKeyValuePairs);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Permanently cancels an in-progress update.
      *
      * <p>See {@link #resetStatus} to undo a finshed update (only available
diff --git a/core/java/android/content/pm/IOnPermissionsChangeListener.aidl b/core/java/android/permission/IOnPermissionsChangeListener.aidl
similarity index 96%
rename from core/java/android/content/pm/IOnPermissionsChangeListener.aidl
rename to core/java/android/permission/IOnPermissionsChangeListener.aidl
index 7791b50..cc52a72 100644
--- a/core/java/android/content/pm/IOnPermissionsChangeListener.aidl
+++ b/core/java/android/permission/IOnPermissionsChangeListener.aidl
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.content.pm;
+package android.permission;
 
 /**
  * Listener for changes in the permissions for installed packages.
diff --git a/core/java/android/permission/IPermissionManager.aidl b/core/java/android/permission/IPermissionManager.aidl
index 3b69b12..d31cee0 100644
--- a/core/java/android/permission/IPermissionManager.aidl
+++ b/core/java/android/permission/IPermissionManager.aidl
@@ -19,6 +19,7 @@
 import android.content.pm.ParceledListSlice;
 import android.content.pm.PermissionGroupInfo;
 import android.content.pm.PermissionInfo;
+import android.permission.IOnPermissionsChangeListener;
 
 /**
  * Interface to communicate directly with the permission manager service.
@@ -39,4 +40,34 @@
     boolean addPermission(in PermissionInfo info, boolean async);
 
     void removePermission(String name);
+
+    int getPermissionFlags(String permName, String packageName, int userId);
+
+    void updatePermissionFlags(String permName, String packageName, int flagMask,
+            int flagValues, boolean checkAdjustPolicyFlagPermission, int userId);
+
+    void updatePermissionFlagsForAllApps(int flagMask, int flagValues, int userId);
+
+    int checkPermission(String permName, String pkgName, int userId);
+
+    int checkUidPermission(String permName, int uid);
+
+    void addOnPermissionsChangeListener(in IOnPermissionsChangeListener listener);
+
+    void removeOnPermissionsChangeListener(in IOnPermissionsChangeListener listener);
+
+    List<String> getWhitelistedRestrictedPermissions(String packageName,
+            int flags, int userId);
+
+    boolean addWhitelistedRestrictedPermission(String packageName, String permName,
+            int flags, int userId);
+
+    boolean removeWhitelistedRestrictedPermission(String packageName, String permName,
+            int flags, int userId);
+
+    void grantRuntimePermission(String packageName, String permName, int userId);
+
+    void revokeRuntimePermission(String packageName, String permName, int userId);
+
+    void resetRuntimePermissions();
 }
diff --git a/core/java/android/permission/PermissionManager.java b/core/java/android/permission/PermissionManager.java
index 182a2ff..42816c0 100644
--- a/core/java/android/permission/PermissionManager.java
+++ b/core/java/android/permission/PermissionManager.java
@@ -43,6 +43,14 @@
 @SystemApi
 @SystemService(Context.PERMISSION_SERVICE)
 public final class PermissionManager {
+    /** @hide */
+    public static final String KILL_APP_REASON_PERMISSIONS_REVOKED =
+            "permissions revoked";
+    /** @hide */
+    public static final String KILL_APP_REASON_GIDS_CHANGED =
+            "permission grant or revoke changed gids";
+
+
     /**
      * {@link android.content.pm.PackageParser} needs access without having a {@link Context}.
      *
diff --git a/core/java/android/permission/PermissionManagerInternal.java b/core/java/android/permission/PermissionManagerInternal.java
index 7167431..3134ec0 100644
--- a/core/java/android/permission/PermissionManagerInternal.java
+++ b/core/java/android/permission/PermissionManagerInternal.java
@@ -21,6 +21,10 @@
 import android.annotation.UserIdInt;
 import android.os.UserHandle;
 
+import com.android.internal.util.function.TriFunction;
+
+import java.util.function.BiFunction;
+
 /**
  * Internal interfaces to be used by other components within the system server.
  *
@@ -46,6 +50,33 @@
                 @UserIdInt int userId);
     }
 
+    /** Interface to override permission checks via composition */
+    public interface CheckPermissionDelegate {
+        /**
+         * Checks whether the given package has been granted the specified permission.
+         *
+         * @return If the package has the permission, PERMISSION_GRANTED is
+         * returned.  If it does not have the permission, PERMISSION_DENIED
+         * is returned.
+         *
+         * @see android.content.pm.PackageManager#checkPermission(String, String)
+         */
+        int checkPermission(String permName, String pkgName, int userId,
+                TriFunction<String, String, Integer, Integer> superImpl);
+
+        /**
+        /**
+         * Checks whether the given uid has been granted the specified permission.
+         *
+         * @return If the package has the permission, PERMISSION_GRANTED is
+         * returned.  If it does not have the permission, PERMISSION_DENIED
+         * is returned.
+         *
+         */
+        int checkUidPermission(String permName, int uid,
+                BiFunction<String, Integer, Integer> superImpl);
+    }
+
     /**
      * Get the state of the runtime permissions as xml file.
      *
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index d226716..d0401e3 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -344,6 +344,15 @@
         @TestApi
         String KEY_SYSTEM_GESTURES_EXCLUDED_BY_PRE_Q_STICKY_IMMERSIVE =
                 "system_gestures_excluded_by_pre_q_sticky_immersive";
+
+        /**
+         * Key for controlling which packages are explicitly blocked from running at refresh rates
+         * higher than 90hz.
+         *
+         * @see android.provider.DeviceConfig#NAMESPACE_WINDOW_MANAGER
+         * @hide
+         */
+        String KEY_HIGH_REFRESH_RATE_BLACKLIST = "high_refresh_rate_blacklist";
     }
 
     private static final Object sLock = new Object();
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 2ee6b7d..5308cd3 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -90,7 +90,6 @@
 import android.util.Log;
 import android.util.MemoryIntArray;
 import android.view.Display;
-import android.view.inputmethod.InputMethodSystemProperty;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.widget.ILockSettings;
@@ -9298,13 +9297,6 @@
             CLONE_TO_MANAGED_PROFILE.add(LOCATION_MODE);
             CLONE_TO_MANAGED_PROFILE.add(LOCATION_PROVIDERS_ALLOWED);
             CLONE_TO_MANAGED_PROFILE.add(SHOW_IME_WITH_HARD_KEYBOARD);
-            if (!InputMethodSystemProperty.PER_PROFILE_IME_ENABLED) {
-                CLONE_TO_MANAGED_PROFILE.add(DEFAULT_INPUT_METHOD);
-                CLONE_TO_MANAGED_PROFILE.add(ENABLED_INPUT_METHODS);
-                CLONE_TO_MANAGED_PROFILE.add(SELECTED_INPUT_METHOD_SUBTYPE);
-                CLONE_TO_MANAGED_PROFILE.add(SELECTED_SPELL_CHECKER);
-                CLONE_TO_MANAGED_PROFILE.add(SELECTED_SPELL_CHECKER_SUBTYPE);
-            }
         }
 
         /** @hide */
diff --git a/core/java/android/util/proto/ProtoInputStream.java b/core/java/android/util/proto/ProtoInputStream.java
index c290dff..24e7d2b 100644
--- a/core/java/android/util/proto/ProtoInputStream.java
+++ b/core/java/android/util/proto/ProtoInputStream.java
@@ -253,12 +253,14 @@
     }
 
     /**
-     * Attempt to guess the next field. If there is a match, the field data will be ready to read.
-     * If there is no match, nextField will need to be called to get the field number
+     * Reads the tag of the next field from the stream. If previous field value was not read, its
+     * data will be skipped over. If {@code fieldId} matches the next field ID, the field data will
+     * be ready to read. If it does not match, {@link #nextField()} or {@link #nextField(long)} will
+     * need to be called again before the field data can be read.
      *
      * @return true if fieldId matches the next field, false if not
      */
-    public boolean isNextField(long fieldId) throws IOException {
+    public boolean nextField(long fieldId) throws IOException {
         if (nextField() == (int) fieldId) {
             return true;
         }
diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java
index 4b92968..203b087 100644
--- a/core/java/android/view/AccessibilityInteractionController.java
+++ b/core/java/android/view/AccessibilityInteractionController.java
@@ -38,7 +38,6 @@
 import android.text.style.ClickableSpan;
 import android.util.LongSparseArray;
 import android.util.Slog;
-import android.view.View.AttachInfo;
 import android.view.accessibility.AccessibilityInteractionClient;
 import android.view.accessibility.AccessibilityManager;
 import android.view.accessibility.AccessibilityNodeIdManager;
@@ -903,38 +902,6 @@
                 }
             }
         }
-
-        if (spec != null) {
-            AttachInfo attachInfo = mViewRootImpl.mAttachInfo;
-            if (attachInfo.mDisplay == null) {
-                return;
-            }
-
-            final float scale = attachInfo.mApplicationScale * spec.scale;
-
-            Rect visibleWinFrame = mTempRect1;
-            visibleWinFrame.left = (int) (attachInfo.mWindowLeft * scale + spec.offsetX);
-            visibleWinFrame.top = (int) (attachInfo.mWindowTop * scale + spec.offsetY);
-            visibleWinFrame.right = (int) (visibleWinFrame.left + mViewRootImpl.mWidth * scale);
-            visibleWinFrame.bottom = (int) (visibleWinFrame.top + mViewRootImpl.mHeight * scale);
-
-            attachInfo.mDisplay.getRealSize(mTempPoint);
-            final int displayWidth = mTempPoint.x;
-            final int displayHeight = mTempPoint.y;
-
-            Rect visibleDisplayFrame = mTempRect2;
-            visibleDisplayFrame.set(0, 0, displayWidth, displayHeight);
-
-            if (!visibleWinFrame.intersect(visibleDisplayFrame)) {
-                // If there's no intersection with display, set visibleWinFrame empty.
-                visibleDisplayFrame.setEmpty();
-            }
-
-            if (!visibleWinFrame.intersects(boundsInScreen.left, boundsInScreen.top,
-                    boundsInScreen.right, boundsInScreen.bottom)) {
-                info.setVisibleToUser(false);
-            }
-        }
     }
 
     private boolean shouldApplyAppScaleAndMagnificationSpec(float appScale,
@@ -948,8 +915,10 @@
         try {
             mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
             adjustBoundsInScreenIfNeeded(infos);
-            applyAppScaleAndMagnificationSpecIfNeeded(infos, spec);
+            // To avoid applyAppScaleAndMagnificationSpecIfNeeded changing the bounds of node,
+            // then impact the visibility result, we need to adjust visibility before apply scale.
             adjustIsVisibleToUserIfNeeded(infos, interactiveRegion);
+            applyAppScaleAndMagnificationSpecIfNeeded(infos, spec);
             callback.setFindAccessibilityNodeInfosResult(infos, interactionId);
             if (infos != null) {
                 infos.clear();
@@ -967,8 +936,10 @@
         try {
             mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
             adjustBoundsInScreenIfNeeded(info);
-            applyAppScaleAndMagnificationSpecIfNeeded(info, spec);
+            // To avoid applyAppScaleAndMagnificationSpecIfNeeded changing the bounds of node,
+            // then impact the visibility result, we need to adjust visibility before apply scale.
             adjustIsVisibleToUserIfNeeded(info, interactiveRegion);
+            applyAppScaleAndMagnificationSpecIfNeeded(info, spec);
             callback.setFindAccessibilityNodeInfoResult(info, interactionId);
         } catch (RemoteException re) {
                 /* ignore - the other side will time out */
diff --git a/core/java/android/view/DisplayCutout.java b/core/java/android/view/DisplayCutout.java
index 715181f..797c128 100644
--- a/core/java/android/view/DisplayCutout.java
+++ b/core/java/android/view/DisplayCutout.java
@@ -319,18 +319,23 @@
             sortedBounds[i] = ZERO_RECT;
         }
         if (safeInsets != null && boundingRects != null) {
+            // There is at most one non-functional area per short edge of the device, but none
+            // on the long edges, so either a) safeInsets.top and safeInsets.bottom is 0, or
+            // b) safeInsets.left and safeInset.right is 0.
+            final boolean topBottomInset = safeInsets.top > 0 || safeInsets.bottom > 0;
             for (Rect bound : boundingRects) {
-                // There is at most one non-functional area per short edge of the device, but none
-                // on the long edges, so either safeInsets.right or safeInsets.bottom must be 0.
-                // TODO(b/117199965): Refine the logic to handle edge cases.
-                if (bound.left == 0) {
-                    sortedBounds[BOUNDS_POSITION_LEFT] = bound;
-                } else if (bound.top == 0) {
-                    sortedBounds[BOUNDS_POSITION_TOP] = bound;
-                } else if (safeInsets.right > 0) {
-                    sortedBounds[BOUNDS_POSITION_RIGHT] = bound;
-                } else if (safeInsets.bottom > 0) {
-                    sortedBounds[BOUNDS_POSITION_BOTTOM] = bound;
+                if (topBottomInset) {
+                    if (bound.top == 0) {
+                        sortedBounds[BOUNDS_POSITION_TOP] = bound;
+                    } else {
+                        sortedBounds[BOUNDS_POSITION_BOTTOM] = bound;
+                    }
+                } else {
+                    if (bound.left == 0) {
+                        sortedBounds[BOUNDS_POSITION_LEFT] = bound;
+                    } else {
+                        sortedBounds[BOUNDS_POSITION_RIGHT] = bound;
+                    }
                 }
             }
         }
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 5b3dbb1..d474b4d 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -1688,6 +1688,11 @@
      * Instead it represents the result of {@link View#getParentForAccessibility()},
      * which returns the closest ancestor where {@link View#isImportantForAccessibility()} is true.
      * So this method is not reliable.
+     * <p>
+     * When magnification is enabled, the bounds in parent are also scaled up by magnification
+     * scale. For example, it returns Rect(20, 20, 200, 200) for original bounds
+     * Rect(10, 10, 100, 100), when the magnification scale is 2.
+     * <p/>
      *
      * @param outBounds The output node bounds.
      * @deprecated Use {@link #getBoundsInScreen(Rect)} instead.
@@ -1725,6 +1730,12 @@
 
     /**
      * Gets the node bounds in screen coordinates.
+     * <p>
+     * When magnification is enabled, the bounds in screen are scaled up by magnification scale
+     * and the positions are also adjusted according to the offset of magnification viewport.
+     * For example, it returns Rect(-180, -180, 0, 0) for original bounds Rect(10, 10, 100, 100),
+     * when the magnification scale is 2 and offsets for X and Y are both 200.
+     * <p/>
      *
      * @param outBounds The output node bounds.
      */
@@ -1861,6 +1872,12 @@
 
     /**
      * Gets whether this node is visible to the user.
+     * <p>
+     * Between {@link Build.VERSION_CODES#JELLY_BEAN API 16} and
+     * {@link Build.VERSION_CODES#Q API 29}, this method may incorrectly return false when
+     * magnification is enabled. On other versions, a node is considered visible even if it is not
+     * on the screen because magnification is active.
+     * </p>
      *
      * @return Whether the node is visible to the user.
      */
diff --git a/core/java/android/view/inputmethod/InputMethodSystemProperty.java b/core/java/android/view/inputmethod/InputMethodSystemProperty.java
index 05143a1..0689806 100644
--- a/core/java/android/view/inputmethod/InputMethodSystemProperty.java
+++ b/core/java/android/view/inputmethod/InputMethodSystemProperty.java
@@ -43,17 +43,6 @@
      */
     private static final String PROP_DEBUG_MULTI_CLIENT_IME = "persist.debug.multi_client_ime";
 
-    /**
-     * System property key for debugging purpose. The value must be empty, "1", or "0".
-     *
-     * <p>Values 'y', 'yes', '1', 'true' or 'on' are considered true.</p>
-     *
-     * <p>To set, run "adb root && adb shell setprop persist.debug.per_profile_ime 1".</p>
-     *
-     * <p>This value will be ignored when {@link Build#IS_DEBUGGABLE} returns {@code false}.</p>
-     */
-    private static final String PROP_DEBUG_PER_PROFILE_IME = "persist.debug.per_profile_ime";
-
     @Nullable
     private static ComponentName getMultiClientImeComponentName() {
         if (Build.IS_DEBUGGABLE) {
@@ -91,19 +80,4 @@
      */
     @TestApi
     public static final boolean MULTI_CLIENT_IME_ENABLED = (sMultiClientImeComponentName != null);
-
-    /**
-     * {@code true} when per-profile IME is enabled.
-     * @hide
-     */
-    public static final boolean PER_PROFILE_IME_ENABLED;
-    static {
-        if (MULTI_CLIENT_IME_ENABLED) {
-            PER_PROFILE_IME_ENABLED = true;
-        } else if (Build.IS_DEBUGGABLE) {
-            PER_PROFILE_IME_ENABLED = SystemProperties.getBoolean(PROP_DEBUG_PER_PROFILE_IME, true);
-        } else {
-            PER_PROFILE_IME_ENABLED = true;
-        }
-    }
 }
diff --git a/core/java/com/android/internal/app/PlatLogoActivity.java b/core/java/com/android/internal/app/PlatLogoActivity.java
index 5778544..157e0a7 100644
--- a/core/java/com/android/internal/app/PlatLogoActivity.java
+++ b/core/java/com/android/internal/app/PlatLogoActivity.java
@@ -16,252 +16,167 @@
 
 package com.android.internal.app;
 
+import android.animation.ObjectAnimator;
 import android.animation.TimeAnimator;
 import android.app.Activity;
 import android.content.ActivityNotFoundException;
 import android.content.ContentResolver;
 import android.content.Intent;
+import android.content.res.ColorStateList;
+import android.graphics.Bitmap;
+import android.graphics.BitmapShader;
 import android.graphics.Canvas;
-import android.graphics.Color;
 import android.graphics.ColorFilter;
+import android.graphics.Matrix;
 import android.graphics.Paint;
 import android.graphics.Path;
+import android.graphics.PixelFormat;
+import android.graphics.Shader;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.provider.Settings;
 import android.util.Log;
+import android.view.HapticFeedbackConstants;
 import android.view.MotionEvent;
-import android.view.MotionEvent.PointerCoords;
 import android.view.View;
-import android.widget.FrameLayout;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+
+import com.android.internal.R;
 
 import org.json.JSONObject;
 
+/**
+ * @hide
+ */
 public class PlatLogoActivity extends Activity {
-    FrameLayout layout;
-    TimeAnimator anim;
-    PBackground bg;
+    ImageView mZeroView, mOneView;
+    BackslashDrawable mBackslash;
+    int mClicks;
 
-    private class PBackground extends Drawable {
-        private float maxRadius, radius, x, y, dp;
-        private int[] palette;
-        private int darkest;
-        private float offset;
+    static final Paint sPaint = new Paint();
+    static {
+        sPaint.setStyle(Paint.Style.STROKE);
+        sPaint.setStrokeWidth(4f);
+        sPaint.setStrokeCap(Paint.Cap.SQUARE);
+    }
 
-        public PBackground() {
-            randomizePalette();
+    @Override
+    protected void onPause() {
+        if (mBackslash != null) {
+            mBackslash.stopAnimating();
         }
-
-        /**
-         * set inner radius of "p" logo
-         */
-        public void setRadius(float r) {
-            this.radius = Math.max(48*dp, r);
-        }
-
-        /**
-         * move the "p"
-         */
-        public void setPosition(float x, float y) {
-            this.x = x;
-            this.y = y;
-        }
-
-        /**
-         * for animating the "p"
-         */
-        public void setOffset(float o) {
-            this.offset = o;
-        }
-
-        /**
-         * rough luminance calculation
-         * https://www.w3.org/TR/AERT/#color-contrast
-         */
-        public float lum(int rgb) {
-            return ((Color.red(rgb) * 299f) + (Color.green(rgb) * 587f) + (Color.blue(rgb) * 114f)) / 1000f;
-        }
-
-        /**
-         * create a random evenly-spaced color palette
-         * guaranteed to contrast!
-         */
-        public void randomizePalette() {
-            final int slots = 2 + (int)(Math.random() * 2);
-            float[] color = new float[] { (float) Math.random() * 360f, 1f, 1f };
-            palette = new int[slots];
-            darkest = 0;
-            for (int i=0; i<slots; i++) {
-                palette[i] = Color.HSVToColor(color);
-                color[0] = (color[0] + 360f/slots) % 360f;
-                if (lum(palette[i]) < lum(palette[darkest])) darkest = i;
-            }
-
-            final StringBuilder str = new StringBuilder();
-            for (int c : palette) {
-                str.append(String.format("#%08x ", c));
-            }
-            Log.v("PlatLogoActivity", "color palette: " + str);
-        }
-
-        @Override
-        public void draw(Canvas canvas) {
-            if (dp == 0) dp = getResources().getDisplayMetrics().density;
-            final float width = canvas.getWidth();
-            final float height = canvas.getHeight();
-            if (radius == 0) {
-                setPosition(width / 2, height / 2);
-                setRadius(width / 6);
-            }
-            final float inner_w = radius * 0.667f;
-
-            final Paint paint = new Paint();
-            paint.setStrokeCap(Paint.Cap.BUTT);
-            canvas.translate(x, y);
-
-            Path p = new Path();
-            p.moveTo(-radius, height);
-            p.lineTo(-radius, 0);
-            p.arcTo(-radius, -radius, radius, radius, -180, 270, false);
-            p.lineTo(-radius, radius);
-
-            float w = Math.max(canvas.getWidth(), canvas.getHeight())  * 1.414f;
-            paint.setStyle(Paint.Style.FILL);
-
-            int i=0;
-            while (w > radius*2 + inner_w*2) {
-                paint.setColor(0xFF000000 | palette[i % palette.length]);
-                // for a slower but more complete version:
-                // paint.setStrokeWidth(w);
-                // canvas.drawPath(p, paint);
-                canvas.drawOval(-w/2, -w/2, w/2, w/2, paint);
-                w -= inner_w * (1.1f + Math.sin((i/20f + offset) * 3.14159f));
-                i++;
-            }
-
-            // the innermost circle needs to be a constant color to avoid rapid flashing
-            paint.setColor(0xFF000000 | palette[(darkest+1) % palette.length]);
-            canvas.drawOval(-radius, -radius, radius, radius, paint);
-
-            p.reset();
-            p.moveTo(-radius, height);
-            p.lineTo(-radius, 0);
-            p.arcTo(-radius, -radius, radius, radius, -180, 270, false);
-            p.lineTo(-radius + inner_w, radius);
-
-            paint.setStyle(Paint.Style.STROKE);
-            paint.setStrokeWidth(inner_w*2);
-            paint.setColor(palette[darkest]);
-            canvas.drawPath(p, paint);
-            paint.setStrokeWidth(inner_w);
-            paint.setColor(0xFFFFFFFF);
-            canvas.drawPath(p, paint);
-        }
-
-        @Override
-        public void setAlpha(int alpha) {
-
-        }
-
-        @Override
-        public void setColorFilter(ColorFilter colorFilter) {
-
-        }
-
-        @Override
-        public int getOpacity() {
-            return 0;
-        }
+        mClicks = 0;
+        super.onPause();
     }
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
+        final float dp = getResources().getDisplayMetrics().density;
 
-        layout = new FrameLayout(this);
-        setContentView(layout);
+        getWindow().getDecorView().setSystemUiVisibility(
+                View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
+        getWindow().setNavigationBarColor(0);
+        getWindow().setStatusBarColor(0);
 
-        bg = new PBackground();
-        layout.setBackground(bg);
+        getActionBar().hide();
 
-        final ContentResolver cr = getContentResolver();
+        setContentView(R.layout.platlogo_layout);
 
-        layout.setOnTouchListener(new View.OnTouchListener() {
-            final String TOUCH_STATS = "touch.stats";
+        mBackslash = new BackslashDrawable((int) (50 * dp));
 
-            final PointerCoords pc0 = new PointerCoords();
-            final PointerCoords pc1 = new PointerCoords();
+        mOneView = findViewById(R.id.one);
+        mOneView.setImageDrawable(new OneDrawable());
+        mZeroView = findViewById(R.id.zero);
+        mZeroView.setImageDrawable(new ZeroDrawable());
 
-            double pressure_min, pressure_max;
-            int maxPointers;
-            int tapCount;
+        final ViewGroup root = (ViewGroup) mOneView.getParent();
+        root.setClipChildren(false);
+        root.setBackground(mBackslash);
+        root.getBackground().setAlpha(0x20);
 
+        View.OnTouchListener tl = new View.OnTouchListener() {
+            float mOffsetX, mOffsetY;
+            long mClickTime;
+            ObjectAnimator mRotAnim;
             @Override
             public boolean onTouch(View v, MotionEvent event) {
-                final float pressure = event.getPressure();
+                measureTouchPressure(event);
                 switch (event.getActionMasked()) {
                     case MotionEvent.ACTION_DOWN:
-                        pressure_min = pressure_max = pressure;
-                        // fall through
-                    case MotionEvent.ACTION_MOVE:
-                        if (pressure < pressure_min) pressure_min = pressure;
-                        if (pressure > pressure_max) pressure_max = pressure;
-                        final int pc = event.getPointerCount();
-                        if (pc > maxPointers) maxPointers = pc;
-                        if (pc > 1) {
-                            event.getPointerCoords(0, pc0);
-                            event.getPointerCoords(1, pc1);
-                            bg.setRadius((float) Math.hypot(pc0.x - pc1.x, pc0.y - pc1.y) / 2f);
+                        v.animate().scaleX(1.1f).scaleY(1.1f);
+                        v.getParent().bringChildToFront(v);
+                        mOffsetX = event.getRawX() - v.getX();
+                        mOffsetY = event.getRawY() - v.getY();
+                        long now = System.currentTimeMillis();
+                        if (now - mClickTime < 350) {
+                            mRotAnim = ObjectAnimator.ofFloat(v, View.ROTATION,
+                                    v.getRotation(), v.getRotation() + 3600);
+                            mRotAnim.setDuration(10000);
+                            mRotAnim.start();
+                            mClickTime = 0;
+                        } else {
+                            mClickTime = now;
                         }
                         break;
-                    case MotionEvent.ACTION_CANCEL:
+                    case MotionEvent.ACTION_MOVE:
+                        v.setX(event.getRawX() - mOffsetX);
+                        v.setY(event.getRawY() - mOffsetY);
+                        v.performHapticFeedback(HapticFeedbackConstants.TEXT_HANDLE_MOVE);
+                        break;
                     case MotionEvent.ACTION_UP:
-                        try {
-                            final String touchDataJson = Settings.System.getString(cr, TOUCH_STATS);
-                            final JSONObject touchData = new JSONObject(
-                                    touchDataJson != null ? touchDataJson : "{}");
-                            if (touchData.has("min")) {
-                                pressure_min = Math.min(pressure_min, touchData.getDouble("min"));
-                            }
-                            if (touchData.has("max")) {
-                                pressure_max = Math.max(pressure_max, touchData.getDouble("max"));
-                            }
-                            touchData.put("min", pressure_min);
-                            touchData.put("max", pressure_max);
-                            Settings.System.putString(cr, TOUCH_STATS, touchData.toString());
-                        } catch (Exception e) {
-                            Log.e("PlatLogoActivity", "Can't write touch settings", e);
-                        }
-
-                        if (maxPointers == 1) {
-                            tapCount ++;
-                            if (tapCount < 7) {
-                                bg.randomizePalette();
-                            } else {
-                                launchNextStage();
-                            }
-                        } else {
-                            tapCount = 0;
-                        }
-                        maxPointers = 0;
+                        v.performClick();
+                        // fall through
+                    case MotionEvent.ACTION_CANCEL:
+                        v.animate().scaleX(1f).scaleY(1f);
+                        if (mRotAnim != null) mRotAnim.cancel();
+                        testOverlap();
                         break;
                 }
                 return true;
             }
-        });
+        };
+
+        findViewById(R.id.one).setOnTouchListener(tl);
+        findViewById(R.id.zero).setOnTouchListener(tl);
+        findViewById(R.id.text).setOnTouchListener(tl);
+    }
+
+    private void testOverlap() {
+        final float width = mZeroView.getWidth();
+        final float targetX = mZeroView.getX() + width * .2f;
+        final float targetY = mZeroView.getY() + width * .3f;
+        if (Math.hypot(targetX - mOneView.getX(), targetY - mOneView.getY()) < width * .2f
+                && Math.abs(mOneView.getRotation() % 360 - 315) < 15) {
+            mOneView.animate().x(mZeroView.getX() + width * .2f);
+            mOneView.animate().y(mZeroView.getY() + width * .3f);
+            mOneView.setRotation(mOneView.getRotation() % 360);
+            mOneView.animate().rotation(315);
+            mOneView.performHapticFeedback(HapticFeedbackConstants.CONFIRM);
+
+            mBackslash.startAnimating();
+
+            mClicks++;
+            if (mClicks >= 7) {
+                launchNextStage();
+            }
+        } else {
+            mBackslash.stopAnimating();
+        }
     }
 
     private void launchNextStage() {
         final ContentResolver cr = getContentResolver();
 
-        if (Settings.System.getLong(cr, Settings.System.EGG_MODE, 0) == 0) {
+        if (Settings.System.getLong(cr, "egg_mode" /* Settings.System.EGG_MODE */, 0) == 0) {
             // For posterity: the moment this user unlocked the easter egg
             try {
                 Settings.System.putLong(cr,
-                        Settings.System.EGG_MODE,
+                        "egg_mode", // Settings.System.EGG_MODE,
                         System.currentTimeMillis());
             } catch (RuntimeException e) {
-                Log.e("PlatLogoActivity", "Can't write settings", e);
+                Log.e("com.android.internal.app.PlatLogoActivity", "Can't write settings", e);
             }
         }
         try {
@@ -270,36 +185,206 @@
                         | Intent.FLAG_ACTIVITY_CLEAR_TASK)
                     .addCategory("com.android.internal.category.PLATLOGO"));
         } catch (ActivityNotFoundException ex) {
-            Log.e("PlatLogoActivity", "No more eggs.");
+            Log.e("com.android.internal.app.PlatLogoActivity", "No more eggs.");
         }
         finish();
     }
 
+    static final String TOUCH_STATS = "touch.stats";
+    double mPressureMin = 0, mPressureMax = -1;
+
+    private void measureTouchPressure(MotionEvent event) {
+        final float pressure = event.getPressure();
+        switch (event.getActionMasked()) {
+            case MotionEvent.ACTION_DOWN:
+                if (mPressureMax < 0) {
+                    mPressureMin = mPressureMax = pressure;
+                }
+                break;
+            case MotionEvent.ACTION_MOVE:
+                if (pressure < mPressureMin) mPressureMin = pressure;
+                if (pressure > mPressureMax) mPressureMax = pressure;
+                break;
+        }
+    }
+
+    private void syncTouchPressure() {
+        try {
+            final String touchDataJson = Settings.System.getString(
+                    getContentResolver(), TOUCH_STATS);
+            final JSONObject touchData = new JSONObject(
+                    touchDataJson != null ? touchDataJson : "{}");
+            if (touchData.has("min")) {
+                mPressureMin = Math.min(mPressureMin, touchData.getDouble("min"));
+            }
+            if (touchData.has("max")) {
+                mPressureMax = Math.max(mPressureMax, touchData.getDouble("max"));
+            }
+            if (mPressureMax >= 0) {
+                touchData.put("min", mPressureMin);
+                touchData.put("max", mPressureMax);
+                Settings.System.putString(getContentResolver(), TOUCH_STATS, touchData.toString());
+            }
+        } catch (Exception e) {
+            Log.e("com.android.internal.app.PlatLogoActivity", "Can't write touch settings", e);
+        }
+    }
+
     @Override
     public void onStart() {
         super.onStart();
-
-        bg.randomizePalette();
-
-        anim = new TimeAnimator();
-        anim.setTimeListener(
-                new TimeAnimator.TimeListener() {
-                    @Override
-                    public void onTimeUpdate(TimeAnimator animation, long totalTime, long deltaTime) {
-                        bg.setOffset((float) totalTime / 60000f);
-                        bg.invalidateSelf();
-                    }
-                });
-
-        anim.start();
+        syncTouchPressure();
     }
 
     @Override
     public void onStop() {
-        if (anim != null) {
-            anim.cancel();
-            anim = null;
-        }
+        syncTouchPressure();
         super.onStop();
     }
+
+    static class ZeroDrawable extends Drawable {
+        int mTintColor;
+
+        @Override
+        public void draw(Canvas canvas) {
+            sPaint.setColor(mTintColor | 0xFF000000);
+
+            canvas.save();
+            canvas.scale(canvas.getWidth() / 24f, canvas.getHeight() / 24f);
+
+            canvas.drawCircle(12f, 12f, 10f, sPaint);
+            canvas.restore();
+        }
+
+        @Override
+        public void setAlpha(int alpha) { }
+
+        @Override
+        public void setColorFilter(ColorFilter colorFilter) { }
+
+        @Override
+        public void setTintList(ColorStateList tint) {
+            mTintColor = tint.getDefaultColor();
+        }
+
+        @Override
+        public int getOpacity() {
+            return PixelFormat.TRANSLUCENT;
+        }
+    }
+
+    static class OneDrawable extends Drawable {
+        int mTintColor;
+
+        @Override
+        public void draw(Canvas canvas) {
+            sPaint.setColor(mTintColor | 0xFF000000);
+
+            canvas.save();
+            canvas.scale(canvas.getWidth() / 24f, canvas.getHeight() / 24f);
+
+            final Path p = new Path();
+            p.moveTo(12f, 21.83f);
+            p.rLineTo(0f, -19.67f);
+            p.rLineTo(-5f, 0f);
+            canvas.drawPath(p, sPaint);
+            canvas.restore();
+        }
+
+        @Override
+        public void setAlpha(int alpha) { }
+
+        @Override
+        public void setColorFilter(ColorFilter colorFilter) { }
+
+        @Override
+        public void setTintList(ColorStateList tint) {
+            mTintColor = tint.getDefaultColor();
+        }
+
+        @Override
+        public int getOpacity() {
+            return PixelFormat.TRANSLUCENT;
+        }
+    }
+
+    private static class BackslashDrawable extends Drawable implements TimeAnimator.TimeListener {
+        Bitmap mTile;
+        Paint mPaint = new Paint();
+        BitmapShader mShader;
+        TimeAnimator mAnimator = new TimeAnimator();
+        Matrix mMatrix = new Matrix();
+
+        public void draw(Canvas canvas) {
+            canvas.drawPaint(mPaint);
+        }
+
+        BackslashDrawable(int width) {
+            mTile = Bitmap.createBitmap(width, width, Bitmap.Config.ALPHA_8);
+            mAnimator.setTimeListener(this);
+
+            final Canvas tileCanvas = new Canvas(mTile);
+            final float w = tileCanvas.getWidth();
+            final float h = tileCanvas.getHeight();
+
+            final Path path = new Path();
+            path.moveTo(0, 0);
+            path.lineTo(w / 2, 0);
+            path.lineTo(w, h / 2);
+            path.lineTo(w, h);
+            path.close();
+
+            path.moveTo(0, h / 2);
+            path.lineTo(w / 2, h);
+            path.lineTo(0, h);
+            path.close();
+
+            final Paint slashPaint = new Paint();
+            slashPaint.setAntiAlias(true);
+            slashPaint.setStyle(Paint.Style.FILL);
+            slashPaint.setColor(0xFF000000);
+            tileCanvas.drawPath(path, slashPaint);
+
+            //mPaint.setColor(0xFF0000FF);
+            mShader = new BitmapShader(mTile, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
+            mPaint.setShader(mShader);
+        }
+
+        public void startAnimating() {
+            if (!mAnimator.isStarted()) {
+                mAnimator.start();
+            }
+        }
+
+        public void stopAnimating() {
+            if (mAnimator.isStarted()) {
+                mAnimator.cancel();
+            }
+        }
+
+        @Override
+        public void setAlpha(int alpha) {
+            mPaint.setAlpha(alpha);
+        }
+
+        @Override
+        public void setColorFilter(ColorFilter colorFilter) {
+            mPaint.setColorFilter(colorFilter);
+        }
+
+        @Override
+        public int getOpacity() {
+            return PixelFormat.TRANSLUCENT;
+        }
+
+        @Override
+        public void onTimeUpdate(TimeAnimator animation, long totalTime, long deltaTime) {
+            if (mShader != null) {
+                mMatrix.postTranslate(deltaTime / 4f, 0);
+                mShader.setLocalMatrix(mMatrix);
+                invalidateSelf();
+            }
+        }
+    }
 }
+
diff --git a/core/java/com/android/internal/infra/AndroidFuture.java b/core/java/com/android/internal/infra/AndroidFuture.java
index c7c2924..c8929e9 100644
--- a/core/java/com/android/internal/infra/AndroidFuture.java
+++ b/core/java/com/android/internal/infra/AndroidFuture.java
@@ -115,6 +115,20 @@
         }
     }
 
+    /**
+     * Create a completed future with the given value.
+     *
+     * @param value the value for the completed future
+     * @param <U> the type of the value
+     * @return the completed future
+     */
+    @NonNull
+    public static <U> AndroidFuture<U> completedFuture(U value) {
+        AndroidFuture<U> future = new AndroidFuture<>();
+        future.complete(value);
+        return future;
+    }
+
     @Override
     public boolean complete(@Nullable T value) {
         boolean changed = super.complete(value);
diff --git a/core/java/com/android/internal/infra/ThrottledRunnable.java b/core/java/com/android/internal/infra/ThrottledRunnable.java
new file mode 100644
index 0000000..9846fa9
--- /dev/null
+++ b/core/java/com/android/internal/infra/ThrottledRunnable.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.internal.infra;
+
+import android.annotation.NonNull;
+import android.os.Handler;
+import android.os.SystemClock;
+
+import com.android.internal.annotations.GuardedBy;
+
+/**
+ * A throttled runnable that can wrap around a runnable and throttle calls to its run().
+ *
+ * The throttling logic makes sure that the original runnable will be called only after the
+ * specified interval passes since the last actual call. The first call in a while (after the
+ * specified interval passes since the last actual call) will always result in the original runnable
+ * being called immediately, and then subsequent calls will start to be throttled. It is guaranteed
+ * that any call to this throttled runnable will always result in the original runnable being called
+ * afterwards, within the specified interval.
+ */
+public class ThrottledRunnable implements Runnable {
+
+    @NonNull
+    private final Handler mHandler;
+    private final long mIntervalMillis;
+    @NonNull
+    private final Runnable mRunnable;
+
+    @NonNull
+    private final Object mLock = new Object();
+
+    @GuardedBy("mLock")
+    private long mScheduledUptimeMillis;
+
+    public ThrottledRunnable(@NonNull Handler handler, long intervalMillis,
+            @NonNull Runnable runnable) {
+        mHandler = handler;
+        mIntervalMillis = intervalMillis;
+        mRunnable = runnable;
+    }
+
+    @Override
+    public void run() {
+        synchronized (mLock) {
+            if (mHandler.hasCallbacks(mRunnable)) {
+                // We have a scheduled runnable.
+                return;
+            }
+            long currentUptimeMillis = SystemClock.uptimeMillis();
+            if (mScheduledUptimeMillis == 0
+                    || currentUptimeMillis > mScheduledUptimeMillis + mIntervalMillis) {
+                // First time in a while, schedule immediately.
+                mScheduledUptimeMillis = currentUptimeMillis;
+            } else {
+                // We were scheduled not long ago, so schedule with delay for throttling.
+                mScheduledUptimeMillis = mScheduledUptimeMillis + mIntervalMillis;
+            }
+            mHandler.postAtTime(mRunnable, mScheduledUptimeMillis);
+        }
+    }
+}
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index 9b51c12..9d4cdc7 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -106,6 +106,14 @@
      */
     public static final int USE_APP_IMAGE_STARTUP_CACHE = 1 << 16;
 
+    /**
+     * When set, application specified signal handlers are not chained (i.e, ignored)
+     * by the runtime.
+     *
+     * Used for debugging only. Usage: set debug.ignoreappsignalhandler to 1.
+     */
+    public static final int DEBUG_IGNORE_APP_SIGNAL_HANDLER = 1 << 17;
+
     /** No external storage should be mounted. */
     public static final int MOUNT_EXTERNAL_NONE = IVold.REMOUNT_MODE_NONE;
     /** Default external storage should be mounted. */
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index fe66cf9..480ff4d 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -983,14 +983,7 @@
 
     @Override
     public void setBackgroundDrawable(Drawable background) {
-
-        // TODO: This should route through setWindowBackground, but late in the release to make this
-        // change.
-        if (mOriginalBackgroundDrawable != background) {
-            mOriginalBackgroundDrawable = background;
-            updateBackgroundDrawable();
-            drawableChanged();
-        }
+        setWindowBackground(background);
     }
 
     public void setWindowFrame(Drawable drawable) {
diff --git a/core/java/com/android/internal/policy/PipSnapAlgorithm.java b/core/java/com/android/internal/policy/PipSnapAlgorithm.java
index 5b6b619..1afc67b 100644
--- a/core/java/com/android/internal/policy/PipSnapAlgorithm.java
+++ b/core/java/com/android/internal/policy/PipSnapAlgorithm.java
@@ -24,8 +24,6 @@
 import android.graphics.Rect;
 import android.util.Size;
 import android.view.Gravity;
-import android.view.ViewConfiguration;
-import android.widget.Scroller;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -180,14 +178,6 @@
         // If we're not flinging along the current edge, find the closest point instead.
         final double distanceVert = Math.hypot(vertPoint.x - x, vertPoint.y - y);
         final double distanceHoriz = Math.hypot(horizPoint.x - x, horizPoint.y - y);
-        // Ensure that we're actually going somewhere
-        if (distanceVert == 0) {
-            return horizPoint;
-        }
-        if (distanceHoriz == 0) {
-            return vertPoint;
-        }
-        // Otherwise use the closest point
         return Math.abs(distanceVert) > Math.abs(distanceHoriz) ? horizPoint : vertPoint;
     }
 
diff --git a/core/java/com/android/internal/policy/ScreenDecorationsUtils.java b/core/java/com/android/internal/policy/ScreenDecorationsUtils.java
index adf7692..52172cf 100644
--- a/core/java/com/android/internal/policy/ScreenDecorationsUtils.java
+++ b/core/java/com/android/internal/policy/ScreenDecorationsUtils.java
@@ -36,13 +36,16 @@
         }
 
         // Radius that should be used in case top or bottom aren't defined.
-        float defaultRadius = resources.getDimension(R.dimen.rounded_corner_radius);
+        float defaultRadius = resources.getDimension(R.dimen.rounded_corner_radius)
+                - resources.getDimension(R.dimen.rounded_corner_radius_adjustment);
 
-        float topRadius = resources.getDimension(R.dimen.rounded_corner_radius_top);
+        float topRadius = resources.getDimension(R.dimen.rounded_corner_radius_top)
+                - resources.getDimension(R.dimen.rounded_corner_radius_top_adjustment);
         if (topRadius == 0f) {
             topRadius = defaultRadius;
         }
-        float bottomRadius = resources.getDimension(R.dimen.rounded_corner_radius_bottom);
+        float bottomRadius = resources.getDimension(R.dimen.rounded_corner_radius_bottom)
+                - resources.getDimension(R.dimen.rounded_corner_radius_bottom_adjustment);
         if (bottomRadius == 0f) {
             bottomRadius = defaultRadius;
         }
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index 14dbabb..c3e7a36 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -575,7 +575,7 @@
     if (outArray != NULL) {
         outLen = MEMINFO_COUNT;
         for (int i = 0; i < outLen; i++) {
-            if (i == MEMINFO_VMALLOC_USED) {
+            if (i == MEMINFO_VMALLOC_USED && mem[i] == 0) {
                 outArray[i] = smi.ReadVmallocInfo() / 1024;
                 continue;
             }
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index df98cdc..0afbaa0e 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -99,7 +99,9 @@
 
 static struct error_offsets_t
 {
-    jclass mClass;
+    jclass mError;
+    jclass mOutOfMemory;
+    jclass mStackOverflow;
 } gErrorOffsets;
 
 // ----------------------------------------------------------------------------
@@ -207,6 +209,16 @@
     return vm->GetEnv((void **)&env, JNI_VERSION_1_4) >= 0 ? env : NULL;
 }
 
+static const char* GetErrorTypeName(JNIEnv* env, jthrowable error) {
+  if (env->IsInstanceOf(error, gErrorOffsets.mOutOfMemory)) {
+    return "OutOfMemoryError";
+  }
+  if (env->IsInstanceOf(error, gErrorOffsets.mStackOverflow)) {
+    return "StackOverflowError";
+  }
+  return nullptr;
+}
+
 // Report a java.lang.Error (or subclass). This will terminate the runtime by
 // calling FatalError with a message derived from the given error.
 static void report_java_lang_error_fatal_error(JNIEnv* env, jthrowable error,
@@ -216,7 +228,7 @@
 
     // Try to get the exception string. Sometimes logcat isn't available,
     // so try to add it to the abort message.
-    std::string exc_msg = "(Unknown exception message)";
+    std::string exc_msg;
     {
         ScopedLocalRef<jclass> exc_class(env, env->GetObjectClass(error));
         jmethodID method_id = env->GetMethodID(exc_class.get(), "toString",
@@ -225,15 +237,36 @@
                 env,
                 reinterpret_cast<jstring>(
                         env->CallObjectMethod(error, method_id)));
-        env->ExceptionClear();  // Just for good measure.
+        ScopedLocalRef<jthrowable> new_error(env, nullptr);
+        bool got_jstr = false;
+        if (env->ExceptionCheck()) {
+            new_error = ScopedLocalRef<jthrowable>(env, env->ExceptionOccurred());
+            env->ExceptionClear();
+        }
         if (jstr.get() != nullptr) {
             ScopedUtfChars jstr_utf(env, jstr.get());
             if (jstr_utf.c_str() != nullptr) {
                 exc_msg = jstr_utf.c_str();
+                got_jstr = true;
             } else {
+                new_error = ScopedLocalRef<jthrowable>(env, env->ExceptionOccurred());
                 env->ExceptionClear();
             }
         }
+        if (!got_jstr) {
+            exc_msg = "(Unknown exception message)";
+            const char* orig_type = GetErrorTypeName(env, error);
+            if (orig_type != nullptr) {
+                exc_msg = base::StringPrintf("%s (Error was %s)", exc_msg.c_str(), orig_type);
+            }
+            const char* new_type =
+                new_error == nullptr ? nullptr : GetErrorTypeName(env, new_error.get());
+            if (new_type != nullptr) {
+                exc_msg = base::StringPrintf("%s (toString() error was %s)",
+                                             exc_msg.c_str(),
+                                             new_type);
+            }
+        }
     }
 
     env->Throw(error);
@@ -291,7 +324,7 @@
         ALOGE("%s", msg);
     }
 
-    if (env->IsInstanceOf(excep, gErrorOffsets.mClass)) {
+    if (env->IsInstanceOf(excep, gErrorOffsets.mError)) {
         report_java_lang_error(env, excep, msg);
     }
 }
@@ -1440,10 +1473,13 @@
 
 static int int_register_android_os_BinderProxy(JNIEnv* env)
 {
-    jclass clazz = FindClassOrDie(env, "java/lang/Error");
-    gErrorOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
+    gErrorOffsets.mError = MakeGlobalRefOrDie(env, FindClassOrDie(env, "java/lang/Error"));
+    gErrorOffsets.mOutOfMemory =
+        MakeGlobalRefOrDie(env, FindClassOrDie(env, "java/lang/OutOfMemoryError"));
+    gErrorOffsets.mStackOverflow =
+        MakeGlobalRefOrDie(env, FindClassOrDie(env, "java/lang/StackOverflowError"));
 
-    clazz = FindClassOrDie(env, kBinderProxyPathName);
+    jclass clazz = FindClassOrDie(env, kBinderProxyPathName);
     gBinderProxyOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
     gBinderProxyOffsets.mGetInstance = GetStaticMethodIDOrDie(env, clazz, "getInstance",
             "(JJ)Landroid/os/BinderProxy;");
diff --git a/core/proto/android/server/jobscheduler.proto b/core/proto/android/server/jobscheduler.proto
index 784e854..c534aa4 100644
--- a/core/proto/android/server/jobscheduler.proto
+++ b/core/proto/android/server/jobscheduler.proto
@@ -231,15 +231,6 @@
     // will use heartbeats, false will use a rolling window.
     optional bool use_heartbeats = 23;
 
-    message TimeController {
-        option (.android.msg_privacy).dest = DEST_AUTOMATIC;
-
-        // Whether or not TimeController should skip setting wakeup alarms for jobs that aren't
-        // ready now.
-        optional bool skip_not_ready_jobs = 1;
-    }
-    optional TimeController time_controller = 25;
-
     message QuotaController {
         option (.android.msg_privacy).dest = DEST_AUTOMATIC;
 
@@ -304,6 +295,15 @@
     }
     optional QuotaController quota_controller = 24;
 
+    message TimeController {
+        option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
+        // Whether or not TimeController should skip setting wakeup alarms for jobs that aren't
+        // ready now.
+        reserved 1; // skip_not_ready_jobs
+    }
+    optional TimeController time_controller = 25;
+
     // Max number of jobs, when screen is ON.
     optional MaxJobCountsPerMemoryTrimLevelProto max_job_counts_screen_on = 26;
 
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index f25f93f..ebf5b93 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -536,6 +536,7 @@
     <protected-broadcast android:name="android.app.action.INTERRUPTION_FILTER_CHANGED_INTERNAL" />
     <protected-broadcast android:name="android.app.action.NOTIFICATION_POLICY_CHANGED" />
     <protected-broadcast android:name="android.app.action.NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED" />
+    <protected-broadcast android:name="android.app.action.AUTOMATIC_ZEN_RULE_STATUS_CHANGED" />
     <protected-broadcast android:name="android.os.action.ACTION_EFFECTS_SUPPRESSOR_CHANGED" />
     <protected-broadcast android:name="android.app.action.NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED" />
     <protected-broadcast android:name="android.app.action.NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED" />
@@ -4656,8 +4657,9 @@
                 android:process=":ui">
         </activity>
         <activity android:name="com.android.internal.app.PlatLogoActivity"
-                android:theme="@style/Theme.Wallpaper.NoTitleBar.Fullscreen"
+                android:theme="@style/Theme.DeviceDefault.DayNight"
                 android:configChanges="orientation|keyboardHidden"
+                android:icon="@drawable/platlogo"
                 android:process=":ui">
         </activity>
         <activity android:name="com.android.internal.app.DisableCarModeActivity"
diff --git a/core/res/res/drawable-nodpi/android_logotype.xml b/core/res/res/drawable-nodpi/android_logotype.xml
new file mode 100644
index 0000000..bd298e4
--- /dev/null
+++ b/core/res/res/drawable-nodpi/android_logotype.xml
@@ -0,0 +1,42 @@
+<!--
+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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="290dp"
+        android:height="64dp"
+        android:viewportWidth="290.0"
+        android:viewportHeight="64.0">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M21.81,28.91c-7.44,0,-12.45,5.85,-12.45,13.37c0,7.52,5.01,13.37,12.45,13.37s12.45,-5.85,12.45,-13.37   C34.26,34.76,29.24,28.91,21.81,28.91 M20.13,20.55c6.02,0,11.03,3.09,13.37,6.43v-5.6l9.19,0l0,41.78l-6.24,0   c-1.63,0,-2.95,-1.32,-2.95,-2.95v-2.65C31.17,60.91,26.15,64,20.14,64C8.69,64,0,54.23,0,42.28C0,30.33,8.69,20.55,20.13,20.55"/>
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M53.13,21.39l9.19,0l0,5.68c2.5,-4.18,7.27,-6.52,12.7,-6.52c9.69,0,15.96,6.85,15.96,17.46l0,25.15l-6.24,0   c-1.63,0,-2.95,-1.32,-2.95,-2.95l0,-20.7c0,-6.6,-3.34,-10.61,-8.69,-10.61c-6.1,0,-10.78,4.76,-10.78,13.7l0,20.55l-6.25,0   c-1.63,0,-2.95,-1.32,-2.95,-2.95L53.13,21.39z"/>
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M120.06,28.91c-7.43,0,-12.45,5.85,-12.45,13.37c0,7.52,5.01,13.37,12.45,13.37c7.43,0,12.45,-5.85,12.45,-13.37   C132.51,34.76,127.5,28.91,120.06,28.91 M118.39,20.55c6.02,0,11.03,3.09,13.37,6.43l0,-26.49l9.19,0l0,62.66h-6.24   c-1.63,0,-2.95,-1.32,-2.95,-2.95v-2.65c-2.34,3.34,-7.35,6.43,-13.37,6.43c-11.45,0,-20.14,-9.77,-20.14,-21.72   C98.25,30.33,106.94,20.55,118.39,20.55"/>
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M151.39,21.39l9.19,0v7.44c1.59,-4.76,6.27,-7.86,11.03,-7.86c1.17,0,2.34,0.08,3.59,0.34v9.44c-1.59,-0.5,-2.92,-0.75,-4.59,-0.75   c-5.26,0,-10.03,4.43,-10.03,12.78l0,20.39l-6.24,0c-1.63,0,-2.95,-1.32,-2.95,-2.95L151.39,21.39z"/>
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M199.98,55.48c7.35,0,12.53,-5.77,12.53,-13.2c0,-7.44,-5.18,-13.2,-12.53,-13.2c-7.44,0,-12.62,5.77,-12.62,13.2   C187.37,49.71,192.55,55.48,199.98,55.48 M199.98,64c-12.37,0,-21.89,-9.61,-21.89,-21.72c0,-12.12,9.52,-21.73,21.89,-21.73   c12.37,0,21.89,9.61,21.89,21.73C221.87,54.39,212.35,64,199.98,64"/>
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M229.32,21.39l9.19,0l0,41.78l-6.24,0c-1.63,0,-2.95,-1.32,-2.95,-2.95L229.32,21.39z M233.92,12.28   c-3.34,0,-6.18,-2.76,-6.18,-6.18c0,-3.34,2.84,-6.1,6.18,-6.1c3.43,0,6.1,2.76,6.1,6.1C240.02,9.53,237.34,12.28,233.92,12.28"/>
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M267.87,28.91c-7.43,0,-12.45,5.85,-12.45,13.37c0,7.52,5.01,13.37,12.45,13.37c7.44,0,12.45,-5.85,12.45,-13.37   C280.32,34.76,275.31,28.91,267.87,28.91 M266.2,20.55c6.02,0,11.03,3.09,13.37,6.43l0,-26.49l9.19,0l0,62.66l-6.24,0   c-1.63,0,-2.95,-1.32,-2.95,-2.95v-2.65c-2.34,3.34,-7.35,6.43,-13.37,6.43c-11.44,0,-20.14,-9.77,-20.14,-21.72S254.76,20.55,266.2,20.55"/>
+</vector>
diff --git a/core/res/res/drawable-nodpi/platlogo.xml b/core/res/res/drawable-nodpi/platlogo.xml
index f5bbadc..19a296a 100644
--- a/core/res/res/drawable-nodpi/platlogo.xml
+++ b/core/res/res/drawable-nodpi/platlogo.xml
@@ -1,5 +1,5 @@
 <!--
-Copyright (C) 2018 The Android Open Source Project
+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.
@@ -13,21 +13,15 @@
     See the License for the specific language governing permissions and
     limitations under the License.
 -->
-<vector
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:name="vector"
-    android:width="640dp"
-    android:height="640dp"
-    android:viewportWidth="64"
-    android:viewportHeight="64">
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
     <path
-        android:name="bg"
-        android:pathData="M 27 43 L 32 43 C 38.075 43 43 38.075 43 32 C 43 25.925 38.075 21 32 21 C 25.925 21 21 25.925 21 32 L 21 64"
-        android:strokeColor="#6823a1"
-        android:strokeWidth="16"/>
+        android:fillColor="#FF000000"
+        android:pathData="M19.45,22.89l-10.250001,-10.249999l-2.6599998,2.6599998l-1.77,-1.7600002l4.43,-4.4300003l12.0199995,12.0199995l-1.7699986,1.7600002z"/>
     <path
-        android:name="fg"
-        android:pathData="M 29 43 L 32 43 C 38.075 43 43 38.075 43 32 C 43 25.925 38.075 21 32 21 C 25.925 21 21 25.925 21 32 L 21 64"
-        android:strokeColor="#ff0000"
-        android:strokeWidth="8"/>
+        android:fillColor="#FF000000"
+        android:pathData="M12,6a6,6 0,1 1,-6 6,6 6,0 0,1 6,-6m0,-2.5A8.5,8.5 0,1 0,20.5 12,8.51 8.51,0 0,0 12,3.5Z"/>
 </vector>
diff --git a/core/res/res/layout/platlogo_layout.xml b/core/res/res/layout/platlogo_layout.xml
new file mode 100644
index 0000000..4a4ad75
--- /dev/null
+++ b/core/res/res/layout/platlogo_layout.xml
@@ -0,0 +1,50 @@
+<?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.
+-->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:clipChildren="false"
+    android:background="@android:color/transparent">
+    <ImageView
+        android:id="@+id/text"
+        android:layout_width="400dp"
+        android:layout_height="wrap_content"
+        android:translationY="-100dp"
+        android:adjustViewBounds="true"
+        android:layout_marginBottom="-80dp"
+        android:layout_centerInParent="true"
+        android:src="@drawable/android_logotype"
+        android:tint="?android:attr/textColorPrimary"
+        />
+    <ImageView
+        android:id="@+id/one"
+        android:layout_width="200dp"
+        android:layout_height="200dp"
+        android:layout_marginLeft="24dp"
+        android:layout_below="@id/text"
+        android:layout_alignLeft="@id/text"
+        android:tint="?android:attr/textColorPrimary"
+        />
+    <ImageView
+        android:id="@+id/zero"
+        android:layout_width="200dp"
+        android:layout_height="200dp"
+        android:layout_marginRight="34dp"
+        android:layout_below="@id/text"
+        android:layout_alignRight="@id/text"
+        android:tint="?android:attr/textColorPrimary"
+        />
+</RelativeLayout>
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 74f0e68c..7a0d475 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"Beweeg foon na links."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"Beweeg foon na regs."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"Kyk asseblief meer reguit na jou toestel."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"Kan nie jou gesig sien nie. Kyk na die foon."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"Posisioneer jou gesig direk voor die foon."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"Te veel beweging. Hou foon stil."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"Skryf jou gesig asseblief weer in."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"Kan nie meer gesig herken nie. Probeer weer."</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"Maak oop met"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Maak oop met %1$s"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"Maak oop"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"Maak <xliff:g id="HOST">%1$s</xliff:g>-skakels oop met"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"Maak skakels oop met"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"Maak skakels oop met <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"Maak <xliff:g id="HOST">%1$s</xliff:g>-skakels oop met <xliff:g id="APPLICATION">%2$s</xliff:g>"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"Verleen toegang"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"Redigeer met"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Redigeer met %1$s"</string>
@@ -1590,8 +1586,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"Begin webblaaier?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Aanvaar oproep?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Altyd"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"Stel om altyd oop te maak"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Net een keer"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"Instellings"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s steun nie werkprofiel nie"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index af0ed28c..11ab44d 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"ስልክን ወደ ግራ ያንቀሳቅሱ።"</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"ስልክን ወደ ቀኝ ያንቀሳቅሱ።"</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"እባክዎ መሣሪያዎን ይበልጥ በቀጥታ ይመልከቱ።"</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"የእርስዎን ፊት መመልከት አይችልም። ስልኩ ላይ ይመልከቱ።"</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"መልክዎን በቀጥታ ከስልኩ ፊት ያድርጉት።"</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"ከልክ በላይ ብዙ እንቅስቃሴ። ስልኩን ቀጥ አድርገው ይያዙት።"</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"እባክዎ ፊትዎን እንደገና ያስመዝግቡ"</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"ከእንግዲህ ፊትን ለይቶ ማወቅ አይችልም። እንደገና ይሞክሩ።"</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"ክፈት በ"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"ክፈት በ%1$s"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"ክፈት"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"<xliff:g id="HOST">%1$s</xliff:g> አገናኞችን ክፈት ከዚህ ጋር"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"አገናኞችን ክፈት ከዚህ ጋር"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"አገናኞችን ከ <xliff:g id="APPLICATION">%1$s</xliff:g> ጋር ክፈት"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"<xliff:g id="HOST">%1$s</xliff:g> አገናኞችን ከ <xliff:g id="APPLICATION">%2$s</xliff:g> ጋር ክፈት"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"መዳረሻ ስጥ"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"ያርትዑ በ"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"ያርትዑ በ%1$s"</string>
@@ -1590,8 +1586,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"ማሰሺያን አስነሳ?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"ጥሪ ተቀበል?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"ዘወትር"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"ሁልጊዜ ክፍት ወደ የሚል ተቀናብሯል"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"አንዴ ብቻ"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"ቅንብሮች"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s የስራ መገለጫ አይደግፍም"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 603239f..6edc933 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -580,7 +580,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"يُرجى نقل الهاتف إلى اليمين."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"يُرجى نقل الهاتف إلى اليسار."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"يُرجى النظر إلى جهازك مباشرة أكثر."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"يتعذّر رؤية وجهك. يُرجى النظر إلى الهاتف."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"ضع وجهك أمام الهاتف مباشرة."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"حركة أكثر من اللازم يُرجى حمل بدون حركة."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"يُرجى إعادة تسجيل وجهك."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"لم يعُد يمكن التعرّف على الوجه. حاول مرة أخرى."</string>
@@ -1211,14 +1211,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"فتح باستخدام"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"‏فتح باستخدام %1$s"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"فتح"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"فتح روابط <xliff:g id="HOST">%1$s</xliff:g> باستخدام"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"فتح الروابط باستخدام"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"فتح الروابط باستخدام <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"فتح روابط <xliff:g id="HOST">%1$s</xliff:g> باستخدام <xliff:g id="APPLICATION">%2$s</xliff:g>"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"منح إذن الوصول"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"تعديل باستخدام"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"‏تعديل باستخدام %1$s"</string>
@@ -1682,8 +1678,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"تشغيل المتصفح؟"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"هل تريد قبول المكالمة؟"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"دومًا"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"ضبط على الفتح دائمًا"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"مرة واحدة فقط"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"الإعدادات"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"‏لا يدعم %1$s الملفات الشخصية للعمل"</string>
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index b126468..3660403 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"ফ’নটো বাওঁফালে নিয়ক।"</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"ফ’নটো সোঁফালে নিয়ক।"</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"আপোনাৰ ডিভাইচটোলৈ অধিক পোনে পোনে চাওক।"</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"আপোনাৰ মুখমণ্ডল দেখা নাই। ফ’নটোলৈ চাওক।"</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"আপোনাৰ মুখখন পোনপটীয়াকৈ ফ’নটোৰ সন্মুখত ৰাখক।"</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"বেছি লৰচৰ কৰি আছে। ফ’নটো স্থিৰকৈ ধৰক।"</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"আপোনাৰ মুখমণ্ডল পুনৰ পঞ্জীয়ন কৰক।"</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"মুখমণ্ডল আৰু চিনাক্ত কৰিব নোৱাৰি। আকৌ চেষ্টা কৰক।"</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"ইয়াৰ জৰিয়তে খোলক"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"%1$sৰ জৰিয়তে খোলক"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"খোলক"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"<xliff:g id="HOST">%1$s</xliff:g> লিংকসমূহ ইয়াৰ জৰিয়তে খোলক"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"লিংকসমূহ ইয়াৰ জৰিয়তে খোলক"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"লিংকসমূহ <xliff:g id="APPLICATION">%1$s</xliff:g>ৰ জৰিয়তে খোলক"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"<xliff:g id="HOST">%1$s</xliff:g> লিংকসমূহ <xliff:g id="APPLICATION">%2$s</xliff:g>ৰ জৰিয়তে খোলক"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"এক্সেছ দিয়ক"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"ইয়াৰ দ্বাৰা সম্পাদনা কৰক"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"%1$sৰদ্বাৰা সম্পাদনা কৰক"</string>
@@ -1590,8 +1586,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"ব্ৰাউজাৰ লঞ্চ কৰিবনে?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"কল স্বীকাৰ কৰিবনে?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"সদায়"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"সদায় খোলক-লৈ ছেট কৰক"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"মাত্ৰ এবাৰ"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"ছেটিংসমূহ"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$sএ কৰ্মস্থানৰ প্ৰ\'ফাইল সমৰ্থন নকৰে।"</string>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index f372fec..e2b3998 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"Telefonu sola hərəkət etdirin."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"Telefonu sağa hərəkət etdirin."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"Birbaşa cihaza baxın."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"Üzünüz görünmür. Telefona baxın."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"Üzünüzü telefonun qarşısında sabit saxlayın."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"Cihaz stabil deyil. Telefonu tərpətməyin."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"Üzünüzü yenidən qeydiyyatdan keçirin."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"Üzü artıq tanımaq olmur. Yenidən cəhd edin."</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"Bununla açın"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"%1$s ilə açın"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"Açın"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"<xliff:g id="HOST">%1$s</xliff:g> linklərini belə açın:"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"Linkləri belə açın:"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"Linkləri <xliff:g id="APPLICATION">%1$s</xliff:g> ilə açın"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"<xliff:g id="HOST">%1$s</xliff:g> linklərini <xliff:g id="APPLICATION">%2$s</xliff:g> ilə açın"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"İcazə verin"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"Bununla düzəliş edin:"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"%1$s ilə düzəliş edin"</string>
@@ -1590,8 +1586,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"Brauzer işə salınsın?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Zəngi qəbul edək?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Həmişə"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"\"Həmişə açıq\" olaraq ayarlayın"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Sadəcə bir dəfə"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"Ayarlar"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s iş profilini dəstəkləmir"</string>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index b4faae7..821b730 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -571,7 +571,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"Pomerite telefon ulevo."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"Pomerite telefon udesno."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"Gledajte pravo u uređaj."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"Ne vidi se lice. Gledajte u telefon."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"Postavite lice direktno ispred telefona"</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"Mnogo se pomerate. Držite telefon mirno."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"Ponovo registrujte lice."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"Više ne može da se prepozna lice. Probajte ponovo."</string>
@@ -1151,14 +1151,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"Otvorite pomoću"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Otvorite pomoću aplikacije %1$s"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"Otvori"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"Otvarajte <xliff:g id="HOST">%1$s</xliff:g> linkove pomoću"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"Otvaratej linkove pomoću"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"Otvarajte linkove pomoću aplikacije <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"Otvarajte <xliff:g id="HOST">%1$s</xliff:g> linkove pomoću aplikacije <xliff:g id="APPLICATION">%2$s</xliff:g>"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"Dozvoli pristup"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"Izmenite pomoću"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Izmenite pomoću aplikacije %1$s"</string>
@@ -1613,8 +1609,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"Želite li da pokrenete pregledač?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Želite li da prihvatite poziv?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Uvek"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"Podesi na „uvek otvaraj“"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Samo jednom"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"Podešavanja"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s ne podržava poslovni profil"</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 996a02b..d573202 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -574,7 +574,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"Перамясціце тэлефон улева."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"Перамясціце тэлефон управа."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"Глядзіце прама на экран прылады."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"Не відаць твару. Глядзіце на тэлефон."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"Трымайце тэлефон прама перад тварам."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"Трымайце прыладу нерухома. Трымайце тэлефон роўна."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"Паўтарыце рэгістрацыю твару."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"Не ўдаецца распазнаць твар. Паўтарыце спробу."</string>
@@ -1171,14 +1171,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"Адкрыць з дапамогай"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Адкрыць з дапамогай %1$s"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"Адкрыць"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"Адкрываць спасылкі <xliff:g id="HOST">%1$s</xliff:g> з дапамогай"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"Адкрываць спасылкі з дапамогай"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"Адкрываць спасылкі з дапамогай праграмы \"<xliff:g id="APPLICATION">%1$s</xliff:g>\""</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"Адкрываць спасылкі <xliff:g id="HOST">%1$s</xliff:g>з дапамогай праграмы \"<xliff:g id="APPLICATION">%2$s</xliff:g>\""</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"Даць доступ"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"Рэдагаваць з дапамогай"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Рэдагаваць з дапамогай %1$s"</string>
@@ -1636,8 +1632,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"Запусцiць браўзер?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Прыняць выклік?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Заўсёды"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"Прызначыць стандартна для адкрыцця"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Толькі адзін раз"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"Налады"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s не падтрымлівае працоўны профіль"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index e4e1e80..e073b7d 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"Преместете телефона наляво."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"Преместете телефона надясно."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"Моля, гледайте точно към устройството си."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"Лицето ви не се вижда. Погледнете към телефона."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"Позиционирайте лицето си директно пред телефона."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"Твърде много движение. Дръжте телефона неподвижно."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"Моля, регистрирайте лицето си отново."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"Лицето не бе разпознато. Опитайте отново."</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"Отваряне чрез"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Отваряне чрез %1$s"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"Отваряне"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"Отваряне на връзките от <xliff:g id="HOST">%1$s</xliff:g> посредством"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"Отваряне на връзките посредством"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"Отваряне на връзките посредством <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"Отваряне на връзките от <xliff:g id="HOST">%1$s</xliff:g> посредством <xliff:g id="APPLICATION">%2$s</xliff:g>"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"Даване на достъп"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"Редактиране чрез"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Редактиране чрез %1$s"</string>
@@ -1590,8 +1586,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"Да се стартира ли браузърът?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Да се приеме ли обаждането?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Винаги"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"Задаване винаги да се отваря"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Само веднъж"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"Настройки"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s не поддържа служебен потребителски профил"</string>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index ca4d122..368ff90 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"ফোনটি বাঁদিকে সরান।"</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"ফোনটি ডানদিকে সরান।"</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"সরাসরি ডিভাইসের দিকে তাকান।"</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"আপনার মুখ দেখা যাচ্ছে না। ফোনের দিকে তাকান।"</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"আপনার মুখ সরাসরি ফোনের সামনে রাখুন।"</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"খুব বেশি নড়ছে। ফোনটি যাতে না কাঁপে সেইভাবে ধরুন।"</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"আপনার মুখের ছবি আবার নথিভুক্ত করুন।"</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"আর মুখ চিনতে পারবেন না। আবার চেষ্টা করুন।"</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"এর মাধ্যমে খুলুন"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"%1$s দিয়ে খুলুন"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"খুলুন"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"এই ব্রাউজারে <xliff:g id="HOST">%1$s</xliff:g> লিঙ্কটি খুলুন"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"এই ব্রাউজারে লিঙ্কটি খুলুন"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"<xliff:g id="APPLICATION">%1$s</xliff:g>-এ লিঙ্ক খুলুন"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"<xliff:g id="APPLICATION">%2$s</xliff:g>-এ <xliff:g id="HOST">%1$s</xliff:g> লিঙ্কটি খুলুন"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"অ্যাক্সেস দিন"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"এর মাধ্যমে সম্পাদনা করুন"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"%1$s দিয়ে সম্পাদনা করুন"</string>
@@ -1591,8 +1587,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"ব্রাউজার লঞ্চ করতে চান?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"কল গ্রহণ করবেন?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"সবসময়"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"\'সবসময় খোলা থাকবে\' হিসেবে সেট করুন"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"শুধু একবার"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"সেটিংস"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s কর্মস্থলের প্রোফাইল সমর্থন করে না।"</string>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index fd44128..ce852b6 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -127,7 +127,7 @@
     <item msgid="3910386316304772394">"Da biste pozivali i slali poruke koristeći WiFi mrežu, prvo zatražite od operatera da postavi tu uslugu. Zatim ponovo uključite pozivanje putem WiFi-ja u Postavkama. (Kôd greške: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
   </string-array>
   <string-array name="wfcOperatorErrorNotificationMessages">
-    <item msgid="7372514042696663278">"Došlo je do problema prilikom registracije pozivanja putem WiFi mreže kod vašeg operatera: <xliff:g id="CODE">%1$s</xliff:g>"</item>
+    <item msgid="7372514042696663278">"Došlo je do problema prilikom registracije pozivanja putem WiFi mreže kod vašeg mobilnog operatera: <xliff:g id="CODE">%1$s</xliff:g>"</item>
   </string-array>
     <!-- no translation found for wfcSpnFormat_spn (4998685024207291232) -->
     <skip />
@@ -571,7 +571,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"Pomjerite telefon ulijevo."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"Pomjerite telefon udesno."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"Gledajte direktno u uređaj."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"Ne vidi se lice. Gledajte u telefon."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"Postavite lice direktno ispred telefona"</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"Previše pokreta. Držite telefon mirno."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"Ponovo registrirajte lice."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"Nije više moguće prepoznati lice. Pokušajte opet."</string>
@@ -802,7 +802,7 @@
     <string name="quick_contacts_not_available" msgid="746098007828579688">"Nije pronađena aplikacija za pregled ovog kontakta."</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Unesite PIN"</string>
     <string name="keyguard_password_enter_puk_code" msgid="4800725266925845333">"Unesite PUK i novi PIN"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUK"</string>
+    <string name="keyguard_password_enter_puk_prompt" msgid="1341112146710087048">"PUK kôd"</string>
     <string name="keyguard_password_enter_pin_prompt" msgid="8027680321614196258">"Novi PIN"</string>
     <string name="keyguard_password_entry_touch_hint" msgid="2644215452200037944"><font size="17">"Dodirnite za unos lozinke"</font></string>
     <string name="keyguard_password_enter_password_code" msgid="1054721668279049780">"Unesite lozinku za otključavanje tipkovnice"</string>
@@ -894,7 +894,7 @@
     <string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"Otključavanje licem."</string>
     <string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"Otključavanje pinom."</string>
     <string name="keyguard_accessibility_sim_pin_unlock" msgid="9149698847116962307">"Otključavanje Pin-om za Sim."</string>
-    <string name="keyguard_accessibility_sim_puk_unlock" msgid="9106899279724723341">"Otključavanje Puk-om za Sim."</string>
+    <string name="keyguard_accessibility_sim_puk_unlock" msgid="9106899279724723341">"Otključavanje SIM-a PUK-om"</string>
     <string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"Otključavanje lozinkom."</string>
     <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"Uzorak oblasti."</string>
     <string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"Oblast za pomjeranje klizača."</string>
@@ -1151,14 +1151,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"Otvori koristeći"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Otvori koristeći %1$s"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"Otvori"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"Otvaranje <xliff:g id="HOST">%1$s</xliff:g> linkova pomoću"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"Otvaranje linkova pomoću"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"Otvaranje linkova pomoću aplikacije <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"Otvaranje <xliff:g id="HOST">%1$s</xliff:g> linkova pomoću aplikacije <xliff:g id="APPLICATION">%2$s</xliff:g>"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"Dozvoli pristup"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"Uredi koristeći"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Uredi koristeći %1$s"</string>
@@ -1547,7 +1543,7 @@
     <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Povećaj sate"</string>
     <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Smanji sate"</string>
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Postavi za poslijepodne (PM)"</string>
-    <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Postavi za prijepodne (AM)"</string>
+    <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Postavi za prijepodne"</string>
     <string name="date_picker_increment_month_button" msgid="5369998479067934110">"Povećaj mjesece"</string>
     <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Smanji mjesece"</string>
     <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Povećaj dane"</string>
@@ -1615,8 +1611,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"Pokretanje preglednika?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Prihvatiti poziv?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Uvijek"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"Postavi da se uvijek otvara"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Samo ovaj put"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"Postavke"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s ne podržava poslovni profil"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 1638fd8..7cfcaf4 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"Mou el telèfon cap a l\'esquerra."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"Mou el telèfon cap a la dreta."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"Mira més directament cap al dispositiu."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"No se\'t veu la cara. Mira el telèfon."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"Posa la cara directament davant del telèfon."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"Massa moviment. Subjecta bé el telèfon."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"Torna a registrar la teva cara."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"Ja no es reconeix la teva cara. Torna-ho a provar."</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"Obre amb"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Obre amb %1$s"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"Obre"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"Obre els enllaços de <xliff:g id="HOST">%1$s</xliff:g> amb"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"Obre els enllaços amb"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"Obre els enllaços amb <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"Obre els enllaços de <xliff:g id="HOST">%1$s</xliff:g> amb <xliff:g id="APPLICATION">%2$s</xliff:g>"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"Dona accés"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"Edita amb"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Edita amb %1$s"</string>
@@ -1590,8 +1586,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"Vols iniciar el navegador?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Vols acceptar la trucada?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Sempre"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"Obre sempre"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Només una vegada"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"Configuració"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s no admet perfils professionals."</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 5208e5b..4171a8b 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -574,7 +574,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"Přesuňte telefon vlevo."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"Přesuňte telefon vpravo."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"Dívejte se přímo na zařízení."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"Obličej není vidět. Podívejte se na telefon."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"Umístěte obličej přímo před telefon."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"Příliš mnoho pohybu. Držte telefon nehybně."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"Zaznamenejte obličej znovu."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"Obličej už nelze rozpoznat. Zkuste to znovu."</string>
@@ -1171,14 +1171,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"Otevřít v aplikaci"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Otevřít v aplikaci %1$s"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"Otevřít"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"Odkazy <xliff:g id="HOST">%1$s</xliff:g> otevírat pomocí aplikace"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"Odkazy otevírat pomocí aplikace"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"Odkazy otevírat pomocí aplikace <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"Odkazy <xliff:g id="HOST">%1$s</xliff:g> otevírat pomocí aplikace <xliff:g id="APPLICATION">%2$s</xliff:g>"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"Udělit přístup"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"Upravit v aplikaci"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Upravit v aplikaci %1$s"</string>
@@ -1636,8 +1632,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"Spustit prohlížeč?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Přijmout hovor?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Vždy"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"Nastavit na Otevírat vždy"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Pouze jednou"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"Nastavení"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s pracovní profily nepodporuje."</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 401fa4f7..b6cb874 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"Flyt telefonen til venstre."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"Flyt telefonen til højre."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"Kig mere direkte på din enhed."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"Dit ansigt kan ikke registreres. Kig på telefonen."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"Sørg for, at dit ansigt er direkte foran telefonen."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"Der er for meget bevægelse. Hold telefonen stille."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"Registrer dit ansigt igen."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"Ansigtet kan ikke længere genkendes. Prøv igen."</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"Åbn med"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Åbn med %1$s"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"Åbn"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"Åbn <xliff:g id="HOST">%1$s</xliff:g>-links med"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"Åbn links med"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"Åbn links med <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"Åbn <xliff:g id="HOST">%1$s</xliff:g>-links med <xliff:g id="APPLICATION">%2$s</xliff:g>"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"Giv adgang"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"Rediger med"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Rediger med %1$s"</string>
@@ -1590,8 +1586,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"Vil du starte browseren?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Vil du besvare opkaldet?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Altid"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"Angiv som altid åben"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Kun én gang"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"Indstillinger"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s understøtter ikke arbejdsprofil"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 67c179d..5316d13 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -316,15 +316,15 @@
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Fensterinhalte abrufen"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"Die Inhalte eines Fensters, mit dem du interagierst, werden abgerufen."</string>
     <string name="capability_title_canRequestTouchExploration" msgid="3108723364676667320">"\"Tippen &amp; Entdecken\" aktivieren"</string>
-    <string name="capability_desc_canRequestTouchExploration" msgid="7543249041581408313">"Berührte Elemente werden laut vorgelesen und der Bildschirm kann über Gesten erkundet werden."</string>
+    <string name="capability_desc_canRequestTouchExploration" msgid="7543249041581408313">"Berührte Elemente werden laut vorgelesen und der Bildschirm kann über Touch-Gesten erkundet werden."</string>
     <string name="capability_title_canRequestFilterKeyEvents" msgid="2103440391902412174">"Text bei der Eingabe beobachten"</string>
     <string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Einschließlich personenbezogener Daten wie Kreditkartennummern und Passwörter."</string>
     <string name="capability_title_canControlMagnification" msgid="3593493281059424855">"Displayvergrößerung festlegen"</string>
     <string name="capability_desc_canControlMagnification" msgid="4791858203568383773">"Legt die Zoom-Stufe und -Position auf dem Display fest."</string>
-    <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Gesten möglich"</string>
-    <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Tippen, Wischen, Zusammenziehen und andere Gesten möglich."</string>
-    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Bewegungen auf dem Fingerabdrucksensor"</string>
-    <string name="capability_desc_canCaptureFingerprintGestures" msgid="4386487962402228670">"Erfasst Bewegungen auf dem Fingerabdrucksensor des Geräts."</string>
+    <string name="capability_title_canPerformGestures" msgid="7418984730362576862">"Touch-Gesten möglich"</string>
+    <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Tippen, Wischen, Zusammenziehen und andere Touch-Gesten möglich."</string>
+    <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Fingerabdrucksensor-Gesten"</string>
+    <string name="capability_desc_canCaptureFingerprintGestures" msgid="4386487962402228670">"Erfasst Touch-Gesten auf dem Fingerabdrucksensor des Geräts."</string>
     <string name="permlab_statusBar" msgid="7417192629601890791">"Statusleiste deaktivieren oder ändern"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Ermöglicht der App, die Statusleiste zu deaktivieren oder Systemsymbole hinzuzufügen oder zu entfernen"</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"Statusleiste darstellen"</string>
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"Beweg das Smartphone nach links."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"Beweg das Smartphone nach rechts."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"Bitte sieh direkt auf dein Gerät."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"Gesicht wurde nicht gefunden. Blicke aufs Telefon."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"Halte dein Gesicht direkt vor dein Smartphone."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"Zu viel Unruhe. Halte das Smartphone ruhig."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"Bitte registriere dein Gesicht noch einmal."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"Gesicht wird nicht mehr erkannt. Erneut versuchen."</string>
@@ -971,8 +971,8 @@
     <string name="searchview_description_submit" msgid="2688450133297983542">"Anfrage senden"</string>
     <string name="searchview_description_voice" msgid="2453203695674994440">"Sprachsuche"</string>
     <string name="enable_explore_by_touch_warning_title" msgid="7460694070309730149">"\"Tippen &amp; Entdecken\" aktivieren?"</string>
-    <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="8655887539089910577">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> fordert die Aktivierung von \"Tippen &amp; Entdecken\" an. Wenn \"Tippen &amp; Entdecken\" aktiviert ist, kannst du Beschreibungen dessen hören oder sehen, was sich unter deinen Fingern befindet, oder Gesten ausführen, um mit dem Tablet zu kommunizieren."</string>
-    <string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> fordert die Aktivierung von \"Tippen &amp; Entdecken\" an. Wenn \"Tippen &amp; Entdecken\" aktiviert ist, kannst du Beschreibungen dessen hören oder sehen, was sich unter deinen Fingern befindet, oder Gesten ausführen, um mit dem Telefon zu kommunizieren."</string>
+    <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="8655887539089910577">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> fordert die Aktivierung von \"Tippen &amp; Entdecken\" an. Wenn \"Tippen &amp; Entdecken\" aktiviert ist, kannst du Beschreibungen dessen hören oder sehen, was sich unter deinen Fingern befindet, oder über Touch-Gesten mit dem Tablet kommunizieren."</string>
+    <string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> fordert die Aktivierung von \"Tippen &amp; Entdecken\" an. Wenn \"Tippen &amp; Entdecken\" aktiviert ist, kannst du Beschreibungen dessen hören oder sehen, was sich unter deinen Fingern befindet, oder über Touch-Gesten mit dem Telefon kommunizieren."</string>
     <string name="oneMonthDurationPast" msgid="7396384508953779925">"Vor 1 Monat"</string>
     <string name="beforeOneMonthDurationPast" msgid="909134546836499826">"Vor mehr als 1 Monat"</string>
     <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"Öffnen mit"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Mit %1$s öffnen"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"Öffnen"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"Links von <xliff:g id="HOST">%1$s</xliff:g> öffnen mit"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"Links öffnen mit"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"Links mit <xliff:g id="APPLICATION">%1$s</xliff:g> öffnen"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"Links von <xliff:g id="HOST">%1$s</xliff:g> mit <xliff:g id="APPLICATION">%2$s</xliff:g> öffnen"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"Zugriff erlauben"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"Bearbeiten mit"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Mit %1$s bearbeiten"</string>
@@ -1590,8 +1586,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>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"Auf \"Immer geöffnet\" 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>
@@ -1675,8 +1670,8 @@
     <string name="accessibility_shortcut_disabling_service" msgid="2747243438223109821">"<xliff:g id="SERVICE_NAME">%1$s</xliff:g> wurde durch die Bedienungshilfenverknüpfung deaktiviert"</string>
     <string name="accessibility_shortcut_spoken_feedback" msgid="8376923232350078434">"Halten Sie beide Lautstärketasten drei Sekunden lang gedrückt, um <xliff:g id="SERVICE_NAME">%1$s</xliff:g> zu verwenden"</string>
     <string name="accessibility_button_prompt_text" msgid="1176658502969738564">"Wähle den Dienst aus, der verwendet werden soll, wenn du auf die Schaltfläche für die Bedienungshilfen tippst:"</string>
-    <string name="accessibility_gesture_prompt_text" msgid="8259145549733019401">"Wähle den Dienst aus, der mit der Bewegung für die Bedienungshilfen verwendet werden soll (mit zwei Fingern vom unteren Bildschirmrand nach oben wischen):"</string>
-    <string name="accessibility_gesture_3finger_prompt_text" msgid="1041435574275047665">"Wähle den Dienst aus, der mit der Geste für die Bedienungshilfen verwendet werden soll (mit drei Fingern vom unteren Bildschirmrand nach oben wischen):"</string>
+    <string name="accessibility_gesture_prompt_text" msgid="8259145549733019401">"Wähle den Dienst aus, der mit der Touch-Geste für die Bedienungshilfen verwendet werden soll (mit zwei Fingern vom unteren Bildschirmrand nach oben wischen):"</string>
+    <string name="accessibility_gesture_3finger_prompt_text" msgid="1041435574275047665">"Wähle den Dienst aus, der mit der Touch-Geste für die Bedienungshilfen verwendet werden soll (mit drei Fingern vom unteren Bildschirmrand nach oben wischen):"</string>
     <string name="accessibility_button_instructional_text" msgid="7003212763213614833">"Wenn du zwischen den Diensten wechseln möchtest, halte die Schaltfläche für die Bedienungshilfen gedrückt."</string>
     <string name="accessibility_gesture_instructional_text" msgid="5261788874937410950">"Wenn du zwischen den Diensten wechseln möchtest, wische mit zwei Fingern nach oben und halte sie gedrückt."</string>
     <string name="accessibility_gesture_3finger_instructional_text" msgid="4969448938984394550">"Wenn du zwischen den Diensten wechseln möchtest, wische mit drei Fingern nach oben und halte sie gedrückt."</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 87d0844..44357ff 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"Μετακινήστε το τηλέφωνο στα αριστερά."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"Μετακινήστε το τηλέφωνο στα δεξιά."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"Κοιτάξτε απευθείας τη συσκευή σας."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"Δεν εντοπίστηκε το πρόσωπό σας. Δείτε το τηλέφωνο."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"Στρέψτε το πρόσωπό σάς απευθείας στο τηλέφωνο."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"Πάρα πολλή κίνηση. Κρατήστε σταθερό το τηλέφωνο."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"Καταχωρίστε ξανά το πρόσωπό σας."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"Αδύνατη η αναγνώριση του προσώπου. Επανάληψη."</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"Άνοιγμα με"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Άνοιγμα με %1$s"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"Άνοιγμα"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"Άνοιγμα συνδέσμων <xliff:g id="HOST">%1$s</xliff:g> με"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"Άνοιγμα συνδέσμων με"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"Άνοιγμα συνδέσμων με την εφαρμογή <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"Άνοιγμα συνδέσμων <xliff:g id="HOST">%1$s</xliff:g> με την εφαρμογή <xliff:g id="APPLICATION">%2$s</xliff:g>"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"Παροχή πρόσβασης"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"Επεξεργασία με"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Επεξεργασία με %1$s"</string>
@@ -1590,8 +1586,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"Εκκίνηση προγράμματος περιήγησης;"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Αποδοχή κλήσης;"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Πάντα"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"Ορισμός ως πάντα ανοικτής"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Μόνο μία φορά"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"Ρυθμίσεις"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"Το προφίλ εργασίας δεν υποστηρίζεται από %1$s"</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 51b031b..cc389f3 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"Move phone to the left."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"Move phone to the right."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"Please look more directly at your device."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"Can’t see your face. Look at the phone."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"Position your face directly in front of the phone."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"Too much motion. Hold phone steady."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"Please re-enroll your face."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"No longer able to recognise face. Try again."</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"Open with"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Open with %1$s"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"Open"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"Open <xliff:g id="HOST">%1$s</xliff:g> links with"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"Open links with"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"Open links with <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"Open <xliff:g id="HOST">%1$s</xliff:g> links with <xliff:g id="APPLICATION">%2$s</xliff:g>"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"Give access"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"Edit with"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Edit with %1$s"</string>
@@ -1590,8 +1586,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"Launch Browser?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Accept call?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Always"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"Set to always open"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Just once"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"Settings"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s doesn\'t support work profile"</string>
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index fd14d4d..0e6d49c 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"Move phone to the left."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"Move phone to the right."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"Please look more directly at your device."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"Can’t see your face. Look at the phone."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"Position your face directly in front of the phone."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"Too much motion. Hold phone steady."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"Please re-enroll your face."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"No longer able to recognise face. Try again."</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"Open with"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Open with %1$s"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"Open"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"Open <xliff:g id="HOST">%1$s</xliff:g> links with"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"Open links with"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"Open links with <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"Open <xliff:g id="HOST">%1$s</xliff:g> links with <xliff:g id="APPLICATION">%2$s</xliff:g>"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"Give access"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"Edit with"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Edit with %1$s"</string>
@@ -1590,8 +1586,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"Launch Browser?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Accept call?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Always"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"Set to always open"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Just once"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"Settings"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s doesn\'t support work profile"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 51b031b..cc389f3 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"Move phone to the left."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"Move phone to the right."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"Please look more directly at your device."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"Can’t see your face. Look at the phone."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"Position your face directly in front of the phone."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"Too much motion. Hold phone steady."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"Please re-enroll your face."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"No longer able to recognise face. Try again."</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"Open with"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Open with %1$s"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"Open"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"Open <xliff:g id="HOST">%1$s</xliff:g> links with"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"Open links with"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"Open links with <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"Open <xliff:g id="HOST">%1$s</xliff:g> links with <xliff:g id="APPLICATION">%2$s</xliff:g>"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"Give access"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"Edit with"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Edit with %1$s"</string>
@@ -1590,8 +1586,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"Launch Browser?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Accept call?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Always"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"Set to always open"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Just once"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"Settings"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s doesn\'t support work profile"</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 51b031b..cc389f3 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"Move phone to the left."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"Move phone to the right."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"Please look more directly at your device."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"Can’t see your face. Look at the phone."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"Position your face directly in front of the phone."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"Too much motion. Hold phone steady."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"Please re-enroll your face."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"No longer able to recognise face. Try again."</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"Open with"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Open with %1$s"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"Open"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"Open <xliff:g id="HOST">%1$s</xliff:g> links with"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"Open links with"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"Open links with <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"Open <xliff:g id="HOST">%1$s</xliff:g> links with <xliff:g id="APPLICATION">%2$s</xliff:g>"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"Give access"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"Edit with"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Edit with %1$s"</string>
@@ -1590,8 +1586,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"Launch Browser?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Accept call?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Always"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"Set to always open"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Just once"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"Settings"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s doesn\'t support work profile"</string>
diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml
index 638d29d..dade85e 100644
--- a/core/res/res/values-en-rXC/strings.xml
+++ b/core/res/res/values-en-rXC/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‎‏‏‏‎‎‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‎‎‎‏‎‏‏‎‏‏‎‏‏‎‏‎‏‎‏‎‏‏‏‏‏‏‏‎‎‏‏‎‎‏‎‎Move phone to the left.‎‏‎‎‏‎"</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‏‏‎‏‏‎‎‎‎‏‏‎‎‏‏‏‎‎‏‎‎‏‎‏‏‏‎‏‎‏‎‎‏‏‎‎‏‎‎‎‏‎‎‎‏‎‏‎‏‎‏‎‎‎‎‎‎‎Move phone to the right.‎‏‎‎‏‎"</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‏‏‏‎‎‏‏‏‎‎‎‏‏‎‏‏‏‎‏‎‎‏‎‎‎‏‎‎‎‏‎‎‏‎‏‏‏‏‏‎‏‏‏‏‏‏‏‏‎‎‏‎‏‏‎‎‏‎Please look more directly at your device.‎‏‎‎‏‎"</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‏‏‏‎‎‏‏‎‎‏‏‎‎‏‏‎‎‏‎‎‏‏‎‏‎‏‏‏‏‎‎‎‎‏‏‎‎‎‏‏‎‏‎‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎Can’t see your face. Look at the phone.‎‏‎‎‏‎"</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‎‎‎‎‏‎‏‏‎‎‎‎‏‎‏‏‎‎‎‎‏‏‏‎‎‎‎‏‏‏‏‎‎‏‎‏‎‏‏‎‏‏‏‎‏‎‎‎‎‏‎‎‏‏‏‏‎‎Position your face directly in front of the phone.‎‏‎‎‏‎"</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‏‏‎‏‏‎‏‎‎‏‎‏‎‏‏‎‎‏‏‏‎‏‏‎‎‎‏‏‏‏‎‏‎‎‏‎‎‎‎‎‎‎‎‏‏‏‏‎‎‏‎‏‏‎‎‏‏‎Too much motion. Hold phone steady.‎‏‎‎‏‎"</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‎‎‏‏‎‏‎‏‎‏‎‎‏‎‎‎‏‎‎‎‏‏‎‎‎‏‎‏‎‎‏‏‎‎‎‎‏‎‏‏‏‎‏‎‎‎‏‎‎‎‏‎‎‏‏‎Please re-enroll your face.‎‏‎‎‏‎"</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‏‎‏‏‎‏‏‏‏‏‏‎‎‎‎‏‎‏‎‎‎‏‎‎‎‏‎‎‏‏‎‏‎‎‏‎‏‏‎‎‏‏‎‎‏‎‏‎‏‏‏‏‏‏‎‎No longer able to recognize face. Try again.‎‏‎‎‏‎"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 43e0823a..3a2ea3e 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -292,7 +292,7 @@
     <string name="permgrouplab_sms" msgid="228308803364967808">"SMS"</string>
     <string name="permgroupdesc_sms" msgid="4656988620100940350">"enviar y ver mensajes SMS"</string>
     <string name="permgrouprequest_sms" msgid="7168124215838204719">"¿Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; envíe y vea SMS?"</string>
-    <string name="permgrouplab_storage" msgid="1971118770546336966">"Espacio de almacenamiento"</string>
+    <string name="permgrouplab_storage" msgid="1971118770546336966">"Almacenamiento"</string>
     <string name="permgroupdesc_storage" msgid="637758554581589203">"acceder a las fotos, el contenido multimedia y los archivos"</string>
     <string name="permgrouprequest_storage" msgid="7885942926944299560">"¿Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda a las fotos, el contenido multimedia y los archivos de tu dispositivo?"</string>
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Micrófono"</string>
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"Mueve el teléfono hacia la izquierda."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"Mueve el teléfono hacia la derecha."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"Mira directamente al dispositivo."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"No se ve tu cara. Mira el teléfono."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"Ubica el rostro directamente frente al teléfono."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"Te estás moviendo demasiado. No muevas el teléfono"</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"Vuelve a registrar tu cara."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"Ya no se reconoce la cara. Vuelve a intentarlo."</string>
@@ -602,7 +602,7 @@
     <string name="permdesc_readSyncStats" msgid="1510143761757606156">"Permite que la aplicación consulte las estadísticas de sincronización de una cuenta, por ejemplo, el historial de eventos sincronizados y la cantidad de datos sincronizados."</string>
     <string name="permlab_sdcardRead" msgid="1438933556581438863">"ver almacenamiento compartido"</string>
     <string name="permdesc_sdcardRead" msgid="1804941689051236391">"Ver almacenamiento compartido"</string>
-    <string name="permlab_sdcardWrite" msgid="9220937740184960897">"Cambia/borra almac. compartido"</string>
+    <string name="permlab_sdcardWrite" msgid="9220937740184960897">"cambiar o borrar contenido de almacenamiento compartido"</string>
     <string name="permdesc_sdcardWrite" msgid="2834431057338203959">"Editar almacen. compartido"</string>
     <string name="permlab_use_sip" msgid="2052499390128979920">"realizar/recibir llamadas SIP"</string>
     <string name="permdesc_use_sip" msgid="2297804849860225257">"Permite que la aplicación realice y reciba llamadas SIP."</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"Abrir con"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Abrir con %1$s"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"Abrir"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"Abrir vínculos de <xliff:g id="HOST">%1$s</xliff:g> con"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"Abrir vínculos con"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"Abrir vínculos con <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"Abrir vínculos de <xliff:g id="HOST">%1$s</xliff:g> con <xliff:g id="APPLICATION">%2$s</xliff:g>"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"Otorgar acceso"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"Editar con"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Editar con %1$s"</string>
@@ -1590,8 +1586,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"¿Deseas iniciar el navegador?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"¿Aceptar la llamada?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Siempre"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"Establecer en \"abrir siempre\""</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Solo una vez"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"Configuración"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s no admite perfiles de trabajo."</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 90bf8b6..633759b 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"Mueve el teléfono hacia la izquierda."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"Mueve el teléfono hacia la derecha."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"Mira de forma más directa al dispositivo."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"No se detecta tu cara. Mira al teléfono."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"Coloca la cara directamente frente al teléfono."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"El teléfono se mueve demasiado. Mantenlo quieto."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"Vuelve a registrar tu cara."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"No puede reconocer tu cara. Vuelve a intentarlo."</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"Abrir con"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Abrir con %1$s"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"Abrir"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"Abrir enlaces de <xliff:g id="HOST">%1$s</xliff:g> con"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"Abrir enlaces con"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"Abrir enlaces con <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"Abrir enlaces de <xliff:g id="HOST">%1$s</xliff:g> con <xliff:g id="APPLICATION">%2$s</xliff:g>"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"Permitir acceso"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"Editar con"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Editar con %1$s"</string>
@@ -1590,8 +1586,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"¿Iniciar el navegador?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"¿Aceptar la llamada?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Siempre"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"Configurar para que se abra siempre"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Solo una vez"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"Ajustes"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s no admite perfiles de trabajo"</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index cf84482..86843c7 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"Liigutage telefoni vasakule."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"Liigutage telefoni paremale."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"Vaadake otse oma seadmesse."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"Teie nägu ei ole näha. Vaadake telefoni poole."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"Hoidke oma nägu otse telefoni ees."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"Liiga palju liikumist. Hoidke telefoni paigal."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"Registreerige oma nägu uuesti."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"Nägu ei õnnestu enam tuvastada. Proovige uuesti."</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"Avamine:"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Avamine rakendusega %1$s"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"Ava"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"Ava teenuse <xliff:g id="HOST">%1$s</xliff:g> lingid rakendusega"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"Ava lingid rakendusega"</string>
+    <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="whichEditApplicationNamed" msgid="1775815530156447790">"Muutmine rakendusega %1$s"</string>
@@ -1590,8 +1586,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"Kas käivitada brauser?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Kas vastata kõnele?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Alati"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"Määra alati avama"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Ainult üks kord"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"Seaded"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s ei toeta tööprofiili"</string>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index ba1e0b2..d25fe8c 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -375,7 +375,7 @@
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Beren zati batzuk memoria modu iraunkorrean ezartzeko baimena ematen die aplikazioei. Horrela, beste aplikazioek erabilgarri duten memoria murritz daiteke eta tableta motel daiteke."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Beren zati batzuk memorian modu iraunkorrean aktibo uztea baimentzen die aplikazioei. Horrela, beste aplikazioek memoria gutxiago izan lezakete erabilgarri eta telebistak motelago funtziona lezake."</string>
     <string name="permdesc_persistentActivity" product="default" msgid="4384760047508278272">"Beren zati batzuk memoria modu iraunkorrean ezartzeko baimena ematen die aplikazioei. Horrela, beste aplikazioek erabilgarri duten memoria murritz daiteke eta telefonoa motel daiteke."</string>
-    <string name="permlab_foregroundService" msgid="3310786367649133115">"Exekutatu zerbitzuak aurreko planoan"</string>
+    <string name="permlab_foregroundService" msgid="3310786367649133115">"Abiarazi zerbitzuak aurreko planoan"</string>
     <string name="permdesc_foregroundService" msgid="6471634326171344622">"Aurreko planoko zerbitzuak erabiltzea baimentzen dio aplikazioari."</string>
     <string name="permlab_getPackageSize" msgid="7472921768357981986">"neurtu aplikazioen biltegiratzeko tokia"</string>
     <string name="permdesc_getPackageSize" msgid="3921068154420738296">"Bere kodea, datuak eta cache-tamainak eskuratzeko baimena ematen die aplikazioei."</string>
@@ -422,7 +422,7 @@
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"Aplikazioa aurreko planoan dagoenean, zure kokapenaren berri izan dezake sareen iturburuak erabilita; adibidez, telefonia mugikorreko dorreak eta Wi-Fi sareak. Kokapen-zerbitzu horiek aktibatuta eta erabilgarri izan behar dituzu telebistan, aplikazioak erabil ditzan."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"Aplikazioa aurreko planoan dagoenean, zure kokapenaren berri izan dezake sareen iturburuak erabilita; adibidez, telefonia mugikorreko dorreak eta Wi-Fi sareak. Kokapen-zerbitzu horiek aktibatuta eta erabilgarri izan behar dituzu telefonoan, aplikazioak erabil ditzan."</string>
     <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"Atzitu kokapena atzeko planoan"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Baimen hau ematen bada kokapen zehatz edo gutxi gorabeherakorako sarbideaz gain, atzeko planoan exekutatu bitartean atzitu ahalko du aplikazioak kokapena."</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Baimen hau ematen bada kokapen zehatz edo gutxi gorabeherakorako sarbideaz gain, atzeko planoan abian den bitartean atzitu ahalko du aplikazioak kokapena."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"aldatu audio-ezarpenak"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Audio-ezarpen orokorrak aldatzeko baimena ematen dio; besteak beste, bolumena eta irteerarako zer bozgorailu erabiltzen den."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"grabatu audioa"</string>
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"Mugitu telefonoa ezkerretara."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"Mugitu telefonoa eskuinetara."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"Begiratu zuzenago gailuari."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"Ez da hautematen aurpegia. Begiratu telefonoari."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"Ipini aurrez aurre aurpegia eta telefonoa."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"Mugimendu gehiegi dago. Eutsi tinko telefonoari."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"Erregistratu berriro aurpegia."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"Ez dugu ezagutzen aurpegi hori. Saiatu berriro."</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"Ireki honekin:"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Irekin %1$s aplikazioarekin"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"Ireki"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"Ireki <xliff:g id="HOST">%1$s</xliff:g> ostalariko estekak honekin:"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"Ireki estekak honekin:"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"Ireki estekak <xliff:g id="APPLICATION">%1$s</xliff:g> aplikazioarekin"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"Ireki <xliff:g id="HOST">%1$s</xliff:g> ostalariko estekak <xliff:g id="APPLICATION">%2$s</xliff:g> aplikazioarekin"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"Eman sarbidea"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"Editatu honekin:"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Editatu %1$s aplikazioarekin"</string>
@@ -1181,7 +1177,7 @@
     <string name="wait" msgid="7147118217226317732">"Itxaron"</string>
     <string name="webpage_unresponsive" msgid="3272758351138122503">"Orriak ez du erantzuten.\n\nItxi egin nahi duzu?"</string>
     <string name="launch_warning_title" msgid="1547997780506713581">"Aplikazioa birbideratu da"</string>
-    <string name="launch_warning_replace" msgid="6202498949970281412">"<xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioa exekutatzen ari da."</string>
+    <string name="launch_warning_replace" msgid="6202498949970281412">"<xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioa abian da."</string>
     <string name="launch_warning_original" msgid="188102023021668683">"<xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioa lehenago abiarazi da."</string>
     <string name="screen_compat_mode_scale" msgid="3202955667675944499">"Eskala"</string>
     <string name="screen_compat_mode_show" msgid="4013878876486655892">"Erakutsi beti"</string>
@@ -1207,7 +1203,7 @@
     <string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> prestatzen."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Aplikazioak abiarazten."</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"Bertsio-berritzea amaitzen."</string>
-    <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> exekutatzen"</string>
+    <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> abian da"</string>
     <string name="heavy_weight_notification_detail" msgid="2304833848484424985">"Sakatu jokora itzultzeko"</string>
     <string name="heavy_weight_switcher_title" msgid="387882830435195342">"Aukeratu joko bat"</string>
     <string name="heavy_weight_switcher_text" msgid="4176781660362912010">"Funtzionamendu hobea izateko, joko hauetako bat baino ezin da egon irekita aldi berean."</string>
@@ -1445,7 +1441,7 @@
     <string name="ime_action_next" msgid="3138843904009813834">"Hurrengoa"</string>
     <string name="ime_action_done" msgid="8971516117910934605">"Eginda"</string>
     <string name="ime_action_previous" msgid="1443550039250105948">"Atzera"</string>
-    <string name="ime_action_default" msgid="2840921885558045721">"Exekutatu"</string>
+    <string name="ime_action_default" msgid="2840921885558045721">"Abiarazi"</string>
     <string name="dial_number_using" msgid="5789176425167573586">"Markatu zenbakia \n<xliff:g id="NUMBER">%s</xliff:g> erabilita"</string>
     <string name="create_contact_using" msgid="4947405226788104538">"Sortu kontaktua\n<xliff:g id="NUMBER">%s</xliff:g> erabilita"</string>
     <string name="grant_credentials_permission_message_header" msgid="2106103817937859662">"Aplikazio hauetako bat edo gehiago kontua orain eta etorkizunean atzitzeko baimena eskatzen ari dira."</string>
@@ -1555,7 +1551,7 @@
     <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>
     <string name="storage_usb_drive_label" msgid="4501418548927759953">"<xliff:g id="MANUFACTURER">%s</xliff:g> enpresaren USB bidezko unitatea"</string>
-    <string name="storage_usb" msgid="3017954059538517278">"USB memoria"</string>
+    <string name="storage_usb" msgid="3017954059538517278">"USB bidezko memoria"</string>
     <string name="extract_edit_menu_button" msgid="8940478730496610137">"Editatu"</string>
     <string name="data_usage_warning_title" msgid="6499834033204801605">"Datuen erabileraren abisua"</string>
     <string name="data_usage_warning_body" msgid="7340198905103751676">"<xliff:g id="APP">%s</xliff:g> erabili dituzu"</string>
@@ -1591,8 +1587,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"Arakatzailea abiarazi nahi duzu?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Deia onartu nahi duzu?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Beti"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"Ezarri beti irekitzeko"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Behin soilik"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"Ezarpenak"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s abiarazleak ez du laneko profil hau onartzen"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 280a56ec..48cdafc 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"تلفن را به‌سمت چپ حرکت دهید."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"تلفن را به سمت راست حرکت دهید."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"لطفاً مستقیم به دستگاه نگه کنید."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"چهره‌تان دیده نمی‌شود. به تلفن نگاه کنید."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"صورتتان را مستقیماً روبروی تلفن قرار دهید."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"حرکت خیلی زیاد است. تلفن را ثابت نگه‌دارید."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"لطفاً چهره‌تان را مجدداً ثبت کنید."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"دیگر چهره را تشخیص نمی‌دهد. دوباره امتحان کنید."</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"باز کردن با"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"‏باز کردن با %1$s"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"باز کردن"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"باز کردن پیوندهای <xliff:g id="HOST">%1$s</xliff:g> با"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"باز کردن پیوندها با"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"باز کردن پیوندها با <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"باز کردن پیوندهای <xliff:g id="HOST">%1$s</xliff:g> با <xliff:g id="APPLICATION">%2$s</xliff:g>"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"ارائه دسترسی"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"ویرایش با"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"‏ویرایش با %1$s"</string>
@@ -1590,8 +1586,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"مرورگر راه‌اندازی شود؟"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"تماس را می‌پذیرید؟"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"همیشه"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"تنظیم روی همیشه باز شدن"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"فقط این بار"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"تنظیمات"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"‏%1$s از نمایه کاری پشتیبانی نمی‌کند"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 7a5003b..cd9a711 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"Siirrä puhelinta vasemmalle."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"Siirrä puhelinta oikealle."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"Katso suoremmin laitteeseen."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"Kasvojasi ei näy. Katso puhelinta."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"Aseta kasvosi suoraan puhelimen eteen."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"Laite liikkui liikaa. Pidä puhelin vakaana."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"Rekisteröi kasvot uudelleen."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"Ei enää tunnista kasvoja. Yritä uudelleen."</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"Avaa sovelluksessa"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Avaa sovelluksessa %1$s"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"Avaa"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"<xliff:g id="HOST">%1$s</xliff:g>-linkit avataan:"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"Linkit avataan:"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"<xliff:g id="APPLICATION">%1$s</xliff:g> avaa linkit"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"<xliff:g id="APPLICATION">%2$s</xliff:g> avaa linkit (<xliff:g id="HOST">%1$s</xliff:g>)"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"Salli"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"Muokkaa sovelluksessa"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Muokkaa sovelluksessa %1$s"</string>
@@ -1590,8 +1586,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"Käynnistetäänkö selain?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Vastataanko puheluun?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Aina"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"Avaa aina"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Vain kerran"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"Asetukset"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s ei tue työprofiilia"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 0ddb19a..2bfef39 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"Déplacez le téléphone vers la gauche."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"Déplacez le téléphone vers la droite."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"Veuillez regarder plus directement votre appareil."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"Visage non détecté. Regardez le téléphone."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"Placez votre visage directement devant le téléphone."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"Trop de mouvement. Tenez le téléphone immobile."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"Veuillez inscrire votre visage à nouveau."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"Ce visage ne sera plus reconnu. Réessayez."</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"Ouvrir avec"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Ouvrir avec %1$s"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"Ouvrir"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"Ouvrir les liens <xliff:g id="HOST">%1$s</xliff:g> avec"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"Ouvrir les liens avec"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"Ouvrir les liens avec <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"Ouvrir les liens <xliff:g id="HOST">%1$s</xliff:g> avec <xliff:g id="APPLICATION">%2$s</xliff:g>"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"Accorder l\'accès"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"Modifier avec"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Modifier avec %1$s"</string>
@@ -1590,8 +1586,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"Lancer le navigateur?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Prendre l\'appel?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Toujours"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"Définir cette activité comme toujours ouverte"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Une seule fois"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"Paramètres"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s ne prend pas en charge le profil professionnel"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 5f98a8a..041668f 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"Déplacez le téléphone vers la gauche."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"Déplacez le téléphone vers la droite."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"Veuillez regarder plus directement l\'appareil."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"Visage non détecté. Regardez le téléphone."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"Placez votre visage en face du téléphone."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"Trop de mouvement. Ne bougez pas le téléphone."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"Veuillez enregistrer à nouveau votre visage."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"Impossible de reconnaître le visage. Réessayez."</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"Ouvrir avec"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Ouvrir avec %1$s"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"Ouvrir"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"Ouvrir les liens <xliff:g id="HOST">%1$s</xliff:g> avec"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"Ouvrir les liens avec"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"Ouvrir les liens avec <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"Ouvrir les liens <xliff:g id="HOST">%1$s</xliff:g> avec <xliff:g id="APPLICATION">%2$s</xliff:g>"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"Accorder l\'accès"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"Modifier avec"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Modifier avec %1$s"</string>
@@ -1590,8 +1586,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"Lancer le navigateur ?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Prendre l\'appel ?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Toujours"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"Définir cette activité comme toujours ouverte"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Une seule fois"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"Paramètres"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s n\'est pas compatible avec le profil professionnel."</string>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index 740f699..18bba90 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"Move o teléfono cara á esquerda."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"Move o teléfono cara á dereita."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"Mira o dispositivo de forma máis directa."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"Non se ve a túa cara. Mira para o teléfono"</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"Coloca a cara directamente diante do teléfono."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"Demasiado movemento. Non movas o teléfono."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"Volve rexistrar a túa cara."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"Xa non se pode recoñecer a cara. Téntao de novo."</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"Abrir con"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Abrir con %1$s"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"Abrir"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"Abrir ligazóns de <xliff:g id="HOST">%1$s</xliff:g> con"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"Abrir ligazóns con"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"Abrir ligazóns con <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"Abrir ligazóns de <xliff:g id="HOST">%1$s</xliff:g> con <xliff:g id="APPLICATION">%2$s</xliff:g>"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"Conceder acceso"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"Editar con"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Editar con %1$s"</string>
@@ -1591,8 +1587,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"Iniciar o navegador?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Aceptar chamada?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Sempre"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"Definir como abrir sempre"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Só unha vez"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"Configuración"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s non admite o perfil de traballo"</string>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index ddc4aae..1b96172 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"ફોનને ડાબી બાજુ ખસેડો."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"ફોનને જમણી બાજુ ખસેડો."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"કૃપા કરીને તમારા ડિવાઇસ તરફ સીધું જુઓ."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"તમારો ચહેરો દેખાતો નથી. ફોનની સામે જુઓ."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"તમારો ચહેરો તમારા ફોનની બિલકુલ સામે રાખો."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"ડિવાઇસ અસ્થિર છે. ફોનને સ્થિર રાખો."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"કૃપા કરીને તમારા ચહેરાની ફરી નોંધણી કરાવો."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"ચહેરો ઓળખી શકાતો નથી. ફરી પ્રયાસ કરો."</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"આની સાથે ખોલો"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"%1$s સાથે ખોલો"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"ખોલો"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"આના વડે <xliff:g id="HOST">%1$s</xliff:g> લિંક ખોલો"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"આના વડે લિંક ખોલો"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"<xliff:g id="APPLICATION">%1$s</xliff:g> વડે લિંક ખોલો"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"<xliff:g id="APPLICATION">%2$s</xliff:g> વડે <xliff:g id="HOST">%1$s</xliff:g> લિંક ખોલો"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"ઍક્સેસ આપો"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"આનાથી સંપાદિત કરો"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"%1$s સાથે સંપાદિત કરો"</string>
@@ -1591,8 +1587,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"બ્રાઉઝર લોન્ચ કરીએ?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"કૉલ સ્વીકારીએ?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"હંમેશા"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"હંમેશાં ખુલ્લી તરીકે સેટ કરો"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"ફક્ત એક વાર"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"સેટિંગ"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s કાર્ય પ્રોફાઇલનું સમર્થન કરતું નથી"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 0a1051b..9f0df13 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"फ़ोन को बाईं ओर घुमाएं."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"फ़ोन को दाईं ओर घुमाएं."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"कृपया अपने डिवाइस की तरफ़ सीधे देखें."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"आपका चेहरा नहीं दिखाई दे रहा. फ़ोन की तरफ़ देखें."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"अपने चेहरे को फोन के ठीक सामने लाएं."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"डिवाइस बहुत ज़्यादा हिल रहा है. फ़ोन को बिना हिलाएं पकड़ें."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"कृपया फिर से अपने चेहरे की पहचान कराएं."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"अब चेहरे की पहचान नहीं कर पा रहा. फिर से कोशिश करें."</string>
@@ -784,7 +784,7 @@
     <string name="relationTypeDomesticPartner" msgid="6904807112121122133">"हमसफ़र"</string>
     <string name="relationTypeFather" msgid="5228034687082050725">"पिता"</string>
     <string name="relationTypeFriend" msgid="7313106762483391262">"दोस्त"</string>
-    <string name="relationTypeManager" msgid="6365677861610137895">"प्रबंधक"</string>
+    <string name="relationTypeManager" msgid="6365677861610137895">"मैनेजर"</string>
     <string name="relationTypeMother" msgid="4578571352962758304">"मां"</string>
     <string name="relationTypeParent" msgid="4755635567562925226">"अभिभावक"</string>
     <string name="relationTypePartner" msgid="7266490285120262781">"सहयोगी"</string>
@@ -904,7 +904,7 @@
     <string name="granularity_label_line" msgid="5764267235026120888">"पंक्ति"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"फ़ैक्‍ट्री परीक्षण विफल"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"FACTORY_TEST का काम केवल /system/app में इंस्‍टॉल किए गए पैकेज के लिए ही हो सकता है."</string>
-    <string name="factorytest_no_action" msgid="872991874799998561">"ऐसा कोई पैकेज नहीं मिला था जो FACTORY_TEST कार्रवाई प्रदान करता हो."</string>
+    <string name="factorytest_no_action" msgid="872991874799998561">"ऐसा कोई पैकेज नहीं मिला था जो FACTORY_TEST कार्रवाई मुहैया करवाता हो."</string>
     <string name="factorytest_reboot" msgid="6320168203050791643">"रीबूट करें"</string>
     <string name="js_dialog_title" msgid="1987483977834603872">"\'<xliff:g id="TITLE">%s</xliff:g>\' पर यह पेज दर्शाता है:"</string>
     <string name="js_dialog_title_default" msgid="6961903213729667573">"JavaScript"</string>
@@ -1085,7 +1085,7 @@
     <string name="undo" msgid="7905788502491742328">"वापस लाएं"</string>
     <string name="redo" msgid="7759464876566803888">"फिर से करें"</string>
     <string name="autofill" msgid="3035779615680565188">"ऑटोमैटिक भरना"</string>
-    <string name="textSelectionCABTitle" msgid="5236850394370820357">"लेख चयन"</string>
+    <string name="textSelectionCABTitle" msgid="5236850394370820357">"टेक्स्ट चुनें"</string>
     <string name="addToDictionary" msgid="4352161534510057874">"शब्दकोश में जोड़ें"</string>
     <string name="deleteText" msgid="6979668428458199034">"मिटाएं"</string>
     <string name="inputMethod" msgid="1653630062304567879">"इनपुट विधि"</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"इसमें खोलें"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"%1$s में खोलें"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"खोलें"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"इसे इस्तेमाल करके <xliff:g id="HOST">%1$s</xliff:g> लिंक खोलें"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"इसे इस्तेमाल करके लिंक खोलें"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"<xliff:g id="APPLICATION">%1$s</xliff:g> इस्तेमाल करके लिंक खोलें"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"<xliff:g id="APPLICATION">%2$s</xliff:g> इस्तेमाल करके <xliff:g id="HOST">%1$s</xliff:g> लिंक खोलें"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"एक्सेस दें"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"इसके ज़रिये बदलाव करें"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"%1$s की मदद से बदलाव करें"</string>
@@ -1288,7 +1284,7 @@
     <item msgid="75483255295529161">"वाई-फ़ाई"</item>
     <item msgid="6862614801537202646">"ब्लूटूथ"</item>
     <item msgid="5447331121797802871">"ईथरनेट"</item>
-    <item msgid="8257233890381651999">"VPN"</item>
+    <item msgid="8257233890381651999">"वीपीएन"</item>
   </string-array>
     <string name="network_switch_type_name_unknown" msgid="4552612897806660656">"अज्ञात नेटवर्क प्रकार"</string>
     <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"वाई-फ़ाई  से कनेक्‍ट नहीं हो सका"</string>
@@ -1590,8 +1586,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"ब्राउज़र लॉन्च करें?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"कॉल स्वीकार करें?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"हमेशा"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"\'हमेशा खुला रखें\' पर सेट करें"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"केवल एक बार"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"सेटिंग"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s वर्क प्रोफ़ाइल का समर्थन नहीं करता"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index cc8eb49..21fdc2f 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -571,7 +571,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"Pomaknite telefon ulijevo."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"Pomaknite telefon udesno."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"Gledajte izravnije prema uređaju."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"Vaše se lice ne vidi. Pogledajte telefon."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"Postavite lice izravno ispred telefona."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"Previše kretanja. Držite telefon mirno."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"Ponovo registrirajte svoje lice."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"Lice nije prepoznato. Pokušajte ponovo."</string>
@@ -1151,14 +1151,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"Otvaranje pomoću aplikacije"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Otvaranje pomoću aplikacije %1$s"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"Otvori"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"Otvaranje veza s <xliff:g id="HOST">%1$s</xliff:g> u aplikaciji"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"Otvaranje veza u aplikaciji"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"Otvaranje veza u aplikaciji <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"Otvaranje veza s <xliff:g id="HOST">%1$s</xliff:g> u aplikaciji <xliff:g id="APPLICATION">%2$s</xliff:g>"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"Omogući pristup"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"Uređivanje pomoću aplikacije"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Uređivanje pomoću aplikacije %1$s"</string>
@@ -1613,8 +1609,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"Pokrenuti preglednik?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Prihvatiti poziv?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Uvijek"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"Postavi to otvaranje kao zadano"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Samo jednom"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"Postavke"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s ne podržava radni profil"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 4ce7d42..1198610 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"Mozgassa a telefont balra."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"Mozgassa a telefont jobbra."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"Szemből nézzen az eszközre."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"Nem látszik az arca. Nézzen a telefonra."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"A telefont közvetlenül az arca elé tegye."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"Túl sok a mozgás. Tartsa stabilan a telefont."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"Rögzítsen újra képet az arcáról."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"Már nem lehet felismerni az arcát. Próbálja újra."</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"Megnyitás a következővel:"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Megnyitás a következővel: %1$s"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"Megnyitás"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"<xliff:g id="HOST">%1$s</xliff:g>-linkek megnyitása a következővel:"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"Linkek megnyitása a következővel:"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"Linkek megnyitása a következővel: <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"<xliff:g id="HOST">%1$s</xliff:g>-linkek megnyitása a következővel: <xliff:g id="APPLICATION">%2$s</xliff:g>"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"Engedély adása"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"Szerkesztés a következővel:"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Szerkesztés a következővel: %1$s"</string>
@@ -1590,8 +1586,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"Böngésző indítása?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Fogadja a hívást?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Mindig"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"Megnyitás mindig ezzel"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Csak egyszer"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"Beállítások"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"A(z) %1$s nem támogatja a munkaprofilokat."</string>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index 2be6d6f..cb4886a 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -104,7 +104,7 @@
     <string name="serviceClassFAX" msgid="5566624998840486475">"Ֆաքս"</string>
     <string name="serviceClassSMS" msgid="2015460373701527489">"SMS"</string>
     <string name="serviceClassDataAsync" msgid="4523454783498551468">"Չհամաժամեցված"</string>
-    <string name="serviceClassDataSync" msgid="7530000519646054776">"Համաժամել"</string>
+    <string name="serviceClassDataSync" msgid="7530000519646054776">"Համաժամացնել"</string>
     <string name="serviceClassPacket" msgid="6991006557993423453">"Փաթեթ"</string>
     <string name="serviceClassPAD" msgid="3235259085648271037">"Հարթակ"</string>
     <string name="roamingText0" msgid="7170335472198694945">"Ռոումինգի ցուցիչը միացված է"</string>
@@ -169,8 +169,8 @@
     <string name="httpErrorFileNotFound" msgid="6203856612042655084">"Չհաջողվեց գտնել հարցվող ֆայլը:"</string>
     <string name="httpErrorTooManyRequests" msgid="1235396927087188253">"Չափից շատ հարցումներ են մշակվում: Փորձեք կրկին ավելի ուշ:"</string>
     <string name="notification_title" msgid="8967710025036163822">"Մուտք գործելու սխալ` <xliff:g id="ACCOUNT">%1$s</xliff:g>-ի համար"</string>
-    <string name="contentServiceSync" msgid="8353523060269335667">"Համաժամեցնել"</string>
-    <string name="contentServiceSyncNotificationTitle" msgid="7036196943673524858">"Չի հաջողվում համաժամեցնել"</string>
+    <string name="contentServiceSync" msgid="8353523060269335667">"Համաժամացնել"</string>
+    <string name="contentServiceSyncNotificationTitle" msgid="7036196943673524858">"Չի հաջողվում համաժամացնել"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="4884451152168188763">"Հետևյալ ծառայությունից չափազանց շատ տարրեր եք ջնջել՝ <xliff:g id="CONTENT_TYPE">%s</xliff:g>:"</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"Պլանշետի պահոցը լիքն է: Ջնջեք մի քանի ֆայլ` տարածք ազատելու համար:"</string>
     <string name="low_memory" product="watch" msgid="4415914910770005166">"Ժամացույցի ֆայլերի պահեստը լիքն է: Ջնջեք որոշ ֆայլեր՝ տարածք ազատելու համար:"</string>
@@ -346,7 +346,7 @@
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"կարդալ բջջային զեկուցվող հաղորդագրությունները"</string>
     <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Թույլ է տալիս հավելվածին կարդալ ձեր սարքի կողմից ստացված բջջային հեռարձակվող հաղորդագրությունները: Բջջային հեռարձակվող զգուշացումները ուղարկվում են որոշ վայրերում` արտակարգ իրավիճակների մասին ձեզ զգուշացնելու համար: Վնասարար հավելվածները կարող են խանգարել ձեր սարքի արդյունավետությանը կամ շահագործմանը, երբ ստացվում է արտակարգ իրավիճակի մասին բջջային հաղորդում:"</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"կարդալ բաժանորդագրված հոսքերը"</string>
-    <string name="permdesc_subscribedFeedsRead" msgid="5557058907906144505">"Թույլ է տալիս հավելվածին մանրամասներ ստանալ ընթացիկ համաժամեցված հոսքերի մասին:"</string>
+    <string name="permdesc_subscribedFeedsRead" msgid="5557058907906144505">"Թույլ է տալիս հավելվածին մանրամասներ ստանալ ընթացիկ համաժամացված հոսքերի մասին:"</string>
     <string name="permlab_sendSms" msgid="7544599214260982981">"SMS հաղորդագրությունների ուղարկում և ընթերցում"</string>
     <string name="permdesc_sendSms" msgid="7094729298204937667">"Թույլ է տալիս հավելվածին ուղարկել SMS հաղորդագրություններ: Այն կարող է անսպասելի ծախսերի պատճառ դառնալ: Վնասարար հավելվածները կարող են ձեր հաշվից գումար ծախսել` ուղարկելով հաղորդագրություններ`  առանց ձեր հաստատման:"</string>
     <string name="permlab_readSms" msgid="8745086572213270480">"կարդալ ձեր տեքստային հաղորդագրությունները (SMS կամ MMS)"</string>
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"Տեղափոխեք հեռախոսը ձախ:"</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"Տեղափոխեք հեռախոսը աջ:"</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"Նայեք ուղիղ էկրանին։"</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"Ձեր դեմքը չի երևում։ Նայեք հեռախոսին։"</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"Պահեք ձեր դեմքն անմիջապես հեռախոսի էկրանի դիմաց:"</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"Շատ եք շարժում։ Հեռախոսն անշարժ պահեք։"</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"Նորից փորձեք։"</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"Չհաջողվեց ճանաչել դեմքը։ Նորից փորձեք:"</string>
@@ -594,12 +594,12 @@
   <string-array name="face_error_vendor">
   </string-array>
     <string name="face_icon_content_description" msgid="4024817159806482191">"Դեմքի պատկերակ"</string>
-    <string name="permlab_readSyncSettings" msgid="6201810008230503052">"կարդալ համաժամեցման կարգավորումները"</string>
-    <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Թույլ է տալիս հավելվածին կարդալ համաժամեցման կարգավորումները հաշվի համար: Օրինակ` այն կարող է որոշել, արդյոք Մարդիկ հավելվածը համաժամեցված է հաշվի հետ:"</string>
-    <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"համաժամեցումը փոխարկել միացվածի և անջատվածի"</string>
-    <string name="permdesc_writeSyncSettings" msgid="8956262591306369868">"Թույլ է տալիս հավելվածին փոփոխել համաժամեցման կարգավորումները հաշվի համար: Օրինակ, այն կարող է օգտագործվել` միացնելու Մարդիկ հավելվածի համաժամեցումը հաշվի հետ:"</string>
-    <string name="permlab_readSyncStats" msgid="7396577451360202448">"կարդալ համաժամեցման վիճակագրությունը"</string>
-    <string name="permdesc_readSyncStats" msgid="1510143761757606156">"Թույլ է տալիս հավելվածին կարդալ հաշվի համաժամեցման վիճակագրությունը, այդ թվում` համաժամեցման իրադարձությունների պատմությունը և թե որքան տվյալ է համաժամեցված:"</string>
+    <string name="permlab_readSyncSettings" msgid="6201810008230503052">"կարդալ համաժամացման կարգավորումները"</string>
+    <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Թույլ է տալիս հավելվածին կարդալ համաժամացման կարգավորումները հաշվի համար: Օրինակ` այն կարող է որոշել, արդյոք Մարդիկ հավելվածը համաժամացված է հաշվի հետ:"</string>
+    <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"համաժամացումը փոխարկել միացվածի և անջատվածի"</string>
+    <string name="permdesc_writeSyncSettings" msgid="8956262591306369868">"Թույլ է տալիս հավելվածին փոփոխել համաժամացման կարգավորումները հաշվի համար: Օրինակ, այն կարող է օգտագործվել` միացնելու Մարդիկ հավելվածի համաժամացումը հաշվի հետ:"</string>
+    <string name="permlab_readSyncStats" msgid="7396577451360202448">"կարդալ համաժամացման վիճակագրությունը"</string>
+    <string name="permdesc_readSyncStats" msgid="1510143761757606156">"Թույլ է տալիս հավելվածին կարդալ հաշվի համաժամացման վիճակագրությունը, այդ թվում` համաժամացման իրադարձությունների պատմությունը և թե որքան տվյալ է համաժամացված:"</string>
     <string name="permlab_sdcardRead" msgid="1438933556581438863">"կարդալ ձեր ընդհանուր հիշողության պարունակությունը"</string>
     <string name="permdesc_sdcardRead" msgid="1804941689051236391">"Հավելվածին թույլ է տալիս կարդալ ձեր ընդհանուր հիշողության պարունակությունը:"</string>
     <string name="permlab_sdcardWrite" msgid="9220937740184960897">"փոփոխել կամ ջնջել ձեր ընդհանուր հիշողության բովանդակությունը"</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"Բացել հետևյալ ծրագրով՝"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Բացել հավելվածով՝ %1$s"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"Բացել"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"<xliff:g id="HOST">%1$s</xliff:g> տեսակի հղումները բացել…"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"Հղումները բացել…"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"Հղումները բացել <xliff:g id="APPLICATION">%1$s</xliff:g> դիտարկիչում"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"<xliff:g id="HOST">%1$s</xliff:g> տեսակի հղումները բացել <xliff:g id="APPLICATION">%2$s</xliff:g> դիտարկիչում"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"Թույլատրել"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"Խմբագրել հետևյալ ծրագրով՝"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Խմբագրել հետևյալով՝ %1$s"</string>
@@ -1156,7 +1152,7 @@
     <string name="whichImageCaptureApplicationNamed" msgid="8619384150737825003">"Լուսանկարել %1$s հավելվածի օգնությամբ"</string>
     <string name="whichImageCaptureApplicationLabel" msgid="6390303445371527066">"Լուսանկարել"</string>
     <string name="alwaysUse" msgid="4583018368000610438">"Օգտագործել ըստ կանխադրման այս գործողության համար:"</string>
-    <string name="use_a_different_app" msgid="8134926230585710243">"Օգտագործել այլ հավելված"</string>
+    <string name="use_a_different_app" msgid="8134926230585710243">"Ուրիշ հավելված"</string>
     <string name="clearDefaultHintMsg" msgid="3252584689512077257">"Մաքրել լռելյայնը Համակարգի կարգավորումներ &gt; Ծրագրեր &gt;Ներբեռնված էջից:"</string>
     <string name="chooseActivity" msgid="7486876147751803333">"Ընտրել գործողություն"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"Ընտրեք հավելված USB սարքի համար"</string>
@@ -1457,7 +1453,7 @@
     <string name="forward_intent_to_owner" msgid="1207197447013960896">"Դուք օգտագործում եք այս հավելվածը ձեր աշխատանքային պրոֆիլից դուրս"</string>
     <string name="forward_intent_to_work" msgid="621480743856004612">"Դուք օգտագործում եք այս հավելվածը ձեր աշխատանքային պրոֆիլում"</string>
     <string name="input_method_binding_label" msgid="1283557179944992649">"Ներածման եղանակը"</string>
-    <string name="sync_binding_label" msgid="3687969138375092423">"Համաժամել"</string>
+    <string name="sync_binding_label" msgid="3687969138375092423">"Համաժամացնել"</string>
     <string name="accessibility_binding_label" msgid="4148120742096474641">"Մատչելիությունը"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Պաստառ"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Փոխել պաստառը"</string>
@@ -1590,9 +1586,8 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"Գործարկե՞լ զննարկիչը:"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Ընդունե՞լ զանգը:"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Միշտ"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
-    <string name="activity_resolver_use_once" msgid="2404644797149173758">"Միայն մեկ անգամ"</string>
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"Միշտ բացել"</string>
+    <string name="activity_resolver_use_once" msgid="2404644797149173758">"Միայն այս անգամ"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"Կարգավորումներ"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s-ը չի աջակցում աշխատանքային պրոֆիլներ"</string>
     <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Գրասալիկ"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index e71ab41..ca369eb 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"Gerakkan ponsel ke kiri."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"Gerakkan ponsel ke kanan."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"Lihat langsung ke perangkat."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"Tidak dapat melihat wajah Anda. Lihat ke ponsel."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"Posisikan wajah Anda langsung di depan ponsel."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"Terlalu banyak gerakan. Stabilkan ponsel."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"Daftarkan ulang wajah Anda."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"Tidak lagi dapat mengenali wajah. Coba lagi."</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"Buka dengan"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Buka dengan %1$s"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"Buka"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"Buka link <xliff:g id="HOST">%1$s</xliff:g> dengan"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"Buka link dengan"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"Buka link dengan <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"Buka link <xliff:g id="HOST">%1$s</xliff:g> dengan <xliff:g id="APPLICATION">%2$s</xliff:g>"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"Berikan akses"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"Edit dengan"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Edit dengan %1$s"</string>
@@ -1383,7 +1379,7 @@
     <string name="alert_windows_notification_channel_group_name" msgid="1463953341148606396">"Tampilkan di atas apl lain"</string>
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> ditampilkan di atas aplikasi lain"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> ditampilkan di atas aplikasi lain"</string>
-    <string name="alert_windows_notification_message" msgid="8917232109522912560">"Jika Anda tidak ingin <xliff:g id="NAME">%s</xliff:g> menggunakan fitur ini, tap untuk membuka setelan dan menonaktifkannya."</string>
+    <string name="alert_windows_notification_message" msgid="8917232109522912560">"Jika Anda tidak ingin <xliff:g id="NAME">%s</xliff:g> menggunakan fitur ini, ketuk untuk membuka setelan dan menonaktifkannya."</string>
     <string name="alert_windows_notification_turn_off_action" msgid="2902891971380544651">"Nonaktifkan"</string>
     <string name="ext_media_checking_notification_title" msgid="4411133692439308924">"Memeriksa <xliff:g id="NAME">%s</xliff:g>…"</string>
     <string name="ext_media_checking_notification_message" msgid="410185170877285434">"Meninjau konten saat ini"</string>
@@ -1590,8 +1586,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"Luncurkan Browser?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Terima panggilan?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Selalu"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"Setel untuk selalu membuka"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Hanya sekali"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"Setelan"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s tidak mendukung profil kerja"</string>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index 3d2acd9..572313a 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"Færðu símann til vinstri."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"Færðu símann til hægri."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"Horfðu beint á tækið."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"Sé ekki andlit þitt. Horfðu á símann."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"Hafðu andlitið beint fyrir framan símann."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"Of mikil hreyfing. Haltu símanum stöðugum."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"Skráðu nafnið þitt aftur."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"Andlit þekkist ekki lengur. Reyndu aftur."</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"Opna með"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Opna með %1$s"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"Opna"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"Opna <xliff:g id="HOST">%1$s</xliff:g> tengla með"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"Opna tengla með"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"Opna tengla með <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"Opna <xliff:g id="HOST">%1$s</xliff:g> tengla með <xliff:g id="APPLICATION">%2$s</xliff:g>"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"Veita aðgang"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"Breyta með"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Breyta með %1$s"</string>
@@ -1591,8 +1587,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"Opna vafra?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Samþykkja símtal?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Alltaf"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"Stilla á „Alltaf opið“"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Bara einu sinni"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"Stillingar"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s styður ekki vinnusnið"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 6d1d132..6c579b8 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -325,7 +325,7 @@
     <string name="capability_desc_canPerformGestures" msgid="8296373021636981249">"Consente di toccare, far scorrere, pizzicare ed eseguire altri gesti."</string>
     <string name="capability_title_canCaptureFingerprintGestures" msgid="6309568287512278670">"Gesti con sensore di impronte digitali"</string>
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="4386487962402228670">"È in grado di rilevare i gesti compiuti con il sensore di impronte digitali dei dispositivi."</string>
-    <string name="permlab_statusBar" msgid="7417192629601890791">"disattivare o modificare la barra di stato"</string>
+    <string name="permlab_statusBar" msgid="7417192629601890791">"disattivazione o modifica della barra di stato"</string>
     <string name="permdesc_statusBar" msgid="8434669549504290975">"Consente all\'applicazione di disattivare la barra di stato o di aggiungere e rimuovere icone di sistema."</string>
     <string name="permlab_statusBarService" msgid="4826835508226139688">"ruolo di barra di stato"</string>
     <string name="permdesc_statusBarService" msgid="716113660795976060">"Consente di visualizzare l\'applicazione nella barra di stato."</string>
@@ -337,7 +337,7 @@
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Consente all\'applicazione di rimuovere le scorciatoie della schermata Home automaticamente."</string>
     <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"reindirizzamento chiamate in uscita"</string>
     <string name="permdesc_processOutgoingCalls" msgid="5156385005547315876">"Consente all\'app di rilevare il numero digitato durante una chiamata in uscita, con la possibilità di reindirizzare la telefonata a un numero diverso o interromperla del tutto."</string>
-    <string name="permlab_answerPhoneCalls" msgid="4077162841226223337">"rispondi a telefonate in arrivo"</string>
+    <string name="permlab_answerPhoneCalls" msgid="4077162841226223337">"risposta a telefonate in arrivo"</string>
     <string name="permdesc_answerPhoneCalls" msgid="2901889867993572266">"Consente all\'app di rispondere a una telefonata in arrivo."</string>
     <string name="permlab_receiveSms" msgid="8673471768947895082">"ricezione messaggi di testo (SMS)"</string>
     <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>
@@ -347,7 +347,7 @@
     <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="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">"inviare e visualizzare SMS"</string>
+    <string name="permlab_sendSms" msgid="7544599214260982981">"invio e visualizzazione di SMS"</string>
     <string name="permdesc_sendSms" msgid="7094729298204937667">"Consente all\'applicazione di inviare messaggi SMS. Ciò potrebbe comportare costi imprevisti. Applicazioni dannose potrebbero generare dei costi inviando messaggi senza la tua conferma."</string>
     <string name="permlab_readSms" msgid="8745086572213270480">"lettura messaggi di testo personali (SMS o MMS)"</string>
     <string name="permdesc_readSms" product="tablet" msgid="4741697454888074891">"Questa app può leggere tutti i messaggi di testo (SMS) memorizzati sul tablet."</string>
@@ -375,7 +375,7 @@
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Consente all\'applicazione di rendere persistenti in memoria alcune sue parti. Ciò può limitare la memoria disponibile per altre applicazioni, rallentando il tablet."</string>
     <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Consente all\'app di rendere alcune sue parti persistenti nella memoria. Potrebbe così essere limitata la memoria a disposizione di altre app ed essere rallentata la TV."</string>
     <string name="permdesc_persistentActivity" product="default" msgid="4384760047508278272">"Consente all\'applicazione di rendere persistenti in memoria alcune sue parti. Ciò può limitare la memoria disponibile per altre applicazioni, rallentando il telefono."</string>
-    <string name="permlab_foregroundService" msgid="3310786367649133115">"esegui servizio in primo piano"</string>
+    <string name="permlab_foregroundService" msgid="3310786367649133115">"esecuzione servizio in primo piano"</string>
     <string name="permdesc_foregroundService" msgid="6471634326171344622">"Consente all\'app di utilizzare i servizi in primo piano."</string>
     <string name="permlab_getPackageSize" msgid="7472921768357981986">"calcolo spazio di archiviazione applicazioni"</string>
     <string name="permdesc_getPackageSize" msgid="3921068154420738296">"Consente all\'applicazione di recuperare il suo codice, i suoi dati e le dimensioni della cache"</string>
@@ -405,7 +405,7 @@
     <string name="permdesc_writeCallLog" product="default" msgid="683941736352787842">"Consente all\'applicazione di modificare il registro chiamate del telefono, inclusi i dati sulle chiamate in arrivo e in uscita. Le applicazioni dannose potrebbero farne uso per cancellare o modificare il registro chiamate."</string>
     <string name="permlab_bodySensors" msgid="4683341291818520277">"accesso ai sensori (come il cardiofrequenzimetro)"</string>
     <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Consente all\'app di accedere ai dati relativi ai sensori che monitorano le tue condizioni fisiche, ad esempio la frequenza cardiaca."</string>
-    <string name="permlab_readCalendar" msgid="6716116972752441641">"Leggi eventi di calendario e dettagli"</string>
+    <string name="permlab_readCalendar" msgid="6716116972752441641">"lettura di eventi di calendario e dettagli"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="4993979255403945892">"Questa app può leggere tutti gli eventi di calendario memorizzati sul tablet e condividere o salvare i dati di calendario."</string>
     <string name="permdesc_readCalendar" product="tv" msgid="8837931557573064315">"Questa app può leggere tutti gli eventi di calendario memorizzati sulla TV e condividere o salvare i dati di calendario."</string>
     <string name="permdesc_readCalendar" product="default" msgid="4373978642145196715">"Questa app può leggere tutti gli eventi di calendario memorizzati sul telefono e condividere o salvare i dati di calendario."</string>
@@ -415,9 +415,9 @@
     <string name="permdesc_writeCalendar" product="default" msgid="7592791790516943173">"Questa app può aggiungere, rimuovere o modificare eventi di calendario sul telefono. Può inviare messaggi che possono sembrare inviati dai proprietari del calendario o modificare eventi senza notificare i proprietari."</string>
     <string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"accesso a comandi aggiuntivi provider di geolocalizz."</string>
     <string name="permdesc_accessLocationExtraCommands" msgid="6078307221056649927">"Consente all\'app di accedere a ulteriori comandi del fornitore di posizione. Ciò potrebbe consentire all\'app di interferire con il funzionamento del GPS o di altre fonti di geolocalizzazione."</string>
-    <string name="permlab_accessFineLocation" msgid="6265109654698562427">"Accesso alla posizione esatta solo in primo piano"</string>
+    <string name="permlab_accessFineLocation" msgid="6265109654698562427">"accesso alla posizione esatta solo in primo piano"</string>
     <string name="permdesc_accessFineLocation" msgid="3520508381065331098">"Questa app può recuperare la tua posizione esatta solo quando è in primo piano. Questi servizi di geolocalizzazione devono essere attivi e disponibili sul telefono affinché l\'app possa usarli. Potrebbe aumentare il consumo della batteria."</string>
-    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"Accesso alla posizione approssimativa (in base alla rete) solo in primo piano"</string>
+    <string name="permlab_accessCoarseLocation" msgid="3707180371693213469">"accesso alla posizione approssimativa (in base alla rete) solo in primo piano"</string>
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="8594719010575779120">"Questa app può recuperare la tua posizione tramite fonti di rete quali ripetitori di telefonia mobile e reti Wi-Fi, ma soltanto quando l\'app è in primo piano. Questi servizi di geolocalizzazione devono essere attivi e disponibili sul tablet affinché l\'app possa usarli."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="3027871910200890806">"Questa app può recuperare la tua posizione tramite fonti di rete quali ripetitori di telefonia mobile e reti Wi-Fi, ma soltanto quando l\'app è in primo piano. Questi servizi di geolocalizzazione devono essere attivi e disponibili sulla TV affinché l\'app possa usarli."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="854896049371048754">"Questa app può recuperare la tua posizione tramite fonti di rete quali ripetitori di telefonia mobile e reti Wi-Fi, ma soltanto quando l\'app è in primo piano. Questi servizi di geolocalizzazione devono essere attivi e disponibili sul telefono affinché l\'app possa usarli."</string>
@@ -425,7 +425,7 @@
     <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Se concedi l\'autorizzazione insieme all\'accesso alla posizione precisa o approssimativa, l\'app potrà accedere alla posizione mentre viene eseguita in background."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"modifica impostazioni audio"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Consente all\'applicazione di modificare le impostazioni audio globali, come il volume e quale altoparlante viene utilizzato per l\'uscita."</string>
-    <string name="permlab_recordAudio" msgid="3876049771427466323">"registrare audio"</string>
+    <string name="permlab_recordAudio" msgid="3876049771427466323">"registrazione audio"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"Questa app può registrare audio tramite il microfono in qualsiasi momento."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"invio di comandi alla SIM"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Consente all\'app di inviare comandi alla SIM. Questo è molto pericoloso."</string>
@@ -437,7 +437,7 @@
     <string name="permdesc_vibrate" msgid="6284989245902300945">"Consente all\'applicazione di controllare la vibrazione."</string>
     <string name="permlab_callPhone" msgid="3925836347681847954">"chiamata diretta n. telefono"</string>
     <string name="permdesc_callPhone" msgid="3740797576113760827">"Consente all\'applicazione di chiamare numeri di telefono senza il tuo intervento. Ciò può comportare chiamate o addebiti imprevisti. Tieni presente che ciò non consente all\'applicazione di chiamare numeri di emergenza. Applicazioni dannose potrebbero generare dei costi effettuando chiamate senza la tua conferma."</string>
-    <string name="permlab_accessImsCallService" msgid="3574943847181793918">"Accesso al servizio di chiamata IMS"</string>
+    <string name="permlab_accessImsCallService" msgid="3574943847181793918">"accesso al servizio di chiamata IMS"</string>
     <string name="permdesc_accessImsCallService" msgid="8992884015198298775">"Consente all\'app di utilizzare il servizio IMS per fare chiamate senza il tuo intervento."</string>
     <string name="permlab_readPhoneState" msgid="9178228524507610486">"lettura stato e identità telefono"</string>
     <string name="permdesc_readPhoneState" msgid="1639212771826125528">"Consente all\'applicazione di accedere alle funzioni telefoniche del dispositivo. Questa autorizzazione consente all\'applicazione di determinare il numero di telefono e gli ID dei dispositivi, se una chiamata è attiva e il numero remoto connesso da una chiamata."</string>
@@ -445,12 +445,12 @@
     <string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"Consente all\'app di indirizzare le proprie chiamate tramite il sistema al fine di migliorare l\'esperienza di chiamata."</string>
     <string name="permlab_callCompanionApp" msgid="3599252979411970473">"visualizzazione e controllo delle chiamate tramite il sistema."</string>
     <string name="permdesc_callCompanionApp" msgid="4567344683275099090">"Consente all\'app di visualizzare e controllare le chiamate in corso sul dispositivo. Sono incluse informazioni quali i numeri e lo stato relativi alle chiamate."</string>
-    <string name="permlab_acceptHandover" msgid="2661534649736022409">"Continuazione di una chiamata da un\'altra app"</string>
+    <string name="permlab_acceptHandover" msgid="2661534649736022409">"continuazione di una chiamata da un\'altra app"</string>
     <string name="permdesc_acceptHandovers" msgid="4570660484220539698">"Consente all\'app di continuare una chiamata che è stata iniziata in un\'altra app."</string>
     <string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"lettura dei numeri di telefono"</string>
     <string name="permdesc_readPhoneNumbers" msgid="8559488833662272354">"Consente all\'app di accedere ai numeri di telefono del dispositivo."</string>
     <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"disattivazione stand-by del tablet"</string>
-    <string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"divieto di attivazione della modalità di sospensione della TV"</string>
+    <string name="permlab_wakeLock" product="tv" msgid="2601193288949154131">"disattivazione della modalità di sospensione della TV"</string>
     <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"disattivazione stand-by del telefono"</string>
     <string name="permdesc_wakeLock" product="tablet" msgid="7311319824400447868">"Consente all\'applicazione di impedire lo stand-by del tablet."</string>
     <string name="permdesc_wakeLock" product="tv" msgid="3208534859208996974">"Consente all\'app di impedire l\'attivazione della modalità di sospensione della TV."</string>
@@ -483,7 +483,7 @@
     <string name="permdesc_accessWifiState" msgid="5002798077387803726">"Consente all\'applicazione di visualizzare informazioni sulle reti Wi-Fi, ad esempio di rilevare se il Wi-Fi è abilitato e il nome dei dispositivi Wi-Fi connessi."</string>
     <string name="permlab_changeWifiState" msgid="6550641188749128035">"connessione e disconnessione dal Wi-Fi"</string>
     <string name="permdesc_changeWifiState" msgid="7137950297386127533">"Consente all\'applicazione di connettersi/disconnettersi da punti di accesso Wi-Fi e di apportare modifiche alla configurazione del dispositivo per le reti Wi-Fi."</string>
-    <string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"consenti ricezione multicast Wi-Fi"</string>
+    <string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"ricezione multicast Wi-Fi"</string>
     <string name="permdesc_changeWifiMulticastState" product="tablet" msgid="7969774021256336548">"Consente all\'applicazione di ricevere pacchetti inviati a tutti i dispositivi su una rete Wi-Fi utilizzando indirizzi multicast, non solo il tuo tablet. Viene consumata più batteria rispetto alla modalità non multicast."</string>
     <string name="permdesc_changeWifiMulticastState" product="tv" msgid="9031975661145014160">"Consente all\'app di ricevere pacchetti inviati a tutti i dispositivi tramite una rete Wi-Fi utilizzando indirizzi multicast, non soltanto la TV. Questa modalità consuma più energia della modalità non multicast."</string>
     <string name="permdesc_changeWifiMulticastState" product="default" msgid="6851949706025349926">"Consente all\'applicazione di ricevere pacchetti inviati a tutti i dispositivi su una rete Wi-Fi utilizzando indirizzi multicast, non solo il tuo telefono. Viene consumata più batteria rispetto alla modalità non multicast."</string>
@@ -505,21 +505,21 @@
     <string name="permdesc_nfc" msgid="7120611819401789907">"Consente all\'applicazione di comunicare con tag, schede e lettori NFC (Near Field Communication)."</string>
     <string name="permlab_disableKeyguard" msgid="3598496301486439258">"disattivazione blocco schermo"</string>
     <string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Consente all\'applicazione di disattivare il blocco tastiera ed eventuali protezioni tramite password associate. Ad esempio, il telefono disattiva il blocco tastiera quando riceve una telefonata in arrivo e lo riattiva al termine della chiamata."</string>
-    <string name="permlab_requestPasswordComplexity" msgid="202650535669249674">"richiedi complessità del blocco schermo"</string>
+    <string name="permlab_requestPasswordComplexity" msgid="202650535669249674">"richiesta di complessità del blocco schermo"</string>
     <string name="permdesc_requestPasswordComplexity" msgid="4730994229754212347">"Consente all\'app di conoscere il livello di complessità del blocco schermo (alto, medio, basso o nessuno), che indica l\'intervallo di caratteri possibile e il tipo di blocco schermo. L\'app può inoltre suggerire agli utenti di aggiornare il blocco schermo a un livello specifico di complessità, ma gli utenti possono ignorare liberamente il suggerimento e uscire. Tieni presente che il blocco schermo non viene memorizzato come testo non crittografato, quindi l\'app non conosce la password esatta."</string>
-    <string name="permlab_useBiometric" msgid="8837753668509919318">"Utilizzo di hardware biometrico"</string>
+    <string name="permlab_useBiometric" msgid="8837753668509919318">"utilizzo di hardware biometrico"</string>
     <string name="permdesc_useBiometric" msgid="8389855232721612926">"Consente all\'app di utilizzare hardware biometrico per eseguire l\'autenticazione"</string>
-    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"gestisci hardware per il riconoscimento delle impronte digitali"</string>
+    <string name="permlab_manageFingerprint" msgid="5640858826254575638">"gestione di hardware per il riconoscimento delle impronte digitali"</string>
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Consente all\'app di richiamare metodi per aggiungere e rimuovere modelli di impronte digitali da utilizzare."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"utilizzo di hardware per il riconoscimento delle impronte digitali"</string>
     <string name="permdesc_useFingerprint" msgid="9165097460730684114">"Consente all\'app di utilizzare l\'hardware per il riconoscimento delle impronte digitali per eseguire l\'autenticazione"</string>
-    <string name="permlab_audioWrite" msgid="2661772059799779292">"Modifica della tua raccolta musicale"</string>
+    <string name="permlab_audioWrite" msgid="2661772059799779292">"modifica della tua raccolta musicale"</string>
     <string name="permdesc_audioWrite" msgid="8888544708166230494">"Consente all\'app di modificare la tua raccolta musicale."</string>
-    <string name="permlab_videoWrite" msgid="128769316366746446">"Modifica della tua raccolta di video"</string>
+    <string name="permlab_videoWrite" msgid="128769316366746446">"modifica della tua raccolta di video"</string>
     <string name="permdesc_videoWrite" msgid="5448565757490640841">"Consente all\'app di modificare la tua raccolta di video."</string>
-    <string name="permlab_imagesWrite" msgid="3391306186247235510">"Modifica della tua raccolta di foto"</string>
+    <string name="permlab_imagesWrite" msgid="3391306186247235510">"modifica della tua raccolta di foto"</string>
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Consente all\'app di modificare la tua raccolta di foto."</string>
-    <string name="permlab_mediaLocation" msgid="8675148183726247864">"Lettura delle posizioni dalla tua raccolta multimediale"</string>
+    <string name="permlab_mediaLocation" msgid="8675148183726247864">"lettura delle posizioni dalla tua raccolta multimediale"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Consente all\'app di leggere le posizioni dalla tua raccolta multimediale."</string>
     <string name="biometric_dialog_default_title" msgid="881952973720613213">"Verifica la tua identità"</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Hardware biometrico non disponibile"</string>
@@ -551,9 +551,9 @@
   <string-array name="fingerprint_error_vendor">
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"Icona dell\'impronta digitale"</string>
-    <string name="permlab_manageFace" msgid="7262837876352591553">"gestisci l\'hardware per Sblocco col sorriso"</string>
+    <string name="permlab_manageFace" msgid="7262837876352591553">"gestione dell\'hardware per Sblocco col sorriso"</string>
     <string name="permdesc_manageFace" msgid="8919637120670185330">"Consente all\'app di richiamare i metodi per aggiungere e rimuovere i modelli di volti."</string>
-    <string name="permlab_useFaceAuthentication" msgid="2565716575739037572">"utilizza l\'hardware per Sblocco col sorriso"</string>
+    <string name="permlab_useFaceAuthentication" msgid="2565716575739037572">"utilizzo dell\'hardware per Sblocco col sorriso"</string>
     <string name="permdesc_useFaceAuthentication" msgid="4712947955047607722">"Consente all\'app di utilizzare hardware per l\'autenticazione con Sblocco col sorriso"</string>
     <string name="face_recalibrate_notification_name" msgid="1913676850645544352">"Sblocco col sorriso"</string>
     <string name="face_recalibrate_notification_title" msgid="4087620069451499365">"Registra di nuovo il volto"</string>
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"Sposta il telefono verso sinistra."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"Sposta il telefono verso destra."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"Guarda più direttamente verso il dispositivo."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"Impossibile vedere il volto. Guarda il telefono."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"Posiziona il viso davanti al telefono."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"Troppo movimento. Tieni fermo il telefono."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"Ripeti l\'acquisizione del volto."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"Non è più possibile riconoscere il volto. Riprova."</string>
@@ -600,21 +600,21 @@
     <string name="permdesc_writeSyncSettings" msgid="8956262591306369868">"Consente a un\'applicazione di modificare le impostazioni di sincronizzazione per un account. Ad esempio, può servire per attivare la sincronizzazione dell\'applicazione Persone con un account."</string>
     <string name="permlab_readSyncStats" msgid="7396577451360202448">"lettura statistiche di sincronizz."</string>
     <string name="permdesc_readSyncStats" msgid="1510143761757606156">"Consente a un\'applicazione di leggere le statistiche di sincronizzazione per un account, incluse la cronologia degli eventi di sincronizzazione e la quantità di dati sincronizzati."</string>
-    <string name="permlab_sdcardRead" msgid="1438933556581438863">"leggere i contenuti dell\'archivio condiviso"</string>
+    <string name="permlab_sdcardRead" msgid="1438933556581438863">"lettura dei contenuti dell\'archivio condiviso"</string>
     <string name="permdesc_sdcardRead" msgid="1804941689051236391">"Consente all\'app di leggere i contenuti del tuo archivio condiviso."</string>
-    <string name="permlab_sdcardWrite" msgid="9220937740184960897">"modificare/eliminare i contenuti dell\'archivio condiviso"</string>
+    <string name="permlab_sdcardWrite" msgid="9220937740184960897">"modifica/eliminazione dei contenuti dell\'archivio condiviso"</string>
     <string name="permdesc_sdcardWrite" msgid="2834431057338203959">"Consente all\'app di modificare i contenuti del tuo archivio condiviso."</string>
-    <string name="permlab_use_sip" msgid="2052499390128979920">"fare/ricevere chiamate SIP"</string>
+    <string name="permlab_use_sip" msgid="2052499390128979920">"invio/ricezione di chiamate SIP"</string>
     <string name="permdesc_use_sip" msgid="2297804849860225257">"Consente all\'app di effettuare e ricevere chiamate SIP."</string>
     <string name="permlab_register_sim_subscription" msgid="3166535485877549177">"registrazione di nuove connessioni SIM di telecomunicazione"</string>
     <string name="permdesc_register_sim_subscription" msgid="2138909035926222911">"Consente all\'app di registrare nuove connessioni SIM di telecomunicazione."</string>
     <string name="permlab_register_call_provider" msgid="108102120289029841">"registrazione di nuove connessioni di telecomunicazione"</string>
     <string name="permdesc_register_call_provider" msgid="7034310263521081388">"Consente all\'app di registrare nuove connessioni di telecomunicazione."</string>
-    <string name="permlab_connection_manager" msgid="1116193254522105375">"gestisci connessioni di telecomunicazione"</string>
+    <string name="permlab_connection_manager" msgid="1116193254522105375">"gestione di connessioni di telecomunicazione"</string>
     <string name="permdesc_connection_manager" msgid="5925480810356483565">"Consente all\'app di gestire connessioni di telecomunicazione."</string>
     <string name="permlab_bind_incall_service" msgid="6773648341975287125">"interazione con lo schermo durante una chiamata"</string>
     <string name="permdesc_bind_incall_service" msgid="8343471381323215005">"Consente all\'app di stabilire quando e come l\'utente vede lo schermo durante una chiamata."</string>
-    <string name="permlab_bind_connection_service" msgid="3557341439297014940">"interagire con i servizi di telefonia"</string>
+    <string name="permlab_bind_connection_service" msgid="3557341439297014940">"interazione con i servizi di telefonia"</string>
     <string name="permdesc_bind_connection_service" msgid="4008754499822478114">"Consente all\'app di interagire con i servizi di telefonia per effettuare/ricevere chiamate."</string>
     <string name="permlab_control_incall_experience" msgid="9061024437607777619">"offerta di un\'esperienza utente durante le chiamate"</string>
     <string name="permdesc_control_incall_experience" msgid="915159066039828124">"Consente all\'app di offrire un\'esperienza utente durante le chiamate."</string>
@@ -630,7 +630,7 @@
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Consente al titolare di vincolarsi all\'interfaccia di primo livello di un servizio listener di notifica. Non dovrebbe mai essere necessaria per le normali applicazioni."</string>
     <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"collegamento a un servizio provider di condizioni"</string>
     <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Consente al titolare di collegarsi all\'interfaccia di primo livello di un servizio provider di condizioni. Non dovrebbe essere mai necessaria per le normali app."</string>
-    <string name="permlab_bindDreamService" msgid="4153646965978563462">"associa a servizio dream"</string>
+    <string name="permlab_bindDreamService" msgid="4153646965978563462">"associazione a servizio dream"</string>
     <string name="permdesc_bindDreamService" msgid="7325825272223347863">"Consente all\'utente di associare l\'interfaccia di primo livello di un servizio dream. Questa impostazione non è mai necessaria per le app normali."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"richiamo dell\'app di configurazione operatore-provider"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Consente al titolare di richiamare l\'app di configurazione dell\'operatore-provider. Non dovrebbe essere mai necessaria per le normali applicazioni."</string>
@@ -646,7 +646,7 @@
     <string name="permdesc_removeDrmCertificates" msgid="7272999075113400993">"Consente a un\'applicazione di rimuovere certificati DRM. Non dovrebbe mai essere necessaria per le normali applicazioni."</string>
     <string name="permlab_bindCarrierMessagingService" msgid="1490229371796969158">"associazione a un servizio di messaggi dell\'operatore"</string>
     <string name="permdesc_bindCarrierMessagingService" msgid="2762882888502113944">"Consente l\'associazione di un servizio di messaggi dell\'operatore all\'interfaccia principale. Non dovrebbe mai essere necessaria per le normali applicazioni."</string>
-    <string name="permlab_bindCarrierServices" msgid="3233108656245526783">"Collegamento a servizi dell\'operatore"</string>
+    <string name="permlab_bindCarrierServices" msgid="3233108656245526783">"associazione a servizi dell\'operatore"</string>
     <string name="permdesc_bindCarrierServices" msgid="1391552602551084192">"Consente al titolare di collegarsi a servizi dell\'operatore. Non dovrebbe mai essere necessaria per le normali app."</string>
     <string name="permlab_access_notification_policy" msgid="4247510821662059671">"accesso alla funzione Non disturbare"</string>
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Consente all\'app di leggere e modificare la configurazione della funzione Non disturbare."</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"Apri con"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Apri con %1$s"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"Apri"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"Apri i link <xliff:g id="HOST">%1$s</xliff:g> con"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"Apri i link con"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"Apri i link con <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"Apri i link <xliff:g id="HOST">%1$s</xliff:g> con <xliff:g id="APPLICATION">%2$s</xliff:g>"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"Fornisci accesso"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"Modifica con"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Modifica con %1$s"</string>
@@ -1434,7 +1430,7 @@
     <string name="permdesc_requestInstallPackages" msgid="5740101072486783082">"Consente a un\'applicazione di richiedere l\'installazione di pacchetti."</string>
     <string name="permlab_requestDeletePackages" msgid="1703686454657781242">"richiesta di eliminazione dei pacchetti"</string>
     <string name="permdesc_requestDeletePackages" msgid="3406172963097595270">"Consente a un\'applicazione di richiedere l\'eliminazione di pacchetti."</string>
-    <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"chiedi di ignorare le ottimizzazioni della batteria"</string>
+    <string name="permlab_requestIgnoreBatteryOptimizations" msgid="8021256345643918264">"richiesta di ignorare le ottimizzazioni della batteria"</string>
     <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="8359147856007447638">"Consente a un\'app di chiedere l\'autorizzazione a ignorare le ottimizzazioni della batteria per quell\'app."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"Tocca due volte per il comando dello zoom"</string>
     <string name="gadget_host_error_inflating" msgid="4882004314906466162">"Aggiunta del widget non riuscita."</string>
@@ -1590,8 +1586,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"Avviare l\'applicazione Browser?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Accettare la chiamata?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Sempre"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"Imposta per aprire sempre"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Solo una volta"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"Impostazioni"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s non supporta il profilo di lavoro"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 8add3d7..437b31b 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -574,7 +574,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"צריך להזיז את הטלפון שמאלה."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"צריך להזיז את הטלפון ימינה."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"יש להביט ישירות אל המכשיר."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"אי אפשר לראות את הפנים שלך. צריך להביט אל הטלפון."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"עליך למקם את הפנים ישירות מול הטלפון."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"יותר מדי תנועה. יש להחזיק את הטלפון בצורה יציבה."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"יש לרשום מחדש את הפנים."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"כבר לא ניתן לזהות פנים. יש לנסות שוב."</string>
@@ -1171,14 +1171,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"פתח באמצעות"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"‏פתח באמצעות %1$s"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"פתח"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"פתיחת קישורים של <xliff:g id="HOST">%1$s</xliff:g> באמצעות"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"פתיחת קישורים באמצעות"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"פתיחת קישורים באמצעות <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"פתיחת קישורים של <xliff:g id="HOST">%1$s</xliff:g> באמצעות <xliff:g id="APPLICATION">%2$s</xliff:g>"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"הענקת גישה"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"ערוך באמצעות"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"‏ערוך באמצעות %1$s"</string>
@@ -1636,8 +1632,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"להפעיל את הדפדפן?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"האם לקבל את השיחה?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"תמיד"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"הגדרה כברירת מחדל לפתיחה"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"רק פעם אחת"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"הגדרות"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"‏%1$s אינו תומך בפרופיל עבודה"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 2d09d67..b558a31 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"スマートフォンを左に動かしてください。"</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"スマートフォンを右に動かしてください。"</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"もっとまっすぐデバイスに顔を向けてください。"</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"顔を確認できません。スマートフォンを見てください。"</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"顔をスマートフォンの真正面に向けてください。"</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"あまり動かさないでください。安定させてください。"</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"顔を登録し直してください。"</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"顔を認識できなくなりました。もう一度お試しください。"</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"アプリで開く"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"%1$sで開く"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"開く"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"<xliff:g id="HOST">%1$s</xliff:g> のリンクを開くブラウザ / アプリの選択"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"リンクを開くブラウザの選択"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"<xliff:g id="APPLICATION">%1$s</xliff:g> でリンクを開く"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"<xliff:g id="APPLICATION">%2$s</xliff:g> で <xliff:g id="HOST">%1$s</xliff:g> のリンクを開く"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"アクセス権を付与"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"編集に使用"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"%1$sで編集"</string>
@@ -1590,8 +1586,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"ブラウザを起動しますか?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"通話を受けますか?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"常時"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"[常に開く] に設定"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"1回のみ"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"設定"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$sは仕事用プロファイルをサポートしていません"</string>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index f810678..3570d4c 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"გადაანაცვლეთ ტელეფონი მარცხნივ."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"გადაანაცვლეთ ტელეფონი მარჯვნივ."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"გთხოვთ, უფრო პირდაპირ შეხედოთ თქვენს მოწყობილობას."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"თქვენი სახე არ ჩანს. შეხედეთ ტელეფონს."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"დაიჭირეთ სახე უშუალოდ ტელეფონის წინ."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"მეტისმეტად მოძრაობთ. მყარად დაიჭირეთ ტელეფონი."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"გთხოვთ, ხელახლა დაარეგისტრიროთ თქვენი სახე."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"სახის ამოცნობა ვეღარ ხერხდება. ცადეთ ხელახლა."</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"გახსნა აპით"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"%1$s-ით გახსნა"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"გახსნა"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"<xliff:g id="HOST">%1$s</xliff:g> ბმულების გახსნა შემდეგით:"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"ბმულების გახსნა შემდეგით:"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"ბმულების გახსნა <xliff:g id="APPLICATION">%1$s</xliff:g>-ით"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"<xliff:g id="HOST">%1$s</xliff:g> ბმულების <xliff:g id="APPLICATION">%2$s</xliff:g>-ით გახსნა"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"წვდომის მინიჭება"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"რედაქტირება აპით:"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"რედაქტირება %1$s-ით"</string>
@@ -1590,8 +1586,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"გსურთ ბრაუზერის გაშვება?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"უპასუხებთ ზარს?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"ყოველთვის"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"ყოველთვის გახსნის დაყენება"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"მხოლოდ ერთხელ"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"პარამეტრები"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s მხარს არ უჭერს სამუშაო პროფილს"</string>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index 3c42986..2ed1e5b 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"Телефонды солға жылжытыңыз."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"Телефонды оңға жылжытыңыз."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"Құрылғының камерасына тура қараңыз."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"Бетіңіз көрінбейді. Телефонға қараңыз."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"Бетіңізді телефонға тура қаратыңыз."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"Қозғалыс тым көп. Телефонды қозғалтпаңыз."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"Қайта тіркеліңіз."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"Енді бет анықтау мүмкін емес. Әрекетті қайталаңыз."</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"Басқаша ашу"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"%1$s қолданбасымен ашу"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"Ашу"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"<xliff:g id="HOST">%1$s</xliff:g> сілтемелерін келесімен ашу:"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"Сілтемелерді келесімен ашу:"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"Сілтемелерді <xliff:g id="APPLICATION">%1$s</xliff:g> браузерімен ашу"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"<xliff:g id="HOST">%1$s</xliff:g> сілтемелерін <xliff:g id="APPLICATION">%2$s</xliff:g> браузерімен ашу"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"Рұқсат беру"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"Келесімен өңдеу"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"%1$s көмегімен өңдеу"</string>
@@ -1591,8 +1587,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"Браузер қосылсын ба?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Қоңырауды қабылдау?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Үнемі"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"Әрдайым ашық күйге орнату"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Бір рет қана"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"Параметрлер"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s жұмыс профилін қолдамайды"</string>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index b088f4e..02c6ba8 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"ផ្លាស់ទី​ទូរសព្ទទៅខាងឆ្វេង។"</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"ផ្លាស់ទីទូរសព្ទទៅខាងស្ដាំ។"</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"សូមមើល​ឱ្យចំ​ឧបករណ៍​របស់អ្នក​ជាងមុន។"</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"មើលមិនឃើញ​មុខ​របស់អ្នកទេ។ សូមសម្លឹងមើល​ទូរសព្ទ។"</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"បែរមុខ​របស់អ្នក​ឱ្យចំ​ពីមុខ​ទូរសព្ទ​ផ្ទាល់។"</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"មាន​ចលនា​ខ្លាំងពេក។ សូមកាន់​ទូរសព្ទ​ឱ្យនឹង។"</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"សូម​​ស្កេន​បញ្ចូល​មុខរបស់អ្នក​ម្ដងទៀត។"</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"មិន​អាច​សម្គាល់មុខ​បាន​ទៀតទេ។ សូមព្យាយាមម្ដងទៀត។"</string>
@@ -1133,14 +1133,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"បើក​ជា​មួយ"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"បើក​ជាមួយ %1$s"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"បើក"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"បើក​តំណ <xliff:g id="HOST">%1$s</xliff:g> ជាមួយ"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"បើកតំណជាមួយ"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"បើក​តំណជាមួយ <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"បើក​តំណ <xliff:g id="HOST">%1$s</xliff:g> ជាមួយ <xliff:g id="APPLICATION">%2$s</xliff:g>"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"ផ្តល់​សិទ្ធិ​ចូល​ប្រើ"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"កែសម្រួល​ជាមួយ"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"កែសម្រួល​ជាមួយ​ %1$s"</string>
@@ -1592,8 +1588,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"ចាប់ផ្ដើម​កម្មវិធី​អ៊ីនធឺណិត?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"ទទួល​ការ​ហៅ​?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"ជា​និច្ច"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"កំណត់​ឱ្យ​បើក​ជានិច្ច"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"តែ​ម្ដង"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"ការកំណត់"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s មិន​គាំទ្រ​ប្រវត្តិរូប​ការងារ"</string>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index 6da7eec..875ecd4 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"ಫೋನ್ ಅನ್ನು ಎಡಕ್ಕೆ ಸರಿಸಿ."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"ಫೋನ್ ಅನ್ನು ಬಲಕ್ಕೆ ಸರಿಸಿ."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿ ಹೆಚ್ಚಿನದ್ದನ್ನು ನೇರವಾಗಿ ನೋಡಿ."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"ನಿಮ್ಮ ಮುಖ ಕಾಣಿಸುತ್ತಿಲ್ಲ. ಫೋನ್ ಕಡೆಗೆ ನೋಡಿ."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"ನಿಮ್ಮ ಮುಖವನ್ನು ಫೋನ್‌ಗೆ ನೇರವಾಗಿ ಇರಿಸಿ."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"ತುಂಬಾ ಅಲುಗಾಡುತ್ತಿದೆ ಫೋನ್ ಅನ್ನು ಸ್ಥಿರವಾಗಿ ಹಿಡಿಯಿರಿ."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"ನಿಮ್ಮ ಮುಖವನ್ನು ಮರುನೋಂದಣಿ ಮಾಡಿ."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"ಮುಖ ಗುರುತಿಸಲು ಸಾಧ್ಯವಾಗುವುದಿಲ್ಲ. ಪುನಃ ಪ್ರಯತ್ನಿಸಿ."</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"ಇದರ ಮೂಲಕ ತೆರೆಯಿರಿ"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"%1$s ಜೊತೆಗೆ ತೆರೆಯಿರಿ"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"ತೆರೆ"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"ಇವುಗಳ ಮೂಲಕ <xliff:g id="HOST">%1$s</xliff:g> ಲಿಂಕ್‌ಗಳನ್ನು ತೆರೆಯಿರಿ"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"ಇವುಗಳ ಮೂಲಕ ಲಿಂಕ್‌ಗಳನ್ನು ತೆರೆಯಿರಿ"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"<xliff:g id="APPLICATION">%1$s</xliff:g> ಮೂಲಕ ಲಿಂಕ್‌ಗಳನ್ನು ತೆರೆಯಿರಿ"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"<xliff:g id="APPLICATION">%2$s</xliff:g> ಮೂಲಕ <xliff:g id="HOST">%1$s</xliff:g> ಲಿಂಕ್‌ಗಳನ್ನು ತೆರೆಯಿರಿ"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"ಪ್ರವೇಶ ಅನುಮತಿಸಿ"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"ಇವರ ಜೊತೆಗೆ ಎಡಿಟ್ ಮಾಡಿ"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"%1$s ಜೊತೆಗೆ ಎಡಿಟ್ ಮಾಡಿ"</string>
@@ -1591,8 +1587,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"ಬ್ರೌಸರ್ ಪ್ರಾರಂಭಿಸುವುದೇ?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"ಕರೆ ಸ್ವೀಕರಿಸುವುದೇ?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"ಯಾವಾಗಲೂ"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"ಯಾವಾಗಲೂ ತೆರೆಯುವುದಕ್ಕೆ ಹೊಂದಿಸಿ"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"ಒಮ್ಮೆ ಮಾತ್ರ"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s ಕೆಲಸದ ಪ್ರೊಫೈಲ್ ಅನ್ನು ಬೆಂಬಲಿಸುವುದಿಲ್ಲ"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 853ccff..9077145 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"휴대전화를 왼쪽으로 이동하세요."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"휴대전화를 오른쪽으로 이동하세요."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"기기에서 더 똑바로 바라보세요."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"얼굴이 보이지 않습니다. 휴대전화를 바라보세요."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"휴대전화가 얼굴 정면을 향하도록 두세요."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"너무 많이 움직였습니다. 휴대전화를 흔들리지 않게 잡으세요."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"얼굴을 다시 등록해 주세요."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"더 이상 얼굴을 인식할 수 없습니다. 다시 시도하세요."</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"연결 프로그램"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"%1$s(으)로 열기"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"열기"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"<xliff:g id="HOST">%1$s</xliff:g> 링크를 열 때 사용할 앱"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"링크를 열 때 사용할 앱"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"<xliff:g id="APPLICATION">%1$s</xliff:g> 앱으로 링크 열기"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"<xliff:g id="APPLICATION">%2$s</xliff:g> 앱으로 <xliff:g id="HOST">%1$s</xliff:g> 링크 열기"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"권한 부여"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"편집 프로그램:"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"%1$s(으)로 수정"</string>
@@ -1590,8 +1586,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"브라우저를 실행하시겠습니까?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"통화를 수락하시겠습니까?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"항상"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"항상 열도록 설정"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"한 번만"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"설정"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s에서 직장 프로필을 지원하지 않습니다."</string>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index e5b11ba..8cac363 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"Телефонду солго жылдырыңыз."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"Телефонду оңго жылдырыңыз."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"Түзмөгүңүзгө түз караңыз."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"Жүзүңүз көрүнбөй жатат. Телефонду караңыз."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"Телефонду жүзүңүздүн маңдайында кармаңыз."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"Кыймылдап жибердиңиз. Телефонду түз кармаңыз."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"Жүзүңүздү кайра таанытыңыз."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"Жүз таанылган жок. Кайра аракет кылыңыз."</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"Төмөнкү менен ачуу"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"%1$s менен ачуу"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"Ачуу"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"<xliff:g id="HOST">%1$s</xliff:g> шилтемелерин төмөнкү колдонмодо ачуу:"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"Шилтемелерди төмөнкү колдонмодо ачуу:"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"Шилтемелерди <xliff:g id="APPLICATION">%1$s</xliff:g> колдонмосунда ачуу"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"<xliff:g id="HOST">%1$s</xliff:g> шилтемелерин <xliff:g id="APPLICATION">%2$s</xliff:g> колдонмосунда ачуу"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"Мүмкүнчүлүк берүү"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"Төмөнкү менен түзөтүү"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"%1$s менен түзөтүү"</string>
@@ -1592,8 +1588,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"Серепчи иштетилсинби?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Чалуу кабыл алынсынбы?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Дайыма"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"Ар дайым ачылсын деп жөндөө"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Бир жолу гана"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"Жөндөөлөр"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s жумуш профилин колдоого албайт"</string>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index 74b311a..47b0fe4 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"ຍ້າຍໂທລະສັບໄປທາງຊ້າຍ."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"ຍ້າຍໂທລະສັບໄປທາງຂວາ."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"ກະລຸນາເບິ່ງອຸປະກອນຂອງທ່ານໃຫ້ຊື່ໆ."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"ບໍ່ສາມາດເບິ່ງເຫັນໜ້າຂອງທ່ານໄດ້. ກະລຸນາເບິ່ງໂທລະສັບ."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"ຫັນໜ້າຂອງທ່ານໄປໃສ່ໜ້າໂທລະສັບໂດຍກົງ."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"ເຄື່ອນໄຫວຫຼາຍເກີນໄປ. ກະລຸນາຖືໂທລະສັບໄວ້ຊື່ໆ."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"ກະລຸນາລົງທະບຽນອຸປະກອນຂອງທ່ານອີກເທື່ອໜຶ່ງ."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"ບໍ່ສາມາດຈຳແນກໃບໜ້າໄດ້ອີກຕໍ່ໄປ. ກະລຸນາລອງໃໝ່."</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"ເປີດໂດຍໃຊ້"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"ເປີດ​ໂດຍ​ໃຊ້ %1$s"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"ເປີດ"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"ເປີດລິ້ງ <xliff:g id="HOST">%1$s</xliff:g> ໂດຍໃຊ້"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"ເປີດລິ້ງໂດຍໃຊ້"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"ເປີດລິ້ງໂດຍໃຊ້ <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"ເປີດລິ້ງ <xliff:g id="HOST">%1$s</xliff:g> ໂດຍໃຊ້ <xliff:g id="APPLICATION">%2$s</xliff:g>"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"ໃຫ້ສິດອະນຸຍາດ"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"​ແກ້​ໄຂ​ໃນ"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"ແກ້​ໄຂ​ໃນ %1$s"</string>
@@ -1590,8 +1586,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"ເປີດໂປຣແກຣມທ່ອງເວັບ?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"ຮັບການໂທບໍ່?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"ທຸກຄັ້ງ"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"ຕັ້ງໃຫ້ເປັນເປີດທຸກເທື່ອ"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"ຄັ້ງດຽວ"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"ການຕັ້ງຄ່າ"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s ບໍ່​ຮອງ​ຮັບ​ໂປຣ​ໄຟລ໌​ບ່ອນ​ເຮັດ​ວຽກ​ຂອງ​ທ່ານ"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 191108a..6f8e2df 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -574,7 +574,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"Pasukite telefoną kairėn."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"Pasukite telefoną dešinėn."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"Žiūrėkite tiesiai į įrenginį."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"Nematau jūsų veido. Žiūrėkite į telefoną."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"Veidas turi būti prieš telefoną."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"Įrenginys per daug judinamas. Nejudink. telefono."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"Užregistruokite veidą iš naujo."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"Nebegalima atpažinti veido. Bandykite dar kartą."</string>
@@ -1171,14 +1171,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"Atidaryti naudojant"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Atidaryti naudojant %1$s"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"Atidaryti"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"Atidaryti <xliff:g id="HOST">%1$s</xliff:g> nuorodas naudojant"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"Atidaryti nuorodas naudojant"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"Atidaryti nuorodas naudojant „<xliff:g id="APPLICATION">%1$s</xliff:g>“"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"Atidaryti <xliff:g id="HOST">%1$s</xliff:g> nuorodas naudojant „<xliff:g id="APPLICATION">%2$s</xliff:g>“"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"Suteikti prieigą"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"Redaguoti naudojant"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Redaguoti naudojant %1$s"</string>
@@ -1636,8 +1632,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"Paleisti naršyklę?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Priimti skambutį?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Visada"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"Nustatyti parinktį „Visada atidaryti“"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Tik kartą"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"Nustatymai"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s nepalaiko darbo profilio"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 94f1489..253ff72 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -571,7 +571,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"Pārvietojiet tālruni pa kreisi."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"Pārvietojiet tālruni pa labi."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"Lūdzu, tiešāk skatieties uz savu ierīci."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"Jūsu seja nav redzama. Paskatieties uz tālruni."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"Novietojiet savu seju tieši pretī tālrunim."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"Pārāk daudz kustību. Nekustīgi turiet tālruni."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"Lūdzu, atkārtoti reģistrējiet savu seju."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"Seju vairs nevar atpazīt. Mēģiniet vēlreiz."</string>
@@ -1151,14 +1151,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"Atvērt, izmantojot"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Atvērt, izmantojot %1$s"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"Atvērt"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"<xliff:g id="HOST">%1$s</xliff:g> saišu atvēršana, izmantojot:"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"Saišu atvēršana, izmantojot:"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"Saišu atvēršana, izmantojot pārlūku <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"<xliff:g id="HOST">%1$s</xliff:g> saišu atvēršana, izmantojot pārlūku <xliff:g id="APPLICATION">%2$s</xliff:g>"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"Atļaut piekļuvi"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"Rediģēt, izmantojot"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Rediģēt, izmantojot %1$s"</string>
@@ -1613,8 +1609,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"Vai palaist pārlūkprogrammu?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Vai atbildēt uz zvanu?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Vienmēr"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"Iestatīt uz “Vienmēr atvērt”"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Tikai vienreiz"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"Iestatījumi"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"Programma %1$s neatbalsta darba profilus"</string>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index 71d695a..19c1c85 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"Поместете го телефонот налево."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"Поместете го телефонот надесно."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"Погледнете подиректно во уредот."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"Не ви се гледа ликот. Гледајте во телефонот."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"Наместете го лицето директно пред телефонот."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"Премногу движење. Држете го телефонот стабилно."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"Повторно регистрирајте го лицето."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"Ликот не се препознава. Обидете се повторно."</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"Отвори со"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Отвори со %1$s"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"Отвори"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"Отворајте врски на <xliff:g id="HOST">%1$s</xliff:g> со"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"Отворајте врски со"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"Отворајте врски со <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"Отворајте врски на <xliff:g id="HOST">%1$s</xliff:g> со <xliff:g id="APPLICATION">%2$s</xliff:g>"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"Дозволи пристап"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"Измени со"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Измени со %1$s"</string>
@@ -1593,8 +1589,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"Стартувај прелистувач?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Прифати повик?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Секогаш"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"Поставете на секогаш отворај"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Само еднаш"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"Поставки"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s не поддржува работен профил"</string>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index b58f195..b2e9b64 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"ഫോൺ ഇടത്തോട്ട് നീക്കുക."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"ഫോൺ വലത്തോട്ട് നീക്കുക."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"നിങ്ങളുടെ ഉപകരണത്തിന് നേരെ കൂടുതൽ നന്നായി നോക്കുക."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"നിങ്ങളുടെ മുഖം കാണാനാവുന്നില്ല. ഫോണിലേക്ക് നോക്കൂ."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"നിങ്ങളുടെ മുഖം ക്യാമറയ്‌ക്ക് നേരെയാക്കുക."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"വളരെയധികം ചലനം. ഫോൺ അനക്കാതെ നേരെ പിടിക്കുക."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"നിങ്ങളുടെ മുഖം വീണ്ടും എൻറോൾ ചെയ്യുക."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"ഇനി മുഖം തിരിച്ചറിയാനാവില്ല. വീണ്ടും ശ്രമിക്കൂ."</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"ഇത് ഉപയോഗിച്ച് തുറക്കുക"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"%1$s ഉപയോഗിച്ച് തുറക്കുക"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"തുറക്കുക"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"ഇനിപ്പറയുന്നത് ഉപയോഗിച്ച് <xliff:g id="HOST">%1$s</xliff:g> ലിങ്കുകൾ തുറക്കുക"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"ഇനിപ്പറയുന്നത് ഉപയോഗിച്ച് ലിങ്കുകൾ തുറക്കുക"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"<xliff:g id="APPLICATION">%1$s</xliff:g> ഉപയോഗിച്ച് ലിങ്കുകൾ തുറക്കുക"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"<xliff:g id="HOST">%1$s</xliff:g> ലിങ്കുകൾ <xliff:g id="APPLICATION">%2$s</xliff:g> ഉപയോഗിച്ച് തുറക്കുക"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"ആക്‌സസ് നൽകുക"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"ഇത് ഉപയോഗിച്ച് എഡിറ്റുചെയ്യുക"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"%1$s ഉപയോഗിച്ച് എഡിറ്റുചെയ്യുക"</string>
@@ -1591,8 +1587,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"ബ്രൗസർ സമാരംഭിക്കണോ?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"കോൾ സ്വീകരിക്കണോ?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"എല്ലായ്പ്പോഴും"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"\'എല്ലായ്‌പ്പോഴും തുറക്കുക\' എന്നതിലേക്കാക്കുക"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"ഒരിക്കൽ മാത്രം"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"ക്രമീകരണം"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s, ഔദ്യോഗിക പ്രൊഫൈലിനെ പിന്തുണയ്‌ക്കുന്നില്ല"</string>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 9f1de46..a229713 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"Утсаа зүүн тийш болгоно уу."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"Утсаа баруун тийш болгоно уу."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"Төхөөрөмж рүүгээ аль болох эгц харна уу."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"Таны царайг харахгүй байна. Утас руу харна уу."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"Царайгаа утасны урд эгц байрлуулна уу"</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"Хэт их хөдөлгөөнтэй байна. Утсаа хөдөлгөөнгүй барина уу."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"Нүүрээ дахин бүртгүүлнэ үү."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"Царайг таних боломжгүй боллоо. Дахин оролдоно уу."</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"Нээх"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"%1$s ашиглан нээх"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"Нээх"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"<xliff:g id="HOST">%1$s</xliff:g>-н холбоосуудыг дараахаар нээх"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"Холбоосуудыг дараахаар нээх"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"Холбоосуудыг <xliff:g id="APPLICATION">%1$s</xliff:g>-р нээх"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"<xliff:g id="HOST">%1$s</xliff:g>-н холбоосуудыг <xliff:g id="APPLICATION">%2$s</xliff:g>-р нээх"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"Хандалт өгөх"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"Засварлах"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"%1$s ашиглан засварлах"</string>
@@ -1590,8 +1586,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"Хөтөч ажиллуулах уу?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Дуудлагыг зөвшөөрөх үү?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Байнга"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"Тогтмол нээлттэй гэж тохируулах"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Нэг удаа"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"Тохиргоо"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s ажлын профайлыг дэмждэггүй"</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index f2111e7..a86caa5 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"फोन डावीकडे हलवा."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"फोन उजवीकडे हलवा."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"कृपया तुमच्या डिव्हाइसकडे थेट पाहा"</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"तुमचा चेहरा दिसत नाही. फोनकडे पहा."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"तुमचा चेहरा थेट फोन समोर आणा."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"खूप हलत आहे. फोन स्थिर धरून ठेवा."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"कृपया तुमच्या चेहऱ्याची पुन्हा नोंदणी करा."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"चेहरा ओळखू शकत नाही. पुन्हा प्रयत्न करा."</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"यासह उघडा"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"%1$s सह उघडा"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"उघडा"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"वापरून <xliff:g id="HOST">%1$s</xliff:g> लिंक उघडा"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"वापरून लिंक उघडा"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"<xliff:g id="APPLICATION">%1$s</xliff:g> वापरून लिंक उघडा"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"<xliff:g id="APPLICATION">%2$s</xliff:g> वापरून <xliff:g id="HOST">%1$s</xliff:g> लिंक उघडा"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"अ‍ॅक्सेस द्या"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"सह संपादित करा"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"%1$s सह संपादित करा"</string>
@@ -1591,8 +1587,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"ब्राउझर लाँच करायचा?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"कॉल स्वीकारायचा?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"नेहमी"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"नेहमी उघडावर सेट करा"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"फक्त एकदाच"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"सेटिंग्ज"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s कार्य प्रोफाईलचे समर्थन करीत नाही"</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 49a5578..c18e078 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"Alihkan telefon ke kiri."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"Alihkan telefon ke kanan."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"Sila lihat terus pada peranti anda."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"Gagal mengesan wajah anda. Lihat telefon."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"Letakkan wajah anda betul-betul di depan telefon."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"Terlalu bnyk gerakan. Pegang telefon dgn stabil."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"Sila daftarkan semula wajah anda."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"Tidak lagi dapat mengecam wajah. Cuba lagi."</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"Buka dengan"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Buka dengan %1$s"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"Buka"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"Buka pautan <xliff:g id="HOST">%1$s</xliff:g> dengan"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"Buka pautan dengan"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"Buka pautan dengan <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"Buka pautan <xliff:g id="HOST">%1$s</xliff:g> dengan <xliff:g id="APPLICATION">%2$s</xliff:g>"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"Berikan akses"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"Edit dengan"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Edit dengan %1$s"</string>
@@ -1590,8 +1586,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"Lancarkan Penyemak Imbas?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Terima panggilan?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Sentiasa"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"Tetapkan agar sentiasa dibuka"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Hanya sekali"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"Tetapan"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s tidak menyokong profil kerja"</string>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index bbe115f..55e7b01 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"ဖုန်းကို ဘယ်ဘက်သို့ရွှေ့ပါ။"</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"ဖုန်းကို ညာဘက်သို့ ရွှေ့ပါ။"</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"သင့်စက်ပစ္စည်းကို တည့်တည့်ကြည့်ပါ။"</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"သင့်မျက်နှာကို မမြင်ရပါ။ ဖုန်းကိုကြည့်ပါ။"</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"မျက်နှာကို ဖုန်းရှေ့တွင် တည့်အောင်ထားပါ။"</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"လှုပ်လွန်းသည်။ ဖုန်းကို ငြိမ်ငြိမ်ကိုင်ပါ။"</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"သင့်မျက်နှာကို ပြန်စာရင်းသွင်းပါ။"</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"မျက်နှာ မမှတ်သားနိုင်တော့ပါ။ ထပ်စမ်းကြည့်ပါ။"</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"...ဖြင့် ဖွင့်မည်"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"%1$s ဖြင့် ဖွင့်မည်"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"ဖွင့်ပါ"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"<xliff:g id="HOST">%1$s</xliff:g> လင့်ခ်များကို အောက်ပါဖြင့် ဖွင့်ရန်−"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"လင့်ခ်များကို အောက်ပါဖြင့် ဖွင့်ရန်−"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"လင့်ခ်ကို <xliff:g id="APPLICATION">%1$s</xliff:g> ဖြင့် ဖွင့်ရန်"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"<xliff:g id="HOST">%1$s</xliff:g> လင့်ခ်များကို <xliff:g id="APPLICATION">%2$s</xliff:g> ဖြင့် ဖွင့်ရန်"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"ဖွင့်ခွင့်ပေးရန်"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"...နှင့် တည်းဖြတ်ရန်"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"%1$s နှင့် တည်းဖြတ်ရန်"</string>
@@ -1591,8 +1587,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"ဘရောက်ဇာ ဖွင့်မည်လား။"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"ဖုန်းခေါ်ဆိုမှုကို လက်ခံမလား?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"အမြဲတမ်း"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"အမြဲဖွင့်မည်အဖြစ် သတ်မှတ်ရန်"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"တစ်ခါတည်း"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"ဆက်တင်များ"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s က အလုပ်ပရိုဖိုင်ကို မပံ့ပိုးပါ။"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 34275df..a589389 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"Flytt telefonen til venstre."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"Flytt telefonen til høyre."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"Se mer direkte på enheten din."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"Kan ikke se ansiktet ditt. Se på telefonen."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"Hold ansiktet ditt rett foran telefonen."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"For mye bevegelse. Hold telefonen stødig."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"Registrer ansiktet ditt på nytt."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"Kan ikke gjenkjenne ansiktet lenger. Prøv igjen."</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"Åpne med"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Åpne med %1$s"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"Åpne"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"Åpne <xliff:g id="HOST">%1$s</xliff:g>-linker med"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"Åpne linker med"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"Åpne linker med <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"Åpne <xliff:g id="HOST">%1$s</xliff:g>-linker med <xliff:g id="APPLICATION">%2$s</xliff:g>"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"Gi tilgang"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"Rediger med"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Rediger med %1$s"</string>
@@ -1590,8 +1586,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"Vil du starte nettleseren?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Vil du besvare anropet?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Alltid"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"Angi som alltid åpen"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Bare én gang"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"Innstillinger"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s støtter ikke arbeidsprofiler"</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index 80bd83a..89e75b4 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"फोन बायाँतिर सार्नुहोस्।"</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"फोन दायाँतिर सार्नुहोस्।"</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"कृपया अझ सीधा गरी आफ्नो स्क्रिनमा हेर्नुहोस्।"</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"तपाईंको अनुहार देखिएन। फोनमा हेर्नुहोस्।"</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"आफ्नो अनुहार फोनको सीधा अगाडि पार्नुहोस्।"</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"अत्यधिक हल्लियो। फोन स्थिर राख्नुहोस्।"</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"कृपया आफ्नो अनुहार पुनः दर्ता गर्नुहोस्।"</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"अब उप्रान्त अनुहार पहिचान गर्न सकिएन। फेरि प्रयास गर्नुहोस्।"</string>
@@ -1135,14 +1135,10 @@
     <!-- no translation found for whichViewApplicationNamed (2286418824011249620) -->
     <skip />
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"खोल्नुहोस्"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"निम्नमार्फत <xliff:g id="HOST">%1$s</xliff:g> का लिंकहरू खोल्नुहोस्"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"निम्नमार्फत लिंकहरू खोल्नुहोस्"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"<xliff:g id="APPLICATION">%1$s</xliff:g> मार्फत लिंकहरू खोल्नुहोस्"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"<xliff:g id="APPLICATION">%2$s</xliff:g> मार्फत <xliff:g id="HOST">%1$s</xliff:g> का लिंकहरू खोल्नुहोस्"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"पहुँच दिनुहोस्"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"सँग सम्पादन गर्नुहोस्"</string>
     <!-- String.format failed for translation -->
@@ -1596,8 +1592,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"ब्राउजर सुरु गर्ने हो?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"कल स्वीकार गर्नुहुन्छ?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"सधैँ"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"सधैँ खुला राख्ने गरी सेट गर्नुहोस्"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"एक पटक मात्र"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"सेटिङहरू"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s  कार्य प्रोफाइल समर्थन गर्दैन"</string>
@@ -1975,7 +1970,7 @@
     <string name="etws_primary_default_message_tsunami" msgid="1887685943498368548">"तटीय क्षेत्र र नदीछेउका ठाउँहरू छाडी उच्च सतहमा अवस्थित कुनै अझ सुरक्षित ठाउँमा जानुहोस्।"</string>
     <string name="etws_primary_default_message_earthquake_and_tsunami" msgid="998797956848445862">"शान्त रहनुहोस् र नजिकै आश्रयस्थल खोज्नुहोस्।"</string>
     <string name="etws_primary_default_message_test" msgid="2709597093560037455">"आपतकालीन सन्देशहरूको परीक्षण"</string>
-    <string name="notification_reply_button_accessibility" msgid="3621714652387814344">"जवाफ दिनुहोस्"</string>
+    <string name="notification_reply_button_accessibility" msgid="3621714652387814344">"जवाफ दिनु…"</string>
     <string name="etws_primary_default_message_others" msgid="6293148756130398971"></string>
     <string name="mmcc_authentication_reject" msgid="5767701075994754356">"SIM मार्फत भ्वाइस कल गर्न मिल्दैन"</string>
     <string name="mmcc_imsi_unknown_in_hlr" msgid="5316658473301462825">"SIM मार्फत भ्वाइस कल गर्ने प्रावधान छैन"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 7c23e2c..4194eb1 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"Beweeg je telefoon meer naar links."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"Beweeg je telefoon meer naar rechts."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"Kijk rechter naar je apparaat."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"Je gezicht is niet te zien. Kijk naar de telefoon."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"Houd je gezicht recht voor de telefoon."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"Te veel beweging. Houd je telefoon stil."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"Registreer je gezicht opnieuw."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"Herkent gezicht niet meer. Probeer het nog eens."</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"Openen met"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Openen met %1$s"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"Openen"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"Links van <xliff:g id="HOST">%1$s</xliff:g> openen met"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"Links openen met"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"Links openen met <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"Links van <xliff:g id="HOST">%1$s</xliff:g> openen met <xliff:g id="APPLICATION">%2$s</xliff:g>"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"Toegang geven"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"Bewerken met"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Bewerken met %1$s"</string>
@@ -1590,8 +1586,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"Browser starten?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Gesprek accepteren?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Altijd"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"Instellen op altijd openen"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Één keer"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"Instellingen"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s ondersteunt werkprofielen niet"</string>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index 257dd06..0f3472c 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"ବାମ ପଟକୁ ଫୋନ୍ ଘୁଞ୍ଚାନ୍ତୁ।"</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"ଡାହାଣ ପଟକୁ ଫୋନ୍ ଘୁଞ୍ଚାନ୍ତୁ।"</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"ଦୟାକରି ଆପଣଙ୍କ ଡିଭାଇସ୍‌କୁ ସିଧାସଳଖ ଦେଖନ୍ତୁ।"</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"ଆପଣଙ୍କର ମୁହଁ ଦେଖି ପାରୁନାହିଁ। ଫୋନ୍‌କୁ ଦେଖନ୍ତୁ।"</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"ଆପଣଙ୍କ ମୁହଁକୁ ଫୋନ୍ ସାମ୍ନାରେ ସିଧାସଳଖ ରଖନ୍ତୁ।"</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"ଅତ୍ୟଧିକ ଅସ୍ଥିର। ଫୋନ୍‍କୁ ସ୍ଥିର ଭାବେ ଧରନ୍ତୁ।"</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"ଦୟାକରି ଆପଣଙ୍କର ମୁହଁ ପୁଣି-ଏନ୍‍ରୋଲ୍ କରନ୍ତୁ।"</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"ଆଉ ମୁହଁ ଚିହ୍ନଟ କରିହେଲା ନାହିଁ। ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"ସହିତ ଖୋଲନ୍ତୁ"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"%1$s ସହିତ ଖୋଲନ୍ତୁ"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"ଖୋଲନ୍ତୁ"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"ଏଥିରେ <xliff:g id="HOST">%1$s</xliff:g> ଲିଙ୍କ୍‍ଗୁଡ଼ିକ ଖୋଲନ୍ତୁ"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"ଏଥିରେ ଲିଙ୍କ୍‍ଗୁଡ଼ିକ ଖୋଲନ୍ତୁ"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"<xliff:g id="APPLICATION">%1$s</xliff:g> ମାଧ୍ୟମରେ ଲିଙ୍କ୍‍ଗୁଡ଼ିକ ଖୋଲନ୍ତୁ"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"<xliff:g id="APPLICATION">%2$s</xliff:g> ମାଧ୍ୟମରେ <xliff:g id="HOST">%1$s</xliff:g> ଲିଙ୍କ୍‍ଗୁଡ଼ିକ ଖୋଲନ୍ତୁ"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"ଆକ୍ସେସ୍‌ ଦିଅନ୍ତୁ"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"ସହିତ ଏଡିଟ୍‌ କରନ୍ତୁ"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"%1$sରେ ସଂଶୋଧନ କରନ୍ତୁ"</string>
@@ -1590,8 +1586,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"ବ୍ରାଉଜର୍‍ ଲଞ୍ଚ କରିବେ?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"କଲ୍‍ ସ୍ୱୀକାର କରିବେ?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"ସର୍ବଦା"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"\'ସର୍ବଦା ଖୋଲା\' ଭାବରେ ସେଟ୍ କରନ୍ତୁ"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"ଥରେ ମାତ୍ର"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"ସେଟିଂସ୍"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s ୱର୍କ ପ୍ରୋଫାଇଲ୍‌କୁ ସପୋର୍ଟ କରୁନାହିଁ"</string>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index 104fb40..8245546 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"ਫ਼ੋਨ ਨੂੰ ਖੱਬੇ ਪਾਸੇ ਲਿਜਾਓ।"</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"ਫ਼ੋਨ ਨੂੰ ਸੱਜੇ ਪਾਸੇ ਲਿਜਾਓ।"</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"ਕਿਰਪਾ ਕਰਕੇ ਸਿੱਧਾ ਆਪਣੇ ਡੀਵਾਈਸ ਵੱਲ ਦੇਖੋ।"</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"ਤੁਹਾਡਾ ਚਿਹਰਾ ਨਹੀਂ ਦਿਸ ਰਿਹਾ। ਫ਼ੋਨ ਵੱਲ ਦੇਖੋ।"</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"ਆਪਣਾ ਚਿਹਰਾ ਫ਼ੋਨ ਦੇ ਬਿਲਕੁਲ ਸਾਹਮਣੇ ਰੱਖੋ।"</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"ਬਹੁਤ ਜ਼ਿਆਦਾ ਹਿਲਜੁਲ। ਫ਼ੋਨ ਨੂੰ ਸਥਿਰ ਰੱਖੋ।"</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"ਕਿਰਪਾ ਕਰਕੇ ਆਪਣਾ ਚਿਹਰਾ ਦੁਬਾਰਾ ਦਰਜ ਕਰੋ।"</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"ਹੁਣ ਚਿਹਰਾ ਪਛਾਣਿਆ ਨਹੀਂ ਜਾ ਸਕਦਾ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"ਨਾਲ ਖੋਲ੍ਹੋ"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"%1$s ਨਾਲ ਖੋਲ੍ਹੋ"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"ਖੋਲ੍ਹੋ"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"<xliff:g id="HOST">%1$s</xliff:g> ਲਿੰਕਾਂ ਨੂੰ ਇਸ ਨਾਲ ਖੋਲ੍ਹੋ"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"ਲਿੰਕਾਂ ਨੂੰ ਇਸ ਨਾਲ ਖੋਲ੍ਹੋ"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"ਲਿੰਕਾਂ ਨੂੰ <xliff:g id="APPLICATION">%1$s</xliff:g> ਨਾਲ ਖੋਲ੍ਹੋ"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"<xliff:g id="HOST">%1$s</xliff:g> ਲਿੰਕਾਂ ਨੂੰ <xliff:g id="APPLICATION">%2$s</xliff:g> ਨਾਲ ਖੋਲ੍ਹੋ"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"ਪਹੁੰਚ ਦਿਓ"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"ਇਸ ਨਾਲ ਸੰਪਾਦਨ ਕਰੋ"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"%1$s ਨਾਲ ਸੰਪਾਦਨ ਕਰੋ"</string>
@@ -1591,8 +1587,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"ਕੀ ਬ੍ਰਾਊਜ਼ਰ ਲਾਂਚ ਕਰਨਾ ਹੈ?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"ਕੀ ਕਾਲ ਸਵੀਕਾਰ ਕਰਨੀ ਹੈ?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"ਹਮੇਸ਼ਾਂ"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"ਹਮੇਸ਼ਾਂ ਖੁੱਲ੍ਹਾ \'ਤੇ ਸੈੱਟ ਕਰੋ"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"ਕੇਵਲ ਇੱਕ ਵਾਰ"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"ਸੈਟਿੰਗਾਂ"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਦਾ ਸਮਰਥਨ ਨਹੀਂ ਕਰਦੀ"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index a61555b..a90acfa 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -574,7 +574,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"Przesuń telefon w lewo."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"Przesuń telefon w prawo."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"Patrz prosto na urządzenie."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"Nie widzę Twojej twarzy. Spójrz na telefon."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"Ustaw twarz dokładnie na wprost telefonu."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"Telefon się porusza. Trzymaj go nieruchomo."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"Zarejestruj swoją twarz ponownie."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"Nie można już rozpoznać twarzy. Spróbuj ponownie."</string>
@@ -1171,14 +1171,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"Otwórz w aplikacji"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Otwórz w aplikacji %1$s"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"Otwórz"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"Otwieraj linki z: <xliff:g id="HOST">%1$s</xliff:g> w"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"Otwieraj linki w"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"Otwieraj linki w aplikacji <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"Otwieraj linki z: <xliff:g id="HOST">%1$s</xliff:g> w aplikacji <xliff:g id="APPLICATION">%2$s</xliff:g>"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"Udziel uprawnień"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"Edytuj w aplikacji"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Edytuj w aplikacji %1$s"</string>
@@ -1636,8 +1632,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"Uruchomić przeglądarkę?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Odebrać połączenie?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Zawsze"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"Zawsze otwieraj"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Tylko raz"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"Ustawienia"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s nie obsługuje profilu do pracy"</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index 11c6a28..742fa81 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"Mova o smartphone para a esquerda."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"Mova o smartphone para a direita."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"Olhe mais diretamente para o dispositivo."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"Não é possível ver o rosto. Olhe para o telefone."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"Deixe o rosto diretamente na frente do smartphone."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"Muito movimento. Não mova o smartphone."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"Registre seu rosto novamente."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"O rosto não é mais reconhecido. Tente novamente."</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"Abrir com"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Abrir com %1$s"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"Abrir"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"Abrir links do domínio <xliff:g id="HOST">%1$s</xliff:g> com"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"Abrir links com"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"Abrir links com <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"Abrir links do domínio <xliff:g id="HOST">%1$s</xliff:g> com <xliff:g id="APPLICATION">%2$s</xliff:g>"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"Conceder acesso"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"Editar com"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Editar com %1$s"</string>
@@ -1590,8 +1586,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"Abrir Navegador?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Aceitar chamada?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Sempre"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"Definir como \"Sempre abrir\""</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Só uma vez"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"Configurações"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s não aceita perfis de trabalho"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index ed26c2d..85fb7fd 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"Mova o telemóvel para a esquerda."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"Mova o telemóvel para a direita."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"Olhe mais diretamente para o dispositivo."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"Não consigo ver o rosto. Olhe para o telemóvel."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"Posicione o rosto em frente ao telemóvel."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"Demasiado movimento. Mantenha o telemóvel firme."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"Volte a inscrever o rosto."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"Impossível reconhecer o rosto. Tente novamente."</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"Abrir com"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Abrir com %1$s"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"Abrir"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"Abra os links de <xliff:g id="HOST">%1$s</xliff:g> com:"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"Abra os links com:"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"Abra os links com a aplicação <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"Abra os links de <xliff:g id="HOST">%1$s</xliff:g> com a aplicação <xliff:g id="APPLICATION">%2$s</xliff:g>"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"Conceder acesso"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"Editar com"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Editar com %1$s"</string>
@@ -1590,8 +1586,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"Iniciar Navegador?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Aceitar chamada?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Sempre"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"Definir como abrir sempre"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Apenas uma vez"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"Definições"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s não suporta o perfil de trabalho"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 11c6a28..742fa81 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"Mova o smartphone para a esquerda."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"Mova o smartphone para a direita."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"Olhe mais diretamente para o dispositivo."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"Não é possível ver o rosto. Olhe para o telefone."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"Deixe o rosto diretamente na frente do smartphone."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"Muito movimento. Não mova o smartphone."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"Registre seu rosto novamente."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"O rosto não é mais reconhecido. Tente novamente."</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"Abrir com"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Abrir com %1$s"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"Abrir"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"Abrir links do domínio <xliff:g id="HOST">%1$s</xliff:g> com"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"Abrir links com"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"Abrir links com <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"Abrir links do domínio <xliff:g id="HOST">%1$s</xliff:g> com <xliff:g id="APPLICATION">%2$s</xliff:g>"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"Conceder acesso"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"Editar com"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Editar com %1$s"</string>
@@ -1590,8 +1586,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"Abrir Navegador?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Aceitar chamada?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Sempre"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"Definir como \"Sempre abrir\""</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Só uma vez"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"Configurações"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s não aceita perfis de trabalho"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index edbc2a4..2f464e9 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -571,7 +571,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"Mutați telefonul spre stânga."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"Mutați telefonul spre dreapta."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"Priviți mai direct spre dispozitiv."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"Nu vi se vede fața. Uitați-vă la telefon."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"Stați cu capul direct în fața telefonului."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"Prea multă mișcare. Țineți telefonul nemișcat."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"Reînregistrați-vă chipul."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"Nu se mai poate recunoaște fața. Încercați din nou."</string>
@@ -1151,14 +1151,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"Deschideți cu"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Deschideți cu %1$s"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"Deschideți"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"Deschideți linkurile <xliff:g id="HOST">%1$s</xliff:g> cu"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"Deschideți linkurile cu"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"Deschideți linkurile cu <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"Deschideți linkurile <xliff:g id="HOST">%1$s</xliff:g> cu <xliff:g id="APPLICATION">%2$s</xliff:g>"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"Permiteți accesul"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"Editați cu"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Editați cu %1$s"</string>
@@ -1613,8 +1609,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"Lansați browserul?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Acceptați apelul?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Întotdeauna"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"Schimbați la „Deschideți întotdeauna”"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Numai o dată"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"Setări"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s nu acceptă profilul de serviciu"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index a7c5c7a..c4b61b2 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -574,7 +574,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"Переместите телефон влево."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"Переместите телефон вправо."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"Смотрите прямо на устройство."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"Вашего лица не видно. Смотрите на телефон."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"Держите телефон прямо перед лицом."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"Не перемещайте устройство. Держите его неподвижно."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"Повторите попытку."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"Не удалось распознать лицо. Повторите попытку."</string>
@@ -1171,14 +1171,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"Открыть с помощью приложения:"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Открыть с помощью приложения \"%1$s\""</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"Открыть"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"Открывать ссылки вида <xliff:g id="HOST">%1$s</xliff:g> с помощью:"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"Открывать ссылки с помощью:"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"Открывать ссылки в браузере <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"Открывать ссылки вида <xliff:g id="HOST">%1$s</xliff:g> в браузере <xliff:g id="APPLICATION">%2$s</xliff:g>"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"Открыть доступ"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"Редактировать с помощью приложения:"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Редактировать с помощью приложения \"%1$s\""</string>
@@ -1636,8 +1632,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"Запустить браузер?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Ответить?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Всегда"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"Всегда открывать"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Только сейчас"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"Настройки"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s не поддерживает рабочие профили"</string>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index c23728e..ddeb94b 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"දුරකථනය වමට ගෙන යන්න."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"දුරකථනය දකුණට ගෙන යන්න."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"ඔබේ උපාංගය වෙත තවත් ඍජුව බලන්න."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"ඔබේ මුහුණ දැකිය නොහැක. දුරකථනය වෙත බලන්න."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"ඔබේ මුහුණ දුරකථනයට සෘජුවම ඉදිරියෙන් ස්ථානගත කරන්න."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"චලනය ඉතා වැඩියි. දුරකථනය ස්ථිරව අල්ලා සිටින්න."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"ඔබේ මුහුණ යළි ලියාපදිංචි කරන්න."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"තවදුරටත් මුහුණ හඳුනාගත නොහැක. නැවත උත්සාහ කරන්න."</string>
@@ -1133,14 +1133,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"සමඟ විවෘත කරන්න"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"%1$s සමඟ විවෘත කරන්න"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"විවෘත කරන්න"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"සමග <xliff:g id="HOST">%1$s</xliff:g> සබැඳි විවෘත කරන්න"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"සමඟ සබැඳි විවෘත කරන්න"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"<xliff:g id="APPLICATION">%1$s</xliff:g> සමඟ සබැඳි විවෘත කරන්න"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"<xliff:g id="APPLICATION">%2$s</xliff:g> සමග <xliff:g id="HOST">%1$s</xliff:g> සබැඳි විවෘත කරන්න"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"ප්‍රවේශය දෙන්න"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"සමඟ සංස්කරණය කරන්න"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"%1$s සමඟ සංස්කරණය කරන්න"</string>
@@ -1592,8 +1588,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"බ්‍රවුසරය දියත් කරන්නද?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"ඇමතුම පිළිගන්නවාද?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"සැම විටම"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"සැම විට විවෘත ලෙස සකසන්න"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"එක් වාරයයි"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"සැකසීම්"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s කාර්යාල පැතිකඩ සඳහා සහාය ලබනොදේ."</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 76b211a..4d19308 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -574,7 +574,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"Posuňte telefón doľava."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"Posuňte telefón doprava."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"Pozrite sa priamejšie na zariadenie."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"Nie je vidieť vašu tvár. Pozrite sa na telefón."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"Umiestnite svoju tvár priamo pred telefón."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"Priveľa pohybu. Nehýbte telefónom."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"Znova zaregistrujte svoju tvár."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"Tvár už nie je možné rozpoznať. Skúste to znova."</string>
@@ -1171,14 +1171,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"Otvoriť v aplikácii"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Otvoriť v aplikácii %1$s"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"Otvoriť"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"Otvárajte odkazy z webu <xliff:g id="HOST">%1$s</xliff:g> v prehliadači alebo aplikácii"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"Otvárajte odkazy v prehliadači"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"Otvárajte odkazy v prehliadači <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"Otvárajte odkazy z webu <xliff:g id="HOST">%1$s</xliff:g> v prehliadači <xliff:g id="APPLICATION">%2$s</xliff:g>"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"Udeliť prístup"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"Upraviť pomocou"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Upraviť v aplikácii %1$s"</string>
@@ -1636,8 +1632,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"Spustiť prehliadač?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Prijať hovor?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Vždy"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"Nastaviť na Vždy otvárať"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Len raz"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"Nastavenia"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"Spúšťač %1$s nepodporuje pracovné profily"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 943e9e2..b2b3109 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -574,7 +574,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"Telefon premaknite v levo."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"Telefon premaknite v desno."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"Glejte bolj naravnost v napravo."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"Obraz ni viden. Poglejte v telefon."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"Obraz nastavite naravnost pred telefon."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"Preveč se premikate. Držite telefon pri miru."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"Znova prijavite svoj obraz."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"Obraza ni več mogoče prepoznati. Poskusite znova."</string>
@@ -1171,14 +1171,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"Odpiranje z aplikacijo"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Odpiranje z aplikacijo %1$s"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"Odpiranje"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"Odpiranje povezav <xliff:g id="HOST">%1$s</xliff:g> z"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"Odpiranje povezav z"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"Odpiranje povezav z aplikacijo <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"Odpiranje povezav <xliff:g id="HOST">%1$s</xliff:g> z aplikacijo <xliff:g id="APPLICATION">%2$s</xliff:g>"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"Omogoči dostop"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"Urejanje z aplikacijo"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Urejanje z aplikacijo %1$s"</string>
@@ -1636,8 +1632,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"Ali želite odpreti brskalnik?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Ali želite sprejeti klic?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Vedno"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"Nastavi na »vedno odpri«"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Samo tokrat"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"Nastavitve"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s ne podpira delovnega profila"</string>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index 28f6062..afed336 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"Lëvize telefonin majtas."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"Lëvize telefonin djathtas"</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"Shiko më drejt në pajisjen tënde."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"Fytyra jote nuk shfaqet. Shiko te telefoni."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"Pozicionoje fytyrën tënde direkt përpara telefonit."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"Ka shumë lëvizje. Mbaje telefonin të palëvizur."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"Regjistroje përsëri fytyrën tënde."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"Fytyra nuk mund të njihet më. Provo përsëri."</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"Hap me"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Hap me %1$s"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"Hap"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"Hapi lidhjet e <xliff:g id="HOST">%1$s</xliff:g> me"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"Hapi lidhjet me"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"Hapi lidhjet me <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"Hapi lidhjet e <xliff:g id="HOST">%1$s</xliff:g> me <xliff:g id="APPLICATION">%2$s</xliff:g>"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"Jep qasje"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"Redakto me"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Redakto me %1$s"</string>
@@ -1591,8 +1587,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"Të hapet shfletuesi?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Dëshiron ta pranosh telefonatën?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Gjithmonë"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"Caktoje si gjithmonë të hapur"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Vetëm një herë"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"Cilësimet"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s nuk e mbështet profilin e punës"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 4fdf301..110b31d 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -571,7 +571,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"Померите телефон улево."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"Померите телефон удесно."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"Гледајте право у уређај."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"Не види се лице. Гледајте у телефон."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"Поставите лице директно испред телефона"</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"Много се померате. Држите телефон мирно."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"Поново региструјте лице."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"Више не може да се препозна лице. Пробајте поново."</string>
@@ -1151,14 +1151,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"Отворите помоћу"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Отворите помоћу апликације %1$s"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"Отвори"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"Отварајте <xliff:g id="HOST">%1$s</xliff:g> линкове помоћу"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"Отваратеј линкове помоћу"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"Отварајте линкове помоћу апликације <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"Отварајте <xliff:g id="HOST">%1$s</xliff:g> линкове помоћу апликације <xliff:g id="APPLICATION">%2$s</xliff:g>"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"Дозволи приступ"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"Измените помоћу"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Измените помоћу апликације %1$s"</string>
@@ -1613,8 +1609,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"Желите ли да покренете прегледач?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Желите ли да прихватите позив?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Увек"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"Подеси на „увек отварај“"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Само једном"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"Подешавања"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s не подржава пословни профил"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index ff82a14..bc1752e 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"Flytta mobilen åt vänster."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"Flytta mobilen åt höger."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"Titta rakt på enheten."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"Ansiktet syns inte. Titta på mobilen."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"Ha ansiktet direkt framför telefonen."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"För mycket rörelse. Håll mobilen stilla."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"Registrera ansiktet på nytt."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"Ansiktet kan inte längre kännas igen. Försök igen."</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"Öppna med"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Öppna med %1$s"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"Öppna"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"Öppna länkar på <xliff:g id="HOST">%1$s</xliff:g> med"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"Öppna länkar med"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"Öppna länkar med <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"Öppna länkar på <xliff:g id="HOST">%1$s</xliff:g> med <xliff:g id="APPLICATION">%2$s</xliff:g>"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"Ge åtkomst"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"Redigera med"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Redigera med %1$s"</string>
@@ -1590,8 +1586,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"Vill du öppna webbläsaren?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Vill du ta emot samtal?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Alltid"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"Ställ in på att alltid öppnas"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Bara en gång"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"Inställningar"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s har inte stöd för arbetsprofil"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 528d5d7a..92510ea 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"Sogeza simu upande wa kushoto."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"Sogeza simu upande wa kulia."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"Tafadhali angalia kifaa chako moja kwa moja."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"Uso wako hauonekani. Angalia simu."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"Weka uso wako moja kwa moja mbele ya simu."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"Inatikisika sana. Ishike simu iwe thabiti."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"Tafadhali sajili uso wako tena."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"Haiwezi tena kutambua uso. Jaribu tena."</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"Fungua ukitumia"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Fungua ukitumia %1$s"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"Fungua"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"Fungua viungo vya <xliff:g id="HOST">%1$s</xliff:g> ukitumia"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"Fungua viungo ukitumia"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"Fungua viungo ukitumia <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"Fungua viungo vya <xliff:g id="HOST">%1$s</xliff:g> ukitumia <xliff:g id="APPLICATION">%2$s</xliff:g>"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"Idhinisha ufikiaji"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"Badilisha kwa"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Badilisha kwa %1$s"</string>
@@ -1590,8 +1586,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"Zindua Kivinjari?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Kubali simu?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Kila mara"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"Weka ifunguke kila wakati"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Mara moja tu"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"Mipangilio"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s haitumii wasifu wa kazini"</string>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index 39cd685..8ddcfe6 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"மொபைலை இடப்புறம் நகர்த்தவும்."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"மொபைலை வலப்புறம் நகர்த்தவும்."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"முழுமுகம் தெரியுமாறு நேராகப் பார்க்கவும்."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"முகம் சரியாகத் தெரியவில்லை. மொபைலைப் பார்க்கவும்."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"முகத்தை மொபைலுக்கு நேராக வைக்கவும்."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"அதிகமாக அசைகிறது. மொபைலை அசைக்காமல் பிடிக்கவும்."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"உங்கள் முகத்தை மீண்டும் பதிவுசெய்யுங்கள்."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"முகத்தைக் கண்டறிய இயலவில்லை. மீண்டும் முயலவும்."</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"இதன்மூலம் திற"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"%1$s மூலம் திற"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"திற"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"<xliff:g id="HOST">%1$s</xliff:g> இணைப்புகளை இதன் மூலம் திற:"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"இணைப்புகளை இதன் மூலம் திற:"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"இணைப்புகளை <xliff:g id="APPLICATION">%1$s</xliff:g> ஆப்ஸில் திறத்தல்"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"<xliff:g id="HOST">%1$s</xliff:g> இணைப்புகளை <xliff:g id="APPLICATION">%2$s</xliff:g> ஆப்ஸில் திறத்தல்"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"அணுகலை வழங்கு"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"இதன் மூலம் திருத்து"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"%1$s மூலம் திருத்து"</string>
@@ -1591,8 +1587,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"உலாவியைத் துவக்கவா?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"அழைப்பை ஏற்கவா?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"எப்போதும்"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"எப்போதும் திறக்குமாறு அமைத்தல்"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"இப்போது மட்டும்"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"அமைப்புகள்"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s பணிக் கணக்கை ஆதரிக்காது"</string>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index 3ba794a..649e17c 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"ఫోన్‌ను ఎడమవైపునకు జరపండి."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"ఫోన్‌ను కుడివైపునకు జరపండి."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"దయచేసి మీ పరికరం వైపు మరింత నేరుగా చూడండి."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"మీ ముఖం కనిపించడం లేదు. ఫోన్ వైపు చూడండి."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"మీ ముఖాన్ని ఫోన్‌కు ఎదురుగా ఉంచండి."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"బాగా కదుపుతున్నారు. ఫోన్‌ను స్థిరంగా పట్టుకోండి"</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"దయచేసి మీ ముఖాన్ని మళ్లీ నమోదు చేయండి."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"ఇక ముఖం గుర్తించలేదు. మళ్లీ ప్రయత్నించండి."</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"దీనితో తెరువు"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"%1$sతో తెరువు"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"తెరువు"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"దీనితో <xliff:g id="HOST">%1$s</xliff:g> లింక్‌లను తెరవండి"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"దీనితో లింక్‌లను తెరవండి"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"<xliff:g id="APPLICATION">%1$s</xliff:g>తో లింక్‌లను తెరవండి"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"<xliff:g id="HOST">%1$s</xliff:g> లింక్‌లను <xliff:g id="APPLICATION">%2$s</xliff:g>తో తెరవండి"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"యాక్సెస్ ఇవ్వండి"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"దీనితో సవరించు"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"%1$sతో సవరించు"</string>
@@ -1591,8 +1587,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"బ్రౌజర్‌ను ప్రారంభించాలా?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"కాల్‌ను ఆమోదించాలా?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"ఎల్లప్పుడూ"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"ఎల్లప్పుడూ తెరవడానికి సెట్ చేయి"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"ఒకసారి మాత్రమే"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"సెట్టింగ్‌లు"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s కార్యాలయ ప్రొఫైల్‌కు మద్దతు ఇవ్వదు"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 437d89e..4e69430 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"เลื่อนโทรศัพท์ไปทางซ้าย"</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"เลื่อนโทรศัพท์ไปทางขวา"</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"โปรดมองตรงมาที่อุปกรณ์"</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"ไม่เห็นหน้าเลย ลองมองที่โทรศัพท์"</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"หันหน้าให้ตรงกับโทรศัพท์"</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"มีการเคลื่อนไหวมากเกินไป ถือโทรศัพท์นิ่งๆ"</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"โปรดลงทะเบียนใบหน้าอีกครั้ง"</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"จำใบหน้าไม่ได้แล้ว ลองอีกครั้ง"</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"เปิดด้วย"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"เปิดด้วย %1$s"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"เปิด"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"เปิดลิงก์ <xliff:g id="HOST">%1$s</xliff:g> ด้วย"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"เปิดลิงก์ด้วย"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"เปิดลิงก์ด้วย <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"เปิดลิงก์ <xliff:g id="HOST">%1$s</xliff:g> ด้วย <xliff:g id="APPLICATION">%2$s</xliff:g>"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"ให้สิทธิ์"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"แก้ไขด้วย"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"แก้ไขด้วย %1$s"</string>
@@ -1590,8 +1586,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"เปิดเบราว์เซอร์หรือไม่"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"รับสายหรือไม่"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"ทุกครั้ง"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"ตั้งค่าให้เปิดทุกครั้ง"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"เฉพาะครั้งนี้"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"การตั้งค่า"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s ไม่สนับสนุนโปรไฟล์งาน"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 8469e7b..6843528 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"Igalaw ang telepono pakaliwa."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"Igalaw ang telepono pakanan."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"Tumingin nang mas direkta sa iyong device."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"Hindi makita ang mukha mo. Tumingin sa telepono."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"Itapat ang mukha mo sa mismong harap ng telepono."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"Masyadong magalaw. Hawakang mabuti ang telepono."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"Paki-enroll muli ang iyong mukha."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"Hindi na makilala ang mukha. Subukang muli."</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"Buksan gamit ang"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Buksan gamit ang %1$s"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"Buksan"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"Buksan ang mga link ng <xliff:g id="HOST">%1$s</xliff:g> gamit ang"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"Buksan ang mga link gamit ang"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"Buksan ang mga link gamit ang <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"Buksan ang mga link ng <xliff:g id="HOST">%1$s</xliff:g> gamit ang <xliff:g id="APPLICATION">%2$s</xliff:g>"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"Bigyan ng access"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"I-edit gamit ang"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"I-edit gamit ang %1$s"</string>
@@ -1590,8 +1586,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"Ilunsad ang Browser?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Tanggapin ang tawag?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Palagi"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"Itakda sa palaging buksan"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Isang beses lang"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"Mga Setting"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"Hindi sinusuportahan ng %1$s ang profile sa trabaho"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 8a28a0d..3592df9 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"Telefonu sola hareket ettirin."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"Telefonu sağa hareket ettirin."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"Lütfen cihazınıza daha doğrudan bakın."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"Yüzünüz görülmüyor. Telefona bakın."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"Yüzünüz telefonun tam karşısına gelmelidir."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"Çok fazla hareket ediyorsunuz. Telefonu sabit tutun."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"Lütfen yüzünüzü yeniden kaydedin."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"Yüz artık tanınamıyor. Tekrar deneyin."</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"Şununla aç:"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"%1$s ile aç"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"Aç"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"<xliff:g id="HOST">%1$s</xliff:g> bağlantılarını şununla aç:"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"Bağlantıları şununla aç:"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"Bağlantıları <xliff:g id="APPLICATION">%1$s</xliff:g> ile aç"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"<xliff:g id="HOST">%1$s</xliff:g> bağlantılarını <xliff:g id="APPLICATION">%2$s</xliff:g> ile aç"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"Erişim ver"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"Şununla düzenle:"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"%1$s ile düzenle"</string>
@@ -1590,8 +1586,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"Tarayıcı Başlatılsın mı?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Çağrı kabul edilsin mi?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Her zaman"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"Her zaman açılmak üzere ayarla"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Yalnızca bir defa"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"Ayarlar"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s, iş profilini desteklemiyor"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index b02208f..347c81f 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -574,7 +574,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"Тримайте телефон лівіше."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"Тримайте телефон правіше."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"Дивіться просто на пристрій."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"Обличчя не видно. Дивіться на телефон."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"Тримайте телефон просто перед обличчям."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"Забагато рухів. Тримайте телефон нерухомо."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"Повторно проскануйте обличчя."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"Розпізнати обличчя вже не вдається. Повторіть спробу."</string>
@@ -1171,14 +1171,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"Відкрити за допомогою"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Відкрити за допомогою %1$s"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"Відкрити"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"Відкривати посилання <xliff:g id="HOST">%1$s</xliff:g> за допомогою"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"Відкривати посилання за допомогою"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"Відкривати посилання за допомогою додатка <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"Відкривати посилання <xliff:g id="HOST">%1$s</xliff:g> за допомогою додатка <xliff:g id="APPLICATION">%2$s</xliff:g>"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"Дозволити"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"Редагувати за допомогою"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Редагувати за допомогою %1$s"</string>
@@ -1636,8 +1632,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"Запустити веб-переглядач?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Прийняти виклик?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Завжди"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"Вибрати додаток для відкривання посилань"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Лише цього разу"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"Налаштування"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s не підтримує робочий профіль"</string>
@@ -2076,7 +2071,7 @@
     <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>
+    <string name="dynamic_mode_notification_summary" msgid="2541166298550402690">"Режим енергозбереження активовано для збільшення часу роботи акумулятора"</string>
     <string name="battery_saver_notification_channel_name" msgid="2083316159716201806">"Режим енергозбереження"</string>
     <string name="battery_saver_sticky_disabled_notification_title" msgid="6376147579378764641">"Режим енергозбереження не ввімкнеться, доки рівень заряду знову не знизиться"</string>
     <string name="battery_saver_sticky_disabled_notification_summary" msgid="8090192609249817945">"Акумулятор заряджено достатньо. Режим енергозбереження буде знову ввімкнено, коли рівень заряду знизиться."</string>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index 5adf84e..3fd6fe7 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"فون کو بائیں جانب لے جائيں۔"</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"فون کو دائیں جانب لے جائیں۔"</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"براہ کرم اپنے آلہ کی طرف چہرے کو سیدھا رکھیں۔"</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"آپ کا چہرہ دکھائی نہیں دے رہا۔ فون کی طرف دیکھیں۔"</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"اپنے چہرے کو براہ راست فون کے سامنے رکھیں۔"</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"کافی حرکت ہو رہی ہے۔ فون کو مضبوطی سے پکڑیں۔"</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"براہ کرم اپنے چہرے کو دوبارہ مندرج کریں۔"</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"اب چہرے کی شناخت نہیں کر سکتے۔ پھر آزمائيں۔"</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"اس کے ساتھ کھولیں"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"‏%1$s کے ساتھ کھولیں"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"کھولیں"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"<xliff:g id="HOST">%1$s</xliff:g> لنکس کے ساتھ کھولیں"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"لنکس کے ساتھ کھولیں"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"<xliff:g id="APPLICATION">%1$s</xliff:g> کے ذریعے لنکس کھولیں"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"<xliff:g id="HOST">%1$s</xliff:g> لنکس کو <xliff:g id="APPLICATION">%2$s</xliff:g> کے ذریعے کھولیں"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"رسائی دیں"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"اس کے ساتھ ترمیم کریں"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"‏%1$s کے ساتھ ترمیم کریں"</string>
@@ -1591,8 +1587,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"براؤزر شروع کریں؟"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"کال قبول کریں؟"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"ہمیشہ"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"ہمیشہ کھلا ہوا ہونے پر سیٹ کریں"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"بس ایک مرتبہ"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"ترتیبات"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"‏%1$s دفتری پروفائل کا تعاون نہیں کرتا ہے"</string>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index 1452573..85ebe00 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"Telefonni chapga suring."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"Telefonni oʻngga suring."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"Qurilmaga tik qarang."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"Yuzingiz koʻrinmayapti. Telefonga qarang."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"Telefoningizga yuzingizni tik tuting."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"Ortiqcha harakatlanmoqda. Qimirlatmasdan ushlang."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"Yuzingizni qaytadan qayd qildiring."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"Yuz tanilmadi. Qaytadan urining."</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"Ochish…"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"%1$s bilan ochish"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"Ochish"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"<xliff:g id="HOST">%1$s</xliff:g> havolalarini quyidagi orqali ochish"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"Havolalarni quyidagi orqali ochish"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"Havolalarni <xliff:g id="APPLICATION">%1$s</xliff:g> orqali ochish"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"<xliff:g id="HOST">%1$s</xliff:g> havolalarini <xliff:g id="APPLICATION">%2$s</xliff:g> orqali ochish"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"Ruxsat berish"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"Tahrirlash…"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"“%1$s” yordamida tahrirlash"</string>
@@ -1591,8 +1587,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"Brauzer ishga tushirilsinmi?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Qo‘ng‘iroqni qabul qilasizmi?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Har doim"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"Doim ochish"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Faqat hozir"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"Sozlamalar"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"“%1$s” ishchi profilni qo‘llab-quvvatlamaydi"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index b27e389..f2eb9d4 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"Đưa điện thoại sang bên trái."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"Đưa điện thoại sang bên phải."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"Vui lòng nhìn thẳng vào thiết bị."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"Hệ thống không phát hiện được khuôn mặt bạn. Hãy nhìn vào điện thoại."</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"Hướng thẳng khuôn mặt về phía trước điện thoại."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"Thiết bị di chuyển quá nhiều. Giữ yên thiết bị."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"Vui lòng đăng ký lại khuôn mặt của bạn."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"Không nhận ra khuôn mặt. Hãy thử lại."</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"Mở bằng"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Mở bằng %1$s"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"Mở"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"Mở đường dẫn liên kết <xliff:g id="HOST">%1$s</xliff:g> bằng"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"Mở đường dẫn liên kết bằng"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"Mở đường dẫn liên kết bằng <xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"Mở đường dẫn liên kết <xliff:g id="HOST">%1$s</xliff:g> bằng <xliff:g id="APPLICATION">%2$s</xliff:g>"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"Cấp quyền truy cập"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"Chỉnh sửa bằng"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Chỉnh sửa bằng %1$s"</string>
@@ -1590,8 +1586,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"Chạy trình duyệt?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Chấp nhận cuộc gọi?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Luôn chọn"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"Đặt thành luôn mở"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Chỉ một lần"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"Cài đặt"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s không hỗ trợ hồ sơ công việc"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 162b880..1012337 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"请将手机向左移动。"</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"请将手机向右移动。"</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"请直视您的设备。"</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"看不到您的脸部,请直视手机。"</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"请将你的面部正对手机。"</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"摄像头过于晃动。请将手机拿稳。"</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"请重新注册您的面孔。"</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"已无法识别人脸,请重试。"</string>
@@ -661,8 +661,8 @@
     <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="4280246270601044505">"监控在解锁屏幕时输错密码的次数,并在输错次数过多时锁定平板电脑或清空此用户的所有数据。"</string>
     <string name="policydesc_watchLogin_secondaryUser" product="TV" msgid="3484832653564483250">"监控在解锁屏幕时输错密码的次数,并在输错次数过多时锁定电视或清空此用户的所有数据。"</string>
     <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="2185480427217127147">"监控在解锁屏幕时输错密码的次数,并在输错次数过多时锁定手机或清空此用户的所有数据。"</string>
-    <string name="policylab_resetPassword" msgid="4934707632423915395">"更改锁屏密码"</string>
-    <string name="policydesc_resetPassword" msgid="1278323891710619128">"更改锁屏密码。"</string>
+    <string name="policylab_resetPassword" msgid="4934707632423915395">"更改锁屏方式"</string>
+    <string name="policydesc_resetPassword" msgid="1278323891710619128">"更改锁屏方式。"</string>
     <string name="policylab_forceLock" msgid="2274085384704248431">"锁定屏幕"</string>
     <string name="policydesc_forceLock" msgid="1141797588403827138">"控制屏幕锁定的方式和时间。"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"清除所有数据"</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"打开方式"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"使用%1$s打开"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"打开"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"<xliff:g id="HOST">%1$s</xliff:g> 链接打开方式"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"链接打开方式"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"使用<xliff:g id="APPLICATION">%1$s</xliff:g>打开链接"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"使用<xliff:g id="APPLICATION">%2$s</xliff:g>打开 <xliff:g id="HOST">%1$s</xliff:g> 链接"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"授予访问权限"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"编辑方式"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"使用%1$s编辑"</string>
@@ -1590,8 +1586,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"要启动浏览器吗?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"要接听电话吗?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"始终"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"设置为始终打开"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"仅此一次"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"设置"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s不支持工作资料"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index f4ec4d0..9ac4582 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"請將手機向左移。"</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"請將手機向右移。"</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"請以更直視的角度看著裝置。"</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"看不到您的臉。請看著手機。"</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"將手機對準您的臉孔正面。"</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"裝置不夠穩定。請拿穩手機。"</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"請重新註冊臉孔。"</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"無法再識別臉孔。請再試一次。"</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"選擇開啟方式"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"使用 %1$s 開啟"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"開啟"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"開啟 <xliff:g id="HOST">%1$s</xliff:g> 連結的方式"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"開啟連結的方式"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"使用 <xliff:g id="APPLICATION">%1$s</xliff:g> 開啟連結"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"使用 <xliff:g id="APPLICATION">%2$s</xliff:g> 開啟 <xliff:g id="HOST">%1$s</xliff:g> 連結"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"授予存取權"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"使用以下選擇器編輯:"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"使用 %1$s 編輯"</string>
@@ -1590,8 +1586,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"要啟動「瀏覽器」嗎?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"接聽電話嗎?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"一律採用"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"設為一律開啟"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"只此一次"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"設定"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s 不支援公司檔案"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 547736a..580a1dc 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"請將手機向左移動。"</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"請將手機向右移動。"</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"請儘可能直視裝置正面。"</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"無法偵測你的臉孔,請直視手機。"</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"將你的臉孔正對手機。"</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"鏡頭過度晃動,請拿穩手機。"</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"請重新註冊你的臉孔。"</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"已無法辨識臉孔,請再試一次。"</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"選擇開啟工具"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"透過 %1$s 開啟"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"開啟"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"開啟 <xliff:g id="HOST">%1$s</xliff:g> 連結時使用的瀏覽器/應用程式"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"開啟連結時使用的瀏覽器"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"使用「<xliff:g id="APPLICATION">%1$s</xliff:g>」開啟連結"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"使用「<xliff:g id="APPLICATION">%2$s</xliff:g>」開啟 <xliff:g id="HOST">%1$s</xliff:g> 連結"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"授予存取權"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"選擇編輯工具"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"使用 %1$s 編輯"</string>
@@ -1590,8 +1586,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"啟動「瀏覽器」嗎?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"接聽電話嗎?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"一律採用"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"設為一律開啟"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"僅限一次"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"設定"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s 不支援工作設定檔"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index fa8eff3..c4f8823 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -568,7 +568,7 @@
     <string name="face_acquired_too_right" msgid="3667075962661863218">"Hambisa ifoni ngakwesokunxele."</string>
     <string name="face_acquired_too_left" msgid="3148242963894703424">"Hambisa ifoni ngakwesokudla."</string>
     <string name="face_acquired_poor_gaze" msgid="5606479370806754905">"Sicela ubheke ngokuqondile kakhulu kudivayisi yakho."</string>
-    <string name="face_acquired_not_detected" msgid="4885504661626728809">"Ayikwazi ukubona ubuso bakho. Bheka ifoni"</string>
+    <string name="face_acquired_not_detected" msgid="1879714205006680222">"Beka ubuso bakho ngqo phambi kwefoni."</string>
     <string name="face_acquired_too_much_motion" msgid="3149332171102108851">"Ukunyakaza okuningi kakhulu. Bamba ifoni iqine."</string>
     <string name="face_acquired_recalibrate" msgid="8077949502893707539">"Sicela uphinde ubhalise ubuso bakho."</string>
     <string name="face_acquired_too_different" msgid="7663983770123789694">"Ayisakwazi ukubona ubuso. Zama futhi."</string>
@@ -1131,14 +1131,10 @@
     <string name="whichViewApplication" msgid="3272778576700572102">"Vula nge-"</string>
     <string name="whichViewApplicationNamed" msgid="2286418824011249620">"Vula nge-%1$s"</string>
     <string name="whichViewApplicationLabel" msgid="2666774233008808473">"Kuvuliwe"</string>
-    <!-- no translation found for whichOpenHostLinksWith (3788174881117226583) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWith (6392123355599572804) -->
-    <skip />
-    <!-- no translation found for whichOpenLinksWithApp (8225991685366651614) -->
-    <skip />
-    <!-- no translation found for whichOpenHostLinksWithApp (3464470639011045589) -->
-    <skip />
+    <string name="whichOpenHostLinksWith" msgid="3788174881117226583">"Vula izixhumanisi ze-<xliff:g id="HOST">%1$s</xliff:g> nge"</string>
+    <string name="whichOpenLinksWith" msgid="6392123355599572804">"Vula izixhumanisi nge"</string>
+    <string name="whichOpenLinksWithApp" msgid="8225991685366651614">"Vula izixhumanisi nge-<xliff:g id="APPLICATION">%1$s</xliff:g>"</string>
+    <string name="whichOpenHostLinksWithApp" msgid="3464470639011045589">"Vula izixhumanisi ze-<xliff:g id="HOST">%1$s</xliff:g> nge-<xliff:g id="APPLICATION">%2$s</xliff:g>"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="6142688895536868827">"Nikeza ukufinyel"</string>
     <string name="whichEditApplication" msgid="144727838241402655">"Hlela nge-"</string>
     <string name="whichEditApplicationNamed" msgid="1775815530156447790">"Hlela nge-%1$s"</string>
@@ -1590,8 +1586,7 @@
     <string name="launchBrowserDefault" msgid="2057951947297614725">"Qala Isiphequluli?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Amukela ucingo?"</string>
     <string name="activity_resolver_use_always" msgid="8017770747801494933">"Njalo"</string>
-    <!-- no translation found for activity_resolver_set_always (1422574191056490585) -->
-    <skip />
+    <string name="activity_resolver_set_always" msgid="1422574191056490585">"Setha ukuthi kuhlale kuvuliwe"</string>
     <string name="activity_resolver_use_once" msgid="2404644797149173758">"Kanye nje"</string>
     <string name="activity_resolver_app_settings" msgid="8965806928986509855">"Izilungiselelo"</string>
     <string name="activity_resolver_work_profiles_support" msgid="185598180676883455">"%1$s ayisekeli iphrofayela yomsebenzi"</string>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index f515b2d..5ea7f5b 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -4133,8 +4133,27 @@
          for higher refresh rates to be automatically used out of the box -->
     <integer name="config_defaultPeakRefreshRate">60</integer>
 
-    <!-- The default brightness threshold that allows to switch to higher refresh rate -->
-    <integer name="config_brightnessThresholdOfPeakRefreshRate">-1</integer>
+    <!-- The display uses different gamma curves for different refresh rates. It's hard for panel
+         vendor to tune the curves to have exact same brightness for different refresh rate. So
+         flicker could be observed at switch time. The issue is worse at the gamma lower end.
+         In addition, human eyes are more sensitive to the flicker at darker environment.
+         To prevent flicker, we only support higher refresh rates if the display brightness is above
+         a threshold. And the darker environment could have higher threshold.
+         For example, no higher refresh rate if
+             display brightness <= disp0 && ambient brightness <= amb0
+             || display brightness <= disp1 && ambient brightness <= amb1 -->
+    <integer-array translatable="false" name="config_brightnessThresholdsOfPeakRefreshRate">
+         <!--
+           <item>disp0</item>
+           <item>disp1</item>
+        -->
+    </integer-array>
+    <integer-array translatable="false" name="config_ambientThresholdsOfPeakRefreshRate">
+         <!--
+           <item>amb0</item>
+           <item>amb1</item>
+        -->
+    </integer-array>
 
     <!-- The type of the light sensor to be used by the display framework for things like
          auto-brightness. If unset, then it just gets the default sensor of type TYPE_LIGHT. -->
@@ -4210,6 +4229,14 @@
          one bar higher than they actually are -->
     <bool name="config_inflateSignalStrength">false</bool>
 
+    <!-- Trigger a warning for notifications with RemoteView objects that are larger in bytes than
+    this value (default 1MB)-->
+    <integer name="config_notificationWarnRemoteViewSizeBytes">1000000</integer>
+
+    <!-- Strip notification RemoteView objects that are larger in bytes than this value (also log)
+    (default 2MB) -->
+    <integer name="config_notificationStripRemoteViewSizeBytes">2000000</integer>
+
     <!-- Sharesheet: define a max number of targets per application for new shortcuts-based direct share introduced in Q -->
     <integer name="config_maxShortcutTargetsPerApp">3</integer>
 
@@ -4217,4 +4244,8 @@
     the default implementation of ACTION_FACTORY_RESET does not work, so it is needed to re-route
     this intent to this package. This is being used in MasterClearReceiver.java. -->
     <string name="config_factoryResetPackage" translatable="false"></string>
+
+    <!-- The list of packages to automatically opt out of refresh rates higher than 60hz because
+         of known compatibility issues. -->
+    <string-array name="config_highRefreshRateBlacklist"></string-array>
 </resources>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 5363ef9..039bc4d 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -90,6 +90,24 @@
         orientation. If zero, the value of rounded_corner_radius is used. -->
     <dimen name="rounded_corner_radius_bottom">0dp</dimen>
 
+    <!-- Default adjustment for the software rounded corners since corners are not perfectly
+        round. This value is used when retrieving the "radius" of the rounded corner in cases
+        where the exact bezier curve cannot be retrieved.  This value will be subtracted from
+        rounded_corner_radius to more accurately provide a "radius" for the rounded corner. -->
+    <dimen name="rounded_corner_radius_adjustment">0px</dimen>
+    <!-- Top adjustment for the software rounded corners since corners are not perfectly
+        round.  This value is used when retrieving the "radius" of the top rounded corner in cases
+        where the exact bezier curve cannot be retrieved.  This value will be subtracted from
+        rounded_corner_radius_top to more accurately provide a "radius" for the top rounded corners.
+         -->
+    <dimen name="rounded_corner_radius_top_adjustment">0px</dimen>
+    <!-- Bottom adjustment for the software rounded corners since corners are not perfectly
+        round.  This value is used when retrieving the "radius" of the bottom rounded corner in
+        cases where the exact bezier curve cannot be retrieved.  This value will be subtracted from
+        rounded_corner_radius_bottom to more accurately provide a "radius" for the bottom rounded
+        corners. -->
+    <dimen name="rounded_corner_radius_bottom_adjustment">0px</dimen>
+
     <!-- Width of the window of the divider bar used to resize docked stacks. -->
     <dimen name="docked_stack_divider_thickness">48dp</dimen>
 
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 6c908aa..c4dbde8 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3708,6 +3708,9 @@
   <java-symbol type="dimen" name="rounded_corner_radius" />
   <java-symbol type="dimen" name="rounded_corner_radius_top" />
   <java-symbol type="dimen" name="rounded_corner_radius_bottom" />
+  <java-symbol type="dimen" name="rounded_corner_radius_adjustment" />
+  <java-symbol type="dimen" name="rounded_corner_radius_top_adjustment" />
+  <java-symbol type="dimen" name="rounded_corner_radius_bottom_adjustment" />
   <java-symbol type="bool" name="config_supportsRoundedCornersOnWindows" />
 
   <java-symbol type="string" name="config_defaultModuleMetadataProvider" />
@@ -3790,7 +3793,8 @@
 
   <!-- For high refresh rate displays -->
   <java-symbol type="integer" name="config_defaultPeakRefreshRate" />
-  <java-symbol type="integer" name="config_brightnessThresholdOfPeakRefreshRate" />
+  <java-symbol type="array" name="config_brightnessThresholdsOfPeakRefreshRate" />
+  <java-symbol type="array" name="config_ambientThresholdsOfPeakRefreshRate" />
 
   <!-- For Auto-Brightness -->
   <java-symbol type="string" name="config_displayLightSensorType" />
@@ -3823,5 +3827,14 @@
 
   <java-symbol type="string" name="config_defaultSupervisionProfileOwnerComponent" />
   <java-symbol type="bool" name="config_inflateSignalStrength" />
+
+  <java-symbol type="drawable" name="android_logotype" />
+  <java-symbol type="layout" name="platlogo_layout" />
+
+  <java-symbol type="integer" name="config_notificationWarnRemoteViewSizeBytes" />
+  <java-symbol type="integer" name="config_notificationStripRemoteViewSizeBytes" />
+
   <java-symbol type="string" name="config_factoryResetPackage" />
+  <java-symbol type="array" name="config_highRefreshRateBlacklist" />
+
 </resources>
diff --git a/core/tests/coretests/res/values/overlayable_icons_test.xml b/core/tests/coretests/res/values/overlayable_icons_test.xml
deleted file mode 100644
index 6503f3e..0000000
--- a/core/tests/coretests/res/values/overlayable_icons_test.xml
+++ /dev/null
@@ -1,86 +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.
--->
-<resources>
-  <!-- overlayable_icons references all of the drawables in this package
-       that are being overlayed by resource overlays. If you remove/rename
-       any of these resources, you must also change the resource overlay icons.-->
-  <array name="overlayable_icons">
-    <item>@*android:drawable/ic_audio_alarm</item>
-    <item>@*android:drawable/ic_audio_alarm_mute</item>
-    <item>@*android:drawable/ic_battery_80_24dp</item>
-    <item>@*android:drawable/ic_bluetooth_share_icon</item>
-    <item>@*android:drawable/ic_bt_headphones_a2dp</item>
-    <item>@*android:drawable/ic_bt_headset_hfp</item>
-    <item>@*android:drawable/ic_bt_hearing_aid</item>
-    <item>@*android:drawable/ic_bt_laptop</item>
-    <item>@*android:drawable/ic_bt_misc_hid</item>
-    <item>@*android:drawable/ic_bt_network_pan</item>
-    <item>@*android:drawable/ic_bt_pointing_hid</item>
-    <item>@*android:drawable/ic_corp_badge</item>
-    <item>@*android:drawable/ic_expand_more</item>
-    <item>@*android:drawable/ic_faster_emergency</item>
-    <item>@*android:drawable/ic_file_copy</item>
-    <item>@*android:drawable/ic_lock</item>
-    <item>@*android:drawable/ic_lock_bugreport</item>
-    <item>@*android:drawable/ic_lock_open</item>
-    <item>@*android:drawable/ic_lock_power_off</item>
-    <item>@*android:drawable/ic_lockscreen_ime</item>
-    <item>@*android:drawable/ic_mode_edit</item>
-    <item>@*android:drawable/ic_notifications_alerted</item>
-    <item>@*android:drawable/ic_phone</item>
-    <item>@*android:drawable/ic_qs_airplane</item>
-    <item>@*android:drawable/ic_qs_auto_rotate</item>
-    <item>@*android:drawable/ic_qs_battery_saver</item>
-    <item>@*android:drawable/ic_qs_bluetooth</item>
-    <item>@*android:drawable/ic_qs_dnd</item>
-    <item>@*android:drawable/ic_qs_flashlight</item>
-    <item>@*android:drawable/ic_qs_night_display_on</item>
-    <item>@*android:drawable/ic_qs_ui_mode_night</item>
-    <item>@*android:drawable/ic_restart</item>
-    <item>@*android:drawable/ic_screenshot</item>
-    <item>@*android:drawable/ic_settings_bluetooth</item>
-    <item>@*android:drawable/ic_signal_cellular_0_4_bar</item>
-    <item>@*android:drawable/ic_signal_cellular_0_5_bar</item>
-    <item>@*android:drawable/ic_signal_cellular_1_4_bar</item>
-    <item>@*android:drawable/ic_signal_cellular_1_5_bar</item>
-    <item>@*android:drawable/ic_signal_cellular_2_4_bar</item>
-    <item>@*android:drawable/ic_signal_cellular_2_5_bar</item>
-    <item>@*android:drawable/ic_signal_cellular_3_4_bar</item>
-    <item>@*android:drawable/ic_signal_cellular_3_5_bar</item>
-    <item>@*android:drawable/ic_signal_cellular_4_4_bar</item>
-    <item>@*android:drawable/ic_signal_cellular_4_5_bar</item>
-    <item>@*android:drawable/ic_signal_cellular_5_5_bar</item>
-    <item>@*android:drawable/ic_signal_location</item>
-    <item>@*android:drawable/ic_wifi_signal_0</item>
-    <item>@*android:drawable/ic_wifi_signal_1</item>
-    <item>@*android:drawable/ic_wifi_signal_2</item>
-    <item>@*android:drawable/ic_wifi_signal_3</item>
-    <item>@*android:drawable/ic_wifi_signal_4</item>
-    <item>@*android:drawable/perm_group_activity_recognition</item>
-    <item>@*android:drawable/perm_group_aural</item>
-    <item>@*android:drawable/perm_group_calendar</item>
-    <item>@*android:drawable/perm_group_call_log</item>
-    <item>@*android:drawable/perm_group_camera</item>
-    <item>@*android:drawable/perm_group_contacts</item>
-    <item>@*android:drawable/perm_group_location</item>
-    <item>@*android:drawable/perm_group_microphone</item>
-    <item>@*android:drawable/perm_group_phone_calls</item>
-    <item>@*android:drawable/perm_group_sensors</item>
-    <item>@*android:drawable/perm_group_sms</item>
-    <item>@*android:drawable/perm_group_storage</item>
-    <item>@*android:drawable/perm_group_visual</item>
-  </array>
-</resources>
diff --git a/core/tests/coretests/src/android/os/RedactingFileDescriptorTest.java b/core/tests/coretests/src/android/os/RedactingFileDescriptorTest.java
index d5163e1..eff4826 100644
--- a/core/tests/coretests/src/android/os/RedactingFileDescriptorTest.java
+++ b/core/tests/coretests/src/android/os/RedactingFileDescriptorTest.java
@@ -64,7 +64,7 @@
     @Test
     public void testSingleByte() throws Exception {
         final FileDescriptor fd = RedactingFileDescriptor.open(mContext, mFile, MODE_READ_ONLY,
-                new long[] { 10, 11 }).getFileDescriptor();
+                new long[] { 10, 11 }, new long[] {}).getFileDescriptor();
 
         final byte[] buf = new byte[1_000];
         assertEquals(buf.length, Os.read(fd, buf, 0, buf.length));
@@ -80,7 +80,7 @@
     @Test
     public void testRanges() throws Exception {
         final FileDescriptor fd = RedactingFileDescriptor.open(mContext, mFile, MODE_READ_ONLY,
-                new long[] { 100, 200, 300, 400 }).getFileDescriptor();
+                new long[] { 100, 200, 300, 400 }, new long[] {}).getFileDescriptor();
 
         final byte[] buf = new byte[10];
         assertEquals(buf.length, Os.pread(fd, buf, 0, 10, 90));
@@ -102,7 +102,7 @@
     @Test
     public void testEntireFile() throws Exception {
         final FileDescriptor fd = RedactingFileDescriptor.open(mContext, mFile, MODE_READ_ONLY,
-                new long[] { 0, 5_000_000 }).getFileDescriptor();
+                new long[] { 0, 5_000_000 }, new long[] {}).getFileDescriptor();
 
         try (FileInputStream in = new FileInputStream(fd)) {
             int val;
@@ -115,7 +115,7 @@
     @Test
     public void testReadWrite() throws Exception {
         final FileDescriptor fd = RedactingFileDescriptor.open(mContext, mFile, MODE_READ_WRITE,
-                new long[] { 100, 200, 300, 400 }).getFileDescriptor();
+                new long[] { 100, 200, 300, 400 }, new long[] {}).getFileDescriptor();
 
         // Redacted at first
         final byte[] buf = new byte[10];
@@ -168,4 +168,76 @@
         assertArrayEquals(new long[] { 100, 200 },
                 removeRange(new long[] { 100, 200 }, 150, 150));
     }
+
+    @Test
+    public void testFreeAtStart() throws Exception {
+        final FileDescriptor fd = RedactingFileDescriptor.open(mContext, mFile, MODE_READ_WRITE,
+                new long[] { 1, 10 }, new long[] {1}).getFileDescriptor();
+
+        final byte[] buf = new byte[10];
+        assertEquals(buf.length, Os.pread(fd, buf, 0, 10, 0));
+        assertArrayEquals(
+                new byte[] { 64, (byte) 'f', (byte) 'r', (byte) 'e', (byte) 'e', 0, 0, 0, 0, 0 },
+                buf);
+    }
+
+    @Test
+    public void testFreeAtOffset() throws Exception {
+        final FileDescriptor fd = RedactingFileDescriptor.open(mContext, mFile, MODE_READ_WRITE,
+                new long[] { 1, 10 }, new long[] {3}).getFileDescriptor();
+
+        final byte[] buf = new byte[10];
+        assertEquals(buf.length, Os.pread(fd, buf, 0, 10, 0));
+        assertArrayEquals(
+                new byte[] { 64, 0, 0, (byte) 'f', (byte) 'r', (byte) 'e', (byte) 'e', 0, 0, 0 },
+                buf);
+    }
+
+    @Test
+    public void testFreeAcrossRedactionStart() throws Exception {
+        final FileDescriptor fd = RedactingFileDescriptor.open(mContext, mFile, MODE_READ_WRITE,
+                new long[] { 1, 10 }, new long[] {0}).getFileDescriptor();
+
+        final byte[] buf = new byte[10];
+        assertEquals(buf.length, Os.pread(fd, buf, 0, 10, 0));
+        assertArrayEquals(
+                new byte[] { 64, (byte) 'r', (byte) 'e', (byte) 'e', 0, 0, 0, 0, 0, 0 },
+                buf);
+    }
+
+    @Test
+    public void testFreeAcrossRedactionEnd() throws Exception {
+        final FileDescriptor fd = RedactingFileDescriptor.open(mContext, mFile, MODE_READ_WRITE,
+                new long[] { 1, 3 }, new long[] {2}).getFileDescriptor();
+
+        final byte[] buf = new byte[10];
+        assertEquals(buf.length, Os.pread(fd, buf, 0, 10, 0));
+        assertArrayEquals(
+                new byte[] { 64, 0, (byte) 'f', 64, 64, 64, 64, 64, 64, 64 },
+                buf);
+    }
+
+    @Test
+    public void testFreeOutsideRedaction() throws Exception {
+        final FileDescriptor fd = RedactingFileDescriptor.open(mContext, mFile, MODE_READ_WRITE,
+                new long[] { 1, 8 }, new long[] { 8 }).getFileDescriptor();
+
+        final byte[] buf = new byte[10];
+        assertEquals(buf.length, Os.pread(fd, buf, 0, 10, 0));
+        assertArrayEquals(
+                new byte[] { 64, 0, 0, 0, 0, 0, 0, 0, 64, 64 },
+                buf);
+    }
+
+    @Test
+    public void testFreeMultipleRedactions() throws Exception {
+        final FileDescriptor fd = RedactingFileDescriptor.open(mContext, mFile, MODE_READ_WRITE,
+                new long[] { 1, 2, 3, 4 }, new long[] { 0 }).getFileDescriptor();
+
+        final byte[] buf = new byte[10];
+        assertEquals(buf.length, Os.pread(fd, buf, 0, 10, 0));
+        assertArrayEquals(
+                new byte[] { 64, (byte) 'r', 64, (byte) 'e', 64, 64, 64, 64, 64, 64 },
+                buf);
+    }
 }
diff --git a/core/tests/coretests/src/android/view/DisplayCutoutTest.java b/core/tests/coretests/src/android/view/DisplayCutoutTest.java
index 182fe78..d5a0dfa 100644
--- a/core/tests/coretests/src/android/view/DisplayCutoutTest.java
+++ b/core/tests/coretests/src/android/view/DisplayCutoutTest.java
@@ -104,8 +104,8 @@
 
     @Test
     public void testExtractBoundsFromList_top_and_bottom() {
-        Rect safeInsets = new Rect(0, 1, 0, 10);
-        Rect boundTop = new Rect(80, 0, 120, 10);
+        Rect safeInsets = new Rect(0, 10, 0, 10);
+        Rect boundTop = new Rect(0, 0, 120, 10);
         Rect boundBottom = new Rect(80, 190, 120, 200);
         assertThat(extractBoundsFromList(safeInsets,
                 Arrays.asList(new Rect[]{boundTop, boundBottom})),
diff --git a/core/tests/coretests/src/com/android/internal/policy/DecorViewTest.java b/core/tests/coretests/src/com/android/internal/policy/DecorViewTest.java
new file mode 100644
index 0000000..f66717e
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/policy/DecorViewTest.java
@@ -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.
+ */
+
+package com.android.internal.policy;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.drawable.Drawable;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.frameworks.coretests.R;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.Arrays;
+
+public class DecorViewTest {
+
+    private Context mContext;
+    private DecorView mDecorView;
+
+    @Before
+    public void setUp() {
+        mContext = InstrumentationRegistry.getInstrumentation().getContext();
+        PhoneWindow phoneWindow = new PhoneWindow(mContext);
+        mDecorView = (DecorView) phoneWindow.getDecorView();
+    }
+
+    @Test
+    public void setBackgroundDrawableSameAsSetWindowBackground() {
+        Drawable bitmapDrawable = mContext.getResources()
+                .getDrawable(R.drawable.test16x12, mContext.getTheme());
+        int w = 16;
+        int h = 12;
+        Bitmap expectedBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
+
+        mDecorView.setWindowBackground(bitmapDrawable);
+        Canvas testCanvas = new Canvas(expectedBitmap);
+        mDecorView.draw(testCanvas);
+        testCanvas.release();
+
+        Drawable expectedBackground = mDecorView.getBackground();
+
+        mDecorView.setBackgroundDrawable(bitmapDrawable);
+        Bitmap resultBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
+        Canvas resCanvas = new Canvas(resultBitmap);
+        mDecorView.draw(resCanvas);
+        resCanvas.release();
+
+        // Check that the drawable is the same.
+        assertThat(mDecorView.getBackground()).isEqualTo(expectedBackground);
+        assertThat(mDecorView.getBackground()).isEqualTo(bitmapDrawable);
+
+        // Check that canvas is the same.
+        int[] expPixels = new int[w * h];
+        int[] resPixels = new int[w * h];
+        resultBitmap.getPixels(resPixels, 0, w, 0, 0, w, h);
+        expectedBitmap.getPixels(expPixels, 0, w, 0, 0, w, h);
+        assertThat(Arrays.toString(expPixels)).isEqualTo(Arrays.toString(resPixels));
+    }
+}
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 54c548a..89e26da 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -269,6 +269,8 @@
         <permission name="android.permission.INSTALL_PACKAGES"/>
         <!-- Needed for test only -->
         <permission name="android.permission.INTERACT_ACROSS_PROFILES"/>
+        <!-- Permission required to test onPermissionsChangedListener -->
+        <permission name="android.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS"/>
         <permission name="android.permission.INTERACT_ACROSS_USERS"/>
         <permission name="android.permission.LOCAL_MAC_ADDRESS"/>
         <permission name="android.permission.MANAGE_ACCESSIBILITY"/>
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index bf948b1..0d837f2 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -195,6 +195,7 @@
         "RecordingCanvas.cpp",
         "RenderNode.cpp",
         "RenderProperties.cpp",
+        "RootRenderNode.cpp",
         "SkiaCanvas.cpp",
         "VectorDrawable.cpp",
     ],
@@ -250,7 +251,6 @@
                 "ProfileData.cpp",
                 "ProfileDataContainer.cpp",
                 "Readback.cpp",
-                "RootRenderNode.cpp",
                 "TreeInfo.cpp",
                 "WebViewFunctorManager.cpp",
                 "protos/graphicsstats.proto",
diff --git a/libs/hwui/Animator.cpp b/libs/hwui/Animator.cpp
index 93b9dec..74cf1fd 100644
--- a/libs/hwui/Animator.cpp
+++ b/libs/hwui/Animator.cpp
@@ -155,11 +155,9 @@
         RenderNode* oldTarget = mTarget;
         mTarget = mStagingTarget;
         mStagingTarget = nullptr;
-#ifdef __ANDROID__ // Layoutlib does not support RenderNode
         if (oldTarget && oldTarget != mTarget) {
             oldTarget->onAnimatorTargetChanged(this);
         }
-#endif
     }
 
     if (!mHasStartValue) {
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
index e58fbbe..c8eb1ca 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -274,7 +274,12 @@
     }
     sk_sp<SkDrawable> drawable;
     SkMatrix matrix = SkMatrix::I();
-    void draw(SkCanvas* c, const SkMatrix&) const { c->drawDrawable(drawable.get(), &matrix); }
+    // It is important that we call drawable->draw(c) here instead of c->drawDrawable(drawable).
+    // Drawables are mutable and in cases, like RenderNodeDrawable, are not expected to produce the
+    // same content if retained outside the duration of the frame. Therefore we resolve
+    // them now and do not allow the canvas to take a reference to the drawable and potentially
+    // keep it alive for longer than the frames duration (e.g. SKP serialization).
+    void draw(SkCanvas* c, const SkMatrix&) const { drawable->draw(c, &matrix); }
 };
 struct DrawPicture final : Op {
     static const auto kType = Type::DrawPicture;
diff --git a/libs/hwui/RootRenderNode.cpp b/libs/hwui/RootRenderNode.cpp
index 2480192..ddbbf58 100644
--- a/libs/hwui/RootRenderNode.cpp
+++ b/libs/hwui/RootRenderNode.cpp
@@ -16,10 +16,13 @@
 
 #include "RootRenderNode.h"
 
+#ifdef __ANDROID__ // Layoutlib does not support Looper (windows)
 #include <utils/Looper.h>
+#endif
 
 namespace android::uirenderer {
 
+#ifdef __ANDROID__ // Layoutlib does not support Looper
 class FinishAndInvokeListener : public MessageHandler {
 public:
     explicit FinishAndInvokeListener(PropertyValuesAnimatorSet* anim) : mAnimator(anim) {
@@ -282,5 +285,22 @@
 AnimationContext* ContextFactoryImpl::createAnimationContext(renderthread::TimeLord& clock) {
     return new AnimationContextBridge(clock, mRootNode);
 }
+#else
+
+void RootRenderNode::prepareTree(TreeInfo& info) {
+    info.errorHandler = mErrorHandler.get();
+    info.updateWindowPositions = true;
+    RenderNode::prepareTree(info);
+    info.updateWindowPositions = false;
+    info.errorHandler = nullptr;
+}
+
+void RootRenderNode::attachAnimatingNode(RenderNode* animatingNode) { }
+
+void RootRenderNode::destroy() { }
+
+void RootRenderNode::addVectorDrawableAnimator(PropertyValuesAnimatorSet* anim) { }
+
+#endif
 
 }  // namespace android::uirenderer
diff --git a/libs/hwui/RootRenderNode.h b/libs/hwui/RootRenderNode.h
index 5c830e0..12de4ec 100644
--- a/libs/hwui/RootRenderNode.h
+++ b/libs/hwui/RootRenderNode.h
@@ -74,6 +74,7 @@
     void detachVectorDrawableAnimator(PropertyValuesAnimatorSet* anim);
 };
 
+#ifdef __ANDROID__ // Layoutlib does not support Animations
 class ANDROID_API ContextFactoryImpl : public IContextFactory {
 public:
     ANDROID_API explicit ContextFactoryImpl(RootRenderNode* rootNode) : mRootNode(rootNode) {}
@@ -84,5 +85,6 @@
 private:
     RootRenderNode* mRootNode;
 };
+#endif
 
 }  // namespace android::uirenderer
diff --git a/libs/hwui/pipeline/skia/LayerDrawable.cpp b/libs/hwui/pipeline/skia/LayerDrawable.cpp
index eed1942..96b17e1 100644
--- a/libs/hwui/pipeline/skia/LayerDrawable.cpp
+++ b/libs/hwui/pipeline/skia/LayerDrawable.cpp
@@ -33,21 +33,47 @@
     }
 }
 
-// This is a less-strict matrix.isTranslate() that will still report being translate-only
-// on imperceptibly small scaleX & scaleY values.
-static bool isBasicallyTranslate(const SkMatrix& matrix) {
-    if (!matrix.isScaleTranslate()) return false;
-    return MathUtils::isOne(matrix.getScaleX()) && MathUtils::isOne(matrix.getScaleY());
-}
-
-static bool shouldFilter(const SkMatrix& matrix) {
-    if (!matrix.isScaleTranslate()) return true;
-
-    // We only care about meaningful scale here
-    bool noScale = MathUtils::isOne(matrix.getScaleX()) && MathUtils::isOne(matrix.getScaleY());
-    bool pixelAligned =
-            SkScalarIsInt(matrix.getTranslateX()) && SkScalarIsInt(matrix.getTranslateY());
-    return !(noScale && pixelAligned);
+// Disable filtering when there is no scaling in screen coordinates and the corners have the same
+// fraction (for translate) or zero fraction (for any other rect-to-rect transform).
+static bool shouldFilterRect(const SkMatrix& matrix, const SkRect& srcRect, const SkRect& dstRect) {
+    if (!matrix.rectStaysRect()) return true;
+    SkRect dstDevRect = matrix.mapRect(dstRect);
+    float dstW, dstH;
+    bool requiresIntegerTranslate = false;
+    if (MathUtils::isZero(matrix.getScaleX()) && MathUtils::isZero(matrix.getScaleY())) {
+        // Has a 90 or 270 degree rotation, although total matrix may also have scale factors
+        // in m10 and m01. Those scalings are automatically handled by mapRect so comparing
+        // dimensions is sufficient, but swap width and height comparison.
+        dstW = dstDevRect.height();
+        dstH = dstDevRect.width();
+        requiresIntegerTranslate = true;
+    } else {
+        // Handle H/V flips or 180 rotation matrices. Axes may have been mirrored, but
+        // dimensions are still safe to compare directly.
+        dstW = dstDevRect.width();
+        dstH = dstDevRect.height();
+        requiresIntegerTranslate =
+                matrix.getScaleX() < -NON_ZERO_EPSILON || matrix.getScaleY() < -NON_ZERO_EPSILON;
+    }
+    if (!(MathUtils::areEqual(dstW, srcRect.width()) &&
+          MathUtils::areEqual(dstH, srcRect.height()))) {
+        return true;
+    }
+    if (requiresIntegerTranslate) {
+        // Device rect and source rect should be integer aligned to ensure there's no difference
+        // in how nearest-neighbor sampling is resolved.
+        return !(MathUtils::isZero(SkScalarFraction(srcRect.x())) &&
+                 MathUtils::isZero(SkScalarFraction(srcRect.y())) &&
+                 MathUtils::isZero(SkScalarFraction(dstDevRect.x())) &&
+                 MathUtils::isZero(SkScalarFraction(dstDevRect.y())));
+    } else {
+        // As long as src and device rects are translated by the same fractional amount,
+        // filtering won't be needed
+        return !(MathUtils::areEqual(SkScalarFraction(srcRect.x()),
+                                     SkScalarFraction(dstDevRect.x())) &&
+                 MathUtils::areEqual(SkScalarFraction(srcRect.y()),
+                                     SkScalarFraction(dstDevRect.y())));
+    }
 }
 
 bool LayerDrawable::DrawLayer(GrContext* context, SkCanvas* canvas, Layer* layer,
@@ -114,24 +140,21 @@
                 skiaDestRect = SkRect::MakeIWH(layerWidth, layerHeight);
             }
             matrixInv.mapRect(&skiaDestRect);
-            // If (matrix is identity or an integer translation) and (src/dst buffers size match),
+            // If (matrix is a rect-to-rect transform)
+            // and (src/dst buffers size match in screen coordinates)
+            // and (src/dst corners align fractionally),
             // then use nearest neighbor, otherwise use bilerp sampling.
-            // Integer translation is defined as when src rect and dst rect align fractionally.
             // Skia TextureOp has the above logic build-in, but not NonAAFillRectOp. TextureOp works
             // only for SrcOver blending and without color filter (readback uses Src blending).
-            bool isIntegerTranslate =
-                    isBasicallyTranslate(totalMatrix) &&
-                    SkScalarFraction(skiaDestRect.fLeft + totalMatrix[SkMatrix::kMTransX]) ==
-                            SkScalarFraction(skiaSrcRect.fLeft) &&
-                    SkScalarFraction(skiaDestRect.fTop + totalMatrix[SkMatrix::kMTransY]) ==
-                            SkScalarFraction(skiaSrcRect.fTop);
-            if (layer->getForceFilter() || !isIntegerTranslate) {
+            if (layer->getForceFilter() ||
+                shouldFilterRect(totalMatrix, skiaSrcRect, skiaDestRect)) {
                 paint.setFilterQuality(kLow_SkFilterQuality);
             }
             canvas->drawImageRect(layerImage.get(), skiaSrcRect, skiaDestRect, &paint,
                                   SkCanvas::kFast_SrcRectConstraint);
         } else {
-            if (layer->getForceFilter() || shouldFilter(totalMatrix)) {
+            SkRect imageRect = SkRect::MakeIWH(layerImage->width(), layerImage->height());
+            if (layer->getForceFilter() || shouldFilterRect(totalMatrix, imageRect, imageRect)) {
                 paint.setFilterQuality(kLow_SkFilterQuality);
             }
             canvas->drawImage(layerImage.get(), 0, 0, &paint);
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
index 84c0d13..530926b 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
@@ -313,8 +313,7 @@
         case CaptureMode::CallbackAPI:
         case CaptureMode::SingleFrameSKP:
             mRecorder.reset(new SkPictureRecorder());
-            pictureCanvas = mRecorder->beginRecording(surface->width(), surface->height(),
-                nullptr, SkPictureRecorder::kPlaybackDrawPicture_RecordFlag);
+            pictureCanvas = mRecorder->beginRecording(surface->width(), surface->height());
             break;
         case CaptureMode::MultiFrameSKP:
             // If a multi frame recording is active, initialize recording for a single frame of a
diff --git a/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp b/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
index c813cd9..e70378b 100644
--- a/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
+++ b/libs/hwui/tests/unit/RenderNodeDrawableTests.cpp
@@ -1096,10 +1096,8 @@
         int getDrawCounter() { return mDrawCounter; }
 
         virtual void onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) override {
-            // expect to draw 2 RenderNodeDrawable, 1 StartReorderBarrierDrawable,
-            // 1 EndReorderBarrierDrawable
-            mDrawCounter++;
-            SkCanvas::onDrawDrawable(drawable, matrix);
+            // Do not expect this to be called. See RecordingCanvas.cpp DrawDrawable for context.
+            EXPECT_TRUE(false);
         }
 
         virtual void didTranslate(SkScalar dx, SkScalar dy) override {
@@ -1159,8 +1157,8 @@
     // create a canvas not backed by any device/pixels, but with dimensions to avoid quick rejection
     ShadowTestCanvas canvas(CANVAS_WIDTH, CANVAS_HEIGHT);
     RenderNodeDrawable drawable(parent.get(), &canvas, false);
-    canvas.drawDrawable(&drawable);
-    EXPECT_EQ(9, canvas.getDrawCounter());
+    drawable.draw(&canvas);
+    EXPECT_EQ(5, canvas.getDrawCounter());
 }
 
 // Draw a vector drawable twice but with different bounds and verify correct bounds are used.
diff --git a/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java b/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java
index 7823971..274e0e4 100644
--- a/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java
+++ b/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java
@@ -40,127 +40,116 @@
  */
 public class GnssMetrics {
 
-  private static final String TAG = GnssMetrics.class.getSimpleName();
+    private static final String TAG = GnssMetrics.class.getSimpleName();
 
-  /* Constant which indicates GPS signal quality is as yet unknown */
-  public static final int GPS_SIGNAL_QUALITY_UNKNOWN =
-          ServerLocationProtoEnums.GPS_SIGNAL_QUALITY_UNKNOWN; // -1
+    /* Constant which indicates GPS signal quality is as yet unknown */
+    private static final int GPS_SIGNAL_QUALITY_UNKNOWN =
+            ServerLocationProtoEnums.GPS_SIGNAL_QUALITY_UNKNOWN; // -1
 
-  /* Constant which indicates GPS signal quality is poor */
-  public static final int GPS_SIGNAL_QUALITY_POOR =
-      ServerLocationProtoEnums.GPS_SIGNAL_QUALITY_POOR; // 0
+    /* Constant which indicates GPS signal quality is poor */
+    private static final int GPS_SIGNAL_QUALITY_POOR =
+            ServerLocationProtoEnums.GPS_SIGNAL_QUALITY_POOR; // 0
 
-  /* Constant which indicates GPS signal quality is good */
-  public static final int GPS_SIGNAL_QUALITY_GOOD =
-      ServerLocationProtoEnums.GPS_SIGNAL_QUALITY_GOOD; // 1
+    /* Constant which indicates GPS signal quality is good */
+    private static final int GPS_SIGNAL_QUALITY_GOOD =
+            ServerLocationProtoEnums.GPS_SIGNAL_QUALITY_GOOD; // 1
 
-  /* Number of GPS signal quality levels */
-  public static final int NUM_GPS_SIGNAL_QUALITY_LEVELS = GPS_SIGNAL_QUALITY_GOOD + 1;
+    /* Number of GPS signal quality levels */
+    public static final int NUM_GPS_SIGNAL_QUALITY_LEVELS = GPS_SIGNAL_QUALITY_GOOD + 1;
 
-  /** Default time between location fixes (in millisecs) */
-  private static final int DEFAULT_TIME_BETWEEN_FIXES_MILLISECS = 1000;
+    /** Default time between location fixes (in millisecs) */
+    private static final int DEFAULT_TIME_BETWEEN_FIXES_MILLISECS = 1000;
 
-  /* The time since boot when logging started */
-  private String logStartInElapsedRealTime;
+    /* The time since boot when logging started */
+    private String mLogStartInElapsedRealTime;
 
-  /* GNSS power metrics */
-  private GnssPowerMetrics mGnssPowerMetrics;
+    /* GNSS power metrics */
+    private GnssPowerMetrics mGnssPowerMetrics;
+
+    /* A boolean array indicating whether the constellation types have been used in fix. */
+    private boolean[] mConstellationTypes;
+    /** Location failure statistics */
+    private Statistics mLocationFailureStatistics;
+    /** Time to first fix statistics */
+    private Statistics mTimeToFirstFixSecStatistics;
+    /** Position accuracy statistics */
+    private Statistics mPositionAccuracyMeterStatistics;
+    /** Top 4 average CN0 statistics */
+    private Statistics mTopFourAverageCn0Statistics;
+
+    public GnssMetrics(IBatteryStats stats) {
+        mGnssPowerMetrics = new GnssPowerMetrics(stats);
+        mLocationFailureStatistics = new Statistics();
+        mTimeToFirstFixSecStatistics = new Statistics();
+        mPositionAccuracyMeterStatistics = new Statistics();
+        mTopFourAverageCn0Statistics = new Statistics();
+        reset();
+    }
 
     /**
-     * A boolean array indicating whether the constellation types have been used in fix.
+     * Logs the status of a location report received from the HAL
      */
-    private boolean[] mConstellationTypes;
-
-  /** Constructor */
-  public GnssMetrics(IBatteryStats stats) {
-    mGnssPowerMetrics = new GnssPowerMetrics(stats);
-    locationFailureStatistics = new Statistics();
-    timeToFirstFixSecStatistics = new Statistics();
-    positionAccuracyMeterStatistics = new Statistics();
-    topFourAverageCn0Statistics = new Statistics();
-    reset();
-  }
-
-  /**
-   * Logs the status of a location report received from the HAL
-   *
-   * @param isSuccessful
-   */
-  public void logReceivedLocationStatus(boolean isSuccessful) {
-    if (!isSuccessful) {
-      locationFailureStatistics.addItem(1.0);
-      return;
+    public void logReceivedLocationStatus(boolean isSuccessful) {
+        if (!isSuccessful) {
+            mLocationFailureStatistics.addItem(1.0);
+            return;
+        }
+        mLocationFailureStatistics.addItem(0.0);
     }
-    locationFailureStatistics.addItem(0.0);
-    return;
-  }
 
-  /**
-   * Logs missed reports
-   *
-   * @param desiredTimeBetweenFixesMilliSeconds
-   * @param actualTimeBetweenFixesMilliSeconds
-   */
-  public void logMissedReports(int desiredTimeBetweenFixesMilliSeconds,
-      int actualTimeBetweenFixesMilliSeconds) {
-    int numReportMissed = (actualTimeBetweenFixesMilliSeconds /
-        Math.max(DEFAULT_TIME_BETWEEN_FIXES_MILLISECS, desiredTimeBetweenFixesMilliSeconds)) - 1;
-    if (numReportMissed > 0) {
-      for (int i = 0; i < numReportMissed; i++) {
-        locationFailureStatistics.addItem(1.0);
-      }
+    /**
+     * Logs missed reports
+     */
+    public void logMissedReports(int desiredTimeBetweenFixesMilliSeconds,
+            int actualTimeBetweenFixesMilliSeconds) {
+        int numReportMissed = (actualTimeBetweenFixesMilliSeconds / Math.max(
+                DEFAULT_TIME_BETWEEN_FIXES_MILLISECS, desiredTimeBetweenFixesMilliSeconds)) - 1;
+        if (numReportMissed > 0) {
+            for (int i = 0; i < numReportMissed; i++) {
+                mLocationFailureStatistics.addItem(1.0);
+            }
+        }
     }
-    return;
-  }
 
-  /**
-   * Logs time to first fix
-   *
-   * @param timeToFirstFixMilliSeconds
-   */
-  public void logTimeToFirstFixMilliSecs(int timeToFirstFixMilliSeconds) {
-    timeToFirstFixSecStatistics.addItem((double) (timeToFirstFixMilliSeconds/1000));
-    return;
-  }
-
-  /**
-   * Logs position accuracy
-   *
-   * @param positionAccuracyMeters
-   */
-  public void logPositionAccuracyMeters(float positionAccuracyMeters) {
-    positionAccuracyMeterStatistics.addItem((double) positionAccuracyMeters);
-    return;
-  }
-
-  /*
-  * Logs CN0 when at least 4 SVs are available
-  *
-  */
-  public void logCn0(float[] cn0s, int numSv) {
-    if (numSv == 0 || cn0s == null || cn0s.length == 0 || cn0s.length < numSv) {
-      if (numSv == 0) {
-         mGnssPowerMetrics.reportSignalQuality(null, 0);
-      }
-      return;
+    /**
+     * Logs time to first fix
+     */
+    public void logTimeToFirstFixMilliSecs(int timeToFirstFixMilliSeconds) {
+        mTimeToFirstFixSecStatistics.addItem((double) (timeToFirstFixMilliSeconds / 1000));
     }
-    float[] cn0Array = Arrays.copyOf(cn0s, numSv);
-    Arrays.sort(cn0Array);
-    mGnssPowerMetrics.reportSignalQuality(cn0Array, numSv);
-    if (numSv < 4) {
-      return;
-    }
-    if (cn0Array[numSv - 4] > 0.0) {
-      double top4AvgCn0 = 0.0;
-      for (int i = numSv - 4; i < numSv; i++) {
-        top4AvgCn0 += (double) cn0Array[i];
-      }
-      top4AvgCn0 /= 4;
-      topFourAverageCn0Statistics.addItem(top4AvgCn0);
-    }
-    return;
-  }
 
+    /**
+     * Logs position accuracy
+     */
+    public void logPositionAccuracyMeters(float positionAccuracyMeters) {
+        mPositionAccuracyMeterStatistics.addItem((double) positionAccuracyMeters);
+    }
+
+    /**
+     * Logs CN0 when at least 4 SVs are available
+     */
+    public void logCn0(float[] cn0s, int numSv) {
+        if (numSv == 0 || cn0s == null || cn0s.length == 0 || cn0s.length < numSv) {
+            if (numSv == 0) {
+                mGnssPowerMetrics.reportSignalQuality(null, 0);
+            }
+            return;
+        }
+        float[] cn0Array = Arrays.copyOf(cn0s, numSv);
+        Arrays.sort(cn0Array);
+        mGnssPowerMetrics.reportSignalQuality(cn0Array, numSv);
+        if (numSv < 4) {
+            return;
+        }
+        if (cn0Array[numSv - 4] > 0.0) {
+            double top4AvgCn0 = 0.0;
+            for (int i = numSv - 4; i < numSv; i++) {
+                top4AvgCn0 += (double) cn0Array[i];
+            }
+            top4AvgCn0 /= 4;
+            mTopFourAverageCn0Statistics.addItem(top4AvgCn0);
+        }
+    }
 
     /**
      * Logs that a constellation type has been observed.
@@ -173,82 +162,82 @@
         mConstellationTypes[constellationType] = true;
     }
 
-  /**
-   * Dumps GNSS metrics as a proto string
-   * @return
-   */
-  public String dumpGnssMetricsAsProtoString() {
-    GnssLog msg = new GnssLog();
-    if (locationFailureStatistics.getCount() > 0) {
-      msg.numLocationReportProcessed = locationFailureStatistics.getCount();
-      msg.percentageLocationFailure = (int) (100.0 * locationFailureStatistics.getMean());
+    /**
+     * Dumps GNSS metrics as a proto string
+     */
+    public String dumpGnssMetricsAsProtoString() {
+        GnssLog msg = new GnssLog();
+        if (mLocationFailureStatistics.getCount() > 0) {
+            msg.numLocationReportProcessed = mLocationFailureStatistics.getCount();
+            msg.percentageLocationFailure = (int) (100.0 * mLocationFailureStatistics.getMean());
+        }
+        if (mTimeToFirstFixSecStatistics.getCount() > 0) {
+            msg.numTimeToFirstFixProcessed = mTimeToFirstFixSecStatistics.getCount();
+            msg.meanTimeToFirstFixSecs = (int) mTimeToFirstFixSecStatistics.getMean();
+            msg.standardDeviationTimeToFirstFixSecs =
+                    (int) mTimeToFirstFixSecStatistics.getStandardDeviation();
+        }
+        if (mPositionAccuracyMeterStatistics.getCount() > 0) {
+            msg.numPositionAccuracyProcessed = mPositionAccuracyMeterStatistics.getCount();
+            msg.meanPositionAccuracyMeters = (int) mPositionAccuracyMeterStatistics.getMean();
+            msg.standardDeviationPositionAccuracyMeters =
+                    (int) mPositionAccuracyMeterStatistics.getStandardDeviation();
+        }
+        if (mTopFourAverageCn0Statistics.getCount() > 0) {
+            msg.numTopFourAverageCn0Processed = mTopFourAverageCn0Statistics.getCount();
+            msg.meanTopFourAverageCn0DbHz = mTopFourAverageCn0Statistics.getMean();
+            msg.standardDeviationTopFourAverageCn0DbHz =
+                    mTopFourAverageCn0Statistics.getStandardDeviation();
+        }
+        msg.powerMetrics = mGnssPowerMetrics.buildProto();
+        msg.hardwareRevision = SystemProperties.get("ro.boot.revision", "");
+        String s = Base64.encodeToString(GnssLog.toByteArray(msg), Base64.DEFAULT);
+        reset();
+        return s;
     }
-    if (timeToFirstFixSecStatistics.getCount() > 0) {
-      msg.numTimeToFirstFixProcessed = timeToFirstFixSecStatistics.getCount();
-      msg.meanTimeToFirstFixSecs = (int) timeToFirstFixSecStatistics.getMean();
-      msg.standardDeviationTimeToFirstFixSecs
-          = (int) timeToFirstFixSecStatistics.getStandardDeviation();
-    }
-    if (positionAccuracyMeterStatistics.getCount() > 0) {
-      msg.numPositionAccuracyProcessed = positionAccuracyMeterStatistics.getCount();
-      msg.meanPositionAccuracyMeters = (int) positionAccuracyMeterStatistics.getMean();
-      msg.standardDeviationPositionAccuracyMeters
-          = (int) positionAccuracyMeterStatistics.getStandardDeviation();
-    }
-    if (topFourAverageCn0Statistics.getCount() > 0) {
-      msg.numTopFourAverageCn0Processed = topFourAverageCn0Statistics.getCount();
-      msg.meanTopFourAverageCn0DbHz = topFourAverageCn0Statistics.getMean();
-      msg.standardDeviationTopFourAverageCn0DbHz
-          = topFourAverageCn0Statistics.getStandardDeviation();
-    }
-    msg.powerMetrics = mGnssPowerMetrics.buildProto();
-    msg.hardwareRevision = SystemProperties.get("ro.boot.revision", "");
-    String s = Base64.encodeToString(GnssLog.toByteArray(msg), Base64.DEFAULT);
-    reset();
-    return s;
-  }
 
-  /**
-   * Dumps GNSS Metrics as text
-   *
-   * @return GNSS Metrics
-   */
-  public String dumpGnssMetricsAsText() {
-    StringBuilder s = new StringBuilder();
-    s.append("GNSS_KPI_START").append('\n');
-    s.append("  KPI logging start time: ").append(logStartInElapsedRealTime).append("\n");
-    s.append("  KPI logging end time: ");
-    TimeUtils.formatDuration(SystemClock.elapsedRealtimeNanos() / 1000000L, s);
-    s.append("\n");
-    s.append("  Number of location reports: ").append(
-        locationFailureStatistics.getCount()).append("\n");
-    if (locationFailureStatistics.getCount() > 0) {
-      s.append("  Percentage location failure: ").append(
-          100.0 * locationFailureStatistics.getMean()).append("\n");
-    }
-    s.append("  Number of TTFF reports: ").append(
-        timeToFirstFixSecStatistics.getCount()).append("\n");
-    if (timeToFirstFixSecStatistics.getCount() > 0) {
-      s.append("  TTFF mean (sec): ").append(timeToFirstFixSecStatistics.getMean()).append("\n");
-      s.append("  TTFF standard deviation (sec): ").append(
-          timeToFirstFixSecStatistics.getStandardDeviation()).append("\n");
-    }
-    s.append("  Number of position accuracy reports: ").append(
-        positionAccuracyMeterStatistics.getCount()).append("\n");
-    if (positionAccuracyMeterStatistics.getCount() > 0) {
-      s.append("  Position accuracy mean (m): ").append(
-          positionAccuracyMeterStatistics.getMean()).append("\n");
-      s.append("  Position accuracy standard deviation (m): ").append(
-          positionAccuracyMeterStatistics.getStandardDeviation()).append("\n");
-    }
-    s.append("  Number of CN0 reports: ").append(
-        topFourAverageCn0Statistics.getCount()).append("\n");
-    if (topFourAverageCn0Statistics.getCount() > 0) {
-      s.append("  Top 4 Avg CN0 mean (dB-Hz): ").append(
-          topFourAverageCn0Statistics.getMean()).append("\n");
-      s.append("  Top 4 Avg CN0 standard deviation (dB-Hz): ").append(
-          topFourAverageCn0Statistics.getStandardDeviation()).append("\n");
-    }
+    /**
+     * Dumps GNSS Metrics as text
+     *
+     * @return GNSS Metrics
+     */
+    public String dumpGnssMetricsAsText() {
+        StringBuilder s = new StringBuilder();
+        s.append("GNSS_KPI_START").append('\n');
+        s.append("  KPI logging start time: ").append(mLogStartInElapsedRealTime).append("\n");
+        s.append("  KPI logging end time: ");
+        TimeUtils.formatDuration(SystemClock.elapsedRealtimeNanos() / 1000000L, s);
+        s.append("\n");
+        s.append("  Number of location reports: ").append(
+                mLocationFailureStatistics.getCount()).append("\n");
+        if (mLocationFailureStatistics.getCount() > 0) {
+            s.append("  Percentage location failure: ").append(
+                    100.0 * mLocationFailureStatistics.getMean()).append("\n");
+        }
+        s.append("  Number of TTFF reports: ").append(
+                mTimeToFirstFixSecStatistics.getCount()).append("\n");
+        if (mTimeToFirstFixSecStatistics.getCount() > 0) {
+            s.append("  TTFF mean (sec): ").append(mTimeToFirstFixSecStatistics.getMean()).append(
+                    "\n");
+            s.append("  TTFF standard deviation (sec): ").append(
+                    mTimeToFirstFixSecStatistics.getStandardDeviation()).append("\n");
+        }
+        s.append("  Number of position accuracy reports: ").append(
+                mPositionAccuracyMeterStatistics.getCount()).append("\n");
+        if (mPositionAccuracyMeterStatistics.getCount() > 0) {
+            s.append("  Position accuracy mean (m): ").append(
+                    mPositionAccuracyMeterStatistics.getMean()).append("\n");
+            s.append("  Position accuracy standard deviation (m): ").append(
+                    mPositionAccuracyMeterStatistics.getStandardDeviation()).append("\n");
+        }
+        s.append("  Number of CN0 reports: ").append(
+                mTopFourAverageCn0Statistics.getCount()).append("\n");
+        if (mTopFourAverageCn0Statistics.getCount() > 0) {
+            s.append("  Top 4 Avg CN0 mean (dB-Hz): ").append(
+                    mTopFourAverageCn0Statistics.getMean()).append("\n");
+            s.append("  Top 4 Avg CN0 standard deviation (dB-Hz): ").append(
+                    mTopFourAverageCn0Statistics.getStandardDeviation()).append("\n");
+        }
         s.append("  Used-in-fix constellation types: ");
         for (int i = 0; i < mConstellationTypes.length; i++) {
             if (mConstellationTypes[i]) {
@@ -256,199 +245,193 @@
             }
         }
         s.append("\n");
-    s.append("GNSS_KPI_END").append("\n");
-    GpsBatteryStats stats = mGnssPowerMetrics.getGpsBatteryStats();
-    if (stats != null) {
-      s.append("Power Metrics").append("\n");
-      s.append("  Time on battery (min): "
-          + stats.getLoggingDurationMs() / ((double) DateUtils.MINUTE_IN_MILLIS)).append("\n");
-      long[] t = stats.getTimeInGpsSignalQualityLevel();
-      if (t != null && t.length == NUM_GPS_SIGNAL_QUALITY_LEVELS) {
-        s.append("  Amount of time (while on battery) Top 4 Avg CN0 > " +
-            Double.toString(GnssPowerMetrics.POOR_TOP_FOUR_AVG_CN0_THRESHOLD_DB_HZ) +
-            " dB-Hz (min): ").append(t[1] / ((double) DateUtils.MINUTE_IN_MILLIS)).append("\n");
-        s.append("  Amount of time (while on battery) Top 4 Avg CN0 <= " +
-            Double.toString(GnssPowerMetrics.POOR_TOP_FOUR_AVG_CN0_THRESHOLD_DB_HZ) +
-            " dB-Hz (min): ").append(t[0] / ((double) DateUtils.MINUTE_IN_MILLIS)).append("\n");
-      }
-      s.append("  Energy consumed while on battery (mAh): ").append(
-          stats.getEnergyConsumedMaMs() / ((double) DateUtils.HOUR_IN_MILLIS)).append("\n");
-    }
-    s.append("Hardware Version: " + SystemProperties.get("ro.boot.revision", "")).append("\n");
-    return s.toString();
-  }
-
-   /** Class for storing statistics */
-  private class Statistics {
-
-    /** Resets statistics */
-    public void reset() {
-      count = 0;
-      sum = 0.0;
-      sumSquare = 0.0;
+        s.append("GNSS_KPI_END").append("\n");
+        GpsBatteryStats stats = mGnssPowerMetrics.getGpsBatteryStats();
+        if (stats != null) {
+            s.append("Power Metrics").append("\n");
+            s.append("  Time on battery (min): ").append(
+                    stats.getLoggingDurationMs() / ((double) DateUtils.MINUTE_IN_MILLIS)).append(
+                    "\n");
+            long[] t = stats.getTimeInGpsSignalQualityLevel();
+            if (t != null && t.length == NUM_GPS_SIGNAL_QUALITY_LEVELS) {
+                s.append("  Amount of time (while on battery) Top 4 Avg CN0 > "
+                        + GnssPowerMetrics.POOR_TOP_FOUR_AVG_CN0_THRESHOLD_DB_HZ
+                        + " dB-Hz (min): ").append(
+                        t[1] / ((double) DateUtils.MINUTE_IN_MILLIS)).append("\n");
+                s.append("  Amount of time (while on battery) Top 4 Avg CN0 <= "
+                        + GnssPowerMetrics.POOR_TOP_FOUR_AVG_CN0_THRESHOLD_DB_HZ
+                        + " dB-Hz (min): ").append(
+                        t[0] / ((double) DateUtils.MINUTE_IN_MILLIS)).append("\n");
+            }
+            s.append("  Energy consumed while on battery (mAh): ").append(
+                    stats.getEnergyConsumedMaMs() / ((double) DateUtils.HOUR_IN_MILLIS)).append(
+                    "\n");
+        }
+        s.append("Hardware Version: ").append(SystemProperties.get("ro.boot.revision", "")).append(
+                "\n");
+        return s.toString();
     }
 
-    /** Adds an item */
-    public void addItem(double item) {
-      count++;
-      sum += item;
-      sumSquare += item * item;
-    }
-
-    /** Returns number of items added */
-    public int getCount() {
-      return count;
-    }
-
-    /** Returns mean */
-    public double getMean() {
-      return sum/count;
-    }
-
-    /** Returns standard deviation */
-    public double getStandardDeviation() {
-      double m = sum/count;
-      m = m * m;
-      double v = sumSquare/count;
-      if (v > m) {
-        return Math.sqrt(v - m);
-      }
-      return 0;
-    }
-
-    private int count;
-    private double sum;
-    private double sumSquare;
-  }
-
-  /** Location failure statistics */
-  private Statistics locationFailureStatistics;
-
-  /** Time to first fix statistics */
-  private Statistics timeToFirstFixSecStatistics;
-
-  /** Position accuracy statistics */
-  private Statistics positionAccuracyMeterStatistics;
-
-  /** Top 4 average CN0 statistics */
-  private Statistics topFourAverageCn0Statistics;
-
-  /**
-   * Resets GNSS metrics
-   */
-  private void reset() {
-    StringBuilder s = new StringBuilder();
-    TimeUtils.formatDuration(SystemClock.elapsedRealtimeNanos() / 1000000L, s);
-    logStartInElapsedRealTime = s.toString();
-    locationFailureStatistics.reset();
-    timeToFirstFixSecStatistics.reset();
-    positionAccuracyMeterStatistics.reset();
-    topFourAverageCn0Statistics.reset();
+    private void reset() {
+        StringBuilder s = new StringBuilder();
+        TimeUtils.formatDuration(SystemClock.elapsedRealtimeNanos() / 1000000L, s);
+        mLogStartInElapsedRealTime = s.toString();
+        mLocationFailureStatistics.reset();
+        mTimeToFirstFixSecStatistics.reset();
+        mPositionAccuracyMeterStatistics.reset();
+        mTopFourAverageCn0Statistics.reset();
         resetConstellationTypes();
-    return;
-  }
+    }
 
     /** Resets {@link #mConstellationTypes} as an all-false boolean array. */
     public void resetConstellationTypes() {
         mConstellationTypes = new boolean[GnssStatus.CONSTELLATION_COUNT];
     }
 
-  /* Class for handling GNSS power related metrics */
-  private class GnssPowerMetrics {
+    /** Class for storing statistics */
+    private class Statistics {
 
-    /* Threshold for Top Four Average CN0 below which GNSS signal quality is declared poor */
-    public static final double POOR_TOP_FOUR_AVG_CN0_THRESHOLD_DB_HZ = 20.0;
+        private int mCount;
+        private double mSum;
+        private double mSumSquare;
 
-    /* Minimum change in Top Four Average CN0 needed to trigger a report */
-    private static final double REPORTING_THRESHOLD_DB_HZ = 1.0;
-
-    /* BatteryStats API */
-    private final IBatteryStats mBatteryStats;
-
-    /* Last reported Top Four Average CN0 */
-    private double mLastAverageCn0;
-
-    /* Last reported signal quality bin (based on Top Four Average CN0) */
-    private int mLastSignalLevel;
-
-    public GnssPowerMetrics(IBatteryStats stats) {
-      mBatteryStats = stats;
-      // Used to initialize the variable to a very small value (unachievable in practice) so that
-      // the first CNO report will trigger an update to BatteryStats
-      mLastAverageCn0 = -100.0;
-      mLastSignalLevel = GPS_SIGNAL_QUALITY_UNKNOWN;
-    }
-
-    /**
-     * Builds power metrics proto buf. This is included in the gnss proto buf.
-     * @return PowerMetrics
-     */
-    public PowerMetrics buildProto() {
-      PowerMetrics p = new PowerMetrics();
-      GpsBatteryStats stats = mGnssPowerMetrics.getGpsBatteryStats();
-      if (stats != null) {
-        p.loggingDurationMs = stats.getLoggingDurationMs();
-        p.energyConsumedMah = stats.getEnergyConsumedMaMs() / ((double) DateUtils.HOUR_IN_MILLIS);
-        long[] t = stats.getTimeInGpsSignalQualityLevel();
-        p.timeInSignalQualityLevelMs = new long[t.length];
-        for (int i = 0; i < t.length; i++) {
-          p.timeInSignalQualityLevelMs[i] = t[i];
+        /** Resets statistics */
+        public void reset() {
+            mCount = 0;
+            mSum = 0.0;
+            mSumSquare = 0.0;
         }
-      }
-      return p;
-    }
 
-    /**
-     * Returns the GPS power stats
-     * @return GpsBatteryStats
-     */
-    public GpsBatteryStats getGpsBatteryStats() {
-      try {
-        return mBatteryStats.getGpsBatteryStats();
-      } catch (Exception e) {
-        Log.w(TAG, "Exception", e);
-        return null;
-      }
-    }
-
-    /**
-     * Reports signal quality to BatteryStats. Signal quality is based on Top four average CN0. If
-     * the number of SVs seen is less than 4, then signal quality is the average CN0.
-     * Changes are reported only if the average CN0 changes by more than REPORTING_THRESHOLD_DB_HZ.
-     */
-    public void reportSignalQuality(float[] ascendingCN0Array, int numSv) {
-      double avgCn0 = 0.0;
-      if (numSv > 0) {
-        for (int i = Math.max(0, numSv - 4); i < numSv; i++) {
-          avgCn0 += (double) ascendingCN0Array[i];
+        /** Adds an item */
+        public void addItem(double item) {
+            mCount++;
+            mSum += item;
+            mSumSquare += item * item;
         }
-        avgCn0 /= Math.min(numSv, 4);
-      }
-      if (Math.abs(avgCn0 - mLastAverageCn0) < REPORTING_THRESHOLD_DB_HZ) {
-        return;
-      }
-      int signalLevel = getSignalLevel(avgCn0);
-      if (signalLevel != mLastSignalLevel) {
-        StatsLog.write(StatsLog.GPS_SIGNAL_QUALITY_CHANGED, signalLevel);
-        mLastSignalLevel = signalLevel;
-      }
-      try {
-        mBatteryStats.noteGpsSignalQuality(signalLevel);
-        mLastAverageCn0 = avgCn0;
-      } catch (Exception e) {
-        Log.w(TAG, "Exception", e);
-      }
-      return;
+
+        /** Returns number of items added */
+        public int getCount() {
+            return mCount;
+        }
+
+        /** Returns mean */
+        public double getMean() {
+            return mSum / mCount;
+        }
+
+        /** Returns standard deviation */
+        public double getStandardDeviation() {
+            double m = mSum / mCount;
+            m = m * m;
+            double v = mSumSquare / mCount;
+            if (v > m) {
+                return Math.sqrt(v - m);
+            }
+            return 0;
+        }
     }
 
-    /**
-     * Obtains signal level based on CN0
-     */
-    private int getSignalLevel(double cn0) {
-      if (cn0 > POOR_TOP_FOUR_AVG_CN0_THRESHOLD_DB_HZ) {
-        return GnssMetrics.GPS_SIGNAL_QUALITY_GOOD;
-      }
-      return GnssMetrics.GPS_SIGNAL_QUALITY_POOR;
+    /* Class for handling GNSS power related metrics */
+    private class GnssPowerMetrics {
+
+        /* Threshold for Top Four Average CN0 below which GNSS signal quality is declared poor */
+        public static final double POOR_TOP_FOUR_AVG_CN0_THRESHOLD_DB_HZ = 20.0;
+
+        /* Minimum change in Top Four Average CN0 needed to trigger a report */
+        private static final double REPORTING_THRESHOLD_DB_HZ = 1.0;
+
+        /* BatteryStats API */
+        private final IBatteryStats mBatteryStats;
+
+        /* Last reported Top Four Average CN0 */
+        private double mLastAverageCn0;
+
+        /* Last reported signal quality bin (based on Top Four Average CN0) */
+        private int mLastSignalLevel;
+
+        private GnssPowerMetrics(IBatteryStats stats) {
+            mBatteryStats = stats;
+            // Used to initialize the variable to a very small value (unachievable in practice)
+          // so that
+            // the first CNO report will trigger an update to BatteryStats
+            mLastAverageCn0 = -100.0;
+            mLastSignalLevel = GPS_SIGNAL_QUALITY_UNKNOWN;
+        }
+
+        /**
+         * Builds power metrics proto buf. This is included in the gnss proto buf.
+         *
+         * @return PowerMetrics
+         */
+        public PowerMetrics buildProto() {
+            PowerMetrics p = new PowerMetrics();
+            GpsBatteryStats stats = mGnssPowerMetrics.getGpsBatteryStats();
+            if (stats != null) {
+                p.loggingDurationMs = stats.getLoggingDurationMs();
+                p.energyConsumedMah =
+                        stats.getEnergyConsumedMaMs() / ((double) DateUtils.HOUR_IN_MILLIS);
+                long[] t = stats.getTimeInGpsSignalQualityLevel();
+                p.timeInSignalQualityLevelMs = new long[t.length];
+                for (int i = 0; i < t.length; i++) {
+                    p.timeInSignalQualityLevelMs[i] = t[i];
+                }
+            }
+            return p;
+        }
+
+        /**
+         * Returns the GPS power stats
+         *
+         * @return GpsBatteryStats
+         */
+        public GpsBatteryStats getGpsBatteryStats() {
+            try {
+                return mBatteryStats.getGpsBatteryStats();
+            } catch (Exception e) {
+                Log.w(TAG, "Exception", e);
+                return null;
+            }
+        }
+
+        /**
+         * Reports signal quality to BatteryStats. Signal quality is based on Top four average CN0.
+         * If
+         * the number of SVs seen is less than 4, then signal quality is the average CN0.
+         * Changes are reported only if the average CN0 changes by more than
+         * REPORTING_THRESHOLD_DB_HZ.
+         */
+        public void reportSignalQuality(float[] ascendingCN0Array, int numSv) {
+            double avgCn0 = 0.0;
+            if (numSv > 0) {
+                for (int i = Math.max(0, numSv - 4); i < numSv; i++) {
+                    avgCn0 += (double) ascendingCN0Array[i];
+                }
+                avgCn0 /= Math.min(numSv, 4);
+            }
+            if (Math.abs(avgCn0 - mLastAverageCn0) < REPORTING_THRESHOLD_DB_HZ) {
+                return;
+            }
+            int signalLevel = getSignalLevel(avgCn0);
+            if (signalLevel != mLastSignalLevel) {
+                StatsLog.write(StatsLog.GPS_SIGNAL_QUALITY_CHANGED, signalLevel);
+                mLastSignalLevel = signalLevel;
+            }
+            try {
+                mBatteryStats.noteGpsSignalQuality(signalLevel);
+                mLastAverageCn0 = avgCn0;
+            } catch (Exception e) {
+                Log.w(TAG, "Exception", e);
+            }
+        }
+
+        /**
+         * Obtains signal level based on CN0
+         */
+        private int getSignalLevel(double cn0) {
+            if (cn0 > POOR_TOP_FOUR_AVG_CN0_THRESHOLD_DB_HZ) {
+                return GnssMetrics.GPS_SIGNAL_QUALITY_GOOD;
+            }
+            return GnssMetrics.GPS_SIGNAL_QUALITY_POOR;
+        }
     }
-  }
 }
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index ce9b07d..0254c97 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -1788,6 +1788,9 @@
      * @hide
      */
     public int getPortId() {
+        if (mNativeRecorderInJavaObj == 0) {
+            return 0;
+        }
         return native_getPortId();
     }
 
diff --git a/media/java/android/media/IMediaRoute2Provider.aidl b/media/java/android/media/IMediaRoute2Provider.aidl
index 4bd5710..f132cef 100644
--- a/media/java/android/media/IMediaRoute2Provider.aidl
+++ b/media/java/android/media/IMediaRoute2Provider.aidl
@@ -23,7 +23,8 @@
  * {@hide}
  */
 oneway interface IMediaRoute2Provider {
-    void registerClient(IMediaRoute2ProviderClient client);
-    void selectRoute(IMediaRoute2ProviderClient client, int uid, String id);
-    void notifyControlRequestSent(IMediaRoute2ProviderClient client, String id, in Intent request);
+    void setClient(IMediaRoute2ProviderClient client);
+    void selectRoute(String packageName, String id);
+    void unselectRoute(String packageName, String id);
+    void notifyControlRequestSent(String id, in Intent request);
 }
diff --git a/media/java/android/media/IMediaRoute2ProviderClient.aidl b/media/java/android/media/IMediaRoute2ProviderClient.aidl
index e849e19..8d08beb 100644
--- a/media/java/android/media/IMediaRoute2ProviderClient.aidl
+++ b/media/java/android/media/IMediaRoute2ProviderClient.aidl
@@ -22,6 +22,5 @@
  * @hide
  */
 oneway interface IMediaRoute2ProviderClient {
-    void notifyRouteSelected(int uid, String routeId);
     void notifyProviderInfoUpdated(in MediaRoute2ProviderInfo info);
 }
diff --git a/media/java/android/media/IMediaRouter2Manager.aidl b/media/java/android/media/IMediaRouter2Manager.aidl
index b8c00a3..b059bd3c 100644
--- a/media/java/android/media/IMediaRouter2Manager.aidl
+++ b/media/java/android/media/IMediaRouter2Manager.aidl
@@ -23,7 +23,7 @@
  * {@hide}
  */
 oneway interface IMediaRouter2Manager {
-    void notifyRouteSelected(int uid, in MediaRoute2Info route);
-    void notifyControlCategoriesChanged(int uid, in List<String> categories);
+    void notifyRouteSelected(String packageName, in MediaRoute2Info route);
+    void notifyControlCategoriesChanged(String packageName, in List<String> categories);
     void notifyProviderInfosUpdated(in List<MediaRoute2ProviderInfo> providers);
 }
diff --git a/media/java/android/media/IMediaRouterService.aidl b/media/java/android/media/IMediaRouterService.aidl
index fb108b4..08266a5 100644
--- a/media/java/android/media/IMediaRouterService.aidl
+++ b/media/java/android/media/IMediaRouterService.aidl
@@ -48,8 +48,8 @@
     /**
      * Changes the selected route of the client.
      *
-     * @param client Client to change it's selected route.
-     * @param route Route to be selected.
+     * @param client the client that changes it's selected route
+     * @param route the route to be selected
      */
     void selectRoute2(IMediaRouter2Client client, in @nullable MediaRoute2Info route);
     void setControlCategories(IMediaRouter2Client client, in List<String> categories);
@@ -60,10 +60,10 @@
     /**
      * Changes the selected route of an application.
      *
-     * @param manager Manager that calls the method
-     * @param uid UID of the client that will change the selected route.
-     * @param route Route to be selected.
+     * @param manager the manager that calls the method
+     * @param packageName the package name of the client that will change the selected route
+     * @param route the route to be selected
      */
-    void selectClientRoute2(IMediaRouter2Manager manager, int clientUid,
+    void selectClientRoute2(IMediaRouter2Manager manager, String packageName,
             in @nullable MediaRoute2Info route);
 }
diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
index 63b22df..bc3de74 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -1624,6 +1624,9 @@
      * @hide
      */
     public int getPortId() {
+        if (mNativeContext == 0) {
+            return 0;
+        }
         return native_getPortId();
     }
 
diff --git a/media/java/android/media/MediaRoute2Info.java b/media/java/android/media/MediaRoute2Info.java
index 855cd77f..f13a64c 100644
--- a/media/java/android/media/MediaRoute2Info.java
+++ b/media/java/android/media/MediaRoute2Info.java
@@ -52,6 +52,8 @@
     @Nullable
     final String mDescription;
     @Nullable
+    final String mClientPackageName;
+    @Nullable
     final Bundle mExtras;
 
     MediaRoute2Info(@NonNull Builder builder) {
@@ -59,6 +61,7 @@
         mProviderId = builder.mProviderId;
         mName = builder.mName;
         mDescription = builder.mDescription;
+        mClientPackageName = builder.mClientPackageName;
         mExtras = builder.mExtras;
     }
 
@@ -67,6 +70,7 @@
         mProviderId = in.readString();
         mName = in.readString();
         mDescription = in.readString();
+        mClientPackageName = in.readString();
         mExtras = in.readBundle();
     }
 
@@ -98,6 +102,7 @@
                 && Objects.equals(mProviderId, other.mProviderId)
                 && Objects.equals(mName, other.mName)
                 && Objects.equals(mDescription, other.mDescription)
+                && Objects.equals(mClientPackageName, other.mClientPackageName)
                 //TODO: This will be evaluated as false in most cases. Try not to.
                 && Objects.equals(mExtras, other.mExtras);
     }
@@ -131,6 +136,16 @@
         return mDescription;
     }
 
+    /**
+     * Gets the package name of the client that uses the route.
+     * Returns null if no clients use this.
+     * @hide
+     */
+    @Nullable
+    public String getClientPackageName() {
+        return mClientPackageName;
+    }
+
     @Nullable
     public Bundle getExtras() {
         return mExtras;
@@ -147,6 +162,7 @@
         dest.writeString(mProviderId);
         dest.writeString(mName);
         dest.writeString(mDescription);
+        dest.writeString(mClientPackageName);
         dest.writeBundle(mExtras);
     }
 
@@ -170,6 +186,7 @@
         String mProviderId;
         String mName;
         String mDescription;
+        String mClientPackageName;
         Bundle mExtras;
 
         public Builder(@NonNull String id, @NonNull String name) {
@@ -194,6 +211,7 @@
             }
             setName(routeInfo.mName);
             mDescription = routeInfo.mDescription;
+            setClientPackageName(routeInfo.mClientPackageName);
             if (routeInfo.mExtras != null) {
                 mExtras = new Bundle(routeInfo.mExtras);
             }
@@ -246,6 +264,15 @@
         }
 
         /**
+         * Sets the package name of the app using the route.
+         */
+        @NonNull
+        public Builder setClientPackageName(@Nullable String packageName) {
+            mClientPackageName = packageName;
+            return this;
+        }
+
+        /**
          * Sets a bundle of extras for the route.
          */
         @NonNull
diff --git a/media/java/android/media/MediaRoute2ProviderService.java b/media/java/android/media/MediaRoute2ProviderService.java
index 30e0ef1..b89b0b1 100644
--- a/media/java/android/media/MediaRoute2ProviderService.java
+++ b/media/java/android/media/MediaRoute2ProviderService.java
@@ -36,7 +36,6 @@
 
     private final Handler mHandler;
     private ProviderStub mStub;
-    //TODO: Should allow multiple clients
     private IMediaRoute2ProviderClient mClient;
     private MediaRoute2ProviderInfo mProviderInfo;
 
@@ -46,6 +45,7 @@
 
     @Override
     public IBinder onBind(Intent intent) {
+        //TODO: Allow binding from media router service only?
         if (SERVICE_INTERFACE.equals(intent.getAction())) {
             if (mStub == null) {
                 mStub = new ProviderStub();
@@ -58,49 +58,37 @@
     /**
      * Called when selectRoute is called on a route of the provider.
      *
-     * @param uid The target application uid
-     * @param routeId The id of the target route
+     * @param packageName the package name of the application that selected the route
+     * @param routeId the id of the route being selected
      */
-    public abstract void onSelect(int uid, String routeId);
+    public abstract void onSelectRoute(String packageName, String routeId);
 
     /**
-     * Called when sendControlRequest is called on a route of the provider.
+     * Called when unselectRoute is called on a route of the provider.
      *
-     * @param routeId The id of the target route
-     * @param request The media control request intent
+     * @param packageName the package name of the application that has selected the route.
+     * @param routeId the id of the route being unselected
+     */
+    public abstract void onUnselectRoute(String packageName, String routeId);
+
+    /**
+     * Called when sendControlRequest is called on a route of the provider
+     *
+     * @param routeId the id of the target route
+     * @param request the media control request intent
      */
     //TODO: Discuss what to use for request (e.g., Intent? Request class?)
     public abstract void onControlRequest(String routeId, Intent request);
 
     /**
-     * Updates provider info from selected route and application.
-     *
-     * TODO: When provider descriptor is defined, this should update the descriptor correctly.
-     *
-     * @param uid
-     * @param routeId
-     */
-    public void updateProvider(int uid, String routeId) {
-        if (mClient != null) {
-            try {
-                //TODO: After publishState() is fully implemented, delete this.
-                mClient.notifyRouteSelected(uid, routeId);
-            } catch (RemoteException ex) {
-                Log.d(TAG, "Failed to update provider");
-            }
-        }
-        publishState();
-    }
-
-    /**
-     * Updates provider info and publish routes
+     * Updates provider info and publishes routes
      */
     public final void setProviderInfo(MediaRoute2ProviderInfo info) {
         mProviderInfo = info;
         publishState();
     }
 
-    void registerClient(IMediaRoute2ProviderClient client) {
+    void setClient(IMediaRoute2ProviderClient client) {
         mClient = client;
         publishState();
     }
@@ -120,20 +108,25 @@
         ProviderStub() { }
 
         @Override
-        public void registerClient(IMediaRoute2ProviderClient client) {
-            mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::registerClient,
+        public void setClient(IMediaRoute2ProviderClient client) {
+            mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::setClient,
                     MediaRoute2ProviderService.this, client));
         }
 
         @Override
-        public void selectRoute(IMediaRoute2ProviderClient client, int uid, String id) {
-            mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onSelect,
-                    MediaRoute2ProviderService.this, uid, id));
+        public void selectRoute(String packageName, String id) {
+            mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onSelectRoute,
+                    MediaRoute2ProviderService.this, packageName, id));
         }
 
         @Override
-        public void notifyControlRequestSent(IMediaRoute2ProviderClient client, String id,
-                Intent request) {
+        public void unselectRoute(String packageName, String id) {
+            mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onUnselectRoute,
+                    MediaRoute2ProviderService.this, packageName, id));
+        }
+
+        @Override
+        public void notifyControlRequestSent(String id, Intent request) {
             mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onControlRequest,
                     MediaRoute2ProviderService.this, id, request));
         }
diff --git a/media/java/android/media/MediaRouter2Manager.java b/media/java/android/media/MediaRouter2Manager.java
index 2d7dc56..5fc37a5 100644
--- a/media/java/android/media/MediaRouter2Manager.java
+++ b/media/java/android/media/MediaRouter2Manager.java
@@ -38,6 +38,7 @@
 import java.util.List;
 import java.util.Objects;
 import java.util.Set;
+import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.Executor;
 
 /**
@@ -58,11 +59,13 @@
     final Handler mHandler;
 
     @GuardedBy("sLock")
-    final ArrayList<CallbackRecord> mCallbacks = new ArrayList<>();
+    final List<CallbackRecord> mCallbacks = new CopyOnWriteArrayList<>();
 
     @SuppressWarnings("WeakerAccess") /* synthetic access */
     @NonNull
     List<MediaRoute2ProviderInfo> mProviders = Collections.emptyList();
+    @NonNull
+    List<MediaRoute2Info> mRoutes = Collections.emptyList();
 
     /**
      * Gets an instance of media router manager that controls media route of other applications.
@@ -158,15 +161,26 @@
     }
 
     /**
-     * Selects media route for the specified application uid.
+     * Gets available routes for an application.
      *
-     * @param uid The uid of the application that should change it's media route.
-     * @param route The route to select
+     * @param packageName the package name of the application
      */
-    public void selectRoute(int uid, MediaRoute2Info route) {
+    @NonNull
+    public List<MediaRoute2Info> getAvailableRoutes(@NonNull String packageName) {
+        //TODO: filter irrelevant routes.
+        return Collections.unmodifiableList(mRoutes);
+    }
+
+    /**
+     * Selects media route for the specified package name.
+     *
+     * @param packageName the package name of the application that should change it's media route
+     * @param route the route to be selected
+     */
+    public void selectRoute(@NonNull String packageName, @NonNull MediaRoute2Info route) {
         if (mClient != null) {
             try {
-                mMediaRouterService.selectClientRoute2(mClient, uid, route);
+                mMediaRouterService.selectClientRoute2(mClient, packageName, route);
             } catch (RemoteException ex) {
                 Log.e(TAG, "Unable to select media route", ex);
             }
@@ -174,14 +188,14 @@
     }
 
     /**
-     * Unselects media route for the specified application uid.
+     * Unselects media route for the specified package name.
      *
-     * @param uid The uid of the application that should stop routing.
+     * @param packageName the package name of the application that should stop routing
      */
-    public void unselectRoute(int uid) {
+    public void unselectRoute(@NonNull String packageName) {
         if (mClient != null) {
             try {
-                mMediaRouterService.selectClientRoute2(mClient, uid, null);
+                mMediaRouterService.selectClientRoute2(mClient, packageName, null);
             } catch (RemoteException ex) {
                 Log.e(TAG, "Unable to select media route", ex);
             }
@@ -260,31 +274,46 @@
         }
     }
 
+    void notifyRouteListChanged() {
+        for (CallbackRecord record: mCallbacks) {
+            record.mExecutor.execute(
+                    () -> record.mCallback.onRouteListChanged(mRoutes));
+        }
+    }
+
     void notifyProviderInfosUpdated(List<MediaRoute2ProviderInfo> providers) {
         if (providers == null) {
             Log.w(TAG, "Providers info is null.");
             return;
         }
 
+        ArrayList<MediaRoute2Info> routes = new ArrayList<>();
+
         for (MediaRoute2ProviderInfo provider : providers) {
             updateProvider(provider);
+            //TODO: Should we do this in updateProvider()?
+            routes.addAll(provider.getRoutes());
         }
         //TODO: Call notifyRouteRemoved for the routes of the removed providers.
 
-        //TODO: Filter invalid providers.
+        //TODO: Filter invalid providers and invalid routes.
         mProviders = providers;
+        mRoutes = routes;
+
+        //TODO: Call this when only the list is modified.
+        notifyRouteListChanged();
     }
 
-    void notifyRouteSelected(int uid, MediaRoute2Info route) {
+    void notifyRouteSelected(String packageName, MediaRoute2Info route) {
         for (CallbackRecord record : mCallbacks) {
-            record.mExecutor.execute(() -> record.mCallback.onRouteSelected(uid, route));
+            record.mExecutor.execute(() -> record.mCallback.onRouteSelected(packageName, route));
         }
     }
 
-    void notifyControlCategoriesChanged(int uid, List<String> categories) {
+    void notifyControlCategoriesChanged(String packageName, List<String> categories) {
         for (CallbackRecord record : mCallbacks) {
             record.mExecutor.execute(
-                    () -> record.mCallback.onControlCategoriesChanged(uid, categories));
+                    () -> record.mCallback.onControlCategoriesChanged(packageName, categories));
         }
     }
 
@@ -309,17 +338,27 @@
 
         /**
          * Called when a route is selected for an application.
-         * @param uid uid of the application
-         * @param route selected route of the application.
+         *
+         * @param packageName the package name of the application
+         * @param route the selected route of the application.
+         *              It is null if the application has no selected route.
          */
-        public void onRouteSelected(int uid, @Nullable MediaRoute2Info route) {}
+        public void onRouteSelected(@NonNull String packageName, @Nullable MediaRoute2Info route) {}
 
         /**
          * Called when the control categories of an application is changed.
-         * @param uid the uid of the app that changed control categories
+         *
+         * @param packageName the package name of the app that changed control categories
          * @param categories the changed categories
          */
-        public void onControlCategoriesChanged(int uid, @NonNull List<String> categories) {}
+        public void onControlCategoriesChanged(@NonNull String packageName,
+                @NonNull List<String> categories) {}
+
+        /**
+         * Called when the list of routes are changed.
+         * A client may refresh available routes for each application.
+         */
+        public void onRouteListChanged(@NonNull List<MediaRoute2Info> routes) {}
     }
 
     final class CallbackRecord {
@@ -343,15 +382,15 @@
 
     class Client extends IMediaRouter2Manager.Stub {
         @Override
-        public void notifyRouteSelected(int uid, MediaRoute2Info route) {
+        public void notifyRouteSelected(String packageName, MediaRoute2Info route) {
             mHandler.sendMessage(obtainMessage(MediaRouter2Manager::notifyRouteSelected,
-                    MediaRouter2Manager.this, uid, route));
+                    MediaRouter2Manager.this, packageName, route));
         }
 
         @Override
-        public void notifyControlCategoriesChanged(int uid, List<String> categories) {
+        public void notifyControlCategoriesChanged(String packageName, List<String> categories) {
             mHandler.sendMessage(obtainMessage(MediaRouter2Manager::notifyControlCategoriesChanged,
-                    MediaRouter2Manager.this, uid, categories));
+                    MediaRouter2Manager.this, packageName, categories));
         }
 
         @Override
diff --git a/media/java/android/media/session/ISessionManager.aidl b/media/java/android/media/session/ISessionManager.aidl
index a67a37e..01e6ed5 100644
--- a/media/java/android/media/session/ISessionManager.aidl
+++ b/media/java/android/media/session/ISessionManager.aidl
@@ -62,7 +62,8 @@
     // For PhoneWindowManager to precheck media keys
     boolean isGlobalPriorityActive();
 
-    void setCallback(in ICallback callback);
+    void registerCallback(in ICallback callback);
+    void unregisterCallback(in ICallback callback);
     void setOnVolumeKeyLongPressListener(in IOnVolumeKeyLongPressListener listener);
     void setOnMediaKeyListener(in IOnMediaKeyListener listener);
 
diff --git a/media/java/android/media/session/MediaSessionManager.java b/media/java/android/media/session/MediaSessionManager.java
index dec0140..1f2283c 100644
--- a/media/java/android/media/session/MediaSessionManager.java
+++ b/media/java/android/media/session/MediaSessionManager.java
@@ -46,7 +46,9 @@
 import com.android.internal.annotations.GuardedBy;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Objects;
 
 /**
@@ -72,6 +74,7 @@
      * @hide
      */
     public static final int RESULT_MEDIA_KEY_HANDLED = 1;
+    private final ISessionManager mService;
 
     private final Object mLock = new Object();
     @GuardedBy("mLock")
@@ -80,13 +83,21 @@
     @GuardedBy("mLock")
     private final ArrayMap<OnSession2TokensChangedListener, Session2TokensChangedWrapper>
             mSession2TokensListeners = new ArrayMap<>();
-    private final ISessionManager mService;
+    @GuardedBy("mLock")
+    private final CallbackStub mCbStub = new CallbackStub();
+    @GuardedBy("mLock")
+    private final Map<Callback, Handler> mCallbacks = new HashMap<>();
+    @GuardedBy("mLock")
+    private MediaSession.Token mCurMediaButtonSession;
+    @GuardedBy("mLock")
+    private ComponentName mCurMediaButtonReceiver;
 
     private Context mContext;
-
-    private CallbackImpl mCallback;
     private OnVolumeKeyLongPressListenerImpl mOnVolumeKeyLongPressListener;
     private OnMediaKeyListenerImpl mOnMediaKeyListener;
+    // TODO: Remove mLegacyCallback once Bluetooth app stop calling setCallback() method.
+    @GuardedBy("mLock")
+    private Callback mLegacyCallback;
 
     /**
      * @hide
@@ -752,18 +763,71 @@
      *            if the callback should be invoked on the calling thread's looper.
      * @hide
      */
+    // TODO: Remove this method once Bluetooth app stop calling it.
     public void setCallback(@Nullable Callback callback, @Nullable Handler handler) {
         synchronized (mLock) {
+            if (mLegacyCallback != null) {
+                unregisterCallback(mLegacyCallback);
+            }
+            mLegacyCallback = callback;
+            if (callback != null) {
+                registerCallback(callback, handler);
+            }
+        }
+    }
+
+    /**
+     * Register a {@link Callback}.
+     *
+     * @param callback A {@link Callback}.
+     * @param handler The handler on which the callback should be invoked, or {@code null}
+     *            if the callback should be invoked on the calling thread's looper.
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(value = android.Manifest.permission.MEDIA_CONTENT_CONTROL)
+    public void registerCallback(@NonNull Callback callback, @Nullable Handler handler) {
+        if (callback == null) {
+            throw new NullPointerException("callback shouldn't be null");
+        }
+        synchronized (mLock) {
             try {
-                if (callback == null) {
-                    mCallback = null;
-                    mService.setCallback(null);
-                } else {
-                    if (handler == null) {
-                        handler = new Handler();
-                    }
-                    mCallback = new CallbackImpl(callback, handler);
-                    mService.setCallback(mCallback);
+                if (handler == null) {
+                    handler = new Handler();
+                }
+                mCallbacks.put(callback, handler);
+                if (mCurMediaButtonSession != null) {
+                    handler.post(() -> callback.onAddressedPlayerChanged(mCurMediaButtonSession));
+                } else if (mCurMediaButtonReceiver != null) {
+                    handler.post(() -> callback.onAddressedPlayerChanged(mCurMediaButtonReceiver));
+                }
+
+                if (mCallbacks.size() == 1) {
+                    mService.registerCallback(mCbStub);
+                }
+            } catch (RemoteException e) {
+                Log.e(TAG, "Failed to set media key callback", e);
+            }
+        }
+    }
+
+    /**
+     * Unregister a {@link Callback}.
+     *
+     * @param callback A {@link Callback}.
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(value = android.Manifest.permission.MEDIA_CONTENT_CONTROL)
+    public void unregisterCallback(@NonNull Callback callback) {
+        if (callback == null) {
+            throw new NullPointerException("callback shouldn't be null");
+        }
+        synchronized (mLock) {
+            try {
+                mCallbacks.remove(callback);
+                if (mCallbacks.size() == 0) {
+                    mService.unregisterCallback(mCbStub);
                 }
             } catch (RemoteException e) {
                 Log.e(TAG, "Failed to set media key callback", e);
@@ -835,6 +899,7 @@
      * receive media key events.
      * @hide
      */
+    @SystemApi
     public static abstract class Callback {
         /**
          * Called when a media key event is dispatched to the media session
@@ -861,7 +926,7 @@
         /**
          * Called when the addressed player is changed to a media session.
          * <p>One of the {@ #onAddressedPlayerChanged} will be also called immediately after
-         * {@link #setCallback} if the addressed player exists.
+         * {@link #registerCallback} if the addressed player exists.
          *
          * @param sessionToken The media session's token.
          */
@@ -870,7 +935,7 @@
         /**
          * Called when the addressed player is changed to the media button receiver.
          * <p>One of the {@ #onAddressedPlayerChanged} will be also called immediately after
-         * {@link #setCallback} if the addressed player exists.
+         * {@link #registerCallback} if the addressed player exists.
          *
          * @param mediaButtonReceiver The media button receiver.
          */
@@ -1076,56 +1141,52 @@
         }
     }
 
-    private static final class CallbackImpl extends ICallback.Stub {
-        private final Callback mCallback;
-        private final Handler mHandler;
-
-        public CallbackImpl(@NonNull Callback callback, @NonNull Handler handler) {
-            mCallback = callback;
-            mHandler = handler;
-        }
+    private final class CallbackStub extends ICallback.Stub {
 
         @Override
         public void onMediaKeyEventDispatchedToMediaSession(KeyEvent event,
                 MediaSession.Token sessionToken) {
-            mHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    mCallback.onMediaKeyEventDispatched(event, sessionToken);
+            synchronized (mLock) {
+                for (Map.Entry<Callback, Handler> e : mCallbacks.entrySet()) {
+                    e.getValue().post(
+                            () -> e.getKey().onMediaKeyEventDispatched(event, sessionToken));
                 }
-            });
+            }
         }
 
         @Override
         public void onMediaKeyEventDispatchedToMediaButtonReceiver(KeyEvent event,
                 ComponentName mediaButtonReceiver) {
-            mHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    mCallback.onMediaKeyEventDispatched(event, mediaButtonReceiver);
+            synchronized (mLock) {
+                for (Map.Entry<Callback, Handler> e : mCallbacks.entrySet()) {
+                    e.getValue().post(
+                            () -> e.getKey().onMediaKeyEventDispatched(event, mediaButtonReceiver));
                 }
-            });
+            }
         }
 
         @Override
         public void onAddressedPlayerChangedToMediaSession(MediaSession.Token sessionToken) {
-            mHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    mCallback.onAddressedPlayerChanged(sessionToken);
+            synchronized (mLock) {
+                mCurMediaButtonSession = sessionToken;
+                mCurMediaButtonReceiver = null;
+                for (Map.Entry<Callback, Handler> e : mCallbacks.entrySet()) {
+                    e.getValue().post(() -> e.getKey().onAddressedPlayerChanged(sessionToken));
                 }
-            });
+            }
         }
 
         @Override
         public void onAddressedPlayerChangedToMediaButtonReceiver(
                 ComponentName mediaButtonReceiver) {
-            mHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    mCallback.onAddressedPlayerChanged(mediaButtonReceiver);
+            synchronized (mLock) {
+                mCurMediaButtonSession = null;
+                mCurMediaButtonReceiver = mediaButtonReceiver;
+                for (Map.Entry<Callback, Handler> e : mCallbacks.entrySet()) {
+                    e.getValue().post(() -> e.getKey().onAddressedPlayerChanged(
+                            mediaButtonReceiver));
                 }
-            });
+            }
         }
     }
 }
diff --git a/media/jni/android_media_ImageReader.cpp b/media/jni/android_media_ImageReader.cpp
index 77878f8..0a02156 100644
--- a/media/jni/android_media_ImageReader.cpp
+++ b/media/jni/android_media_ImageReader.cpp
@@ -416,11 +416,13 @@
     if (res != OK) {
         jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
                           "Failed to set buffer consumer default format 0x%x", nativeFormat);
+        return;
     }
     res = bufferConsumer->setDefaultBufferDataSpace(nativeDataspace);
     if (res != OK) {
         jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
                           "Failed to set buffer consumer default dataSpace 0x%x", nativeDataspace);
+        return;
     }
 }
 
@@ -704,7 +706,7 @@
     // and we don't set them here.
 }
 
-static void Image_getLockedImageInfo(JNIEnv* env, LockedImage* buffer, int idx,
+static bool Image_getLockedImageInfo(JNIEnv* env, LockedImage* buffer, int idx,
         int32_t writerFormat, uint8_t **base, uint32_t *size, int *pixelStride, int *rowStride) {
     ALOGV("%s", __FUNCTION__);
 
@@ -713,7 +715,9 @@
     if (res != OK) {
         jniThrowExceptionFmt(env, "java/lang/UnsupportedOperationException",
                              "Pixel format: 0x%x is unsupported", buffer->flexFormat);
+        return false;
     }
+    return true;
 }
 
 static jobjectArray Image_createSurfacePlanes(JNIEnv* env, jobject thiz,
@@ -756,8 +760,10 @@
     }
     // Create all SurfacePlanes
     for (int i = 0; i < numPlanes; i++) {
-        Image_getLockedImageInfo(env, &lockedImg, i, halReaderFormat,
-                &pData, &dataSize, &pixelStride, &rowStride);
+        if (!Image_getLockedImageInfo(env, &lockedImg, i, halReaderFormat,
+                &pData, &dataSize, &pixelStride, &rowStride)) {
+            return NULL;
+        }
         byteBuffer = env->NewDirectByteBuffer(pData, dataSize);
         if ((byteBuffer == NULL) && (env->ExceptionCheck() == false)) {
             jniThrowException(env, "java/lang/IllegalStateException",
diff --git a/media/jni/android_media_ImageWriter.cpp b/media/jni/android_media_ImageWriter.cpp
index 728c55e..6d8b966 100644
--- a/media/jni/android_media_ImageWriter.cpp
+++ b/media/jni/android_media_ImageWriter.cpp
@@ -777,6 +777,7 @@
         status_t res = buffer->unlock();
         if (res != OK) {
             jniThrowRuntimeException(env, "unlock buffer failed");
+            return;
         }
         ALOGV("Successfully unlocked the image");
     }
@@ -872,7 +873,7 @@
     // and we don't set them here.
 }
 
-static void Image_getLockedImageInfo(JNIEnv* env, LockedImage* buffer, int idx,
+static bool Image_getLockedImageInfo(JNIEnv* env, LockedImage* buffer, int idx,
         int32_t writerFormat, uint8_t **base, uint32_t *size, int *pixelStride, int *rowStride) {
     ALOGV("%s", __FUNCTION__);
 
@@ -880,8 +881,10 @@
             pixelStride, rowStride);
     if (res != OK) {
         jniThrowExceptionFmt(env, "java/lang/UnsupportedOperationException",
-                             "Pixel format: 0x%x is unsupported", buffer->flexFormat);
+                             "Pixel format: 0x%x is unsupported", writerFormat);
+        return false;
     }
+    return true;
 }
 
 static jobjectArray Image_createSurfacePlanes(JNIEnv* env, jobject thiz,
@@ -920,8 +923,10 @@
     PublicFormat publicWriterFormat = static_cast<PublicFormat>(writerFormat);
     writerFormat = mapPublicFormatToHalFormat(publicWriterFormat);
     for (int i = 0; i < numPlanes; i++) {
-        Image_getLockedImageInfo(env, &lockedImg, i, writerFormat,
-                &pData, &dataSize, &pixelStride, &rowStride);
+        if (!Image_getLockedImageInfo(env, &lockedImg, i, writerFormat,
+                &pData, &dataSize, &pixelStride, &rowStride)) {
+            return NULL;
+        }
         byteBuffer = env->NewDirectByteBuffer(pData, dataSize);
         if ((byteBuffer == NULL) && (env->ExceptionCheck() == false)) {
             jniThrowException(env, "java/lang/IllegalStateException",
diff --git a/media/jni/android_media_MediaMetadataRetriever.cpp b/media/jni/android_media_MediaMetadataRetriever.cpp
index a480784..3809bc4 100644
--- a/media/jni/android_media_MediaMetadataRetriever.cpp
+++ b/media/jni/android_media_MediaMetadataRetriever.cpp
@@ -501,15 +501,7 @@
         return NULL;
     }
 
-    int colorFormat = getColorFormat(env, params);
 
-    std::vector<sp<IMemory> > frames;
-    status_t err = retriever->getFrameAtIndex(&frames, frameIndex, numFrames, colorFormat);
-    if (err != OK || frames.size() == 0) {
-        jniThrowException(env,
-                "java/lang/IllegalStateException", "No frames from retriever");
-        return NULL;
-    }
     jobject arrayList = env->NewObject(fields.arrayListClazz, fields.arrayListInit);
     if (arrayList == NULL) {
         jniThrowException(env,
@@ -517,18 +509,29 @@
         return NULL;
     }
 
+    int colorFormat = getColorFormat(env, params);
     SkColorType outColorType = setOutColorType(env, colorFormat, params);
-
-    for (size_t i = 0; i < frames.size(); i++) {
-        if (frames[i] == NULL || frames[i]->pointer() == NULL) {
+    size_t i = 0;
+    for (; i < numFrames; i++) {
+        sp<IMemory> frame = retriever->getFrameAtIndex(frameIndex + i, colorFormat);
+        if (frame == NULL || frame->pointer() == NULL) {
             ALOGE("video frame at index %zu is a NULL pointer", frameIndex + i);
-            continue;
+            break;
         }
-        VideoFrame *videoFrame = static_cast<VideoFrame *>(frames[i]->pointer());
+        VideoFrame *videoFrame = static_cast<VideoFrame *>(frame->pointer());
         jobject bitmapObj = getBitmapFromVideoFrame(env, videoFrame, -1, -1, outColorType);
         env->CallBooleanMethod(arrayList, fields.arrayListAdd, bitmapObj);
         env->DeleteLocalRef(bitmapObj);
     }
+
+    if (i == 0) {
+        env->DeleteLocalRef(arrayList);
+
+        jniThrowException(env,
+                "java/lang/IllegalStateException", "No frames from retriever");
+        return NULL;
+    }
+
     return arrayList;
 }
 
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 21cb93d..2cdc6a8 100644
--- a/media/tests/MediaRouteProvider/src/com/android/mediarouteprovider/example/SampleMediaRoute2ProviderService.java
+++ b/media/tests/MediaRouteProvider/src/com/android/mediarouteprovider/example/SampleMediaRoute2ProviderService.java
@@ -59,8 +59,26 @@
     }
 
     @Override
-    public void onSelect(int uid, String routeId) {
-        updateProvider(uid, routeId);
+    public void onSelectRoute(String packageName, String routeId) {
+        MediaRoute2Info route = mRoutes.get(routeId);
+        if (route == null) {
+            return;
+        }
+        mRoutes.put(routeId, new MediaRoute2Info.Builder(route)
+                .setClientPackageName(packageName)
+                .build());
+        publishRoutes();
+    }
+
+    @Override
+    public void onUnselectRoute(String packageName, String routeId) {
+        MediaRoute2Info route = mRoutes.get(routeId);
+        if (route == null) {
+            return;
+        }
+        mRoutes.put(routeId, new MediaRoute2Info.Builder(route)
+                .setClientPackageName(null)
+                .build());
         publishRoutes();
     }
 
diff --git a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java
index aa062cd..03b43e2 100644
--- a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java
+++ b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java
@@ -16,6 +16,8 @@
 
 package com.android.mediaroutertest;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
 import static org.mockito.ArgumentMatchers.argThat;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.timeout;
@@ -37,7 +39,9 @@
 import org.junit.runner.RunWith;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.Executor;
 import java.util.concurrent.SynchronousQueue;
@@ -49,8 +53,6 @@
 public class MediaRouterManagerTest {
     private static final String TAG = "MediaRouterManagerTest";
 
-    private static final int TARGET_UID = 109992;
-
     // Must be the same as SampleMediaRoute2ProviderService
     public static final String ROUTE_ID1 = "route_id1";
     public static final String ROUTE_NAME1 = "Sample Route 1";
@@ -59,13 +61,13 @@
     public static final String ACTION_REMOVE_ROUTE =
             "com.android.mediarouteprovider.action_remove_route";
 
-    private static final int AWAIT_MS = 1000;
     private static final int TIMEOUT_MS = 5000;
 
     private Context mContext;
     private MediaRouter2Manager mManager;
     private MediaRouter2 mRouter;
     private Executor mExecutor;
+    private String mPackageName;
 
     private static final List<String> TEST_CONTROL_CATEGORIES = new ArrayList();
     private static final String CONTROL_CATEGORY_1 = "android.media.mediarouter.MEDIA1";
@@ -83,6 +85,20 @@
         mExecutor = new ThreadPoolExecutor(
             1, 20, 3, TimeUnit.SECONDS,
             new SynchronousQueue<Runnable>());
+        mPackageName = mContext.getPackageName();
+    }
+
+    @Test
+    public void testMediaRoute2Info() {
+        MediaRoute2Info routeInfo1 = new MediaRoute2Info.Builder("id", "name")
+                .build();
+        MediaRoute2Info routeInfo2 = new MediaRoute2Info.Builder(routeInfo1).build();
+
+        MediaRoute2Info routeInfo3 = new MediaRoute2Info.Builder(routeInfo1)
+                .setClientPackageName(mPackageName).build();
+
+        assertEquals(routeInfo1, routeInfo2);
+        assertNotEquals(routeInfo1, routeInfo3);
     }
 
     //TODO: Test onRouteChanged when it's properly implemented.
@@ -124,34 +140,30 @@
 
     @Test
     public void controlCategoryTest() throws Exception {
-        final int uid = android.os.Process.myUid();
-
         MediaRouter2Manager.Callback mockCallback = mock(MediaRouter2Manager.Callback.class);
         mManager.addCallback(mExecutor, mockCallback);
 
         MediaRouter2.Callback mockRouterCallback = mock(MediaRouter2.Callback.class);
 
         InstrumentationRegistry.getInstrumentation().runOnMainSync(
-                (Runnable) () -> {
+                () -> {
                     mRouter.addCallback(TEST_CONTROL_CATEGORIES, mExecutor, mockRouterCallback);
                     mRouter.removeCallback(mockRouterCallback);
                 }
         );
         verify(mockCallback, timeout(TIMEOUT_MS).atLeastOnce())
-                .onControlCategoriesChanged(uid, TEST_CONTROL_CATEGORIES);
+                .onControlCategoriesChanged(mPackageName, TEST_CONTROL_CATEGORIES);
 
         mManager.removeCallback(mockCallback);
     }
 
     @Test
-    public void selectRouteTest() throws Exception {
-        final int uid = android.os.Process.myUid();
-
+    public void onRouteSelectedTest() throws Exception {
         CountDownLatch latch = new CountDownLatch(1);
 
         MediaRouter2.Callback mockRouterCallback = mock(MediaRouter2.Callback.class);
         InstrumentationRegistry.getInstrumentation().runOnMainSync(
-                (Runnable) () -> {
+                () -> {
                     mRouter.addCallback(TEST_CONTROL_CATEGORIES, mExecutor, mockRouterCallback);
                 }
         );
@@ -163,22 +175,19 @@
             public void onRouteAdded(MediaRoute2Info routeInfo) {
                 if (mSelectedRoute == null) {
                     mSelectedRoute = routeInfo;
-                    mManager.selectRoute(uid, mSelectedRoute);
+                    mManager.selectRoute(mPackageName, mSelectedRoute);
                 }
             }
 
             @Override
-            public void onRouteSelected(int uid, MediaRoute2Info route) {
-                if (mSelectedRoute != null && route != null
+            public void onRouteSelected(String packageName, MediaRoute2Info route) {
+                if (TextUtils.equals(packageName, mPackageName)
+                        && mSelectedRoute != null
+                        && route != null
                         && TextUtils.equals(route.getId(), mSelectedRoute.getId())) {
                     latch.countDown();
                 }
             }
-
-            @Override
-            public void onControlCategoriesChanged(int uid, List<String> categories) {
-
-            }
         };
 
         mManager.addCallback(mExecutor, managerCallback);
@@ -187,4 +196,55 @@
 
         mManager.removeCallback(managerCallback);
     }
+
+    @Test
+    /**
+     * Tests selecting and unselecting routes of a single provider.
+     */
+    public void testSingleProviderSelect() {
+        MediaRouter2Manager.Callback managerCallback = mock(MediaRouter2Manager.Callback.class);
+        MediaRouter2.Callback routerCallback = mock(MediaRouter2.Callback.class);
+
+        mManager.addCallback(mExecutor, managerCallback);
+        InstrumentationRegistry.getInstrumentation().runOnMainSync(
+                () -> {
+                    mRouter.addCallback(TEST_CONTROL_CATEGORIES, mExecutor, routerCallback);
+                }
+        );
+        verify(managerCallback, timeout(TIMEOUT_MS))
+                .onRouteListChanged(argThat(routes -> routes.size() > 0));
+
+        Map<String, MediaRoute2Info> routes =
+                createRouteMap(mManager.getAvailableRoutes(mPackageName));
+
+        mManager.selectRoute(mPackageName, routes.get(ROUTE_ID1));
+        verify(managerCallback, timeout(TIMEOUT_MS))
+                .onRouteChanged(argThat(routeInfo -> TextUtils.equals(ROUTE_ID1, routeInfo.getId())
+                        && TextUtils.equals(routeInfo.getClientPackageName(), mPackageName)));
+
+        mManager.selectRoute(mPackageName, routes.get(ROUTE_ID2));
+        verify(managerCallback, timeout(TIMEOUT_MS))
+                .onRouteChanged(argThat(routeInfo -> TextUtils.equals(ROUTE_ID2, routeInfo.getId())
+                        && TextUtils.equals(routeInfo.getClientPackageName(), mPackageName)));
+
+        mManager.unselectRoute(mPackageName);
+        verify(managerCallback, timeout(TIMEOUT_MS))
+                .onRouteChanged(argThat(routeInfo -> TextUtils.equals(ROUTE_ID2, routeInfo.getId())
+                        && TextUtils.equals(routeInfo.getClientPackageName(), null)));
+
+        InstrumentationRegistry.getInstrumentation().runOnMainSync(
+                () -> {
+                    mRouter.removeCallback(routerCallback);
+                }
+        );
+        mManager.removeCallback(managerCallback);
+    }
+
+    Map<String, MediaRoute2Info> createRouteMap(List<MediaRoute2Info> routes) {
+        Map<String, MediaRoute2Info> routeMap = new HashMap<>();
+        for (MediaRoute2Info route : routes) {
+            routeMap.put(route.getId(), route);
+        }
+        return routeMap;
+    }
 }
diff --git a/packages/CarSystemUI/res/values-night/colors.xml b/packages/CarSystemUI/res/values-night/colors.xml
index dad94a8..a2edd7dc 100644
--- a/packages/CarSystemUI/res/values-night/colors.xml
+++ b/packages/CarSystemUI/res/values-night/colors.xml
@@ -19,6 +19,9 @@
     <color name="status_bar_background_color">#ff000000</color>
     <color name="system_bar_background_opaque">#ff0c1013</color>
 
+    <!-- The background color of the notification shade -->
+    <color name="notification_shade_background_color">#E0000000</color>
+    
     <!-- The color of the ripples on the untinted notifications -->
     <color name="notification_ripple_untinted_color">@color/ripple_material_dark</color>
 </resources>
diff --git a/packages/CarSystemUI/res/values/colors.xml b/packages/CarSystemUI/res/values/colors.xml
index e13c940..e0ae4566 100644
--- a/packages/CarSystemUI/res/values/colors.xml
+++ b/packages/CarSystemUI/res/values/colors.xml
@@ -35,7 +35,7 @@
     <drawable name="system_bar_background">@android:color/transparent</drawable>
 
     <!-- The background color of the notification shade -->
-    <color name="notification_shade_background_color">#DD000000</color>
+    <color name="notification_shade_background_color">#D6000000</color>
 
     <!-- The background color of the car volume dialog -->
     <color name="car_volume_dialog_background_color">@color/system_bar_background_opaque</color>
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java
index 0f4cf21..0421c3b 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java
@@ -20,6 +20,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.TypedArray;
+import android.os.Build;
 import android.os.UserHandle;
 import android.util.AttributeSet;
 import android.view.Display;
@@ -122,7 +123,7 @@
                         new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS), UserHandle.CURRENT);
             });
 
-            if (longPressIntentString != null) {
+            if (longPressIntentString != null && (Build.IS_ENG || Build.IS_USERDEBUG)) {
                 final Intent longPressIntent = Intent.parseUri(longPressIntentString,
                         Intent.URI_INTENT_SCHEME);
                 setOnLongClickListener(v -> {
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java
index 095e2e9..05a41e6 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java
@@ -17,7 +17,6 @@
 package com.android.systemui.statusbar.car;
 
 import android.content.Context;
-import android.graphics.Rect;
 import android.util.AttributeSet;
 import android.view.MotionEvent;
 import android.view.View;
@@ -75,40 +74,13 @@
     @Override
     public boolean onInterceptTouchEvent(MotionEvent ev) {
         if (mStatusBarWindowTouchListener != null) {
-            boolean shouldConsumeEvent = shouldConsumeNotificationButtonEvent(ev);
             // Forward touch events to the status bar window so it can drag
             // windows if required (Notification shade)
             mStatusBarWindowTouchListener.onTouch(this, ev);
-            // return true if child views should not receive this event.
-            if (shouldConsumeEvent) {
-                return true;
-            }
         }
         return super.onInterceptTouchEvent(ev);
     }
 
-    /**
-     * If the motion event is over top of the notification button while the notification
-     * panel is open, we need the statusbar touch listeners handle the event instead of the button.
-     * Since the statusbar listener will trigger a close of the notification panel before the
-     * any button click events are fired this will prevent reopening the panel.
-     *
-     * Note: we can't use requestDisallowInterceptTouchEvent because the gesture detector will
-     * always receive the ACTION_DOWN and thus think a longpress happened if no other events are
-     * received
-     *
-     * @return true if the notification button should not receive the event
-     */
-    private boolean shouldConsumeNotificationButtonEvent(MotionEvent ev) {
-        if (mNotificationsButton == null || !mCarStatusBar.isNotificationPanelOpen()) {
-            return false;
-        }
-        Rect notificationButtonLocation = new Rect();
-        mNotificationsButton.getHitRect(notificationButtonLocation);
-        return notificationButtonLocation.contains((int) ev.getX(), (int) ev.getY());
-    }
-
-
     void setStatusBar(CarStatusBar carStatusBar) {
         mCarStatusBar = carStatusBar;
     }
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarNavigationButton.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarNavigationButton.java
index 9de4ef5..fc5e791 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarNavigationButton.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarNavigationButton.java
@@ -20,6 +20,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.TypedArray;
+import android.os.Build;
 import android.os.UserHandle;
 import android.util.AttributeSet;
 import android.util.Log;
@@ -114,7 +115,7 @@
         }
 
         try {
-            if (mLongIntent != null) {
+            if (mLongIntent != null && (Build.IS_ENG || Build.IS_USERDEBUG)) {
                 final Intent intent = Intent.parseUri(mLongIntent, Intent.URI_INTENT_SCHEME);
                 setOnLongClickListener(v -> {
                     try {
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 812adf9..a452bae 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -27,6 +27,7 @@
 import android.car.drivingstate.CarUxRestrictionsManager;
 import android.car.hardware.power.CarPowerManager.CarPowerStateListener;
 import android.content.Context;
+import android.content.res.Configuration;
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
@@ -1078,6 +1079,21 @@
         }
     }
 
+    @Override
+    public void onConfigChanged(Configuration newConfig) {
+        super.onConfigChanged(newConfig);
+
+        int uiModeNightMask = (newConfig.uiMode & Configuration.UI_MODE_NIGHT_MASK);
+
+        boolean dayNightModeChanged = uiModeNightMask == Configuration.UI_MODE_NIGHT_YES
+                || uiModeNightMask == Configuration.UI_MODE_NIGHT_NO;
+
+        if (dayNightModeChanged) {
+            mNotificationView.setBackgroundColor(
+                    mContext.getColor(R.color.notification_shade_background_color));
+        }
+    }
+
     private void calculatePercentageFromBottom(float height) {
         if (mNotificationView.getHeight() > 0) {
             mPercentageFromBottom = (int) Math.abs(
@@ -1232,13 +1248,6 @@
             setNotificationViewClipBounds((int) event2.getRawY());
             return true;
         }
-
-        @Override
-        public void onLongPress(MotionEvent e) {
-            mClosingVelocity = DEFAULT_FLING_VELOCITY;
-            close();
-            super.onLongPress(e);
-        }
     }
 
     /**
diff --git a/packages/EasterEgg/AndroidManifest.xml b/packages/EasterEgg/AndroidManifest.xml
index c7dd40d..7f76a45 100644
--- a/packages/EasterEgg/AndroidManifest.xml
+++ b/packages/EasterEgg/AndroidManifest.xml
@@ -1,40 +1,38 @@
 <?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.
--->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.android.egg"
     android:versionCode="1"
     android:versionName="1.0">
 
-    <uses-sdk android:minSdkVersion="28" />
+    <uses-permission android:name="android.permission.WRITE_SETTINGS" />
 
     <application
-        android:icon="@drawable/icon"
+        android:icon="@drawable/q_icon"
         android:label="@string/app_name">
+        <activity android:name=".quares.QuaresActivity"
+            android:icon="@drawable/q_icon"
+            android:label="@string/q_egg_name"
+            android:theme="@style/QuaresTheme">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
 
+                <category android:name="android.intent.category.DEFAULT" />
+                <!-- <category android:name="android.intent.category.LAUNCHER" /> -->
+                <category android:name="com.android.internal.category.PLATLOGO" />
+            </intent-filter>
+        </activity>
         <activity
             android:name=".paint.PaintActivity"
             android:configChanges="orientation|keyboardHidden|screenSize|uiMode"
-            android:label="@string/app_name"
+            android:icon="@drawable/p_icon"
+            android:label="@string/p_egg_name"
             android:theme="@style/AppTheme">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <!--<category android:name="android.intent.category.LAUNCHER" />-->
-                <category android:name="com.android.internal.category.PLATLOGO" />
+
+                <!-- <category android:name="android.intent.category.DEFAULT" /> -->
+                <!-- <category android:name="android.intent.category.LAUNCHER" /> -->
+                <!-- <category android:name="com.android.internal.category.PLATLOGO" /> -->
             </intent-filter>
         </activity>
     </application>
diff --git a/packages/EasterEgg/res/drawable/icon_bg.xml b/packages/EasterEgg/res/drawable/icon_bg.xml
index c1553ce..659f98b 100644
--- a/packages/EasterEgg/res/drawable/icon_bg.xml
+++ b/packages/EasterEgg/res/drawable/icon_bg.xml
@@ -15,4 +15,4 @@
     limitations under the License.
 -->
 <color xmlns:android="http://schemas.android.com/apk/res/android"
-    android:color="#C5E1A5" />
\ No newline at end of file
+    android:color="@color/q_clue_text" />
diff --git a/packages/EasterEgg/res/drawable/icon.xml b/packages/EasterEgg/res/drawable/p_icon.xml
similarity index 100%
rename from packages/EasterEgg/res/drawable/icon.xml
rename to packages/EasterEgg/res/drawable/p_icon.xml
diff --git a/packages/EasterEgg/res/drawable/pixel_bg.xml b/packages/EasterEgg/res/drawable/pixel_bg.xml
new file mode 100644
index 0000000..4d4a113
--- /dev/null
+++ b/packages/EasterEgg/res/drawable/pixel_bg.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:exitFadeDuration="100">
+    <item android:state_pressed="true">
+        <shape><solid android:color="@color/red"/></shape>
+    </item>
+    <item android:state_checked="true">
+        <shape><solid android:color="@color/pixel_on"/></shape>
+    </item>
+    <item>
+        <shape><solid android:color="@color/pixel_off"/></shape>
+    </item>
+</selector>
\ No newline at end of file
diff --git a/packages/EasterEgg/res/drawable/q.xml b/packages/EasterEgg/res/drawable/q.xml
new file mode 100644
index 0000000..75baa47
--- /dev/null
+++ b/packages/EasterEgg/res/drawable/q.xml
@@ -0,0 +1,27 @@
+<!--
+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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="@color/q_icon_fg"
+        android:pathData="M19.45,22.89l-10.250001,-10.249999l-2.6599998,2.6599998l-1.77,-1.7600002l4.43,-4.4300003l12.0199995,12.0199995l-1.7699986,1.7600002z"/>
+    <path
+        android:fillColor="@color/q_icon_fg"
+        android:pathData="M12,6a6,6 0,1 1,-6 6,6 6,0 0,1 6,-6m0,-2.5A8.5,8.5 0,1 0,20.5 12,8.51 8.51,0 0,0 12,3.5Z"/>
+</vector>
diff --git a/packages/EasterEgg/res/drawable/q_icon.xml b/packages/EasterEgg/res/drawable/q_icon.xml
new file mode 100644
index 0000000..ef4b0a3
--- /dev/null
+++ b/packages/EasterEgg/res/drawable/q_icon.xml
@@ -0,0 +1,19 @@
+<!--
+    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.
+-->
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+    <background android:drawable="@drawable/icon_bg"/>
+    <foreground android:drawable="@drawable/q_smaller"/>
+</adaptive-icon>
diff --git a/packages/EasterEgg/res/drawable/q_smaller.xml b/packages/EasterEgg/res/drawable/q_smaller.xml
new file mode 100644
index 0000000..c71dff0
--- /dev/null
+++ b/packages/EasterEgg/res/drawable/q_smaller.xml
@@ -0,0 +1,23 @@
+<!--
+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.
+-->
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:insetBottom="5dp"
+        android:insetLeft="5dp"
+        android:insetRight="5dp"
+        android:insetTop="5dp"
+        android:drawable="@drawable/q" />
diff --git a/packages/EasterEgg/res/layout/activity_quares.xml b/packages/EasterEgg/res/layout/activity_quares.xml
new file mode 100644
index 0000000..dcc90f6
--- /dev/null
+++ b/packages/EasterEgg/res/layout/activity_quares.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:animateLayoutChanges="true"
+    tools:context="com.android.egg.quares.QuaresActivity">
+
+   <GridLayout
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center"
+        android:alignmentMode="alignBounds"
+        android:id="@+id/grid"
+        />
+
+    <Button
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:id="@+id/label"
+        android:layout_gravity="center_horizontal|bottom"
+        android:gravity="center"
+        android:textSize="18dp"
+        android:visibility="gone"
+        android:drawablePadding="8dp"
+        android:padding="12dp"
+        android:backgroundTint="@color/q_clue_bg_correct"
+        android:textColor="@color/q_clue_text"
+        android:layout_marginBottom="48dp"
+        android:elevation="30dp"
+        />
+</FrameLayout>
diff --git a/packages/EasterEgg/res/values-night/q_colors.xml b/packages/EasterEgg/res/values-night/q_colors.xml
new file mode 100644
index 0000000..191bd94
--- /dev/null
+++ b/packages/EasterEgg/res/values-night/q_colors.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<resources>
+    <color name="pixel_off">#000000</color>
+    <color name="pixel_on">#FFFFFF</color>
+
+    <color name="q_clue_bg">@color/navy</color>
+    <color name="q_clue_text">@color/tan</color>
+</resources>
\ No newline at end of file
diff --git a/packages/EasterEgg/res/values/q_colors.xml b/packages/EasterEgg/res/values/q_colors.xml
new file mode 100644
index 0000000..5e92c84
--- /dev/null
+++ b/packages/EasterEgg/res/values/q_colors.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<resources>
+    <color name="emerald">#3ddc84</color>
+    <color name="red">#f8c734</color>
+    <color name="navy">#073042</color>
+    <color name="vapor">#d7effe</color>
+    <color name="tan">#eff7cf</color>
+
+    <color name="pixel_off">#FFFFFF</color>
+    <color name="pixel_on">#000000</color>
+
+    <color name="q_clue_bg">@color/tan</color>
+    <color name="q_clue_text">@color/navy</color>
+    <color name="q_clue_bg_correct">@color/emerald</color>
+
+    <color name="q_icon_fg">@color/emerald</color>
+</resources>
diff --git a/packages/EasterEgg/res/values/q_puzzles.xml b/packages/EasterEgg/res/values/q_puzzles.xml
new file mode 100644
index 0000000..7c2eff1
--- /dev/null
+++ b/packages/EasterEgg/res/values/q_puzzles.xml
@@ -0,0 +1,214 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string-array name="puzzles">
+
+        <item>q</item>
+        <item>q</item>
+        <item>q</item>
+        <item>q</item>
+        <item>q</item>
+
+        <item>android:drawable/ic_info</item>
+
+        <item>android:drawable/stat_sys_adb</item>
+        <item>android:drawable/stat_sys_battery</item>
+        <item>android:drawable/stat_sys_phone_call</item>
+        <item>android:drawable/stat_sys_certificate_info</item>
+        <item>android:drawable/stat_sys_data_bluetooth</item>
+        <item>android:drawable/stat_sys_data_usb</item>
+        <item>android:drawable/stat_sys_download</item>
+        <item>android:drawable/stat_sys_gps_on</item>
+        <item>android:drawable/stat_sys_phone_call</item>
+        <item>android:drawable/stat_sys_tether_wifi</item>
+        <item>android:drawable/stat_sys_throttled</item>
+        <item>android:drawable/stat_sys_upload</item>
+
+        <item>android:drawable/stat_notify_car_mode</item>
+        <item>android:drawable/stat_notify_chat</item>
+        <item>android:drawable/stat_notify_disk_full</item>
+        <item>android:drawable/stat_notify_email_generic</item>
+        <item>android:drawable/stat_notify_error</item>
+        <item>android:drawable/stat_notify_gmail</item>
+        <item>android:drawable/stat_notify_missed_call</item>
+        <item>android:drawable/stat_notify_mmcc_indication_icn</item>
+        <item>android:drawable/stat_notify_more</item>
+        <item>android:drawable/stat_notify_rssi_in_range</item>
+        <item>android:drawable/stat_notify_sdcard</item>
+        <item>android:drawable/stat_notify_sdcard_prepare</item>
+        <item>android:drawable/stat_notify_sdcard_usb</item>
+        <item>android:drawable/stat_notify_sim_toolkit</item>
+        <item>android:drawable/stat_notify_sync</item>
+        <item>android:drawable/stat_notify_sync_anim0</item>
+        <item>android:drawable/stat_notify_sync_error</item>
+        <item>android:drawable/stat_notify_voicemail</item>
+
+        <item>android:drawable/ic_audio_alarm</item>
+        <item>android:drawable/ic_audio_alarm_mute</item>
+        <item>android:drawable/ic_bluetooth_share_icon</item>
+        <item>android:drawable/ic_bt_headphones_a2dp</item>
+        <item>android:drawable/ic_bt_headset_hfp</item>
+        <item>android:drawable/ic_bt_hearing_aid</item>
+        <item>android:drawable/ic_bt_laptop</item>
+        <item>android:drawable/ic_bt_misc_hid</item>
+        <item>android:drawable/ic_bt_network_pan</item>
+        <item>android:drawable/ic_bt_pointing_hid</item>
+        <item>android:drawable/ic_corp_badge</item>
+        <item>android:drawable/ic_expand_more</item>
+        <item>android:drawable/ic_faster_emergency</item>
+        <item>android:drawable/ic_file_copy</item>
+        <item>android:drawable/ic_info_outline_24</item>
+        <item>android:drawable/ic_lock</item>
+        <item>android:drawable/ic_lock_bugreport</item>
+        <item>android:drawable/ic_lock_open</item>
+        <item>android:drawable/ic_lock_power_off</item>
+        <item>android:drawable/ic_lockscreen_ime</item>
+        <item>android:drawable/ic_mode_edit</item>
+        <item>android:drawable/ic_phone</item>
+        <item>android:drawable/ic_qs_airplane</item>
+        <item>android:drawable/ic_qs_auto_rotate</item>
+        <item>android:drawable/ic_qs_battery_saver</item>
+        <item>android:drawable/ic_qs_bluetooth</item>
+        <item>android:drawable/ic_qs_dnd</item>
+        <item>android:drawable/ic_qs_flashlight</item>
+        <item>android:drawable/ic_qs_night_display_on</item>
+        <item>android:drawable/ic_restart</item>
+        <item>android:drawable/ic_screenshot</item>
+        <item>android:drawable/ic_settings_bluetooth</item>
+        <item>android:drawable/ic_signal_cellular_0_4_bar</item>
+        <item>android:drawable/ic_signal_cellular_0_5_bar</item>
+        <item>android:drawable/ic_signal_cellular_1_4_bar</item>
+        <item>android:drawable/ic_signal_cellular_1_5_bar</item>
+        <item>android:drawable/ic_signal_cellular_2_4_bar</item>
+        <item>android:drawable/ic_signal_cellular_2_5_bar</item>
+        <item>android:drawable/ic_signal_cellular_3_4_bar</item>
+        <item>android:drawable/ic_signal_cellular_3_5_bar</item>
+        <item>android:drawable/ic_signal_cellular_4_4_bar</item>
+        <item>android:drawable/ic_signal_cellular_4_5_bar</item>
+        <item>android:drawable/ic_signal_cellular_5_5_bar</item>
+        <item>android:drawable/ic_signal_location</item>
+        <item>android:drawable/ic_wifi_signal_0</item>
+        <item>android:drawable/ic_wifi_signal_1</item>
+        <item>android:drawable/ic_wifi_signal_2</item>
+        <item>android:drawable/ic_wifi_signal_3</item>
+        <item>android:drawable/ic_wifi_signal_4</item>
+        <item>android:drawable/perm_group_activity_recognition</item>
+        <item>android:drawable/perm_group_calendar</item>
+        <item>android:drawable/perm_group_call_log</item>
+        <item>android:drawable/perm_group_camera</item>
+        <item>android:drawable/perm_group_contacts</item>
+        <item>android:drawable/perm_group_location</item>
+        <item>android:drawable/perm_group_microphone</item>
+        <item>android:drawable/perm_group_phone_calls</item>
+        <item>android:drawable/perm_group_sensors</item>
+        <item>android:drawable/perm_group_sms</item>
+        <item>android:drawable/perm_group_storage</item>
+        <item>android:drawable/perm_group_visual</item>
+
+        <item>com.android.settings:drawable/ic_add_24dp</item>
+        <item>com.android.settings:drawable/ic_airplanemode_active</item>
+        <item>com.android.settings:drawable/ic_android</item>
+        <item>com.android.settings:drawable/ic_apps</item>
+        <item>com.android.settings:drawable/ic_arrow_back</item>
+        <item>com.android.settings:drawable/ic_arrow_down_24dp</item>
+        <item>com.android.settings:drawable/ic_battery_charging_full</item>
+        <item>com.android.settings:drawable/ic_battery_status_bad_24dp</item>
+        <item>com.android.settings:drawable/ic_battery_status_good_24dp</item>
+        <item>com.android.settings:drawable/ic_battery_status_maybe_24dp</item>
+        <item>com.android.settings:drawable/ic_call_24dp</item>
+        <item>com.android.settings:drawable/ic_cancel</item>
+        <item>com.android.settings:drawable/ic_cast_24dp</item>
+        <item>com.android.settings:drawable/ic_chevron_right_24dp</item>
+        <item>com.android.settings:drawable/ic_data_saver</item>
+        <item>com.android.settings:drawable/ic_delete</item>
+        <item>com.android.settings:drawable/ic_devices_other</item>
+        <item>com.android.settings:drawable/ic_devices_other_opaque_black</item>
+        <item>com.android.settings:drawable/ic_do_not_disturb_on_24dp</item>
+        <item>com.android.settings:drawable/ic_eject_24dp</item>
+        <item>com.android.settings:drawable/ic_expand_less</item>
+        <item>com.android.settings:drawable/ic_expand_more_inverse</item>
+        <item>com.android.settings:drawable/ic_folder_vd_theme_24</item>
+        <item>com.android.settings:drawable/ic_friction_lock_closed</item>
+        <item>com.android.settings:drawable/ic_gray_scale_24dp</item>
+        <item>com.android.settings:drawable/ic_headset_24dp</item>
+        <item>com.android.settings:drawable/ic_help</item>
+        <item>com.android.settings:drawable/ic_local_movies</item>
+        <item>com.android.settings:drawable/ic_lock</item>
+        <item>com.android.settings:drawable/ic_media_stream</item>
+        <item>com.android.settings:drawable/ic_network_cell</item>
+        <item>com.android.settings:drawable/ic_notifications</item>
+        <item>com.android.settings:drawable/ic_notifications_off_24dp</item>
+        <item>com.android.settings:drawable/ic_phone_info</item>
+        <item>com.android.settings:drawable/ic_photo_library</item>
+        <item>com.android.settings:drawable/ic_settings_accessibility</item>
+        <item>com.android.settings:drawable/ic_settings_accounts</item>
+        <item>com.android.settings:drawable/ic_settings_backup</item>
+        <item>com.android.settings:drawable/ic_settings_battery_white</item>
+        <item>com.android.settings:drawable/ic_settings_data_usage</item>
+        <item>com.android.settings:drawable/ic_settings_date_time</item>
+        <item>com.android.settings:drawable/ic_settings_delete</item>
+        <item>com.android.settings:drawable/ic_settings_display_white</item>
+        <item>com.android.settings:drawable/ic_settings_home</item>
+        <item>com.android.settings:drawable/ic_settings_location</item>
+        <item>com.android.settings:drawable/ic_settings_night_display</item>
+        <item>com.android.settings:drawable/ic_settings_open</item>
+        <item>com.android.settings:drawable/ic_settings_print</item>
+        <item>com.android.settings:drawable/ic_settings_privacy</item>
+        <item>com.android.settings:drawable/ic_settings_security_white</item>
+        <item>com.android.settings:drawable/ic_settings_sim</item>
+        <item>com.android.settings:drawable/ic_settings_wireless</item>
+        <item>com.android.settings:drawable/ic_storage</item>
+        <item>com.android.settings:drawable/ic_storage_white</item>
+        <item>com.android.settings:drawable/ic_suggestion_night_display</item>
+        <item>com.android.settings:drawable/ic_sync</item>
+        <item>com.android.settings:drawable/ic_system_update</item>
+        <item>com.android.settings:drawable/ic_videogame_vd_theme_24</item>
+        <item>com.android.settings:drawable/ic_volume_ringer_vibrate</item>
+        <item>com.android.settings:drawable/ic_volume_up_24dp</item>
+        <item>com.android.settings:drawable/ic_vpn_key</item>
+        <item>com.android.settings:drawable/ic_wifi_tethering</item>
+
+        <item>com.android.systemui:drawable/ic_alarm</item>
+        <item>com.android.systemui:drawable/ic_alarm_dim</item>
+        <item>com.android.systemui:drawable/ic_arrow_back</item>
+        <item>com.android.systemui:drawable/ic_bluetooth_connected</item>
+        <item>com.android.systemui:drawable/ic_brightness_thumb</item>
+        <item>com.android.systemui:drawable/ic_camera</item>
+        <item>com.android.systemui:drawable/ic_cast</item>
+        <item>com.android.systemui:drawable/ic_cast_connected</item>
+        <item>com.android.systemui:drawable/ic_cast_connected_fill</item>
+        <item>com.android.systemui:drawable/ic_close_white</item>
+        <item>com.android.systemui:drawable/ic_data_saver</item>
+        <item>com.android.systemui:drawable/ic_data_saver_off</item>
+        <item>com.android.systemui:drawable/ic_drag_handle</item>
+        <item>com.android.systemui:drawable/ic_headset</item>
+        <item>com.android.systemui:drawable/ic_headset_mic</item>
+        <item>com.android.systemui:drawable/ic_hotspot</item>
+        <item>com.android.systemui:drawable/ic_invert_colors</item>
+        <item>com.android.systemui:drawable/ic_location</item>
+        <item>com.android.systemui:drawable/ic_lockscreen_ime</item>
+        <item>com.android.systemui:drawable/ic_notifications_alert</item>
+        <item>com.android.systemui:drawable/ic_notifications_silence</item>
+        <item>com.android.systemui:drawable/ic_power_low</item>
+        <item>com.android.systemui:drawable/ic_power_saver</item>
+        <item>com.android.systemui:drawable/ic_qs_bluetooth_connecting</item>
+        <item>com.android.systemui:drawable/ic_qs_bluetooth_on</item>
+        <item>com.android.systemui:drawable/ic_qs_cancel</item>
+        <item>com.android.systemui:drawable/ic_qs_no_sim</item>
+        <item>com.android.systemui:drawable/ic_screenshot_delete</item>
+        <item>com.android.systemui:drawable/ic_settings</item>
+        <item>com.android.systemui:drawable/ic_swap_vert</item>
+        <item>com.android.systemui:drawable/ic_volume_alarm</item>
+        <item>com.android.systemui:drawable/ic_volume_alarm_mute</item>
+        <item>com.android.systemui:drawable/ic_volume_media</item>
+        <item>com.android.systemui:drawable/ic_volume_media_mute</item>
+        <item>com.android.systemui:drawable/ic_volume_ringer</item>
+        <item>com.android.systemui:drawable/ic_volume_ringer_mute</item>
+        <item>com.android.systemui:drawable/ic_volume_ringer_vibrate</item>
+        <item>com.android.systemui:drawable/ic_volume_voice</item>
+        <item>com.android.systemui:drawable/stat_sys_camera</item>
+        <item>com.android.systemui:drawable/stat_sys_managed_profile_status</item>
+        <item>com.android.systemui:drawable/stat_sys_mic_none</item>
+        <item>com.android.systemui:drawable/stat_sys_vpn_ic</item>
+
+    </string-array>
+</resources>
diff --git a/packages/EasterEgg/res/values/strings.xml b/packages/EasterEgg/res/values/strings.xml
index 32dbc97..b95ec6b 100644
--- a/packages/EasterEgg/res/values/strings.xml
+++ b/packages/EasterEgg/res/values/strings.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
+<?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");
@@ -15,5 +14,11 @@
     limitations under the License.
 -->
 <resources xmlns:android="http://schemas.android.com/apk/res/android">
-    <string name="app_name" translatable="false">PAINT.APK</string>
+    <string name="app_name" translatable="false">Android Q Easter Egg</string>
+
+    <!-- name of the Q easter egg, a nonogram-style icon puzzle -->
+    <string name="q_egg_name" translatable="false">Icon Quiz</string>
+
+    <!-- name of the P easter egg, a humble paint program -->
+    <string name="p_egg_name" translatable="false">PAINT.APK</string>
 </resources>
diff --git a/packages/EasterEgg/res/values/styles.xml b/packages/EasterEgg/res/values/styles.xml
index 44e2ce5..e576526 100644
--- a/packages/EasterEgg/res/values/styles.xml
+++ b/packages/EasterEgg/res/values/styles.xml
@@ -20,4 +20,16 @@
         <item name="android:windowLightNavigationBar">true</item>
     </style>
 
+    <style name="QuaresTheme" parent="@android:style/Theme.DeviceDefault.DayNight">
+        <item name="android:windowIsTranslucent">true</item>
+        <item name="android:windowBackground">@android:color/transparent</item>
+        <item name="android:colorBackgroundCacheHint">@null</item>
+        <item name="android:windowShowWallpaper">true</item>
+        <item name="android:windowContentOverlay">@null</item>
+        <item name="android:windowNoTitle">true</item>
+        <item name="android:windowFullscreen">true</item>
+        <item name="android:statusBarColor">@android:color/transparent</item>
+        <item name="android:navigationBarColor">@android:color/transparent</item>
+    </style>
+
 </resources>
diff --git a/packages/EasterEgg/src/com/android/egg/quares/Quare.kt b/packages/EasterEgg/src/com/android/egg/quares/Quare.kt
new file mode 100644
index 0000000..eb77362
--- /dev/null
+++ b/packages/EasterEgg/src/com/android/egg/quares/Quare.kt
@@ -0,0 +1,168 @@
+/*
+ * 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.egg.quares
+
+import android.content.Context
+import android.graphics.Bitmap
+import android.graphics.Canvas
+import android.graphics.drawable.Drawable
+import android.graphics.drawable.Icon
+import android.os.Parcel
+import android.os.Parcelable
+import java.util.ArrayList
+import kotlin.math.abs
+import kotlin.math.round
+
+class Quare(val width: Int, val height: Int, val depth: Int) : Parcelable {
+    private val data: IntArray = IntArray(width * height)
+    private val user: IntArray = data.copyOf()
+
+    private fun loadAndQuantize(bitmap8bpp: Bitmap) {
+        bitmap8bpp.getPixels(data, 0, width, 0, 0, width, height)
+        if (depth == 8) return
+        val s = (255f / depth)
+        for (i in 0 until data.size) {
+            var f = (data[i] ushr 24).toFloat() / s
+            // f = f.pow(0.75f) // gamma adjust for bolder lines
+            f *= 1.25f // brightness adjust for bolder lines
+            f.coerceAtMost(1f)
+            data[i] = (round(f) * s).toInt() shl 24
+        }
+    }
+
+    fun isBlank(): Boolean {
+        return data.sum() == 0
+    }
+
+    fun load(drawable: Drawable) {
+        val resized = Bitmap.createBitmap(width, height, Bitmap.Config.ALPHA_8)
+        val canvas = Canvas(resized)
+        drawable.setBounds(0, 0, width, height)
+        drawable.setTint(0xFF000000.toInt())
+        drawable.draw(canvas)
+        loadAndQuantize(resized)
+        resized.recycle()
+    }
+
+    fun load(context: Context, icon: Icon) {
+        icon.loadDrawable(context)?.let {
+            load(it)
+        }
+    }
+
+    fun bitmap(): Bitmap {
+        return Bitmap.createBitmap(data, width, height, Bitmap.Config.ALPHA_8)
+    }
+
+    fun getUserMark(x: Int, y: Int): Int {
+        return user[y * width + x] ushr 24
+    }
+
+    fun setUserMark(x: Int, y: Int, v: Int) {
+        user[y * width + x] = v shl 24
+    }
+
+    fun getDataAt(x: Int, y: Int): Int {
+        return data[y * width + x] ushr 24
+    }
+
+    fun check(): Boolean {
+        return data.contentEquals(user)
+    }
+
+    fun check(xSel: Int, ySel: Int): Boolean {
+        val xStart = if (xSel < 0) 0 else xSel
+        val xEnd = if (xSel < 0) width - 1 else xSel
+        val yStart = if (ySel < 0) 0 else ySel
+        val yEnd = if (ySel < 0) height - 1 else ySel
+        for (y in yStart..yEnd)
+            for (x in xStart..xEnd)
+                if (getDataAt(x, y) != getUserMark(x, y)) return false
+        return true
+    }
+
+    fun errors(): IntArray {
+        return IntArray(width * height) {
+            abs(data[it] - user[it])
+        }
+    }
+
+    fun getRowClue(y: Int): IntArray {
+        return getClue(-1, y)
+    }
+    fun getColumnClue(x: Int): IntArray {
+        return getClue(x, -1)
+    }
+    fun getClue(xSel: Int, ySel: Int): IntArray {
+        val arr = ArrayList<Int>()
+        var len = 0
+        val xStart = if (xSel < 0) 0 else xSel
+        val xEnd = if (xSel < 0) width - 1 else xSel
+        val yStart = if (ySel < 0) 0 else ySel
+        val yEnd = if (ySel < 0) height - 1 else ySel
+        for (y in yStart..yEnd)
+            for (x in xStart..xEnd)
+                if (getDataAt(x, y) != 0) {
+                    len++
+                } else if (len > 0) {
+                    arr.add(len)
+                    len = 0
+                }
+        if (len > 0) arr.add(len)
+        else if (arr.size == 0) arr.add(0)
+        return arr.toIntArray()
+    }
+
+    fun resetUserMarks() {
+        user.forEachIndexed { index, _ -> user[index] = 0 }
+    }
+
+    // Parcelable interface
+
+    override fun describeContents(): Int {
+        return 0
+    }
+
+    override fun writeToParcel(p: Parcel?, flags: Int) {
+        p?.let {
+            p.writeInt(width)
+            p.writeInt(height)
+            p.writeInt(depth)
+            p.writeIntArray(data)
+            p.writeIntArray(user)
+        }
+    }
+
+    companion object CREATOR : Parcelable.Creator<Quare> {
+        override fun createFromParcel(p: Parcel?): Quare {
+            return p!!.let {
+                Quare(
+                        p.readInt(), // width
+                        p.readInt(), // height
+                        p.readInt()  // depth
+                ).also {
+                    p.readIntArray(it.data)
+                    p.readIntArray(it.user)
+                }
+            }
+        }
+
+        override fun newArray(size: Int): Array<Quare?> {
+            return arrayOfNulls(size)
+        }
+    }
+}
diff --git a/packages/EasterEgg/src/com/android/egg/quares/QuaresActivity.kt b/packages/EasterEgg/src/com/android/egg/quares/QuaresActivity.kt
new file mode 100644
index 0000000..ce439a9
--- /dev/null
+++ b/packages/EasterEgg/src/com/android/egg/quares/QuaresActivity.kt
@@ -0,0 +1,312 @@
+/*
+ * 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.egg.quares
+
+import android.app.Activity
+import android.content.Context
+import android.content.res.Configuration
+import android.graphics.Canvas
+import android.graphics.Paint
+import android.graphics.Typeface
+import android.graphics.drawable.Icon
+import android.os.Bundle
+import android.text.StaticLayout
+import android.text.TextPaint
+import android.util.Log
+import android.view.View
+import android.view.View.GONE
+import android.view.View.VISIBLE
+import android.widget.Button
+import android.widget.CompoundButton
+import android.widget.GridLayout
+
+import java.util.Random
+
+import com.android.egg.R
+
+const val TAG = "Quares"
+
+class QuaresActivity : Activity() {
+    private var q: Quare = Quare(16, 16, 1)
+    private var resId = 0
+    private var resName = ""
+    private var icon: Icon? = null
+
+    private lateinit var label: Button
+    private lateinit var grid: GridLayout
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+
+        window.decorView.systemUiVisibility =
+                View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
+
+        actionBar?.hide()
+
+        setContentView(R.layout.activity_quares)
+
+        grid = findViewById(R.id.grid)
+        label = findViewById(R.id.label)
+
+        if (savedInstanceState != null) {
+            Log.v(TAG, "restoring puzzle from state")
+            q = savedInstanceState.getParcelable("q") ?: q
+            resId = savedInstanceState.getInt("resId")
+            resName = savedInstanceState.getString("resName", "")
+            loadPuzzle()
+        }
+
+        label.setOnClickListener { newPuzzle() }
+    }
+
+    override fun onResume() {
+        super.onResume()
+        if (resId == 0) {
+            // lazy init from onCreate
+            newPuzzle()
+        }
+        checkVictory()
+    }
+
+    override fun onSaveInstanceState(outState: Bundle) {
+        super.onSaveInstanceState(outState)
+
+        outState.putParcelable("q", q)
+        outState.putInt("resId", resId)
+        outState.putString("resName", resName)
+    }
+
+    fun newPuzzle() {
+        Log.v(TAG, "new puzzle...")
+
+        q.resetUserMarks()
+        val oldResId = resId
+        resId = android.R.drawable.stat_sys_warning
+        try {
+            for (tries in 0..3) {
+                val ar = resources.obtainTypedArray(R.array.puzzles)
+                val newName = ar.getString(Random().nextInt(ar.length()))
+                if (newName == null) continue
+
+                Log.v(TAG, "Looking for icon " + newName)
+
+                val pkg = getPackageNameForResourceName(newName)
+                val newId = packageManager.getResourcesForApplication(pkg)
+                        .getIdentifier(newName, "drawable", pkg)
+                if (newId == 0) {
+                    Log.v(TAG, "oops, " + newName + " doesn't resolve from pkg " + pkg)
+                } else if (newId != oldResId) {
+                    // got a good one
+                    resId = newId
+                    resName = newName
+                    break
+                }
+            }
+        } catch (e: RuntimeException) {
+            Log.v(TAG, "problem loading puzzle, using fallback", e)
+        }
+        loadPuzzle()
+    }
+
+    fun getPackageNameForResourceName(name: String): String {
+        return if (name.contains(":") && !name.startsWith("android:")) {
+            name.substring(0, name.indexOf(":"))
+        } else {
+            packageName
+        }
+    }
+
+    fun checkVictory() {
+        if (q.check()) {
+            val dp = resources.displayMetrics.density
+
+            val label: Button = findViewById(R.id.label)
+            label.text = resName.replace(Regex("^.*/"), "")
+            val drawable = icon?.loadDrawable(this)?.also {
+                it.setBounds(0, 0, (32 * dp).toInt(), (32 * dp).toInt())
+                it.setTint(label.currentTextColor)
+            }
+            label.setCompoundDrawables(drawable, null, null, null)
+
+            label.visibility = VISIBLE
+        } else {
+            label.visibility = GONE
+        }
+    }
+
+    fun loadPuzzle() {
+        Log.v(TAG, "loading " + resName + " at " + q.width + "x" + q.height)
+
+        val dp = resources.displayMetrics.density
+
+        icon = Icon.createWithResource(getPackageNameForResourceName(resName), resId)
+        q.load(this, icon!!)
+
+        if (q.isBlank()) {
+            // this is a really boring puzzle, let's try again
+            resId = 0
+            resName = ""
+            recreate()
+            return
+        }
+
+        grid.removeAllViews()
+        grid.columnCount = q.width + 1
+        grid.rowCount = q.height + 1
+
+        label.visibility = GONE
+
+        val orientation = resources.configuration.orientation
+
+        // clean this up a bit
+        val minSide = resources.configuration.smallestScreenWidthDp - 25 // ish
+        val size = (minSide / (q.height + 0.5) * dp).toInt()
+
+        val sb = StringBuffer()
+
+        for (j in 0 until grid.rowCount) {
+            for (i in 0 until grid.columnCount) {
+                val tv: View
+                val params = GridLayout.LayoutParams().also {
+                    it.width = size
+                    it.height = size
+                    it.setMargins(1, 1, 1, 1)
+                    it.rowSpec = GridLayout.spec(GridLayout.UNDEFINED, GridLayout.TOP) // UGH
+                }
+                val x = i - 1
+                val y = j - 1
+                if (i > 0 && j > 0) {
+                    if (i == 1 && j > 1) sb.append("\n")
+                    sb.append(if (q.getDataAt(x, y) == 0) " " else "X")
+                    tv = PixelButton(this)
+                    tv.isChecked = q.getUserMark(x, y) != 0
+                    tv.setOnClickListener {
+                        q.setUserMark(x, y, if (tv.isChecked) 0xFF else 0)
+                        val columnCorrect = (grid.getChildAt(i) as? ClueView)?.check(q) ?: false
+                        val rowCorrect = (grid.getChildAt(j*(grid.columnCount)) as? ClueView)
+                                ?.check(q) ?: false
+                        if (columnCorrect && rowCorrect) {
+                            checkVictory()
+                        } else {
+                            label.visibility = GONE
+                        }
+                    }
+                } else if (i == j) { // 0,0
+                    tv = View(this)
+                    tv.visibility = GONE
+                } else {
+                    tv = ClueView(this)
+                    if (j == 0) {
+                        tv.textRotation = 90f
+                        if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
+                            params.height /= 2
+                            tv.showText = false
+                        } else {
+                            params.height = (96 * dp).toInt()
+                        }
+                        if (x >= 0) {
+                            tv.setColumn(q, x)
+                        }
+                    }
+                    if (i == 0) {
+                        if (orientation == Configuration.ORIENTATION_PORTRAIT) {
+                            params.width /= 2
+                            tv.showText = false
+                        } else {
+                            params.width = (96 * dp).toInt()
+                        }
+                        if (y >= 0) {
+                            tv.setRow(q, y)
+                        }
+                    }
+                }
+                grid.addView(tv, params)
+            }
+        }
+
+        Log.v(TAG, "icon: \n" + sb)
+    }
+}
+
+class PixelButton(context: Context) : CompoundButton(context) {
+    init {
+        setBackgroundResource(R.drawable.pixel_bg)
+        isClickable = true
+        isEnabled = true
+    }
+}
+
+class ClueView(context: Context) : View(context) {
+    var row: Int = -1
+    var column: Int = -1
+    var textRotation: Float = 0f
+    var text: CharSequence = ""
+    var showText = true
+    val paint: TextPaint
+    val incorrectColor: Int
+    val correctColor: Int
+
+    init {
+        setBackgroundColor(0)
+        paint = TextPaint().also {
+            it.textSize = 14f * context.resources.displayMetrics.density
+            it.color = context.getColor(R.color.q_clue_text)
+            it.typeface = Typeface.DEFAULT_BOLD
+            it.textAlign = Paint.Align.CENTER
+        }
+        incorrectColor = context.getColor(R.color.q_clue_bg)
+        correctColor = context.getColor(R.color.q_clue_bg_correct)
+    }
+
+    fun setRow(q: Quare, row: Int): Boolean {
+        this.row = row
+        this.column = -1
+        this.textRotation = 0f
+        text = q.getRowClue(row).joinToString("-")
+        return check(q)
+    }
+    fun setColumn(q: Quare, column: Int): Boolean {
+        this.column = column
+        this.row = -1
+        this.textRotation = 90f
+        text = q.getColumnClue(column).joinToString("-")
+        return check(q)
+    }
+    fun check(q: Quare): Boolean {
+        val correct = q.check(column, row)
+        setBackgroundColor(if (correct) correctColor else incorrectColor)
+        return correct
+    }
+
+    override fun onDraw(canvas: Canvas?) {
+        super.onDraw(canvas)
+        if (!showText) return
+        canvas?.let {
+            val x = canvas.width / 2f
+            val y = canvas.height / 2f
+            var textWidth = canvas.width
+            if (textRotation != 0f) {
+                canvas.rotate(textRotation, x, y)
+                textWidth = canvas.height
+            }
+            val textLayout = StaticLayout.Builder.obtain(
+                    text, 0, text.length, paint, textWidth).build()
+            canvas.translate(x, y - textLayout.height / 2)
+            textLayout.draw(canvas)
+        }
+    }
+}
diff --git a/packages/ExternalStorageProvider/res/values-pt-rPT/strings.xml b/packages/ExternalStorageProvider/res/values-pt-rPT/strings.xml
index 96046ad..35de8ef 100644
--- a/packages/ExternalStorageProvider/res/values-pt-rPT/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-pt-rPT/strings.xml
@@ -19,5 +19,5 @@
     <string name="app_label" msgid="7123375275748530234">"Armazenamento externo"</string>
     <string name="storage_description" msgid="8541974407321172792">"Armazenamento local"</string>
     <string name="root_internal_storage" msgid="827844243068584127">"Armazenamento interno"</string>
-    <string name="root_documents" msgid="4051252304075469250">"Documentos"</string>
+    <string name="root_documents" msgid="4051252304075469250">"Docs"</string>
 </resources>
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidProfile.java
index 7f906f6..6d874ab 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HidProfile.java
@@ -117,7 +117,7 @@
 
     public boolean isPreferred(BluetoothDevice device) {
         if (mService == null) return false;
-        return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF;
+        return mService.getPriority(device) != BluetoothProfile.PRIORITY_OFF;
     }
 
     public int getPreferred(BluetoothDevice device) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageUtils.java b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageUtils.java
index de38e8a..23e29493 100644
--- a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageUtils.java
@@ -18,15 +18,11 @@
 
 import android.content.Context;
 import android.net.NetworkTemplate;
-import android.os.ParcelUuid;
-import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 import android.util.Log;
 
-import java.util.ArrayList;
-import java.util.List;
-
+import com.android.internal.util.ArrayUtils;
 /**
  * Utils class for data usage
  */
@@ -41,31 +37,22 @@
                 TelephonyManager.class);
         final SubscriptionManager subscriptionManager = context.getSystemService(
                 SubscriptionManager.class);
-        final SubscriptionInfo info = subscriptionManager.getActiveSubscriptionInfo(subId);
         final NetworkTemplate mobileAll = NetworkTemplate.buildTemplateMobileAll(
                 telephonyManager.getSubscriberId(subId));
 
-        if (info == null) {
+        if (!subscriptionManager.isActiveSubId(subId)) {
             Log.i(TAG, "Subscription is not active: " + subId);
             return mobileAll;
         }
-        final ParcelUuid groupUuid = info.getGroupUuid();
-        if (groupUuid == null) {
-            Log.i(TAG, "Subscription doesn't have valid group uuid: " + subId);
+
+        final String[] mergedSubscriberIds = telephonyManager.createForSubscriptionId(subId)
+                .getMergedSubscriberIdsFromGroup();
+
+        if (ArrayUtils.isEmpty(mergedSubscriberIds)) {
+            Log.i(TAG, "mergedSubscriberIds is null.");
             return mobileAll;
         }
 
-        // Otherwise merge other subscriberId to create new NetworkTemplate
-        final List<SubscriptionInfo> groupInfos = subscriptionManager.getSubscriptionsInGroup(
-                groupUuid);
-        final List<String> mergedSubscriberIds = new ArrayList<>();
-        for (SubscriptionInfo subInfo : groupInfos) {
-            final String subscriberId = telephonyManager.getSubscriberId(
-                    subInfo.getSubscriptionId());
-            if (subscriberId != null) {
-                mergedSubscriberIds.add(subscriberId);
-            }
-        }
-        return NetworkTemplate.normalize(mobileAll, mergedSubscriberIds.toArray(new String[0]));
+        return NetworkTemplate.normalize(mobileAll, mergedSubscriberIds);
     }
 }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageUtilsTest.java
index dc33cfe..5cae611 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageUtilsTest.java
@@ -18,6 +18,7 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.Matchers.anyInt;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 
@@ -37,7 +38,6 @@
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
 
-import java.util.ArrayList;
 import java.util.List;
 
 @RunWith(RobolectricTestRunner.class)
@@ -70,18 +70,13 @@
         when(mContext.getSystemService(SubscriptionManager.class)).thenReturn(mSubscriptionManager);
         when(mTelephonyManager.getSubscriberId(SUB_ID)).thenReturn(SUBSCRIBER_ID);
         when(mTelephonyManager.getSubscriberId(SUB_ID_2)).thenReturn(SUBSCRIBER_ID_2);
-        when(mInfo1.getSubscriptionId()).thenReturn(SUB_ID);
-        when(mInfo2.getSubscriptionId()).thenReturn(SUB_ID_2);
-
-        mInfos = new ArrayList<>();
-        mInfos.add(mInfo1);
-        mInfos.add(mInfo2);
-        when(mSubscriptionManager.getSubscriptionsInGroup(mParcelUuid)).thenReturn(mInfos);
+        when(mTelephonyManager.createForSubscriptionId(anyInt())).thenReturn(mTelephonyManager);
+        when(mSubscriptionManager.isActiveSubId(anyInt())).thenReturn(true);
     }
 
     @Test
     public void getMobileTemplate_infoNull_returnMobileAll() {
-        when(mSubscriptionManager.getActiveSubscriptionInfo(SUB_ID)).thenReturn(null);
+        when(mSubscriptionManager.isActiveSubId(SUB_ID)).thenReturn(false);
 
         final NetworkTemplate networkTemplate = DataUsageUtils.getMobileTemplate(mContext, SUB_ID);
         assertThat(networkTemplate.matchesSubscriberId(SUBSCRIBER_ID)).isTrue();
@@ -92,6 +87,8 @@
     public void getMobileTemplate_groupUuidNull_returnMobileAll() {
         when(mSubscriptionManager.getActiveSubscriptionInfo(SUB_ID)).thenReturn(mInfo1);
         when(mInfo1.getGroupUuid()).thenReturn(null);
+        when(mTelephonyManager.getMergedSubscriberIdsFromGroup())
+                .thenReturn(new String[] {SUBSCRIBER_ID});
 
         final NetworkTemplate networkTemplate = DataUsageUtils.getMobileTemplate(mContext, SUB_ID);
         assertThat(networkTemplate.matchesSubscriberId(SUBSCRIBER_ID)).isTrue();
@@ -102,6 +99,8 @@
     public void getMobileTemplate_groupUuidExist_returnMobileMerged() {
         when(mSubscriptionManager.getActiveSubscriptionInfo(SUB_ID)).thenReturn(mInfo1);
         when(mInfo1.getGroupUuid()).thenReturn(mParcelUuid);
+        when(mTelephonyManager.getMergedSubscriberIdsFromGroup())
+                .thenReturn(new String[] {SUBSCRIBER_ID, SUBSCRIBER_ID_2});
 
         final NetworkTemplate networkTemplate = DataUsageUtils.getMobileTemplate(mContext, SUB_ID);
         assertThat(networkTemplate.matchesSubscriberId(SUBSCRIBER_ID)).isTrue();
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/GenerationRegistry.java b/packages/SettingsProvider/src/com/android/providers/settings/GenerationRegistry.java
index 044ec86..5617331 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/GenerationRegistry.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/GenerationRegistry.java
@@ -22,14 +22,16 @@
 import android.util.MemoryIntArray;
 import android.util.Slog;
 import android.util.SparseIntArray;
+
 import com.android.internal.annotations.GuardedBy;
 
 import java.io.IOException;
 
 /**
- * This class tracks changes for global/secure/system tables on a
- * per user basis and updates a shared memory region which client
- * processes can read to determine if their local caches are stale,
+ * This class tracks changes for config/global/secure/system tables
+ * on a per user basis and updates a shared memory region which
+ * client processes can read to determine if their local caches are
+ * stale.
  */
 final class GenerationRegistry {
     private static final String LOG_TAG = "GenerationRegistry";
@@ -114,11 +116,12 @@
     @GuardedBy("mLock")
     private MemoryIntArray getBackingStoreLocked() {
         if (mBackingStore == null) {
-            // One for the global table, two for system and secure tables for a
-            // managed profile (managed profile is not included in the max user
-            // count), ten for partially deleted users if users are quickly removed,
-            // and twice max user count for system and secure.
-            final int size = 1 + 2 + 10 + 2 * UserManager.getMaxSupportedUsers();
+            // One for the config table, one for the global table, two for system
+            // and secure tables for a managed profile (managed profile is not
+            // included in the max user count), ten for partially deleted users if
+            // users are quickly removed, and twice max user count for system and
+            // secure.
+            final int size = 1 + 1 + 2 + 10 + 2 * UserManager.getMaxSupportedUsers();
             try {
                 mBackingStore = new MemoryIntArray(size);
                 if (DEBUG) {
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 98c6702..8689eef 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -101,6 +101,8 @@
     <uses-permission android:name="android.permission.REVOKE_RUNTIME_PERMISSIONS" />
     <uses-permission android:name="android.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS" />
     <uses-permission android:name="android.permission.WHITELIST_RESTRICTED_PERMISSIONS" />
+    <!-- Permission required to test onPermissionsChangedListener -->
+    <uses-permission android:name="android.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS" />
     <uses-permission android:name="android.permission.SET_KEYBOARD_LAYOUT" />
     <uses-permission android:name="android.permission.GET_DETAILED_TASKS" />
     <uses-permission android:name="android.permission.SET_SCREEN_COMPATIBILITY" />
diff --git a/packages/SystemUI/res-keyguard/values-bs/strings.xml b/packages/SystemUI/res-keyguard/values-bs/strings.xml
index b23824e..8547bc8 100644
--- a/packages/SystemUI/res-keyguard/values-bs/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-bs/strings.xml
@@ -22,7 +22,7 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_name" msgid="3171996292755059205">"Zaključavanje tastature"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3420548423949593123">"Upišite PIN"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="670683628782925409">"Upišite PUK kôd za SIM karticu i novi PIN"</string>
+    <string name="keyguard_password_enter_puk_code" msgid="670683628782925409">"Upišite PUK za SIM i novi PIN kôd"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="3747778500166059332">"PUK kôd za SIM karticu"</string>
     <string name="keyguard_password_enter_pin_prompt" msgid="8188243197504453830">"Novi PIN za SIM karticu"</string>
     <string name="keyguard_password_entry_touch_hint" msgid="5790410752696806482"><font size="17">"Dodirnite da upišete lozinku"</font></string>
@@ -54,7 +54,7 @@
     <string name="keyguard_accessibility_pin_area" msgid="703175752097279029">"Prostor za PIN"</string>
     <string name="keyguard_accessibility_password" msgid="7695303207740941101">"Lozinka uređaja"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="912702510825058921">"Prostor za PIN za SIM karticu"</string>
-    <string name="keyguard_accessibility_sim_puk_area" msgid="136979425761438705">"Prostor za PUK kôd za SIM karticu"</string>
+    <string name="keyguard_accessibility_sim_puk_area" msgid="136979425761438705">"Prostor za PUK za SIM"</string>
     <string name="keyguard_accessibility_next_alarm" msgid="5835196989158584991">"Naredni alarm je podešen za <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="6883116827512721630">"Izbriši"</string>
     <string name="disable_carrier_button_text" msgid="6914341927421916114">"Onemogući eSIM karticu"</string>
@@ -116,7 +116,7 @@
       <item quantity="other">PUK kôd za SIM karticu je netačan. Imate još <xliff:g id="NUMBER_1">%d</xliff:g> pokušaja prije nego što SIM kartica postane trajno neupotrebljiva.</item>
     </plurals>
     <string name="kg_password_pin_failed" msgid="8769990811451236223">"Korištenje PIN-a za SIM karticu nije uspjelo!"</string>
-    <string name="kg_password_puk_failed" msgid="1331621440873439974">"Korištenje PUK koda za SIM karticu nije uspjelo!"</string>
+    <string name="kg_password_puk_failed" msgid="1331621440873439974">"Korištenje PUK-a za SIM nije uspjelo!"</string>
     <string name="kg_pin_accepted" msgid="7637293533973802143">"Kôd je prihvaćen"</string>
     <string name="keyguard_carrier_default" msgid="4274828292998453695">"Nema mreže."</string>
     <string name="accessibility_ime_switch_button" msgid="2695096475319405612">"Promjena načina unosa"</string>
diff --git a/packages/SystemUI/res-keyguard/values-sq/strings.xml b/packages/SystemUI/res-keyguard/values-sq/strings.xml
index 1d42f1f..e4b37d0 100644
--- a/packages/SystemUI/res-keyguard/values-sq/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sq/strings.xml
@@ -38,7 +38,7 @@
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Po karikohet"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Po karikohet me shpejtësi"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Po karikohet ngadalë"</string>
-    <string name="keyguard_low_battery" msgid="9218432555787624490">"Lidh ngarkuesin."</string>
+    <string name="keyguard_low_battery" msgid="9218432555787624490">"Lidh karikuesin."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8566679946700751371">"Shtyp \"Meny\" për të shkyçur."</string>
     <string name="keyguard_network_locked_message" msgid="6743537524631420759">"Rrjeti është i kyçur"</string>
     <string name="keyguard_missing_sim_message_short" msgid="6327533369959764518">"Nuk ka kartë SIM"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 7f85ec0..3d297ae 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -464,7 +464,7 @@
     <string name="battery_saver_notification_title" msgid="8614079794522291840">"تم تفعيل ميزة توفير شحن البطارية"</string>
     <string name="battery_saver_notification_text" msgid="820318788126672692">"لخفض مستوى الأداء وبيانات الخلفية"</string>
     <string name="battery_saver_notification_action_text" msgid="132118784269455533">"إيقاف ميزة توفير شحن البطارية"</string>
-    <string name="media_projection_dialog_text" msgid="8585357687598538511">"أثناء التسجيل أو الإرسال، يمكن لتطبيق <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> تسجيل أي معلومات حساسة يتم عرضها على الشاشة أو تشغيلها من جهازك، بما فيها المعلومات الحساسة مثل الصوت الذي تشغّله وكلمات المرور ومعلومات الدفع والصور والرسائل."</string>
+    <string name="media_projection_dialog_text" msgid="8585357687598538511">"أثناء التسجيل أو البث، يمكن لتطبيق <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> تسجيل أي معلومات حسّاسة يتم عرضها على الشاشة أو تشغيلها من جهازك، بما فيها المعلومات الحسّاسة مثل المقاطع الصوتية وكلمات المرور ومعلومات الدفع والصور والرسائل."</string>
     <string name="media_projection_dialog_service_text" msgid="3075544489835858258">"أثناء التسجيل أو الإرسال، يمكن للخدمة التي تقدّم هذه الوظيفة تسجيل أي معلومات حساسة يتم عرضها على الشاشة أو تشغيلها من جهازك، بما فيها المعلومات الحساسة مثل الصوت الذي تشغّله وكلمات المرور ومعلومات الدفع والصور والرسائل."</string>
     <string name="media_projection_dialog_title" msgid="8124184308671641248">"عرض معلومات حسّاسة أثناء الإرسال/التسجيل"</string>
     <string name="media_projection_remember_text" msgid="3103510882172746752">"عدم الإظهار مرة أخرى"</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index a5f9989..7b2d793 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -871,7 +871,7 @@
     <string name="notification_channel_storage" msgid="3077205683020695313">"Memoria"</string>
     <string name="notification_channel_hints" msgid="7323870212489152689">"Aholkuak"</string>
     <string name="instant_apps" msgid="6647570248119804907">"Zuzeneko aplikazioak"</string>
-    <string name="instant_apps_title" msgid="8738419517367449783">"<xliff:g id="APP">%1$s</xliff:g> exekutatzen ari da"</string>
+    <string name="instant_apps_title" msgid="8738419517367449783">"<xliff:g id="APP">%1$s</xliff:g> abian da"</string>
     <string name="instant_apps_message" msgid="1183313016396018086">"Ezer instalatu gabe ireki da aplikazioa."</string>
     <string name="instant_apps_message_with_help" msgid="6179830437630729747">"Ezer instalatu gabe ireki da aplikazioa. Sakatu informazio gehiago lortzeko."</string>
     <string name="app_info" msgid="6856026610594615344">"Aplikazioari buruzko informazioa"</string>
@@ -888,7 +888,7 @@
     <string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> arte"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"Utzi bere horretan"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"Ordeztu"</string>
-    <string name="running_foreground_services_title" msgid="381024150898615683">"Aplikazioak exekutatzen ari dira atzeko planoan"</string>
+    <string name="running_foreground_services_title" msgid="381024150898615683">"Aplikazioak abian dira atzeko planoan"</string>
     <string name="running_foreground_services_msg" msgid="6326247670075574355">"Sakatu bateria eta datuen erabilerari buruzko xehetasunak ikusteko"</string>
     <string name="mobile_data_disable_title" msgid="1068272097382942231">"Datu-konexioa desaktibatu nahi duzu?"</string>
     <string name="mobile_data_disable_message" msgid="4756541658791493506">"<xliff:g id="CARRIER">%s</xliff:g> erabilita ezingo dituzu erabili datuak edo Internet. Wifi-sare baten bidez soilik konektatu ahal izango zara Internetera."</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index ef29f9b..263fe8a 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -484,7 +484,7 @@
     <string name="monitoring_title_device_owned" msgid="1652495295941959815">"डिवाइस प्रबंधन"</string>
     <string name="monitoring_title_profile_owned" msgid="6790109874733501487">"प्रोफ़ाइल को मॉनीटर करना"</string>
     <string name="monitoring_title" msgid="169206259253048106">"नेटवर्क को मॉनीटर करना"</string>
-    <string name="monitoring_subtitle_vpn" msgid="876537538087857300">"VPN"</string>
+    <string name="monitoring_subtitle_vpn" msgid="876537538087857300">"वीपीएन"</string>
     <string name="monitoring_subtitle_network_logging" msgid="3341264304793193386">"नेटवर्क लॉगिंग"</string>
     <string name="monitoring_subtitle_ca_certificate" msgid="3874151893894355988">"CA प्रमाणपत्र"</string>
     <string name="disable_vpn" msgid="4435534311510272506">"VPN अक्षम करें"</string>
@@ -513,7 +513,7 @@
     <string name="monitoring_description_network_logging" msgid="7223505523384076027">"आपके एडमिन ने नेटवर्क लॉग करना चालू कर दिया है, जो आपके डिवाइस पर ट्रैफ़िक की निगरानी करता है.\n\nज़्यादा जानकारी के लिए अपने एडमिन से संपर्क करें."</string>
     <string name="monitoring_description_vpn" msgid="4445150119515393526">"आपने किसी ऐप को VPN कनेक्‍शन सेट करने की अनुमति दी है.\n\nयह ऐप ईमेल, ऐप्‍स और सुरक्षित वेबसाइटों सहित आपके डिवाइस और नेटवर्क की गतिविधि की निगरानी कर सकता है."</string>
     <string name="monitoring_description_vpn_profile_owned" msgid="2958019119161161530">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> आपकी वर्क प्रोफ़ाइल को प्रबंधित करता है.\n\n आपका एडमिन ईमेल, ऐप्लिकेशन और वेबसाइटों सहित आपकी नेटवर्क गतिविधि की निगरानी कर सकता है.\n\nऔर जानकारी के लिए अपने एडमिन से संपर्क करें.\n\nआप ऐसे VPN से भी कनेक्‍ट हैं, जो आपकी नेटवर्क गतिविधि की निगरानी कर सकता है."</string>
-    <string name="legacy_vpn_name" msgid="6604123105765737830">"VPN"</string>
+    <string name="legacy_vpn_name" msgid="6604123105765737830">"वीपीएन"</string>
     <string name="monitoring_description_app" msgid="1828472472674709532">"आप <xliff:g id="APPLICATION">%1$s</xliff:g> से कनेक्ट हैं, जो ईमेल, ऐप्लिकेशन और वेबसाइटों सहित आपकी नेटवर्क गतिविधि की निगरानी कर सकता है."</string>
     <string name="monitoring_description_app_personal" msgid="484599052118316268">"आप <xliff:g id="APPLICATION">%1$s</xliff:g> से कनेक्‍ट हैं, जो ईमेल, ऐप्‍स और वेबसाइटों सहित आपकी व्‍यक्‍तिगत नेटवर्क गतिविधि की निगरानी कर सकता है."</string>
     <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"आप <xliff:g id="APPLICATION">%1$s</xliff:g> से कनेक्‍ट हैं, जो ईमेल, ऐप्लिकेशन और वेबसाइट सहित आपकी व्‍यक्‍तिगत नेटवर्क गतिविधि को मॉनिटर कर सकता है."</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 6d614b1..3156a6f 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -130,7 +130,7 @@
     <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>
-    <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Դիտափոխել փոքրից ավելի մեծ էկրան:"</string>
+    <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Մասշտաբը մեծացնել փոքրից ավելի մեծ էկրան:"</string>
     <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth-ը միացված է:"</string>
     <string name="accessibility_bluetooth_disconnected" msgid="7416648669976870175">"Bluetooth-ն անջատված է:"</string>
     <string name="accessibility_no_battery" msgid="358343022352820946">"Մարտկոց չկա:"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 59b6eb3..19b2b99 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -89,7 +89,7 @@
     <string name="screenrecord_share_label" msgid="4197867360204019389">"Bagikan"</string>
     <string name="screenrecord_delete_label" msgid="7893716870917824013">"Hapus"</string>
     <string name="screenrecord_cancel_success" msgid="7768976011702614782">"Rekaman layar dibatalkan"</string>
-    <string name="screenrecord_save_message" msgid="4733982661301846778">"Rekaman layar disimpan, tap untuk melihat"</string>
+    <string name="screenrecord_save_message" msgid="4733982661301846778">"Rekaman layar disimpan, ketuk untuk melihat"</string>
     <string name="screenrecord_delete_description" msgid="5743190456090354585">"Rekaman layar dihapus"</string>
     <string name="screenrecord_delete_error" msgid="8154904464563560282">"Error saat menghapus rekaman layar"</string>
     <string name="screenrecord_permission_error" msgid="1526755299469001000">"Gagal mendapatkan izin"</string>
@@ -836,7 +836,7 @@
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Tarik ke bawah untuk menutup"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"Menu"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> adalah picture-in-picture"</string>
-    <string name="pip_notification_message" msgid="5619512781514343311">"Jika Anda tidak ingin <xliff:g id="NAME">%s</xliff:g> menggunakan fitur ini, tap untuk membuka setelan dan menonaktifkannya."</string>
+    <string name="pip_notification_message" msgid="5619512781514343311">"Jika Anda tidak ingin <xliff:g id="NAME">%s</xliff:g> menggunakan fitur ini, ketuk untuk membuka setelan dan menonaktifkannya."</string>
     <string name="pip_play" msgid="1417176722760265888">"Putar"</string>
     <string name="pip_pause" msgid="8881063404466476571">"Jeda"</string>
     <string name="pip_skip_to_next" msgid="1948440006726306284">"Lewati ke berikutnya"</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index 1058d74..08816c7 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -29,9 +29,9 @@
     <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> të mbetura, rreth <xliff:g id="TIME">%2$s</xliff:g> të mbetura bazuar në përdorimin tënd"</string>
     <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> të mbetura, rreth <xliff:g id="TIME">%2$s</xliff:g> të mbetura"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Ka mbetur edhe <xliff:g id="PERCENTAGE">%s</xliff:g>. \"Kursyesi i baterisë\" është i aktivizuar."</string>
-    <string name="invalid_charger" msgid="2741987096648693172">"Nuk mund të ngarkohet përmes USB-së. Përdor ngarkuesin që ke marrë me pajisjen."</string>
+    <string name="invalid_charger" msgid="2741987096648693172">"Nuk mund të karikohet përmes USB-së. Përdor karikuesin që ke marrë me pajisjen."</string>
     <string name="invalid_charger_title" msgid="2836102177577255404">"Nuk mund të ngarkohet përmes USB-së"</string>
-    <string name="invalid_charger_text" msgid="6480624964117840005">"Përdor ngarkuesin që ke marrë me pajisjen"</string>
+    <string name="invalid_charger_text" msgid="6480624964117840005">"Përdor karikuesin që ke marrë me pajisjen"</string>
     <string name="battery_low_why" msgid="4553600287639198111">"Cilësimet"</string>
     <string name="battery_saver_confirmation_title" msgid="2052100465684817154">"Të aktivizohet \"Kursyesi i baterisë\"?"</string>
     <string name="battery_saver_confirmation_title_generic" msgid="2090922638411744540">"Rreth \"Kursyesit të baterisë\""</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 0e74993..56521f6 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -33,7 +33,7 @@
     <string name="invalid_charger_title" msgid="2836102177577255404">"Не вдається зарядити через USB"</string>
     <string name="invalid_charger_text" msgid="6480624964117840005">"Використовуйте зарядний пристрій, який входить у комплект пристрою"</string>
     <string name="battery_low_why" msgid="4553600287639198111">"Налаштування"</string>
-    <string name="battery_saver_confirmation_title" msgid="2052100465684817154">"Увімкнути режим економії заряду акумулятора?"</string>
+    <string name="battery_saver_confirmation_title" msgid="2052100465684817154">"Увімкнути режим енергозбереження?"</string>
     <string name="battery_saver_confirmation_title_generic" msgid="2090922638411744540">"Про режим енергозбереження"</string>
     <string name="battery_saver_confirmation_ok" msgid="7507968430447930257">"Увімкнути"</string>
     <string name="battery_saver_start_action" msgid="8187820911065797519">"Увімкнути режим економії заряду акумулятора"</string>
@@ -455,7 +455,7 @@
     <string name="user_remove_user_title" msgid="4681256956076895559">"Видалити користувача?"</string>
     <string name="user_remove_user_message" msgid="1453218013959498039">"Усі додатки й дані цього користувача буде видалено."</string>
     <string name="user_remove_user_remove" msgid="7479275741742178297">"Видалити"</string>
-    <string name="battery_saver_notification_title" msgid="8614079794522291840">"Режим економії заряду акумулятора ввімкнено"</string>
+    <string name="battery_saver_notification_title" msgid="8614079794522291840">"Режим енергозбереження ввімкнено"</string>
     <string name="battery_saver_notification_text" msgid="820318788126672692">"Знижується продуктивність і обмежуються фонові дані"</string>
     <string name="battery_saver_notification_action_text" msgid="132118784269455533">"Вимкнути режим економії заряду акумулятора"</string>
     <string name="media_projection_dialog_text" msgid="8585357687598538511">"Під час запису або трансляції додаток <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> може фіксувати будь-яку конфіденційну інформацію (зокрема, аудіо, паролі, платіжну інформацію, фотографії та повідомлення), яка з\'являється на екрані або відтворюється на пристрої."</string>
@@ -913,7 +913,7 @@
     <string name="auto_saver_title" msgid="1217959994732964228">"Торкніться, щоб увімкнути автоматичний режим економії заряду акумулятора"</string>
     <string name="auto_saver_text" msgid="2563289953551438248">"Вмикати, коли заряд акумулятора закінчується"</string>
     <string name="no_auto_saver_action" msgid="8086002101711328500">"Ні, дякую"</string>
-    <string name="auto_saver_enabled_title" msgid="6726474226058316862">"Автоматичний режим економії заряду акумулятора ввімкнено"</string>
+    <string name="auto_saver_enabled_title" msgid="6726474226058316862">"Автоматичний перехід у режим енергозбереження ввімкнено"</string>
     <string name="auto_saver_enabled_text" msgid="874711029884777579">"Режим економії заряду акумулятора вмикається автоматично, коли рівень заряду нижчий за <xliff:g id="PERCENTAGE">%d</xliff:g>%%."</string>
     <string name="open_saver_setting_action" msgid="8314624730997322529">"Налаштування"</string>
     <string name="auto_saver_okay_action" msgid="2701221740227683650">"OK"</string>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/Task.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/Task.java
index 5b9ee1c..dcb134e 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/Task.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/Task.java
@@ -20,6 +20,7 @@
 
 import android.app.ActivityManager;
 import android.app.ActivityManager.TaskDescription;
+import android.app.TaskInfo;
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
@@ -75,7 +76,7 @@
 
         private int mHashCode;
 
-        public TaskKey(ActivityManager.RecentTaskInfo t) {
+        public TaskKey(TaskInfo t) {
             ComponentName sourceComponent = t.origActivity != null
                     // Activity alias if there is one
                     ? t.origActivity
@@ -226,6 +227,17 @@
         // Do nothing
     }
 
+    /**
+     * Creates a task object from the provided task info
+     */
+    public static Task from(TaskKey taskKey, TaskInfo taskInfo, boolean isLocked) {
+        ActivityManager.TaskDescription td = taskInfo.taskDescription;
+        return new Task(taskKey,
+                td != null ? td.getPrimaryColor() : 0,
+                td != null ? td.getBackgroundColor() : 0,
+                taskInfo.supportsSplitScreenMultiWindow, isLocked, td, taskInfo.topActivity);
+    }
+
     public Task(TaskKey key) {
         this.key = key;
         this.taskDescription = new TaskDescription();
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 506813b..328116d 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
@@ -30,10 +30,12 @@
 import android.annotation.NonNull;
 import android.app.ActivityManager;
 import android.app.ActivityManager.RecentTaskInfo;
+import android.app.ActivityManager.RunningTaskInfo;
 import android.app.ActivityOptions;
 import android.app.ActivityTaskManager;
 import android.app.AppGlobals;
 import android.app.IAssistDataReceiver;
+import android.app.WindowConfiguration;
 import android.app.WindowConfiguration.ActivityType;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -500,4 +502,12 @@
                 PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT)
                 || freeformDevOption);
     }
+
+    /**
+     * Returns true if the running task represents the home task
+     */
+    public static boolean isHomeTask(RunningTaskInfo info) {
+        return info.configuration.windowConfiguration.getActivityType()
+                == WindowConfiguration.ACTIVITY_TYPE_HOME;
+    }
 }
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
index 7fbe5db..cc7863c 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
@@ -49,6 +49,15 @@
     public static final String NAV_BAR_MODE_GESTURAL_OVERLAY =
             WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY;
 
+    // Action sent by a system app to switch to gesture nav
+    public static final String ACTION_ENABLE_GESTURE_NAV =
+            "com.android.systemui.ENABLE_GESTURE_NAV";
+    // Action for the intent to receive the result
+    public static final String ACTION_ENABLE_GESTURE_NAV_RESULT =
+            "com.android.systemui.action.ENABLE_GESTURE_NAV_RESULT";
+    // Extra containing the pending intent to receive the result
+    public static final String EXTRA_RESULT_INTENT = "com.android.systemui.EXTRA_RESULT_INTENT";
+
     // Overview is disabled, either because the device is in lock task mode, or because the device
     // policy has disabled the feature
     public static final int SYSUI_STATE_SCREEN_PINNING = 1 << 0;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 05e14a7..2eb93d3 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -2203,6 +2203,15 @@
         if (DEBUG) Log.d(TAG, "handleKeyguardBouncerChanged(" + bouncer + ")");
         boolean isBouncer = (bouncer == 1);
         mBouncer = isBouncer;
+
+        if (isBouncer) {
+            // If the bouncer is shown, always clear this flag. This can happen in the following
+            // situations: 1) Default camera with SHOW_WHEN_LOCKED is not chosen yet. 2) Secure
+            // camera requests dismiss keyguard (tapping on photos for example). When these happen,
+            // face auth should resume.
+            mSecureCameraLaunched = false;
+        }
+
         for (int i = 0; i < mCallbacks.size(); i++) {
             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
             if (cb != null) {
@@ -2649,6 +2658,7 @@
             pw.println("    strongAuthFlags=" + Integer.toHexString(strongAuthFlags));
             pw.println("    trustManaged=" + getUserTrustIsManaged(userId));
             pw.println("    enabledByUser=" + mFaceSettingEnabledForUser);
+            pw.println("    mSecureCameraLaunched=" + mSecureCameraLaunched);
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
index 9a0e9fc..c9d4957 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
@@ -46,6 +46,8 @@
     // We delayed destroy render context that subsequent render requests have chance to cancel it.
     // This is to avoid destroying then recreating render context in a very short time.
     private static final int DELAY_FINISH_RENDERING = 1000;
+    private static final int INTERVAL_WAIT_FOR_RENDERING = 100;
+    private static final int PATIENCE_WAIT_FOR_RENDERING = 5;
     private HandlerThread mWorker;
 
     @Override
@@ -80,7 +82,10 @@
         private StatusBarStateController mController;
         private final Runnable mFinishRenderingTask = this::finishRendering;
         private final boolean mNeedTransition;
+        private final Object mMonitor = new Object();
         private boolean mNeedRedraw;
+        // This variable can only be accessed in synchronized block.
+        private boolean mWaitingForRendering;
 
         GLEngine(Context context) {
             mNeedTransition = ActivityManager.isHighEndGfx()
@@ -122,6 +127,27 @@
             long duration = mNeedTransition || animationDuration != 0 ? animationDuration : 0;
             mWorker.getThreadHandler().post(
                     () -> mRenderer.updateAmbientMode(inAmbientMode, duration));
+            if (inAmbientMode && duration == 0) {
+                // This means that we are transiting from home to aod, to avoid
+                // race condition between window visibility and transition,
+                // we don't return until the transition is finished. See b/136643341.
+                waitForBackgroundRendering();
+            }
+        }
+
+        private void waitForBackgroundRendering() {
+            synchronized (mMonitor) {
+                try {
+                    mWaitingForRendering = true;
+                    for (int patience = 1; mWaitingForRendering; patience++) {
+                        mMonitor.wait(INTERVAL_WAIT_FOR_RENDERING);
+                        mWaitingForRendering &= patience < PATIENCE_WAIT_FOR_RENDERING;
+                    }
+                } catch (InterruptedException ex) {
+                } finally {
+                    mWaitingForRendering = false;
+                }
+            }
         }
 
         @Override
@@ -178,7 +204,8 @@
 
         @Override
         public void preRender() {
-            mWorker.getThreadHandler().post(this::preRenderInternal);
+            // This method should only be invoked from worker thread.
+            preRenderInternal();
         }
 
         private void preRenderInternal() {
@@ -212,7 +239,8 @@
 
         @Override
         public void requestRender() {
-            mWorker.getThreadHandler().post(this::requestRenderInternal);
+            // This method should only be invoked from worker thread.
+            requestRenderInternal();
         }
 
         private void requestRenderInternal() {
@@ -234,7 +262,21 @@
 
         @Override
         public void postRender() {
-            mWorker.getThreadHandler().post(this::scheduleFinishRendering);
+            // This method should only be invoked from worker thread.
+            notifyWaitingThread();
+            scheduleFinishRendering();
+        }
+
+        private void notifyWaitingThread() {
+            synchronized (mMonitor) {
+                if (mWaitingForRendering) {
+                    try {
+                        mWaitingForRendering = false;
+                        mMonitor.notify();
+                    } catch (IllegalMonitorStateException ex) {
+                    }
+                }
+            }
         }
 
         private void cancelFinishRenderingTask() {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogView.java b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogView.java
index 932e40c..a5857df 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogView.java
@@ -282,6 +282,7 @@
 
         if (mRestoredState == null) {
             updateState(STATE_AUTHENTICATING);
+            mNegativeButton.setText(mBundle.getCharSequence(BiometricPrompt.KEY_NEGATIVE_TEXT));
             final int hint = getHintStringResourceId();
             if (hint != 0) {
                 mErrorText.setText(hint);
@@ -319,8 +320,6 @@
             mDescriptionText.setText(descriptionText);
         }
 
-        mNegativeButton.setText(mBundle.getCharSequence(BiometricPrompt.KEY_NEGATIVE_TEXT));
-
         if (requiresConfirmation() && mRestoredState == null) {
             mPositiveButton.setVisibility(View.VISIBLE);
             mPositiveButton.setEnabled(false);
@@ -474,6 +473,8 @@
             mHandler.removeMessages(MSG_RESET_MESSAGE);
             mErrorText.setTextColor(mTextColor);
             mErrorText.setText(R.string.biometric_dialog_tap_confirm);
+            mErrorText.setContentDescription(
+                    getResources().getString(R.string.biometric_dialog_tap_confirm));
             mErrorText.setVisibility(View.VISIBLE);
             announceAccessibilityEvent();
             mPositiveButton.setVisibility(View.VISIBLE);
@@ -487,6 +488,7 @@
 
         if (newState == STATE_PENDING_CONFIRMATION || newState == STATE_AUTHENTICATED) {
             mNegativeButton.setText(R.string.cancel);
+            mNegativeButton.setContentDescription(getResources().getString(R.string.cancel));
         }
 
         updateIcon(mState, newState);
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerImpl.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerImpl.java
index 6fb6467..67dfdca 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerImpl.java
@@ -67,8 +67,8 @@
             Sensor.TYPE_LIGHT,
             Sensor.TYPE_ROTATION_VECTOR,
     };
-    private static final String FALSING_REMAIN_LOCKED = "falsing_failure_after_attempts";
-    private static final String FALSING_SUCCESS = "falsing_success_after_attempts";
+    public static final String FALSING_REMAIN_LOCKED = "falsing_failure_after_attempts";
+    public static final String FALSING_SUCCESS = "falsing_success_after_attempts";
 
     private final Handler mHandler = new Handler(Looper.getMainLooper());
     private final Context mContext;
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java
index 19c46e4..00f35aa 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java
@@ -16,6 +16,9 @@
 
 package com.android.systemui.classifier.brightline;
 
+import static com.android.systemui.classifier.FalsingManagerImpl.FALSING_REMAIN_LOCKED;
+import static com.android.systemui.classifier.FalsingManagerImpl.FALSING_SUCCESS;
+
 import android.hardware.Sensor;
 import android.hardware.SensorEvent;
 import android.hardware.SensorEventListener;
@@ -24,6 +27,7 @@
 import android.util.Log;
 import android.view.MotionEvent;
 
+import com.android.internal.logging.MetricsLogger;
 import com.android.systemui.classifier.Classifier;
 import com.android.systemui.plugins.FalsingManager;
 
@@ -44,6 +48,8 @@
     private final SensorManager mSensorManager;
     private final FalsingDataProvider mDataProvider;
     private boolean mSessionStarted;
+    private MetricsLogger mMetricsLogger;
+    private int mIsFalseTouchCalls;
 
     private final ExecutorService mBackgroundExecutor = Executors.newSingleThreadExecutor();
 
@@ -64,6 +70,7 @@
             SensorManager sensorManager) {
         mDataProvider = falsingDataProvider;
         mSensorManager = sensorManager;
+        mMetricsLogger = new MetricsLogger();
         mClassifiers = new ArrayList<>();
         DistanceClassifier distanceClassifier = new DistanceClassifier(mDataProvider);
         ProximityClassifier proximityClassifier = new ProximityClassifier(distanceClassifier,
@@ -111,6 +118,10 @@
             unregisterSensors();
             mDataProvider.onSessionEnd();
             mClassifiers.forEach(FalsingClassifier::onSessionEnded);
+            if (mIsFalseTouchCalls != 0) {
+                mMetricsLogger.histogram(FALSING_REMAIN_LOCKED, mIsFalseTouchCalls);
+                mIsFalseTouchCalls = 0;
+            }
         }
     }
 
@@ -157,6 +168,10 @@
 
     @Override
     public void onSucccessfulUnlock() {
+        if (mIsFalseTouchCalls != 0) {
+            mMetricsLogger.histogram(FALSING_SUCCESS, mIsFalseTouchCalls);
+            mIsFalseTouchCalls = 0;
+        }
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageRevealHelper.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageRevealHelper.java
index 6a1f24a..45e97b3 100644
--- a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageRevealHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageRevealHelper.java
@@ -84,7 +84,17 @@
     void updateAwake(boolean awake, long duration) {
         mAwake = awake;
         mAnimator.setDuration(duration);
-        animate();
+        if (!mAwake && duration == 0) {
+            // We are transiting from home to aod,
+            // since main thread is waiting for rendering finished, we only need draw
+            // the last state directly, which is a black screen.
+            mReveal = MIN_REVEAL;
+            mRevealListener.onRevealStart();
+            mRevealListener.onRevealStateChanged();
+            mRevealListener.onRevealEnd();
+        } else {
+            animate();
+        }
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 819ce5f..6b2721a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -210,6 +210,7 @@
     private boolean mBootCompleted;
     private boolean mBootSendUserPresent;
     private boolean mShuttingDown;
+    private boolean mDozing;
 
     /** High level access to the power manager for WakeLocks */
     private PowerManager mPM;
@@ -713,11 +714,10 @@
                 com.android.keyguard.R.bool.config_enableKeyguardService)) {
             setShowingLocked(!shouldWaitForProvisioning()
                     && !mLockPatternUtils.isLockScreenDisabled(
-                            KeyguardUpdateMonitor.getCurrentUser()),
-                    mAodShowing, true /* forceCallbacks */);
+                            KeyguardUpdateMonitor.getCurrentUser()), true /* forceCallbacks */);
         } else {
             // The system's keyguard is disabled or missing.
-            setShowingLocked(false, mAodShowing, true);
+            setShowingLocked(false /* showing */, true /* forceCallbacks */);
         }
 
         mStatusBarKeyguardViewManager =
@@ -1326,7 +1326,7 @@
             if (mLockPatternUtils.checkVoldPassword(KeyguardUpdateMonitor.getCurrentUser())) {
                 if (DEBUG) Log.d(TAG, "Not showing lock screen since just decrypted");
                 // Without this, settings is not enabled until the lock screen first appears
-                setShowingLocked(false, mAodShowing);
+                setShowingLocked(false);
                 hideLocked();
                 return;
             }
@@ -1742,6 +1742,9 @@
 
     private void updateActivityLockScreenState(boolean showing, boolean aodShowing) {
         mUiOffloadThread.submit(() -> {
+            if (DEBUG) {
+                Log.d(TAG, "updateActivityLockScreenState(" + showing + ", " + aodShowing + ")");
+            }
             try {
                 ActivityTaskManager.getService().setLockScreenShown(showing, aodShowing);
             } catch (RemoteException e) {
@@ -1767,10 +1770,10 @@
                 if (DEBUG) Log.d(TAG, "handleShow");
             }
 
-            setShowingLocked(true, mAodShowing);
-            mStatusBarKeyguardViewManager.show(options);
             mHiding = false;
             mWakeAndUnlocking = false;
+            setShowingLocked(true);
+            mStatusBarKeyguardViewManager.show(options);
             resetKeyguardDonePendingLocked();
             mHideAnimationRun = false;
             adjustStatusBarLocked();
@@ -1877,7 +1880,7 @@
 
             if (!mHiding) {
                 // Tell ActivityManager that we canceled the keyguardExitAnimation.
-                setShowingLocked(mShowing, mAodShowing, true /* force */);
+                setShowingLocked(mShowing, true /* force */);
                 return;
             }
             mHiding = false;
@@ -1898,8 +1901,8 @@
                 playSounds(false);
             }
 
+            setShowingLocked(false);
             mWakeAndUnlocking = false;
-            setShowingLocked(false, mAodShowing);
             mDismissCallbackRegistry.notifyDismissSucceeded();
             mStatusBarKeyguardViewManager.hide(startTime, fadeoutDuration);
             resetKeyguardDonePendingLocked();
@@ -1959,7 +1962,7 @@
         Trace.beginSection("KeyguardViewMediator#handleVerifyUnlock");
         synchronized (KeyguardViewMediator.this) {
             if (DEBUG) Log.d(TAG, "handleVerifyUnlock");
-            setShowingLocked(true, mAodShowing);
+            setShowingLocked(true);
             mStatusBarKeyguardViewManager.dismissAndCollapse();
         }
         Trace.endSection();
@@ -2107,6 +2110,8 @@
         pw.print("  mDeviceInteractive: "); pw.println(mDeviceInteractive);
         pw.print("  mGoingToSleep: "); pw.println(mGoingToSleep);
         pw.print("  mHiding: "); pw.println(mHiding);
+        pw.print("  mDozing: "); pw.println(mDozing);
+        pw.print("  mAodShowing: "); pw.println(mAodShowing);
         pw.print("  mWaitingUntilKeyguardVisible: "); pw.println(mWaitingUntilKeyguardVisible);
         pw.print("  mKeyguardDonePending: "); pw.println(mKeyguardDonePending);
         pw.print("  mHideAnimationRun: "); pw.println(mHideAnimationRun);
@@ -2117,10 +2122,14 @@
     }
 
     /**
-     * @param aodShowing true when AOD - or ambient mode - is showing.
+     * @param dozing true when AOD - or ambient mode - is showing.
      */
-    public void setAodShowing(boolean aodShowing) {
-        setShowingLocked(mShowing, aodShowing);
+    public void setDozing(boolean dozing) {
+        if (dozing == mDozing) {
+            return;
+        }
+        mDozing = dozing;
+        setShowingLocked(mShowing);
     }
 
     /**
@@ -2141,19 +2150,18 @@
         }
     }
 
-    private void setShowingLocked(boolean showing, boolean aodShowing) {
-        setShowingLocked(showing, aodShowing, false /* forceCallbacks */);
+    private void setShowingLocked(boolean showing) {
+        setShowingLocked(showing, false /* forceCallbacks */);
     }
 
-    private void setShowingLocked(boolean showing, boolean aodShowing, boolean forceCallbacks) {
+    private void setShowingLocked(boolean showing, boolean forceCallbacks) {
+        final boolean aodShowing = mDozing && !mWakeAndUnlocking;
         final boolean notifyDefaultDisplayCallbacks = showing != mShowing
                 || aodShowing != mAodShowing || forceCallbacks;
+        mShowing = showing;
+        mAodShowing = aodShowing;
         if (notifyDefaultDisplayCallbacks) {
-            mShowing = showing;
-            mAodShowing = aodShowing;
-            if (notifyDefaultDisplayCallbacks) {
-                notifyDefaultDisplayCallbacks(showing);
-            }
+            notifyDefaultDisplayCallbacks(showing);
             updateActivityLockScreenState(showing, aodShowing);
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
index 70ee752..c9050d4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
@@ -398,7 +398,7 @@
             }
         }
 
-        if (!riv.isAttachedToWindow()) {
+        if (riv != null && !riv.isAttachedToWindow()) {
             // the remoteInput isn't attached to the window anymore :/ Let's focus on the expanded
             // one instead if it's available
             riv = null;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
index 35ba801..01e2b28 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
@@ -514,11 +514,11 @@
         for (int i = 0; i < childCount; i++) {
             View child = algorithmState.visibleChildren.get(i);
             if (!(child instanceof ExpandableNotificationRow)) {
-                break;
+                continue;
             }
             ExpandableNotificationRow row = (ExpandableNotificationRow) child;
             if (!row.isHeadsUp()) {
-                break;
+                continue;
             }
             ExpandableViewState childState = row.getViewState();
             if (topHeadsUpEntry == null && row.mustStayOnScreen() && !childState.headsUpIsVisible) {
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 05d26b0..bc7174d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
@@ -261,6 +261,8 @@
                 biometricSourceType);
         if (unlockAllowed) {
             startWakeAndUnlock(biometricSourceType);
+        } else {
+            Log.d(TAG, "onBiometricAuthenticated aborted by bypass controller");
         }
     }
 
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 c44f953..cbaf85c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
@@ -22,6 +22,7 @@
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.graphics.Rect;
+import android.graphics.Region;
 import android.util.Log;
 import android.util.Pools;
 import android.view.DisplayCutout;
@@ -88,7 +89,7 @@
     private int[] mTmpTwoArray = new int[2];
     private boolean mHeadsUpGoingAway;
     private int mStatusBarState;
-    private Rect mTouchableRegion = new Rect();
+    private Region mTouchableRegion = new Region();
 
     private AnimationStateHandler mAnimationStateHandler;
 
@@ -365,10 +366,11 @@
         info.touchableRegion.set(calculateTouchableRegion());
     }
 
-    public Rect calculateTouchableRegion() {
+    public Region calculateTouchableRegion() {
         if (!hasPinnedHeadsUp()) {
             mTouchableRegion.set(0, 0, mStatusBarWindowView.getWidth(), mStatusBarHeight);
             updateRegionForNotch(mTouchableRegion);
+
         } else {
             NotificationEntry topEntry = getTopEntry();
             if (topEntry.isChildInGroup()) {
@@ -388,7 +390,7 @@
         return mTouchableRegion;
     }
 
-    private void updateRegionForNotch(Rect region) {
+    private void updateRegionForNotch(Region region) {
         DisplayCutout cutout = mStatusBarWindowView.getRootWindowInsets().getDisplayCutout();
         if (cutout == null) {
             return;
@@ -460,6 +462,8 @@
         super.dumpInternal(fd, pw, args);
         pw.print("  mBarState=");
         pw.println(mStatusBarState);
+        pw.print("  mTouchableRegion=");
+        pw.println(mTouchableRegion);
     }
 
     ///////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index 21a22ec..d6f8a60 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -346,10 +346,10 @@
     }
 
     /**
-     * {@link #show(boolean)} was called but we're not showing yet.
+     * {@link #show(boolean)} was called but we're not showing yet, or being dragged.
      */
-    public boolean willShowSoon() {
-        return mShowingSoon;
+    public boolean inTransit() {
+        return mShowingSoon || mExpansion != EXPANSION_HIDDEN;
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt
index d7deedc..c88b22b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt
@@ -21,11 +21,11 @@
 import android.hardware.biometrics.BiometricSourceType
 import android.hardware.face.FaceManager
 import android.provider.Settings
-import com.android.keyguard.KeyguardUpdateMonitor
 import com.android.systemui.plugins.statusbar.StatusBarStateController
 import com.android.systemui.statusbar.NotificationLockscreenUserManager
 import com.android.systemui.statusbar.StatusBarState
 import com.android.systemui.tuner.TunerService
+import java.io.PrintWriter
 import javax.inject.Inject
 import javax.inject.Singleton
 
@@ -62,18 +62,15 @@
         }
 
     @Inject
-    constructor(context: Context, tunerService: TunerService,
-                statusBarStateController: StatusBarStateController,
-                lockscreenUserManager: NotificationLockscreenUserManager) {
+    constructor(
+        context: Context,
+        tunerService: TunerService,
+        statusBarStateController: StatusBarStateController,
+        lockscreenUserManager: NotificationLockscreenUserManager
+    ) {
         unlockMethodCache = UnlockMethodCache.getInstance(context)
         this.statusBarStateController = statusBarStateController
-        statusBarStateController.addCallback(object : StatusBarStateController.StateListener {
-            override fun onStateChanged(newState: Int) {
-                if (newState != StatusBarState.KEYGUARD) {
-                    pendingUnlockType = null;
-                }
-            }
-        })
+
         if (!context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FACE)) {
             return
         }
@@ -82,16 +79,19 @@
             return
         }
 
+        statusBarStateController.addCallback(object : StatusBarStateController.StateListener {
+            override fun onStateChanged(newState: Int) {
+                if (newState != StatusBarState.KEYGUARD) {
+                    pendingUnlockType = null
+                }
+            }
+        })
+
         val dismissByDefault = if (context.resources.getBoolean(
-                com.android.internal.R.bool.config_faceAuthDismissesKeyguard)) 1 else 0
-        tunerService.addTunable(
-                object : TunerService.Tunable {
-                        override fun onTuningChanged(key: String?, newValue: String?) {
-                                bypassEnabled = Settings.Secure.getIntForUser(
-                                        context.contentResolver,
-                                        Settings.Secure.FACE_UNLOCK_DISMISSES_KEYGUARD,
-                                        dismissByDefault,
-                                        KeyguardUpdateMonitor.getCurrentUser()) != 0
+                        com.android.internal.R.bool.config_faceAuthDismissesKeyguard)) 1 else 0
+        tunerService.addTunable(object : TunerService.Tunable {
+            override fun onTuningChanged(key: String?, newValue: String?) {
+                bypassEnabled = tunerService.getValue(key, dismissByDefault) != 0
             }
         }, Settings.Secure.FACE_UNLOCK_DISMISSES_KEYGUARD)
         lockscreenUserManager.addUserChangedListener { pendingUnlockType = null }
@@ -155,4 +155,16 @@
     fun onStartedGoingToSleep() {
         pendingUnlockType = null
     }
+
+    fun dump(pw: PrintWriter) {
+        pw.println("KeyguardBypassController:")
+        pw.print("  pendingUnlockType: "); pw.println(pendingUnlockType)
+        pw.print("  bypassEnabled: "); pw.println(bypassEnabled)
+        pw.print("  canBypass: "); pw.println(canBypass())
+        pw.print("  bouncerShowing: "); pw.println(bouncerShowing)
+        pw.print("  isPulseExpanding: "); pw.println(isPulseExpanding)
+        pw.print("  launchingAffordance: "); pw.println(launchingAffordance)
+        pw.print("  qSExpanded: "); pw.println(qSExpanded)
+        pw.print("  bouncerShowing: "); pw.println(bouncerShowing)
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java
index 4d7cf27..64fef55 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java
@@ -16,17 +16,26 @@
 
 package com.android.systemui.statusbar.phone;
 
+import static android.app.Activity.RESULT_CANCELED;
+import static android.app.Activity.RESULT_OK;
+import static android.app.admin.DevicePolicyManager.STATE_USER_UNMANAGED;
 import static android.content.Intent.ACTION_OVERLAY_CHANGED;
 import static android.content.Intent.ACTION_PREFERRED_ACTIVITY_CHANGED;
+import static android.content.pm.PackageManager.FEATURE_DEVICE_ADMIN;
 import static android.os.UserHandle.USER_CURRENT;
 import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON;
 import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON_OVERLAY;
 import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
 import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY;
 
+import static com.android.systemui.shared.system.QuickStepContract.ACTION_ENABLE_GESTURE_NAV;
+import static com.android.systemui.shared.system.QuickStepContract.ACTION_ENABLE_GESTURE_NAV_RESULT;
+import static com.android.systemui.shared.system.QuickStepContract.EXTRA_RESULT_INTENT;
+
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
+import android.app.admin.DevicePolicyManager;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
@@ -40,6 +49,7 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.UserHandle;
+import android.os.UserManager;
 import android.provider.Settings;
 import android.provider.Settings.Secure;
 import android.text.TextUtils;
@@ -157,6 +167,8 @@
                 }
             };
 
+    private BroadcastReceiver mEnableGestureNavReceiver;
+
     @Inject
     public NavigationModeController(Context context,
             DeviceProvisionedController deviceProvisionedController,
@@ -177,6 +189,7 @@
         IntentFilter preferredActivityFilter = new IntentFilter(ACTION_PREFERRED_ACTIVITY_CHANGED);
         mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, preferredActivityFilter, null,
                 null);
+
         // We are only interested in launcher changes, so keeping track of the current default.
         mLastDefaultLauncher = getDefaultLauncherPackageName(mContext);
 
@@ -187,6 +200,82 @@
         deferGesturalNavOverlayIfNecessary();
     }
 
+    private void removeEnableGestureNavListener() {
+        if (mEnableGestureNavReceiver != null) {
+            if (DEBUG) {
+                Log.d(TAG, "mEnableGestureNavReceiver unregistered");
+            }
+            mContext.unregisterReceiver(mEnableGestureNavReceiver);
+            mEnableGestureNavReceiver = null;
+        }
+    }
+
+    private boolean setGestureModeOverlayForMainLauncher() {
+        removeEnableGestureNavListener();
+        if (getCurrentInteractionMode(mCurrentUserContext) == NAV_BAR_MODE_GESTURAL) {
+            // Already in gesture mode
+            return true;
+        }
+        final Boolean supported = isGestureNavSupportedByDefaultLauncher(mCurrentUserContext);
+        if (supported == null || supported) {
+            Log.d(TAG, "Switching system navigation to full-gesture mode:"
+                    + " defaultLauncher="
+                    + getDefaultLauncherPackageName(mCurrentUserContext)
+                    + " contextUser="
+                    + mCurrentUserContext.getUserId());
+
+            setModeOverlay(NAV_BAR_MODE_GESTURAL_OVERLAY, USER_CURRENT);
+            return true;
+        } else {
+            Log.e(TAG, "Gesture nav is not supported for defaultLauncher="
+                    + getDefaultLauncherPackageName(mCurrentUserContext));
+            return false;
+        }
+    }
+
+    private boolean enableGestureNav(Intent intent) {
+        if (!(intent.getParcelableExtra(EXTRA_RESULT_INTENT) instanceof PendingIntent)) {
+            Log.e(TAG, "No callback pending intent was attached");
+            return false;
+        }
+
+        PendingIntent callback = intent.getParcelableExtra(EXTRA_RESULT_INTENT);
+        Intent callbackIntent = callback.getIntent();
+        if (callbackIntent == null
+                || !ACTION_ENABLE_GESTURE_NAV_RESULT.equals(callbackIntent.getAction())) {
+            Log.e(TAG, "Invalid callback intent");
+            return false;
+        }
+        String callerPackage = callback.getCreatorPackage();
+        UserHandle callerUser = callback.getCreatorUserHandle();
+
+        DevicePolicyManager dpm = mCurrentUserContext.getSystemService(DevicePolicyManager.class);
+        ComponentName ownerComponent = dpm.getDeviceOwnerComponentOnCallingUser();
+
+        if (ownerComponent != null) {
+            // Verify that the caller is the owner component
+            if (!ownerComponent.getPackageName().equals(callerPackage)
+                    || !mCurrentUserContext.getUser().equals(callerUser)) {
+                Log.e(TAG, "Callback must be from the device owner");
+                return false;
+            }
+        } else {
+            UserHandle callerParent = mCurrentUserContext.getSystemService(UserManager.class)
+                    .getProfileParent(callerUser);
+            if (callerParent == null || !callerParent.equals(mCurrentUserContext.getUser())) {
+                Log.e(TAG, "Callback must be from a managed user");
+                return false;
+            }
+            ComponentName profileOwner = dpm.getProfileOwnerAsUser(callerUser);
+            if (profileOwner == null || !profileOwner.getPackageName().equals(callerPackage)) {
+                Log.e(TAG, "Callback must be from the profile owner");
+                return false;
+            }
+        }
+
+        return setGestureModeOverlayForMainLauncher();
+    }
+
     public void updateCurrentInteractionMode(boolean notify) {
         mCurrentUserContext = getCurrentUserContext();
         int mode = getCurrentInteractionMode(mCurrentUserContext);
@@ -245,6 +334,10 @@
         }
     }
 
+    private boolean supportsDeviceAdmin() {
+        return mContext.getPackageManager().hasSystemFeature(FEATURE_DEVICE_ADMIN);
+    }
+
     private void deferGesturalNavOverlayIfNecessary() {
         final int userId = mDeviceProvisionedController.getCurrentUser();
         mRestoreGesturalNavBarMode.put(userId, false);
@@ -255,6 +348,7 @@
                 Log.d(TAG, "deferGesturalNavOverlayIfNecessary: device is provisioned and user is "
                         + "setup");
             }
+            removeEnableGestureNavListener();
             return;
         }
 
@@ -270,6 +364,7 @@
                 Log.d(TAG, "deferGesturalNavOverlayIfNecessary: no default gestural overlay, "
                         + "default=" + defaultOverlays);
             }
+            removeEnableGestureNavListener();
             return;
         }
 
@@ -277,6 +372,24 @@
         // provisioned
         setModeOverlay(NAV_BAR_MODE_3BUTTON_OVERLAY, USER_CURRENT);
         mRestoreGesturalNavBarMode.put(userId, true);
+
+        if (supportsDeviceAdmin() && mEnableGestureNavReceiver == null) {
+            mEnableGestureNavReceiver = new BroadcastReceiver() {
+                @Override
+                public void onReceive(Context context, Intent intent) {
+                    if (DEBUG) {
+                        Log.d(TAG, "ACTION_ENABLE_GESTURE_NAV");
+                    }
+                    setResultCode(enableGestureNav(intent) ? RESULT_OK : RESULT_CANCELED);
+                }
+            };
+            // Register for all users so that we can get managed users as well
+            mContext.registerReceiverAsUser(mEnableGestureNavReceiver, UserHandle.ALL,
+                    new IntentFilter(ACTION_ENABLE_GESTURE_NAV), null, null);
+            if (DEBUG) {
+                Log.d(TAG, "mEnableGestureNavReceiver registered");
+            }
+        }
         if (DEBUG) {
             Log.d(TAG, "deferGesturalNavOverlayIfNecessary: setting to 3 button mode");
         }
@@ -290,7 +403,15 @@
         final int userId = mDeviceProvisionedController.getCurrentUser();
         if (mRestoreGesturalNavBarMode.get(userId)) {
             // Restore the gestural state if necessary
-            setModeOverlay(NAV_BAR_MODE_GESTURAL_OVERLAY, USER_CURRENT);
+            if (!supportsDeviceAdmin()
+                    || mCurrentUserContext.getSystemService(DevicePolicyManager.class)
+                    .getUserProvisioningState() == STATE_USER_UNMANAGED) {
+                setGestureModeOverlayForMainLauncher();
+            } else {
+                if (DEBUG) {
+                    Log.d(TAG, "Not restoring to gesture nav for managed user");
+                }
+            }
             mRestoreGesturalNavBarMode.put(userId, false);
         }
     }
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 f64fc81..971a7ee 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -38,6 +38,7 @@
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuffXfermode;
 import android.graphics.Rect;
+import android.graphics.Region;
 import android.os.PowerManager;
 import android.util.AttributeSet;
 import android.util.Log;
@@ -676,9 +677,10 @@
 
     private Rect calculateGestureExclusionRect() {
         Rect exclusionRect = null;
-        if (isFullyCollapsed()) {
+        Region touchableRegion = mHeadsUpManager.calculateTouchableRegion();
+        if (isFullyCollapsed() && touchableRegion != null) {
             // Note: The heads up manager also calculates the non-pinned touchable region
-            exclusionRect = mHeadsUpManager.calculateTouchableRegion();
+            exclusionRect = touchableRegion.getBounds();
         }
         return exclusionRect != null
                 ? exclusionRect
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 0970f2a..40ebe58 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -1937,6 +1937,7 @@
 
         if (start) {
             mNotificationPanel.startWaitingForOpenPanelGesture();
+            setPanelExpanded(true);
         } else {
             mNotificationPanel.stopWaitingForOpenPanelGesture(velocity);
         }
@@ -2385,6 +2386,10 @@
             mLightBarController.dump(fd, pw, args);
         }
 
+        if (mKeyguardBypassController != null) {
+            mKeyguardBypassController.dump(pw);
+        }
+
         if (mKeyguardUpdateMonitor != null) {
             mKeyguardUpdateMonitor.dump(fd, pw, args);
         }
@@ -3434,7 +3439,7 @@
         mNotificationPanel.resetViews(dozingAnimated);
 
         updateQsExpansionEnabled();
-        mKeyguardViewMediator.setAodShowing(mDozing);
+        mKeyguardViewMediator.setDozing(mDozing);
 
         mEntryManager.updateNotifications();
         updateDozingState();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index d678182..65be708 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -720,7 +720,7 @@
      * animation didn't finish yet.
      */
     public boolean bouncerIsOrWillBeShowing() {
-        return mBouncer.isShowing() || mBouncer.willShowSoon();
+        return mBouncer.isShowing() || mBouncer.inTransit();
     }
 
     public boolean isFullscreenBouncer() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index b21ba09..4562763 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -163,7 +163,8 @@
                         | PhoneStateListener.LISTEN_CALL_STATE
                         | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
                         | PhoneStateListener.LISTEN_DATA_ACTIVITY
-                        | PhoneStateListener.LISTEN_CARRIER_NETWORK_CHANGE);
+                        | PhoneStateListener.LISTEN_CARRIER_NETWORK_CHANGE
+                        | PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE);
         mContext.getContentResolver().registerContentObserver(Global.getUriFor(Global.MOBILE_DATA),
                 true, mObserver);
         mContext.getContentResolver().registerContentObserver(Global.getUriFor(
@@ -636,6 +637,13 @@
 
             updateTelephony();
         }
+
+        @Override
+        public void onActiveDataSubscriptionIdChanged(int subId) {
+            if (DEBUG) Log.d(mTag, "onActiveDataSubscriptionIdChanged: subId=" + subId);
+            updateDataSim();
+            updateTelephony();
+        }
     };
 
     static class MobileIconGroup extends SignalController.IconGroup {
diff --git a/packages/SystemUI/tests/res/values/overlayable_icons_test.xml b/packages/SystemUI/tests/res/values/overlayable_icons_test.xml
deleted file mode 100644
index 24cd8cb..0000000
--- a/packages/SystemUI/tests/res/values/overlayable_icons_test.xml
+++ /dev/null
@@ -1,72 +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.
--->
-<resources>
-  <!-- overlayable_icons references all of the drawables in this package
-       that are being overlayed by resource overlays. If you remove/rename
-       any of these resources, you must also change the resource overlay icons.-->
-  <array name="overlayable_icons">
-    <item>@drawable/ic_alarm</item>
-    <item>@drawable/ic_alarm_dim</item>
-    <item>@drawable/ic_arrow_back</item>
-    <item>@drawable/ic_bluetooth_connected</item>
-    <item>@drawable/ic_brightness_thumb</item>
-    <item>@drawable/ic_camera</item>
-    <item>@drawable/ic_cast</item>
-    <item>@drawable/ic_cast_connected</item>
-    <item>@drawable/ic_close_white</item>
-    <item>@drawable/ic_data_saver</item>
-    <item>@drawable/ic_data_saver_off</item>
-    <item>@drawable/ic_drag_handle</item>
-    <item>@drawable/ic_headset</item>
-    <item>@drawable/ic_headset_mic</item>
-    <item>@drawable/ic_hotspot</item>
-    <item>@drawable/ic_info</item>
-    <item>@drawable/ic_info_outline</item>
-    <item>@drawable/ic_invert_colors</item>
-    <item>@drawable/ic_location</item>
-    <item>@drawable/ic_lockscreen_ime</item>
-    <item>@drawable/ic_notifications_alert</item>
-    <item>@drawable/ic_notifications_silence</item>
-    <item>@drawable/ic_power_low</item>
-    <item>@drawable/ic_power_saver</item>
-    <item>@drawable/ic_qs_bluetooth_connecting</item>
-    <item>@drawable/ic_qs_cancel</item>
-    <item>@drawable/ic_qs_no_sim</item>
-    <item>@drawable/ic_qs_wifi_0</item>
-    <item>@drawable/ic_qs_wifi_1</item>
-    <item>@drawable/ic_qs_wifi_2</item>
-    <item>@drawable/ic_qs_wifi_3</item>
-    <item>@drawable/ic_qs_wifi_4</item>
-    <item>@drawable/ic_qs_wifi_disconnected</item>
-    <item>@drawable/ic_screenshot_delete</item>
-    <item>@drawable/ic_settings</item>
-    <item>@drawable/ic_swap_vert</item>
-    <item>@drawable/ic_tune_black_16dp</item>
-    <item>@drawable/ic_volume_alarm_mute</item>
-    <item>@drawable/ic_volume_bt_sco</item>
-    <item>@drawable/ic_volume_media</item>
-    <item>@drawable/ic_volume_media_mute</item>
-    <item>@drawable/ic_volume_odi_captions</item>
-    <item>@drawable/ic_volume_odi_captions_disabled</item>
-    <item>@drawable/ic_volume_ringer</item>
-    <item>@drawable/ic_volume_ringer_mute</item>
-    <item>@drawable/ic_volume_ringer_vibrate</item>
-    <item>@drawable/ic_volume_voice</item>
-    <item>@drawable/stat_sys_managed_profile_status</item>
-    <item>@drawable/stat_sys_mic_none</item>
-    <item>@drawable/stat_sys_vpn_ic</item>
-  </array>
-</resources>
diff --git a/packages/SystemUI/tests/src/com/android/systemui/IconPackOverlayTest.java b/packages/SystemUI/tests/src/com/android/systemui/IconPackOverlayTest.java
deleted file mode 100644
index ccc9afc..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/IconPackOverlayTest.java
+++ /dev/null
@@ -1,192 +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;
-
-import static junit.framework.Assert.fail;
-
-import static org.junit.Assert.assertEquals;
-
-import android.annotation.DrawableRes;
-import android.content.pm.PackageManager;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.content.res.XmlResourceParser;
-import android.text.TextUtils;
-import android.util.TypedValue;
-
-import androidx.test.filters.MediumTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import com.android.internal.util.XmlUtils;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.xmlpull.v1.XmlPullParserException;
-
-import java.io.IOException;
-
-@RunWith(AndroidJUnit4.class)
-@MediumTest
-public class IconPackOverlayTest extends SysuiTestCase {
-
-    private static final String[] ICON_PACK_OVERLAY_PACKAGES = {
-            "com.android.theme.icon_pack.circular.systemui",
-            "com.android.theme.icon_pack.rounded.systemui",
-            "com.android.theme.icon_pack.filled.systemui",
-    };
-
-    private static final int[] VECTOR_ATTRIBUTES = {
-            android.R.attr.tint,
-            android.R.attr.height,
-            android.R.attr.width,
-            android.R.attr.alpha,
-            android.R.attr.autoMirrored,
-    };
-
-    private final TypedValue mTargetTypedValue = new TypedValue();
-    private final TypedValue mOverlayTypedValue = new TypedValue();
-
-    private Resources mResources;
-    private TypedArray mOverlayableIcons;
-
-    @Before
-    public void setup() {
-        mResources = mContext.getResources();
-        mOverlayableIcons = mResources.obtainTypedArray(R.array.overlayable_icons);
-    }
-
-    @After
-    public void teardown() {
-        mOverlayableIcons.recycle();
-    }
-
-    /**
-     * Ensure that all icons contained in overlayable_icons_test.xml exist in all 3 overlay icon
-     * packs for systemui. This test fails if you remove or rename an overlaid icon. If so,
-     * make the same change to the corresponding drawables in {@link #ICON_PACK_OVERLAY_PACKAGES}.
-     */
-    @Test
-    public void testIconPack_containAllOverlayedIcons() {
-        StringBuilder errors = new StringBuilder();
-
-        for (String overlayPackage : ICON_PACK_OVERLAY_PACKAGES) {
-            Resources overlayResources;
-            try {
-                overlayResources = mContext.getPackageManager()
-                        .getResourcesForApplication(overlayPackage);
-            } catch (PackageManager.NameNotFoundException e) {
-                continue; // No need to test overlay resources if apk is not on the system.
-            }
-
-            for (int i = 0; i < mOverlayableIcons.length(); i++) {
-                int sysuiRid = mOverlayableIcons.getResourceId(i, 0);
-                String sysuiResourceName = mResources.getResourceName(sysuiRid);
-                String overlayResourceName = sysuiResourceName
-                        .replace(mContext.getPackageName(), overlayPackage);
-                if (overlayResources.getIdentifier(overlayResourceName, null, null)
-                        == Resources.ID_NULL) {
-                    errors.append(String.format("[%s] is not contained in overlay package [%s]",
-                            overlayResourceName, overlayPackage));
-                }
-            }
-        }
-
-        if (!TextUtils.isEmpty(errors)) {
-            fail(errors.toString());
-        }
-    }
-
-    /**
-     * Ensures that all overlay icons have the same values for {@link #VECTOR_ATTRIBUTES} as the
-     * underlying drawable in systemui. To fix this test, make the attribute change to all of the
-     * corresponding drawables in {@link #ICON_PACK_OVERLAY_PACKAGES}.
-     */
-    @Test
-    public void testIconPacks_haveEqualVectorDrawableAttributes() {
-        StringBuilder errors = new StringBuilder();
-
-        for (String overlayPackage : ICON_PACK_OVERLAY_PACKAGES) {
-            Resources overlayResources;
-            try {
-                overlayResources = mContext.getPackageManager()
-                        .getResourcesForApplication(overlayPackage);
-            } catch (PackageManager.NameNotFoundException e) {
-                continue; // No need to test overlay resources if apk is not on the system.
-            }
-
-            for (int i = 0; i < mOverlayableIcons.length(); i++) {
-                int sysuiRid = mOverlayableIcons.getResourceId(i, 0);
-                String sysuiResourceName = mResources.getResourceName(sysuiRid);
-                TypedArray sysuiAttrs = getAVDAttributes(mResources, sysuiRid);
-                if (sysuiAttrs == null) {
-                    errors.append(String.format("[%s] does not exist or is not a valid AVD.",
-                            sysuiResourceName));
-                    continue;
-                }
-
-                String overlayResourceName = sysuiResourceName
-                        .replace(mContext.getPackageName(), overlayPackage);
-                int overlayRid = overlayResources.getIdentifier(overlayResourceName, null, null);
-                TypedArray overlayAttrs = getAVDAttributes(overlayResources, overlayRid);
-                if (overlayAttrs == null) {
-                    errors.append(String.format("[%s] does not exist or is not a valid AVD.",
-                            overlayResourceName));
-                    continue;
-                }
-
-                if (!attributesEquals(sysuiAttrs, overlayAttrs)) {
-                    errors.append(String.format("[%s] AVD attributes do not match [%s]\n",
-                            sysuiResourceName, overlayResourceName));
-                }
-                sysuiAttrs.recycle();
-                overlayAttrs.recycle();
-            }
-        }
-
-        if (!TextUtils.isEmpty(errors)) {
-            fail(errors.toString());
-        }
-    }
-
-    private TypedArray getAVDAttributes(Resources resources, @DrawableRes int rid) {
-        try {
-            XmlResourceParser parser = resources.getXml(rid);
-            XmlUtils.nextElement(parser);
-            return resources.obtainAttributes(parser, VECTOR_ATTRIBUTES);
-        } catch (XmlPullParserException | IOException  | Resources.NotFoundException e) {
-            return null;
-        }
-    }
-
-    private boolean attributesEquals(TypedArray target, TypedArray overlay) {
-        assertEquals(target.length(), overlay.length());
-        for (int i = 0; i < target.length(); i++) {
-            target.getValue(i, mTargetTypedValue);
-            overlay.getValue(i, mOverlayTypedValue);
-            if (!attributesEquals(mTargetTypedValue, mOverlayTypedValue)) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    private boolean attributesEquals(TypedValue target, TypedValue overlay) {
-        return target.type == overlay.type && target.data == overlay.data;
-    }
-}
diff --git a/packages/overlays/tests/Android.bp b/packages/overlays/tests/Android.bp
new file mode 100644
index 0000000..343367a
--- /dev/null
+++ b/packages/overlays/tests/Android.bp
@@ -0,0 +1,37 @@
+// 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: "OverlayTests",
+
+    certificate: "platform",
+
+    srcs: ["src/**/*.java"],
+
+    libs: [
+        "android.test.runner",
+        "android.test.base",
+    ],
+
+    platform_apis: true,
+
+    static_libs: [
+        "androidx.test.rules",
+        "androidx.test.espresso.core",
+        "mockito-target-minus-junit4",
+        "truth-prebuilt",
+    ],
+
+    dxflags: ["--multi-dex"],
+}
diff --git a/packages/overlays/tests/AndroidManifest.xml b/packages/overlays/tests/AndroidManifest.xml
new file mode 100644
index 0000000..6ebc555
--- /dev/null
+++ b/packages/overlays/tests/AndroidManifest.xml
@@ -0,0 +1,37 @@
+<?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.overlays">
+
+    <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
+    <uses-permission android:name="android.permission.MANAGE_USERS" />
+    <uses-permission android:name="android.permission.MANAGE_NETWORK_POLICY"/>
+    <uses-permission android:name="android.permission.SET_TIME_ZONE" />
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
+    <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+        android:targetPackage="com.android.systemui"
+        android:label="Tests for Overlays">
+    </instrumentation>
+</manifest>
diff --git a/packages/overlays/tests/AndroidTest.xml b/packages/overlays/tests/AndroidTest.xml
new file mode 100644
index 0000000..8843d62
--- /dev/null
+++ b/packages/overlays/tests/AndroidTest.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
+  -->
+<configuration description="Runs Tests for Overlays.">
+    <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
+        <option name="test-file-name" value="OverlayTests.apk" />
+    </target_preparer>
+
+    <option name="test-suite-tag" value="apct" />
+    <option name="test-tag" value="OverlayTests" />
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+        <option name="package" value="com.android.overlays" />
+        <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
+        <option name="hidden-api-checks" value="false"/>
+    </test>
+</configuration>
diff --git a/packages/overlays/tests/src/com/android/theme/icon/IconPackOverlayTest.java b/packages/overlays/tests/src/com/android/theme/icon/IconPackOverlayTest.java
new file mode 100644
index 0000000..6bc56ba
--- /dev/null
+++ b/packages/overlays/tests/src/com/android/theme/icon/IconPackOverlayTest.java
@@ -0,0 +1,293 @@
+/*
+ * 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.theme.icon;
+
+import static junit.framework.Assert.fail;
+
+import static org.junit.Assert.assertEquals;
+
+import android.annotation.DrawableRes;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+import android.text.TextUtils;
+import android.util.TypedValue;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.MediumTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.util.XmlUtils;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+@RunWith(AndroidJUnit4.class)
+@MediumTest
+public class IconPackOverlayTest {
+    private static final String SYSTEMUI_PACKAGE = "com.android.systemui";
+    private static final String[] SYSTEMUI_ICON_PACK_OVERLAY_PACKAGES = {
+            "com.android.theme.icon_pack.circular.systemui",
+            "com.android.theme.icon_pack.rounded.systemui",
+            "com.android.theme.icon_pack.filled.systemui",
+    };
+    private static final String ANDROID_PACKAGE = "android";
+    private static final String[] ANDROID_ICON_PACK_OVERLAY_PACKAGES = {
+            "com.android.theme.icon_pack.circular.android",
+            "com.android.theme.icon_pack.rounded.android",
+            "com.android.theme.icon_pack.filled.android",
+    };
+    private static final String SETTINGS_PACKAGE = "com.android.settings";
+    private static final String[] SETTINGS_ICON_PACK_OVERLAY_PACKAGES = {
+            "com.android.theme.icon_pack.circular.settings",
+            "com.android.theme.icon_pack.rounded.settings",
+            "com.android.theme.icon_pack.filled.settings",
+    };
+
+    private static final int[] VECTOR_ATTRIBUTES = {
+            android.R.attr.tint,
+            android.R.attr.height,
+            android.R.attr.width,
+            android.R.attr.alpha,
+            android.R.attr.autoMirrored,
+    };
+
+    private final TypedValue mTargetTypedValue = new TypedValue();
+    private final TypedValue mOverlayTypedValue = new TypedValue();
+    private Context mContext;
+
+    @Before
+    public void setup() {
+        mContext = InstrumentationRegistry.getContext();
+    }
+
+    /**
+     * Ensure that drawable icons in icon packs targeting android have corresponding underlying
+     * drawables in android. This test fails if you remove/rename an overlaid icon in android.
+     * If so, make the same change to the corresponding drawables in the overlay packages.
+     */
+    @Test
+    public void testAndroidFramework_containsAllOverlayedIcons() {
+        containsAllOverlayedIcons(ANDROID_PACKAGE, ANDROID_ICON_PACK_OVERLAY_PACKAGES);
+    }
+
+    /**
+     * Ensure that drawable icons in icon packs targeting settings have corresponding underlying
+     * drawables in settings. This test fails if you remove/rename an overlaid icon in settings.
+     * If so, make the same change to the corresponding drawables in the overlay packages.
+     */
+    @Test
+    public void testSettings_containsAllOverlayedIcons() {
+        containsAllOverlayedIcons(SETTINGS_PACKAGE, SETTINGS_ICON_PACK_OVERLAY_PACKAGES);
+    }
+
+    /**
+     * Ensure that drawable icons in icon packs targeting systemui have corresponding underlying
+     * drawables in systemui. This test fails if you remove/rename an overlaid icon in systemui.
+     * If so, make the same change to the corresponding drawables in the overlay packages.
+     */
+    @Test
+    public void testSystemUI_containAllOverlayedIcons() {
+        containsAllOverlayedIcons(SYSTEMUI_PACKAGE, SYSTEMUI_ICON_PACK_OVERLAY_PACKAGES);
+    }
+
+    /**
+     * Ensures that all overlay icons have the same values for {@link #VECTOR_ATTRIBUTES} as the
+     * underlying drawable in android. To fix this test, make the attribute change to all of the
+     * corresponding drawables in the overlay packages.
+     */
+    @Test
+    public void testAndroidFramework_hasEqualVectorDrawableAttributes() {
+        hasEqualVectorDrawableAttributes(ANDROID_PACKAGE, ANDROID_ICON_PACK_OVERLAY_PACKAGES);
+    }
+
+    /**
+     * Ensures that all overlay icons have the same values for {@link #VECTOR_ATTRIBUTES} as the
+     * underlying drawable in settings. To fix this test, make the attribute change to all of the
+     * corresponding drawables in the overlay packages.
+     */
+    @Test
+    public void testSettings_hasEqualVectorDrawableAttributes() {
+        hasEqualVectorDrawableAttributes(SETTINGS_PACKAGE, SETTINGS_ICON_PACK_OVERLAY_PACKAGES);
+    }
+
+    /**
+     * Ensures that all overlay icons have the same values for {@link #VECTOR_ATTRIBUTES} as the
+     * underlying drawable in systemui. To fix this test, make the attribute change to all of the
+     * corresponding drawables in the overlay packages.
+     */
+    @Test
+    public void testSystemUI_hasEqualVectorDrawableAttributes() {
+        hasEqualVectorDrawableAttributes(SYSTEMUI_PACKAGE, SYSTEMUI_ICON_PACK_OVERLAY_PACKAGES);
+    }
+
+    private void containsAllOverlayedIcons(String targetPkg, String[] overlayPkgs) {
+        final Resources targetResources;
+        try {
+            targetResources = mContext.getPackageManager()
+                    .getResourcesForApplication(targetPkg);
+        } catch (PackageManager.NameNotFoundException e) {
+            return; // No need to test overlays if target package does not exist on the system.
+        }
+
+        StringBuilder errors = new StringBuilder();
+        for (String overlayPackage : overlayPkgs) {
+            final ApplicationInfo info;
+            try {
+                info = mContext.getPackageManager().getApplicationInfo(overlayPackage, 0);
+            } catch (PackageManager.NameNotFoundException e) {
+                continue; // No need to test overlay resources if apk is not on the system.
+            }
+            final List<String> iconPackDrawables = getDrawablesFromOverlay(info);
+            for (int i = 0; i < iconPackDrawables.size(); i++) {
+                String resourceName = iconPackDrawables.get(i);
+                int targetRid = targetResources.getIdentifier(resourceName, "drawable", targetPkg);
+                if (targetRid == Resources.ID_NULL) {
+                    errors.append(String.format("[%s] is not contained in the target package [%s]",
+                            resourceName, targetPkg));
+                }
+            }
+        }
+
+        if (!TextUtils.isEmpty(errors)) {
+            fail(errors.toString());
+        }
+    }
+
+    private void hasEqualVectorDrawableAttributes(String targetPkg, String[] overlayPackages) {
+        final Resources targetRes;
+        try {
+            targetRes = mContext.getPackageManager().getResourcesForApplication(targetPkg);
+        } catch (PackageManager.NameNotFoundException e) {
+            return; // No need to test overlays if target package does not exist on the system.
+        }
+
+        StringBuilder errors = new StringBuilder();
+
+        for (String overlayPkg : overlayPackages) {
+            final ApplicationInfo info;
+            try {
+                info = mContext.getPackageManager().getApplicationInfo(overlayPkg, 0);
+            } catch (PackageManager.NameNotFoundException e) {
+                continue; // No need to test overlay resources if apk is not on the system.
+            }
+            final List<String> iconPackDrawables = getDrawablesFromOverlay(info);
+            final Resources overlayRes;
+            try {
+                overlayRes = mContext.getPackageManager().getResourcesForApplication(overlayPkg);
+            } catch (PackageManager.NameNotFoundException e) {
+                continue; // No need to test overlay resources if apk is not on the system.
+            }
+
+            for (int i = 0; i < iconPackDrawables.size(); i++) {
+                String resourceName = iconPackDrawables.get(i);
+                int targetRid = targetRes.getIdentifier(resourceName, "drawable", targetPkg);
+                int overlayRid = overlayRes.getIdentifier(resourceName, "drawable", overlayPkg);
+                TypedArray targetAttrs = getAVDAttributes(targetRes, targetRid);
+                if (targetAttrs == null) {
+                    errors.append(String.format(
+                            "[%s] in pkg [%s] does not exist or is not a valid vector drawable.\n",
+                            resourceName, targetPkg));
+                    continue;
+                }
+
+                TypedArray overlayAttrs = getAVDAttributes(overlayRes, overlayRid);
+                if (overlayAttrs == null) {
+                    errors.append(String.format(
+                            "[%s] in pkg [%s] does not exist or is not a valid vector drawable.\n",
+                            resourceName, overlayPkg));
+                    continue;
+                }
+
+                if (!attributesEquals(targetAttrs, overlayAttrs)) {
+                    errors.append(String.format("[drawable/%s] in [%s] does not have the same "
+                                    + "attributes as the corresponding drawable from [%s]\n",
+                            resourceName, targetPkg, overlayPkg));
+                }
+                targetAttrs.recycle();
+                overlayAttrs.recycle();
+            }
+        }
+
+        if (!TextUtils.isEmpty(errors)) {
+            fail(errors.toString());
+        }
+    }
+
+    private TypedArray getAVDAttributes(Resources resources, @DrawableRes int rid) {
+        try {
+            XmlResourceParser parser = resources.getXml(rid);
+            XmlUtils.nextElement(parser);
+            // Always use the the test apk theme to resolve attributes.
+            return mContext.getTheme().obtainStyledAttributes(parser, VECTOR_ATTRIBUTES, 0, 0);
+        } catch (XmlPullParserException | IOException  | Resources.NotFoundException e) {
+            return null;
+        }
+    }
+
+    private boolean attributesEquals(TypedArray target, TypedArray overlay) {
+        assertEquals(target.length(), overlay.length());
+        for (int i = 0; i < target.length(); i++) {
+            target.getValue(i, mTargetTypedValue);
+            overlay.getValue(i, mOverlayTypedValue);
+            if (!attributesEquals(mTargetTypedValue, mOverlayTypedValue)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    private static boolean attributesEquals(TypedValue target, TypedValue overlay) {
+        return target.type == overlay.type && target.data == overlay.data;
+    }
+
+    private static List<String> getDrawablesFromOverlay(ApplicationInfo applicationInfo) {
+        try {
+            final ArrayList<String> drawables = new ArrayList<>();
+            ZipFile file = new ZipFile(applicationInfo.sourceDir);
+            Enumeration<? extends ZipEntry> entries = file.entries();
+            while (entries.hasMoreElements()) {
+                ZipEntry element = entries.nextElement();
+                String name = element.getName();
+                if (name.contains("/drawable/")) {
+                    name = name.substring(name.lastIndexOf('/') + 1);
+                    if (name.contains(".")) {
+                        name = name.substring(0, name.indexOf('.'));
+                    }
+                    drawables.add(name);
+                }
+            }
+            return drawables;
+        } catch (IOException e) {
+            fail(String.format("Failed to retrieve drawables from package [%s] with message [%s]",
+                    applicationInfo.packageName, e.getMessage()));
+            return null;
+        }
+    }
+}
diff --git a/services/backup/java/com/android/server/backup/FullBackupJob.java b/services/backup/java/com/android/server/backup/FullBackupJob.java
index f62a875..088e1f9 100644
--- a/services/backup/java/com/android/server/backup/FullBackupJob.java
+++ b/services/backup/java/com/android/server/backup/FullBackupJob.java
@@ -16,6 +16,8 @@
 
 package com.android.server.backup;
 
+import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
+
 import android.app.job.JobInfo;
 import android.app.job.JobParameters;
 import android.app.job.JobScheduler;
@@ -37,7 +39,7 @@
     public static final int MAX_JOB_ID = 52419896;
 
     private static ComponentName sIdleService =
-            new ComponentName("android", FullBackupJob.class.getName());
+            new ComponentName(PLATFORM_PACKAGE_NAME, FullBackupJob.class.getName());
 
     @GuardedBy("mParamsForUser")
     private final SparseArray<JobParameters> mParamsForUser = new SparseArray<>();
diff --git a/services/backup/java/com/android/server/backup/KeyValueBackupJob.java b/services/backup/java/com/android/server/backup/KeyValueBackupJob.java
index 72d81d3..ac43fc3 100644
--- a/services/backup/java/com/android/server/backup/KeyValueBackupJob.java
+++ b/services/backup/java/com/android/server/backup/KeyValueBackupJob.java
@@ -17,6 +17,7 @@
 package com.android.server.backup;
 
 import static com.android.server.backup.BackupManagerService.DEBUG_SCHEDULING;
+import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
 
 import android.app.AlarmManager;
 import android.app.job.JobInfo;
@@ -43,7 +44,7 @@
 public class KeyValueBackupJob extends JobService {
     private static final String TAG = "KeyValueBackupJob";
     private static ComponentName sKeyValueJobService =
-            new ComponentName("android", KeyValueBackupJob.class.getName());
+            new ComponentName(PLATFORM_PACKAGE_NAME, KeyValueBackupJob.class.getName());
 
     private static final String USER_ID_EXTRA_KEY = "userId";
 
diff --git a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
index a45f0c0..675a6eb 100644
--- a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
+++ b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
@@ -26,6 +26,7 @@
 import static com.android.server.backup.internal.BackupHandler.MSG_BACKUP_RESTORE_STEP;
 import static com.android.server.backup.internal.BackupHandler.MSG_RESTORE_OPERATION_TIMEOUT;
 import static com.android.server.backup.internal.BackupHandler.MSG_RESTORE_SESSION_TIMEOUT;
+import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
 
 import android.annotation.Nullable;
 import android.app.ApplicationThreadConstants;
@@ -222,7 +223,7 @@
                 try {
                     PackageManager pm = backupManagerService.getPackageManager();
                     PackageInfo info = pm.getPackageInfoAsUser(filterSet[i], 0, mUserId);
-                    if ("android".equals(info.packageName)) {
+                    if (PLATFORM_PACKAGE_NAME.equals(info.packageName)) {
                         hasSystem = true;
                         continue;
                     }
@@ -241,7 +242,7 @@
             if (hasSystem) {
                 try {
                     mAcceptSet.add(0, backupManagerService.getPackageManager().getPackageInfoAsUser(
-                                    "android", 0, mUserId));
+                                    PLATFORM_PACKAGE_NAME, 0, mUserId));
                 } catch (NameNotFoundException e) {
                     // won't happen; we know a priori that it's valid
                 }
@@ -681,7 +682,7 @@
         // an optimization: we know there's no widget data hosted/published by that
         // package, and this way we avoid doing a spurious copy of MB-sized wallpaper
         // data following the download.
-        boolean staging = !packageName.equals("android");
+        boolean staging = !packageName.equals(PLATFORM_PACKAGE_NAME);
         ParcelFileDescriptor stage;
         File downloadFile = (staging) ? mStageName : mBackupDataName;
         boolean startedAgentRestore = false;
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 3ebe702..930cf9e 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -97,6 +97,7 @@
 import com.android.internal.location.ProviderRequest;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.DumpUtils;
+import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.Preconditions;
 import com.android.server.location.AbstractLocationProvider;
 import com.android.server.location.ActivityRecognitionProxy;
@@ -466,7 +467,7 @@
         // the user being changed will cause a reload of all user specific settings, which causes
         // provider initialization, and propagates changes until a steady state is reached
         mCurrentUserId = UserHandle.USER_NULL;
-        onUserChangedLocked(UserHandle.USER_SYSTEM);
+        onUserChangedLocked(ActivityManager.getCurrentUser());
 
         // initialize in-memory settings values
         onBackgroundThrottleWhitelistChangedLocked();
@@ -905,7 +906,8 @@
                     Integer.parseInt(fragments[9]) /* accuracy */);
             LocationProvider testProviderManager = new LocationProvider(name);
             addProviderLocked(testProviderManager);
-            new MockProvider(mContext, testProviderManager, properties);
+            testProviderManager.attachLocked(
+                    new MockProvider(mContext, testProviderManager, properties));
         }
     }
 
@@ -1026,38 +1028,55 @@
             return mProperties;
         }
 
-        @GuardedBy("mLock")
-        public void setRequestLocked(ProviderRequest request, WorkSource workSource) {
-            if (mProvider != null) {
-                long identity = Binder.clearCallingIdentity();
-                try {
-                    mProvider.setRequest(request, workSource);
-                } finally {
-                    Binder.restoreCallingIdentity(identity);
+        public void setRequest(ProviderRequest request, WorkSource workSource) {
+            // move calls going to providers onto a different thread to avoid deadlock
+            mHandler.post(() -> {
+                synchronized (mLock) {
+                    if (mProvider != null) {
+                        mProvider.onSetRequest(request, workSource);
+                    }
                 }
-            }
+            });
+        }
+
+        public void sendExtraCommand(String command, Bundle extras) {
+            int uid = Binder.getCallingUid();
+            int pid = Binder.getCallingPid();
+
+            // move calls going to providers onto a different thread to avoid deadlock
+            mHandler.post(() -> {
+                synchronized (mLock) {
+                    if (mProvider != null) {
+                        mProvider.onSendExtraCommand(uid, pid, command, extras);
+                    }
+                }
+            });
         }
 
         @GuardedBy("mLock")
-        public void dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args) {
-            pw.print("  " + mName + " provider");
+        public void dumpLocked(FileDescriptor fd, IndentingPrintWriter pw, String[] args) {
+            pw.print(mName + " provider");
             if (isMock()) {
                 pw.print(" [mock]");
             }
             pw.println(":");
 
-            pw.println("    useable=" + mUseable);
+            pw.increaseIndent();
+
+            pw.println("useable=" + mUseable);
             if (!mUseable) {
-                pw.println("    attached=" + (mProvider != null));
+                pw.println("attached=" + (mProvider != null));
                 if (mIsManagedBySettings) {
-                    pw.println("    allowed=" + mAllowed);
+                    pw.println("allowed=" + mAllowed);
                 }
-                pw.println("    enabled=" + mEnabled);
+                pw.println("enabled=" + mEnabled);
             }
 
-            pw.println("    properties=" + mProperties);
+            pw.println("properties=" + mProperties);
 
             if (mProvider != null) {
+                // in order to be consistent with other provider APIs, this should be run on the
+                // location thread... but this likely isn't worth it just for dumping info.
                 long identity = Binder.clearCallingIdentity();
                 try {
                     mProvider.dump(fd, pw, args);
@@ -1065,6 +1084,8 @@
                     Binder.restoreCallingIdentity(identity);
                 }
             }
+
+            pw.decreaseIndent();
         }
 
         @GuardedBy("mLock")
@@ -1095,79 +1116,53 @@
             }
         }
 
-        @GuardedBy("mLock")
-        public void sendExtraCommandLocked(String command, Bundle extras) {
-            if (mProvider != null) {
-                // intentionally do not clear binder identity so that providers can evaluate who
-                // is sending the extra command
-                mProvider.sendExtraCommand(command, extras);
+        @Override
+        public void onReportLocation(Location location) {
+            synchronized (mLock) {
+                handleLocationChangedLocked(location, this);
             }
         }
 
-        // called from any thread
-        @Override
-        public void onReportLocation(Location location) {
-            // no security check necessary because this is coming from an internal-only interface
-            // move calls coming from below LMS onto a different thread to avoid deadlock
-            mHandler.post(() -> {
-                synchronized (mLock) {
-                    handleLocationChangedLocked(location, this);
-                }
-            });
-        }
-
-        // called from any thread
         @Override
         public void onReportLocation(List<Location> locations) {
-            // move calls coming from below LMS onto a different thread to avoid deadlock
-            mHandler.post(() -> {
-                synchronized (mLock) {
-                    LocationProvider gpsProvider = getLocationProviderLocked(GPS_PROVIDER);
-                    if (gpsProvider == null || !gpsProvider.isUseableLocked()) {
-                        Slog.w(TAG, "reportLocationBatch() called without user permission");
-                        return;
-                    }
-
-                    if (mGnssBatchingCallback == null) {
-                        Slog.e(TAG, "reportLocationBatch() called without active Callback");
-                        return;
-                    }
-
-                    try {
-                        mGnssBatchingCallback.onLocationBatch(locations);
-                    } catch (RemoteException e) {
-                        Slog.e(TAG, "mGnssBatchingCallback.onLocationBatch failed", e);
-                    }
+            synchronized (mLock) {
+                LocationProvider gpsProvider = getLocationProviderLocked(GPS_PROVIDER);
+                if (gpsProvider == null || !gpsProvider.isUseableLocked()) {
+                    Slog.w(TAG, "reportLocationBatch() called without user permission");
+                    return;
                 }
-            });
+
+                if (mGnssBatchingCallback == null) {
+                    Slog.e(TAG, "reportLocationBatch() called without active Callback");
+                    return;
+                }
+
+                try {
+                    mGnssBatchingCallback.onLocationBatch(locations);
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "mGnssBatchingCallback.onLocationBatch failed", e);
+                }
+            }
         }
 
-        // called from any thread
         @Override
         public void onSetEnabled(boolean enabled) {
-            // move calls coming from below LMS onto a different thread to avoid deadlock
-            mHandler.post(() -> {
-                synchronized (mLock) {
-                    if (enabled == mEnabled) {
-                        return;
-                    }
-
-                    if (D) {
-                        Log.d(TAG, mName + " provider enabled is now " + mEnabled);
-                    }
-
-                    mEnabled = enabled;
-                    onUseableChangedLocked(false);
+            synchronized (mLock) {
+                if (enabled == mEnabled) {
+                    return;
                 }
-            });
+
+                if (D) {
+                    Log.d(TAG, mName + " provider enabled is now " + mEnabled);
+                }
+
+                mEnabled = enabled;
+                onUseableChangedLocked(false);
+            }
         }
 
         @Override
         public void onSetProperties(ProviderProperties properties) {
-            // because this does not invoke any other methods which might result in calling back
-            // into the location provider, it is safe to run this on the calling thread. it is also
-            // currently necessary to run this on the calling thread to ensure that property changes
-            // are publicly visibly immediately, ie for mock providers which are created.
             synchronized (mLock) {
                 mProperties = properties;
             }
@@ -1325,9 +1320,8 @@
         }
 
         @Override
-        @GuardedBy("mLock")
-        public void setRequestLocked(ProviderRequest request, WorkSource workSource) {
-            super.setRequestLocked(request, workSource);
+        public void setRequest(ProviderRequest request, WorkSource workSource) {
+            super.setRequest(request, workSource);
             mCurrentRequest = request;
         }
 
@@ -2232,7 +2226,7 @@
             }
         }
 
-        provider.setRequestLocked(providerRequest, worksource);
+        provider.setRequest(providerRequest, worksource);
     }
 
     /**
@@ -2916,6 +2910,12 @@
             mCallerIdentity = callerIdentity;
             mListenerName = listenerName;
         }
+
+        @Override
+        public String toString() {
+            return mListenerName + "[" + mCallerIdentity.mPackageName + "(" + mCallerIdentity.mPid
+                    + ")]";
+        }
     }
 
     private static class LinkedListener<TListener> extends LinkedListenerBase {
@@ -3116,7 +3116,7 @@
 
             LocationProvider provider = getLocationProviderLocked(providerName);
             if (provider != null) {
-                provider.sendExtraCommandLocked(command, extras);
+                provider.sendExtraCommand(command, extras);
             }
 
             mLocationUsageLogger.logLocationApiUsage(
@@ -3671,6 +3671,8 @@
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
 
+        IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
+
         synchronized (mLock) {
             if (args.length > 0 && args[0].equals("--gnssmetrics")) {
                 if (mGnssMetricsProvider != null) {
@@ -3678,115 +3680,133 @@
                 }
                 return;
             }
-            pw.println("Current Location Manager state:");
-            pw.print("  Current System Time: "
+
+            ipw.println("Location Manager State:");
+            ipw.increaseIndent();
+            ipw.print("Current System Time: "
                     + TimeUtils.logTimeOfDay(System.currentTimeMillis()));
-            pw.println(", Current Elapsed Time: "
+            ipw.println(", Current Elapsed Time: "
                     + TimeUtils.formatDuration(SystemClock.elapsedRealtime()));
-            pw.println("  Current user: " + mCurrentUserId + " " + Arrays.toString(
+            ipw.println("Current user: " + mCurrentUserId + " " + Arrays.toString(
                     mCurrentUserProfiles));
-            pw.println("  Location mode: " + isLocationEnabled());
-            pw.println("  Battery Saver Location Mode: "
+            ipw.println("Location Mode: " + isLocationEnabled());
+            ipw.println("Battery Saver Location Mode: "
                     + locationPowerSaveModeToString(mBatterySaverMode));
-            pw.println("  Location Listeners:");
+
+            ipw.println("Location Listeners:");
+            ipw.increaseIndent();
             for (Receiver receiver : mReceivers.values()) {
-                pw.println("    " + receiver);
+                ipw.println(receiver);
             }
-            pw.println("  Active Records by Provider:");
+            ipw.decreaseIndent();
+
+            ipw.println("Active Records by Provider:");
+            ipw.increaseIndent();
             for (Map.Entry<String, ArrayList<UpdateRecord>> entry : mRecordsByProvider.entrySet()) {
-                pw.println("    " + entry.getKey() + ":");
+                ipw.println(entry.getKey() + ":");
+                ipw.increaseIndent();
                 for (UpdateRecord record : entry.getValue()) {
-                    pw.println("      " + record);
+                    ipw.println(record);
                 }
+                ipw.decreaseIndent();
             }
+            ipw.decreaseIndent();
 
-            pw.println("  Active GnssMeasurement Listeners:");
-            dumpGnssDataListenersLocked(pw, mGnssMeasurementsListeners);
-            pw.println("  Active GnssNavigationMessage Listeners:");
-            dumpGnssDataListenersLocked(pw, mGnssNavigationMessageListeners);
-            pw.println("  Active GnssStatus Listeners:");
-            dumpGnssDataListenersLocked(pw, mGnssStatusListeners);
+            ipw.println("GnssMeasurement Listeners:");
+            ipw.increaseIndent();
+            for (LinkedListenerBase listener : mGnssMeasurementsListeners.values()) {
+                ipw.println(listener + ": " + isThrottlingExemptLocked(listener.mCallerIdentity));
+            }
+            ipw.decreaseIndent();
 
-            pw.println("  Historical Records by Provider:");
+            ipw.println("GnssNavigationMessage Listeners:");
+            ipw.increaseIndent();
+            for (LinkedListenerBase listener : mGnssNavigationMessageListeners.values()) {
+                ipw.println(listener + ": " + isThrottlingExemptLocked(listener.mCallerIdentity));
+            }
+            ipw.decreaseIndent();
+
+            ipw.println("GnssStatus Listeners:");
+            ipw.increaseIndent();
+            for (LinkedListenerBase listener : mGnssStatusListeners.values()) {
+                ipw.println(listener + ": " + isThrottlingExemptLocked(listener.mCallerIdentity));
+            }
+            ipw.decreaseIndent();
+
+            ipw.println("Historical Records by Provider:");
+            ipw.increaseIndent();
             for (Map.Entry<PackageProviderKey, PackageStatistics> entry
                     : mRequestStatistics.statistics.entrySet()) {
                 PackageProviderKey key = entry.getKey();
-                PackageStatistics stats = entry.getValue();
-                pw.println("    " + key.packageName + ": " + key.providerName + ": " + stats);
+                ipw.println(key.packageName + ": " + key.providerName + ": " + entry.getValue());
             }
-            pw.println("  Last Known Locations:");
-            for (Map.Entry<String, Location> entry : mLastLocation.entrySet()) {
-                String provider = entry.getKey();
-                Location location = entry.getValue();
-                pw.println("    " + provider + ": " + location);
-            }
+            ipw.decreaseIndent();
 
-            pw.println("  Last Known Locations Coarse Intervals:");
-            for (Map.Entry<String, Location> entry : mLastLocationCoarseInterval.entrySet()) {
-                String provider = entry.getKey();
-                Location location = entry.getValue();
-                pw.println("    " + provider + ": " + location);
+            ipw.println("Last Known Locations:");
+            ipw.increaseIndent();
+            for (Map.Entry<String, Location> entry : mLastLocation.entrySet()) {
+                ipw.println(entry.getKey() + ": " + entry.getValue());
             }
+            ipw.decreaseIndent();
+
+            ipw.println("Last Known Coarse Locations:");
+            ipw.increaseIndent();
+            for (Map.Entry<String, Location> entry : mLastLocationCoarseInterval.entrySet()) {
+                ipw.println(entry.getKey() + ": " + entry.getValue());
+            }
+            ipw.decreaseIndent();
 
             if (mGeofenceManager != null) {
-                mGeofenceManager.dump(pw);
-            } else {
-                pw.println("  Geofences: null");
+                ipw.println("Geofences:");
+                ipw.increaseIndent();
+                mGeofenceManager.dump(ipw);
+                ipw.decreaseIndent();
             }
           
             if (mBlacklist != null) {
-                pw.append("  ");
-                mBlacklist.dump(pw);
-            } else {
-                pw.println("  mBlacklist=null");
+                mBlacklist.dump(ipw);
             }
 
             if (mExtraLocationControllerPackage != null) {
-                pw.println(" Location controller extra package: " + mExtraLocationControllerPackage
-                        + " enabled: " + mExtraLocationControllerPackageEnabled);
+                ipw.println("Location Controller Extra Package: " + mExtraLocationControllerPackage
+                        + (mExtraLocationControllerPackageEnabled ? " [enabled]" : "[disabled]"));
             }
 
             if (!mBackgroundThrottlePackageWhitelist.isEmpty()) {
-                pw.println("  Throttling Whitelisted Packages:");
+                ipw.println("Throttling Whitelisted Packages:");
+                ipw.increaseIndent();
                 for (String packageName : mBackgroundThrottlePackageWhitelist) {
-                    pw.println("    " + packageName);
+                    ipw.println(packageName);
                 }
+                ipw.decreaseIndent();
             }
 
             if (!mIgnoreSettingsPackageWhitelist.isEmpty()) {
-                pw.println("  Bypass Whitelisted Packages:");
+                ipw.println("Bypass Whitelisted Packages:");
+                ipw.increaseIndent();
                 for (String packageName : mIgnoreSettingsPackageWhitelist) {
-                    pw.println("    " + packageName);
+                    ipw.println(packageName);
                 }
+                ipw.decreaseIndent();
             }
 
             if (mLocationFudger != null) {
-                pw.append("  fudger: ");
-                mLocationFudger.dump(fd, pw, args);
-            } else {
-                pw.println("  fudger: null");
+                ipw.println("Location Fudger:");
+                ipw.increaseIndent();
+                mLocationFudger.dump(fd, ipw, args);
+                ipw.decreaseIndent();
             }
 
-            if (args.length > 0 && "short".equals(args[0])) {
-                return;
-            }
+            ipw.println("Location Providers:");
+            ipw.increaseIndent();
             for (LocationProvider provider : mProviders) {
-                provider.dumpLocked(fd, pw, args);
+                provider.dumpLocked(fd, ipw, args);
             }
-            if (mGnssBatchingInProgress) {
-                pw.println("  GNSS batching in progress");
-            }
-        }
-    }
+            ipw.decreaseIndent();
 
-    @GuardedBy("mLock")
-    private void dumpGnssDataListenersLocked(PrintWriter pw,
-            ArrayMap<IBinder, ? extends LinkedListenerBase> gnssDataListeners) {
-        for (LinkedListenerBase listener : gnssDataListeners.values()) {
-            CallerIdentity callerIdentity = listener.mCallerIdentity;
-            pw.println("    " + callerIdentity.mPid + " " + callerIdentity.mUid + " "
-                    + callerIdentity.mPackageName + ": "
-                    + isThrottlingExemptLocked(callerIdentity));
+            if (mGnssBatchingInProgress) {
+                ipw.println("GNSS batching in progress");
+            }
         }
     }
 }
diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java
index bc7da3f..30a3563 100644
--- a/services/core/java/com/android/server/UiModeManagerService.java
+++ b/services/core/java/com/android/server/UiModeManagerService.java
@@ -413,15 +413,15 @@
             try {
                 synchronized (mLock) {
                     if (mNightMode != mode) {
-                        if (UserManager.get(getContext()).isPrimaryUser()) {
-                            SystemProperties.set(SYSTEM_PROPERTY_DEVICE_THEME,
-                                    Integer.toString(mode));
-                        }
-
                         // Only persist setting if not in car mode
                         if (!mCarModeEnabled) {
                             Secure.putIntForUser(getContext().getContentResolver(),
                                     Secure.UI_NIGHT_MODE, mode, user);
+
+                            if (UserManager.get(getContext()).isPrimaryUser()) {
+                                SystemProperties.set(SYSTEM_PROPERTY_DEVICE_THEME,
+                                        Integer.toString(mode));
+                            }
                         }
 
                         mNightMode = mode;
diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java
index 19ad32e..a502ff2 100644
--- a/services/core/java/com/android/server/Watchdog.java
+++ b/services/core/java/com/android/server/Watchdog.java
@@ -103,6 +103,7 @@
     public static final List<String> HAL_INTERFACES_OF_INTEREST = Arrays.asList(
             "android.hardware.audio@2.0::IDevicesFactory",
             "android.hardware.audio@4.0::IDevicesFactory",
+            "android.hardware.audio@5.0::IDevicesFactory",
             "android.hardware.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/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index d848796..4f54e64 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -1440,6 +1440,11 @@
 
     @Override
     public void onServiceChanged(AuthenticatorDescription desc, int userId, boolean removed) {
+        UserInfo user = getUserManager().getUserInfo(userId);
+        if (user == null) {
+            Log.w(TAG, "onServiceChanged: ignore removed user " + userId);
+            return;
+        }
         validateAccountsInternal(getUserAccounts(userId), false /* invalidateAuthenticatorCache */);
     }
 
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 8cd675c..adb0909 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -210,7 +210,6 @@
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.PackageManagerInternal;
-import android.content.pm.PackageManagerInternal.CheckPermissionDelegate;
 import android.content.pm.PackageParser;
 import android.content.pm.ParceledListSlice;
 import android.content.pm.PathPermission;
@@ -270,6 +269,7 @@
 import android.os.WorkSource;
 import android.os.storage.IStorageManager;
 import android.os.storage.StorageManager;
+import android.permission.PermissionManagerInternal.CheckPermissionDelegate;
 import android.provider.DeviceConfig;
 import android.provider.DeviceConfig.Properties;
 import android.provider.Settings;
@@ -352,6 +352,7 @@
 import com.android.server.job.JobSchedulerInternal;
 import com.android.server.pm.Installer;
 import com.android.server.pm.Installer.InstallerException;
+import com.android.server.pm.permission.PermissionManagerServiceInternal;
 import com.android.server.uri.GrantUri;
 import com.android.server.uri.UriGrantsManagerInternal;
 import com.android.server.utils.PriorityDump;
@@ -1561,6 +1562,7 @@
     final HiddenApiSettings mHiddenApiBlacklist;
 
     PackageManagerInternal mPackageManagerInt;
+    PermissionManagerServiceInternal mPermissionManagerInt;
 
     /**
      * Whether to force background check on all apps (for battery saver) or not.
@@ -7207,6 +7209,14 @@
         return mPackageManagerInt;
     }
 
+    private PermissionManagerServiceInternal getPermissionManagerInternalLocked() {
+        if (mPermissionManagerInt == null) {
+            mPermissionManagerInt =
+                    LocalServices.getService(PermissionManagerServiceInternal.class);
+        }
+        return mPermissionManagerInt;
+    }
+
     @Override
     public final ContentProviderHolder getContentProvider(
             IApplicationThread caller, String callingPackage, String name, int userId,
@@ -15937,7 +15947,7 @@
             // Can't call out of the system process with a lock held, so post a message.
             if (instr.mUiAutomationConnection != null) {
                 mAppOpsService.setAppOpsServiceDelegate(null);
-                getPackageManagerInternalLocked().setCheckPermissionDelegate(null);
+                getPermissionManagerInternalLocked().setCheckPermissionDelegate(null);
                 mHandler.obtainMessage(SHUTDOWN_UI_AUTOMATION_CONNECTION_MSG,
                         instr.mUiAutomationConnection).sendToTarget();
             }
@@ -18893,7 +18903,7 @@
         synchronized (ActivityManagerService.this) {
             // If there is a delegate it should be the same instance for app ops and permissions.
             if (mAppOpsService.getAppOpsServiceDelegate()
-                    != getPackageManagerInternalLocked().getCheckPermissionDelegate()) {
+                    != getPermissionManagerInternalLocked().getCheckPermissionDelegate()) {
                 throw new IllegalStateException("Bad shell delegate state");
             }
 
@@ -18928,7 +18938,7 @@
                 final ShellDelegate shellDelegate = new ShellDelegate(
                         instr.mTargetInfo.packageName, delegateUid, permissions);
                 mAppOpsService.setAppOpsServiceDelegate(shellDelegate);
-                getPackageManagerInternalLocked().setCheckPermissionDelegate(shellDelegate);
+                getPermissionManagerInternalLocked().setCheckPermissionDelegate(shellDelegate);
                 return;
             }
         }
@@ -18942,7 +18952,7 @@
         }
         synchronized (ActivityManagerService.this) {
             mAppOpsService.setAppOpsServiceDelegate(null);
-            getPackageManagerInternalLocked().setCheckPermissionDelegate(null);
+            getPermissionManagerInternalLocked().setCheckPermissionDelegate(null);
         }
     }
 
diff --git a/services/core/java/com/android/server/am/OomAdjProfiler.java b/services/core/java/com/android/server/am/OomAdjProfiler.java
index 9846b31..7e381840 100644
--- a/services/core/java/com/android/server/am/OomAdjProfiler.java
+++ b/services/core/java/com/android/server/am/OomAdjProfiler.java
@@ -16,6 +16,7 @@
 
 package com.android.server.am;
 
+import android.os.Message;
 import android.os.PowerManagerInternal;
 import android.os.Process;
 import android.os.SystemClock;
@@ -29,14 +30,20 @@
 import java.io.PrintWriter;
 
 public class OomAdjProfiler {
-    // Disable profiling for Q. Re-enable once b/130635979 is fixed.
-    private static final boolean PROFILING_DISABLED = true;
+    private static final int MSG_UPDATE_CPU_TIME = 42;
 
     @GuardedBy("this")
     private boolean mOnBattery;
     @GuardedBy("this")
     private boolean mScreenOff;
 
+    /** The value of {@link #mOnBattery} when the CPU time update was last scheduled. */
+    @GuardedBy("this")
+    private boolean mLastScheduledOnBattery;
+    /** The value of {@link #mScreenOff} when the CPU time update was last scheduled. */
+    @GuardedBy("this")
+    private boolean mLastScheduledScreenOff;
+
     @GuardedBy("this")
     private long mOomAdjStartTimeMs;
     @GuardedBy("this")
@@ -59,9 +66,6 @@
     final RingBuffer<CpuTimes> mSystemServerCpuTimesHist = new RingBuffer<>(CpuTimes.class, 10);
 
     void batteryPowerChanged(boolean onBattery) {
-        if (PROFILING_DISABLED) {
-            return;
-        }
         synchronized (this) {
             scheduleSystemServerCpuTimeUpdate();
             mOnBattery = onBattery;
@@ -69,9 +73,6 @@
     }
 
     void onWakefulnessChanged(int wakefulness) {
-        if (PROFILING_DISABLED) {
-            return;
-        }
         synchronized (this) {
             scheduleSystemServerCpuTimeUpdate();
             mScreenOff = wakefulness != PowerManagerInternal.WAKEFULNESS_AWAKE;
@@ -79,9 +80,6 @@
     }
 
     void oomAdjStarted() {
-        if (PROFILING_DISABLED) {
-            return;
-        }
         synchronized (this) {
             mOomAdjStartTimeMs = SystemClock.currentThreadTimeMillis();
             mOomAdjStarted = true;
@@ -89,9 +87,6 @@
     }
 
     void oomAdjEnded() {
-        if (PROFILING_DISABLED) {
-            return;
-        }
         synchronized (this) {
             if (!mOomAdjStarted) {
                 return;
@@ -101,31 +96,33 @@
     }
 
     private void scheduleSystemServerCpuTimeUpdate() {
-        if (PROFILING_DISABLED) {
-            return;
-        }
         synchronized (this) {
             if (mSystemServerCpuTimeUpdateScheduled) {
                 return;
             }
+            mLastScheduledOnBattery = mOnBattery;
+            mLastScheduledScreenOff = mScreenOff;
             mSystemServerCpuTimeUpdateScheduled = true;
-            BackgroundThread.getHandler().sendMessage(PooledLambda.obtainMessage(
+            Message scheduledMessage = PooledLambda.obtainMessage(
                     OomAdjProfiler::updateSystemServerCpuTime,
-                    this, mOnBattery, mScreenOff));
+                    this, mLastScheduledOnBattery, mLastScheduledScreenOff, true);
+            scheduledMessage.setWhat(MSG_UPDATE_CPU_TIME);
+
+            BackgroundThread.getHandler().sendMessage(scheduledMessage);
         }
     }
 
-    private void updateSystemServerCpuTime(boolean onBattery, boolean screenOff) {
-        if (PROFILING_DISABLED) {
-            return;
-        }
+    private void updateSystemServerCpuTime(boolean onBattery, boolean screenOff,
+            boolean onlyIfScheduled) {
         final long cpuTimeMs = mProcessCpuTracker.getCpuTimeForPid(Process.myPid());
         synchronized (this) {
+            if (onlyIfScheduled && !mSystemServerCpuTimeUpdateScheduled) {
+                return;
+            }
             mSystemServerCpuTime.addCpuTimeMs(
                     cpuTimeMs - mLastSystemServerCpuTimeMs, onBattery, screenOff);
             mLastSystemServerCpuTimeMs = cpuTimeMs;
             mSystemServerCpuTimeUpdateScheduled = false;
-            notifyAll();
         }
     }
 
@@ -142,20 +139,14 @@
     }
 
     void dump(PrintWriter pw) {
-        if (PROFILING_DISABLED) {
-            return;
-        }
         synchronized (this) {
             if (mSystemServerCpuTimeUpdateScheduled) {
-                while (mSystemServerCpuTimeUpdateScheduled) {
-                    try {
-                        wait();
-                    } catch (InterruptedException e) {
-                        Thread.currentThread().interrupt();
-                    }
-                }
+                // Cancel the scheduled update since we're going to update it here instead.
+                BackgroundThread.getHandler().removeMessages(MSG_UPDATE_CPU_TIME);
+                // Make sure the values are attributed to the right states.
+                updateSystemServerCpuTime(mLastScheduledOnBattery, mLastScheduledScreenOff, false);
             } else {
-                updateSystemServerCpuTime(mOnBattery, mScreenOff);
+                updateSystemServerCpuTime(mOnBattery, mScreenOff, false);
             }
 
             pw.println("System server and oomAdj runtimes (ms) in recent battery sessions "
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index ffbc6b3..5465309 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -1526,6 +1526,9 @@
             if ("1".equals(SystemProperties.get("debug.assert"))) {
                 runtimeFlags |= Zygote.DEBUG_ENABLE_ASSERT;
             }
+            if ("1".equals(SystemProperties.get("debug.ignoreappsignalhandler"))) {
+                runtimeFlags |= Zygote.DEBUG_IGNORE_APP_SIGNAL_HANDLER;
+            }
             if (mService.mNativeDebuggingApp != null
                     && mService.mNativeDebuggingApp.equals(app.processName)) {
                 // Enable all debug flags required by the native debugger.
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index 4d09c3b..cb6cf74 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -125,6 +125,8 @@
     /*package*/ void onAudioServerDied() {
         // Restore forced usage for communications and record
         synchronized (mDeviceStateLock) {
+            AudioSystem.setParameters(
+                    "BT_SCO=" + (mForcedUseForComm == AudioSystem.FORCE_BT_SCO ? "on" : "off"));
             onSetForceUse(AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, "onAudioServerDied");
             onSetForceUse(AudioSystem.FOR_RECORD, mForcedUseForComm, "onAudioServerDied");
         }
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index a537865..7458bee 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -54,8 +54,6 @@
 import android.content.pm.ResolveInfo;
 import android.content.pm.UserInfo;
 import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.content.res.XmlResourceParser;
 import android.database.ContentObserver;
 import android.hardware.hdmi.HdmiAudioSystemClient;
 import android.hardware.hdmi.HdmiControlManager;
@@ -82,11 +80,7 @@
 import android.media.IVolumeController;
 import android.media.MediaExtractor;
 import android.media.MediaFormat;
-import android.media.MediaPlayer;
-import android.media.MediaPlayer.OnCompletionListener;
-import android.media.MediaPlayer.OnErrorListener;
 import android.media.PlayerBase;
-import android.media.SoundPool;
 import android.media.VolumePolicy;
 import android.media.audiofx.AudioEffect;
 import android.media.audiopolicy.AudioMix;
@@ -102,7 +96,6 @@
 import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
-import android.os.Environment;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
@@ -137,7 +130,6 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.DumpUtils;
 import com.android.internal.util.Preconditions;
-import com.android.internal.util.XmlUtils;
 import com.android.server.EventLogTags;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
@@ -146,15 +138,11 @@
 import com.android.server.pm.UserManagerService;
 import com.android.server.wm.ActivityTaskManagerInternal;
 
-import org.xmlpull.v1.XmlPullParserException;
-
-import java.io.File;
 import java.io.FileDescriptor;
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
-import java.lang.reflect.Field;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
@@ -294,19 +282,6 @@
     // protects mRingerMode
     private final Object mSettingsLock = new Object();
 
-    private SoundPool mSoundPool;
-    private final Object mSoundEffectsLock = new Object();
-    private static final int NUM_SOUNDPOOL_CHANNELS = 4;
-
-    /* Sound effect file names  */
-    private static final String SOUND_EFFECTS_PATH = "/media/audio/ui/";
-    private static final List<String> SOUND_EFFECT_FILES = new ArrayList<String>();
-
-    /* Sound effect file name mapping sound effect id (AudioManager.FX_xxx) to
-     * file index in SOUND_EFFECT_FILES[] (first column) and indicating if effect
-     * uses soundpool (second column) */
-    private final int[][] SOUND_EFFECT_FILES_MAP = new int[AudioManager.NUM_SOUND_EFFECTS][2];
-
    /** Maximum volume index values for audio streams */
     protected static int[] MAX_STREAM_VOLUME = new int[] {
         5,  // STREAM_VOICE_CALL
@@ -366,7 +341,7 @@
         AudioSystem.STREAM_MUSIC,       // STREAM_MUSIC
         AudioSystem.STREAM_MUSIC,       // STREAM_ALARM
         AudioSystem.STREAM_MUSIC,       // STREAM_NOTIFICATION
-        AudioSystem.STREAM_MUSIC,       // STREAM_BLUETOOTH_SCO
+        AudioSystem.STREAM_BLUETOOTH_SCO,       // STREAM_BLUETOOTH_SCO
         AudioSystem.STREAM_MUSIC,       // STREAM_SYSTEM_ENFORCED
         AudioSystem.STREAM_MUSIC,       // STREAM_DTMF
         AudioSystem.STREAM_MUSIC,       // STREAM_TTS
@@ -453,6 +428,9 @@
      * @see System#MUTE_STREAMS_AFFECTED */
     private int mMuteAffectedStreams;
 
+    @NonNull
+    private SoundEffectsHelper mSfxHelper;
+
     /**
      * NOTE: setVibrateSetting(), getVibrateSetting(), shouldVibrate() are deprecated.
      * mVibrateSetting is just maintained during deprecation period but vibration policy is
@@ -493,14 +471,6 @@
     private boolean mSystemReady;
     // true if Intent.ACTION_USER_SWITCHED has ever been received
     private boolean mUserSwitchedReceived;
-    // listener for SoundPool sample load completion indication
-    private SoundPoolCallback mSoundPoolCallBack;
-    // thread for SoundPool listener
-    private SoundPoolListenerThread mSoundPoolListenerThread;
-    // message looper for SoundPool listener
-    private Looper mSoundPoolLooper = null;
-    // volume applied to sound played with playSoundEffect()
-    private static int sSoundEffectVolumeDb;
     // previous volume adjustment direction received by checkForRingerModeChange()
     private int mPrevVolDirection = AudioManager.ADJUST_SAME;
     // mVolumeControlStream is set by VolumePanel to temporarily force the stream type which volume
@@ -642,6 +612,8 @@
         PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
         mAudioEventWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "handleAudioEvent");
 
+        mSfxHelper = new SoundEffectsHelper(mContext);
+
         mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
         mHasVibrator = mVibrator == null ? false : mVibrator.hasVibrator();
 
@@ -732,9 +704,6 @@
                         MAX_STREAM_VOLUME[AudioSystem.STREAM_SYSTEM];
         }
 
-        sSoundEffectVolumeDb = context.getResources().getInteger(
-                com.android.internal.R.integer.config_soundEffectVolumeDb);
-
         createAudioSystemThread();
 
         AudioSystem.setErrorCallback(mAudioSystemCallback);
@@ -3369,104 +3338,30 @@
     //==========================================================================================
     // Sound Effects
     //==========================================================================================
+    private static final class LoadSoundEffectReply
+            implements SoundEffectsHelper.OnEffectsLoadCompleteHandler {
+        private static final int SOUND_EFFECTS_LOADING = 1;
+        private static final int SOUND_EFFECTS_LOADED = 0;
+        private static final int SOUND_EFFECTS_ERROR = -1;
+        private static final int SOUND_EFFECTS_LOAD_TIMEOUT_MS = 5000;
 
-    private static final String TAG_AUDIO_ASSETS = "audio_assets";
-    private static final String ATTR_VERSION = "version";
-    private static final String TAG_GROUP = "group";
-    private static final String ATTR_GROUP_NAME = "name";
-    private static final String TAG_ASSET = "asset";
-    private static final String ATTR_ASSET_ID = "id";
-    private static final String ATTR_ASSET_FILE = "file";
+        private int mStatus = SOUND_EFFECTS_LOADING;
 
-    private static final String ASSET_FILE_VERSION = "1.0";
-    private static final String GROUP_TOUCH_SOUNDS = "touch_sounds";
-
-    private static final int SOUND_EFFECTS_LOAD_TIMEOUT_MS = 5000;
-
-    class LoadSoundEffectReply {
-        public int mStatus = 1;
-    };
-
-    private void loadTouchSoundAssetDefaults() {
-        SOUND_EFFECT_FILES.add("Effect_Tick.ogg");
-        for (int i = 0; i < AudioManager.NUM_SOUND_EFFECTS; i++) {
-            SOUND_EFFECT_FILES_MAP[i][0] = 0;
-            SOUND_EFFECT_FILES_MAP[i][1] = -1;
-        }
-    }
-
-    private void loadTouchSoundAssets() {
-        XmlResourceParser parser = null;
-
-        // only load assets once.
-        if (!SOUND_EFFECT_FILES.isEmpty()) {
-            return;
+        @Override
+        public synchronized void run(boolean success) {
+            mStatus = success ? SOUND_EFFECTS_LOADED : SOUND_EFFECTS_ERROR;
+            notify();
         }
 
-        loadTouchSoundAssetDefaults();
-
-        try {
-            parser = mContext.getResources().getXml(com.android.internal.R.xml.audio_assets);
-
-            XmlUtils.beginDocument(parser, TAG_AUDIO_ASSETS);
-            String version = parser.getAttributeValue(null, ATTR_VERSION);
-            boolean inTouchSoundsGroup = false;
-
-            if (ASSET_FILE_VERSION.equals(version)) {
-                while (true) {
-                    XmlUtils.nextElement(parser);
-                    String element = parser.getName();
-                    if (element == null) {
-                        break;
-                    }
-                    if (element.equals(TAG_GROUP)) {
-                        String name = parser.getAttributeValue(null, ATTR_GROUP_NAME);
-                        if (GROUP_TOUCH_SOUNDS.equals(name)) {
-                            inTouchSoundsGroup = true;
-                            break;
-                        }
-                    }
-                }
-                while (inTouchSoundsGroup) {
-                    XmlUtils.nextElement(parser);
-                    String element = parser.getName();
-                    if (element == null) {
-                        break;
-                    }
-                    if (element.equals(TAG_ASSET)) {
-                        String id = parser.getAttributeValue(null, ATTR_ASSET_ID);
-                        String file = parser.getAttributeValue(null, ATTR_ASSET_FILE);
-                        int fx;
-
-                        try {
-                            Field field = AudioManager.class.getField(id);
-                            fx = field.getInt(null);
-                        } catch (Exception e) {
-                            Log.w(TAG, "Invalid touch sound ID: "+id);
-                            continue;
-                        }
-
-                        int i = SOUND_EFFECT_FILES.indexOf(file);
-                        if (i == -1) {
-                            i = SOUND_EFFECT_FILES.size();
-                            SOUND_EFFECT_FILES.add(file);
-                        }
-                        SOUND_EFFECT_FILES_MAP[fx][0] = i;
-                    } else {
-                        break;
-                    }
+        public synchronized boolean waitForLoaded(int attempts) {
+            while ((mStatus == SOUND_EFFECTS_LOADING) && (attempts-- > 0)) {
+                try {
+                    wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS);
+                } catch (InterruptedException e) {
+                    Log.w(TAG, "Interrupted while waiting sound pool loaded.");
                 }
             }
-        } catch (Resources.NotFoundException e) {
-            Log.w(TAG, "audio assets file not found", e);
-        } catch (XmlPullParserException e) {
-            Log.w(TAG, "XML parser exception reading touch sound assets", e);
-        } catch (IOException e) {
-            Log.w(TAG, "I/O exception reading touch sound assets", e);
-        } finally {
-            if (parser != null) {
-                parser.close();
-            }
+            return mStatus == SOUND_EFFECTS_LOADED;
         }
     }
 
@@ -3496,20 +3391,9 @@
      * This method must be called at first when sound effects are enabled
      */
     public boolean loadSoundEffects() {
-        int attempts = 3;
         LoadSoundEffectReply reply = new LoadSoundEffectReply();
-
-        synchronized (reply) {
-            sendMsg(mAudioHandler, MSG_LOAD_SOUND_EFFECTS, SENDMSG_QUEUE, 0, 0, reply, 0);
-            while ((reply.mStatus == 1) && (attempts-- > 0)) {
-                try {
-                    reply.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS);
-                } catch (InterruptedException e) {
-                    Log.w(TAG, "loadSoundEffects Interrupted while waiting sound pool loaded.");
-                }
-            }
-        }
-        return (reply.mStatus == 0);
+        sendMsg(mAudioHandler, MSG_LOAD_SOUND_EFFECTS, SENDMSG_QUEUE, 0, 0, reply, 0);
+        return reply.waitForLoaded(3 /*attempts*/);
     }
 
     /**
@@ -3529,61 +3413,6 @@
         sendMsg(mAudioHandler, MSG_UNLOAD_SOUND_EFFECTS, SENDMSG_QUEUE, 0, 0, null, 0);
     }
 
-    class SoundPoolListenerThread extends Thread {
-        public SoundPoolListenerThread() {
-            super("SoundPoolListenerThread");
-        }
-
-        @Override
-        public void run() {
-
-            Looper.prepare();
-            mSoundPoolLooper = Looper.myLooper();
-
-            synchronized (mSoundEffectsLock) {
-                if (mSoundPool != null) {
-                    mSoundPoolCallBack = new SoundPoolCallback();
-                    mSoundPool.setOnLoadCompleteListener(mSoundPoolCallBack);
-                }
-                mSoundEffectsLock.notify();
-            }
-            Looper.loop();
-        }
-    }
-
-    private final class SoundPoolCallback implements
-            android.media.SoundPool.OnLoadCompleteListener {
-
-        int mStatus = 1; // 1 means neither error nor last sample loaded yet
-        List<Integer> mSamples = new ArrayList<Integer>();
-
-        public int status() {
-            return mStatus;
-        }
-
-        public void setSamples(int[] samples) {
-            for (int i = 0; i < samples.length; i++) {
-                // do not wait ack for samples rejected upfront by SoundPool
-                if (samples[i] > 0) {
-                    mSamples.add(samples[i]);
-                }
-            }
-        }
-
-        public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
-            synchronized (mSoundEffectsLock) {
-                int i = mSamples.indexOf(sampleId);
-                if (i >= 0) {
-                    mSamples.remove(i);
-                }
-                if ((status != 0) || mSamples. isEmpty()) {
-                    mStatus = status;
-                    mSoundEffectsLock.notify();
-                }
-            }
-        }
-    }
-
     /** @see AudioManager#reloadAudioSettings() */
     public void reloadAudioSettings() {
         readAudioSettings(false /*userSwitch*/);
@@ -5104,230 +4933,6 @@
             Settings.Global.putInt(mContentResolver, Settings.Global.MODE_RINGER, ringerMode);
         }
 
-        private String getSoundEffectFilePath(int effectType) {
-            String filePath = Environment.getProductDirectory() + SOUND_EFFECTS_PATH
-                    + SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effectType][0]);
-            if (!new File(filePath).isFile()) {
-                filePath = Environment.getRootDirectory() + SOUND_EFFECTS_PATH
-                        + SOUND_EFFECT_FILES.get(SOUND_EFFECT_FILES_MAP[effectType][0]);
-            }
-            return filePath;
-        }
-
-        private boolean onLoadSoundEffects() {
-            int status;
-
-            synchronized (mSoundEffectsLock) {
-                if (!mSystemReady) {
-                    Log.w(TAG, "onLoadSoundEffects() called before boot complete");
-                    return false;
-                }
-
-                if (mSoundPool != null) {
-                    return true;
-                }
-
-                loadTouchSoundAssets();
-
-                mSoundPool = new SoundPool.Builder()
-                        .setMaxStreams(NUM_SOUNDPOOL_CHANNELS)
-                        .setAudioAttributes(new AudioAttributes.Builder()
-                            .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
-                            .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
-                            .build())
-                        .build();
-                mSoundPoolCallBack = null;
-                mSoundPoolListenerThread = new SoundPoolListenerThread();
-                mSoundPoolListenerThread.start();
-                int attempts = 3;
-                while ((mSoundPoolCallBack == null) && (attempts-- > 0)) {
-                    try {
-                        // Wait for mSoundPoolCallBack to be set by the other thread
-                        mSoundEffectsLock.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS);
-                    } catch (InterruptedException e) {
-                        Log.w(TAG, "Interrupted while waiting sound pool listener thread.");
-                    }
-                }
-
-                if (mSoundPoolCallBack == null) {
-                    Log.w(TAG, "onLoadSoundEffects() SoundPool listener or thread creation error");
-                    if (mSoundPoolLooper != null) {
-                        mSoundPoolLooper.quit();
-                        mSoundPoolLooper = null;
-                    }
-                    mSoundPoolListenerThread = null;
-                    mSoundPool.release();
-                    mSoundPool = null;
-                    return false;
-                }
-                /*
-                 * poolId table: The value -1 in this table indicates that corresponding
-                 * file (same index in SOUND_EFFECT_FILES[] has not been loaded.
-                 * Once loaded, the value in poolId is the sample ID and the same
-                 * sample can be reused for another effect using the same file.
-                 */
-                int[] poolId = new int[SOUND_EFFECT_FILES.size()];
-                for (int fileIdx = 0; fileIdx < SOUND_EFFECT_FILES.size(); fileIdx++) {
-                    poolId[fileIdx] = -1;
-                }
-                /*
-                 * Effects whose value in SOUND_EFFECT_FILES_MAP[effect][1] is -1 must be loaded.
-                 * If load succeeds, value in SOUND_EFFECT_FILES_MAP[effect][1] is > 0:
-                 * this indicates we have a valid sample loaded for this effect.
-                 */
-
-                int numSamples = 0;
-                for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) {
-                    // Do not load sample if this effect uses the MediaPlayer
-                    if (SOUND_EFFECT_FILES_MAP[effect][1] == 0) {
-                        continue;
-                    }
-                    if (poolId[SOUND_EFFECT_FILES_MAP[effect][0]] == -1) {
-                        String filePath = getSoundEffectFilePath(effect);
-                        int sampleId = mSoundPool.load(filePath, 0);
-                        if (sampleId <= 0) {
-                            Log.w(TAG, "Soundpool could not load file: "+filePath);
-                        } else {
-                            SOUND_EFFECT_FILES_MAP[effect][1] = sampleId;
-                            poolId[SOUND_EFFECT_FILES_MAP[effect][0]] = sampleId;
-                            numSamples++;
-                        }
-                    } else {
-                        SOUND_EFFECT_FILES_MAP[effect][1] =
-                                poolId[SOUND_EFFECT_FILES_MAP[effect][0]];
-                    }
-                }
-                // wait for all samples to be loaded
-                if (numSamples > 0) {
-                    mSoundPoolCallBack.setSamples(poolId);
-
-                    attempts = 3;
-                    status = 1;
-                    while ((status == 1) && (attempts-- > 0)) {
-                        try {
-                            mSoundEffectsLock.wait(SOUND_EFFECTS_LOAD_TIMEOUT_MS);
-                            status = mSoundPoolCallBack.status();
-                        } catch (InterruptedException e) {
-                            Log.w(TAG, "Interrupted while waiting sound pool callback.");
-                        }
-                    }
-                } else {
-                    status = -1;
-                }
-
-                if (mSoundPoolLooper != null) {
-                    mSoundPoolLooper.quit();
-                    mSoundPoolLooper = null;
-                }
-                mSoundPoolListenerThread = null;
-                if (status != 0) {
-                    Log.w(TAG,
-                            "onLoadSoundEffects(), Error "+status+ " while loading samples");
-                    for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) {
-                        if (SOUND_EFFECT_FILES_MAP[effect][1] > 0) {
-                            SOUND_EFFECT_FILES_MAP[effect][1] = -1;
-                        }
-                    }
-
-                    mSoundPool.release();
-                    mSoundPool = null;
-                }
-            }
-            return (status == 0);
-        }
-
-        /**
-         *  Unloads samples from the sound pool.
-         *  This method can be called to free some memory when
-         *  sound effects are disabled.
-         */
-        private void onUnloadSoundEffects() {
-            synchronized (mSoundEffectsLock) {
-                if (mSoundPool == null) {
-                    return;
-                }
-
-                int[] poolId = new int[SOUND_EFFECT_FILES.size()];
-                for (int fileIdx = 0; fileIdx < SOUND_EFFECT_FILES.size(); fileIdx++) {
-                    poolId[fileIdx] = 0;
-                }
-
-                for (int effect = 0; effect < AudioManager.NUM_SOUND_EFFECTS; effect++) {
-                    if (SOUND_EFFECT_FILES_MAP[effect][1] <= 0) {
-                        continue;
-                    }
-                    if (poolId[SOUND_EFFECT_FILES_MAP[effect][0]] == 0) {
-                        mSoundPool.unload(SOUND_EFFECT_FILES_MAP[effect][1]);
-                        SOUND_EFFECT_FILES_MAP[effect][1] = -1;
-                        poolId[SOUND_EFFECT_FILES_MAP[effect][0]] = -1;
-                    }
-                }
-                mSoundPool.release();
-                mSoundPool = null;
-            }
-        }
-
-        private void onPlaySoundEffect(int effectType, int volume) {
-            synchronized (mSoundEffectsLock) {
-
-                onLoadSoundEffects();
-
-                if (mSoundPool == null) {
-                    return;
-                }
-                float volFloat;
-                // use default if volume is not specified by caller
-                if (volume < 0) {
-                    volFloat = (float)Math.pow(10, (float)sSoundEffectVolumeDb/20);
-                } else {
-                    volFloat = volume / 1000.0f;
-                }
-
-                if (SOUND_EFFECT_FILES_MAP[effectType][1] > 0) {
-                    mSoundPool.play(SOUND_EFFECT_FILES_MAP[effectType][1],
-                                        volFloat, volFloat, 0, 0, 1.0f);
-                } else {
-                    MediaPlayer mediaPlayer = new MediaPlayer();
-                    try {
-                        String filePath = getSoundEffectFilePath(effectType);
-                        mediaPlayer.setDataSource(filePath);
-                        mediaPlayer.setAudioStreamType(AudioSystem.STREAM_SYSTEM);
-                        mediaPlayer.prepare();
-                        mediaPlayer.setVolume(volFloat);
-                        mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
-                            public void onCompletion(MediaPlayer mp) {
-                                cleanupPlayer(mp);
-                            }
-                        });
-                        mediaPlayer.setOnErrorListener(new OnErrorListener() {
-                            public boolean onError(MediaPlayer mp, int what, int extra) {
-                                cleanupPlayer(mp);
-                                return true;
-                            }
-                        });
-                        mediaPlayer.start();
-                    } catch (IOException ex) {
-                        Log.w(TAG, "MediaPlayer IOException: "+ex);
-                    } catch (IllegalArgumentException ex) {
-                        Log.w(TAG, "MediaPlayer IllegalArgumentException: "+ex);
-                    } catch (IllegalStateException ex) {
-                        Log.w(TAG, "MediaPlayer IllegalStateException: "+ex);
-                    }
-                }
-            }
-        }
-
-        private void cleanupPlayer(MediaPlayer mp) {
-            if (mp != null) {
-                try {
-                    mp.stop();
-                    mp.release();
-                } catch (IllegalStateException ex) {
-                    Log.w(TAG, "MediaPlayer IllegalStateException: "+ex);
-                }
-            }
-        }
-
         private void onPersistSafeVolumeState(int state) {
             Settings.Global.putInt(mContentResolver,
                     Settings.Global.AUDIO_SAFE_VOLUME_STATE,
@@ -5374,24 +4979,25 @@
                     break;
 
                 case MSG_UNLOAD_SOUND_EFFECTS:
-                    onUnloadSoundEffects();
+                    mSfxHelper.unloadSoundEffects();
                     break;
 
                 case MSG_LOAD_SOUND_EFFECTS:
-                    //FIXME: onLoadSoundEffects() should be executed in a separate thread as it
-                    // can take several dozens of milliseconds to complete
-                    boolean loaded = onLoadSoundEffects();
-                    if (msg.obj != null) {
-                        LoadSoundEffectReply reply = (LoadSoundEffectReply)msg.obj;
-                        synchronized (reply) {
-                            reply.mStatus = loaded ? 0 : -1;
-                            reply.notify();
+                {
+                    LoadSoundEffectReply reply = (LoadSoundEffectReply) msg.obj;
+                    if (mSystemReady) {
+                        mSfxHelper.loadSoundEffects(reply);
+                    } else {
+                        Log.w(TAG, "[schedule]loadSoundEffects() called before boot complete");
+                        if (reply != null) {
+                            reply.run(false);
                         }
                     }
+                }
                     break;
 
                 case MSG_PLAY_SOUND_EFFECT:
-                    onPlaySoundEffect(msg.arg1, msg.arg2);
+                    mSfxHelper.playSoundEffect(msg.arg1, msg.arg2);
                     break;
 
                 case MSG_SET_FORCE_USE:
@@ -5575,6 +5181,7 @@
 
     /**
      * @return true if there is currently a registered dynamic mixing policy that affects media
+     * and is not a render + loopback policy
      */
     /*package*/ boolean hasMediaDynamicPolicy() {
         synchronized (mAudioPolicies) {
@@ -5583,7 +5190,8 @@
             }
             final Collection<AudioPolicyProxy> appColl = mAudioPolicies.values();
             for (AudioPolicyProxy app : appColl) {
-                if (app.hasMixAffectingUsage(AudioAttributes.USAGE_MEDIA)) {
+                if (app.hasMixAffectingUsage(AudioAttributes.USAGE_MEDIA,
+                        AudioMix.ROUTE_FLAG_LOOP_BACK_RENDER)) {
                     return true;
                 }
             }
@@ -6422,6 +6030,8 @@
 
         pw.println("\nAudioDeviceBroker:");
         mDeviceBroker.dump(pw, "  ");
+        pw.println("\nSoundEffects:");
+        mSfxHelper.dump(pw, "  ");
 
         pw.println("\n");
         pw.println("\nEvent logs:");
@@ -7353,9 +6963,10 @@
             Binder.restoreCallingIdentity(identity);
         }
 
-        boolean hasMixAffectingUsage(int usage) {
+        boolean hasMixAffectingUsage(int usage, int excludedFlags) {
             for (AudioMix mix : mMixes) {
-                if (mix.isAffectingUsage(usage)) {
+                if (mix.isAffectingUsage(usage)
+                        && ((mix.getRouteFlags() & excludedFlags) != excludedFlags)) {
                     return true;
                 }
             }
diff --git a/services/core/java/com/android/server/audio/SoundEffectsHelper.java b/services/core/java/com/android/server/audio/SoundEffectsHelper.java
new file mode 100644
index 0000000..cf5bc8d
--- /dev/null
+++ b/services/core/java/com/android/server/audio/SoundEffectsHelper.java
@@ -0,0 +1,521 @@
+/*
+ * 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.audio;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.XmlResourceParser;
+import android.media.AudioAttributes;
+import android.media.AudioManager;
+import android.media.AudioSystem;
+import android.media.MediaPlayer;
+import android.media.MediaPlayer.OnCompletionListener;
+import android.media.MediaPlayer.OnErrorListener;
+import android.media.SoundPool;
+import android.os.Environment;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.util.Log;
+import android.util.PrintWriterPrinter;
+
+import com.android.internal.util.XmlUtils;
+
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A helper class for managing sound effects loading / unloading
+ * used by AudioService. As its methods are called on the message handler thread
+ * of AudioService, the actual work is offloaded to a dedicated thread.
+ * This helps keeping AudioService responsive.
+ * @hide
+ */
+class SoundEffectsHelper {
+    private static final String TAG = "AS.SfxHelper";
+
+    private static final int NUM_SOUNDPOOL_CHANNELS = 4;
+
+    /* Sound effect file names  */
+    private static final String SOUND_EFFECTS_PATH = "/media/audio/ui/";
+
+    private static final int EFFECT_NOT_IN_SOUND_POOL = 0; // SoundPool sample IDs > 0
+
+    private static final int MSG_LOAD_EFFECTS = 0;
+    private static final int MSG_UNLOAD_EFFECTS = 1;
+    private static final int MSG_PLAY_EFFECT = 2;
+    private static final int MSG_LOAD_EFFECTS_TIMEOUT = 3;
+
+    interface OnEffectsLoadCompleteHandler {
+        void run(boolean success);
+    }
+
+    private final AudioEventLogger mSfxLogger = new AudioEventLogger(
+            AudioManager.NUM_SOUND_EFFECTS + 10, "Sound Effects Loading");
+
+    private final Context mContext;
+    // default attenuation applied to sound played with playSoundEffect()
+    private final int mSfxAttenuationDb;
+
+    // thread for doing all work
+    private SfxWorker mSfxWorker;
+    // thread's message handler
+    private SfxHandler mSfxHandler;
+
+    private static final class Resource {
+        final String mFileName;
+        int mSampleId;
+        boolean mLoaded;  // for effects in SoundPool
+        Resource(String fileName) {
+            mFileName = fileName;
+            mSampleId = EFFECT_NOT_IN_SOUND_POOL;
+        }
+    }
+    // All the fields below are accessed by the worker thread exclusively
+    private final List<Resource> mResources = new ArrayList<Resource>();
+    private final int[] mEffects = new int[AudioManager.NUM_SOUND_EFFECTS]; // indexes in mResources
+    private SoundPool mSoundPool;
+    private SoundPoolLoader mSoundPoolLoader;
+
+    SoundEffectsHelper(Context context) {
+        mContext = context;
+        mSfxAttenuationDb = mContext.getResources().getInteger(
+                com.android.internal.R.integer.config_soundEffectVolumeDb);
+        startWorker();
+    }
+
+    /*package*/ void loadSoundEffects(OnEffectsLoadCompleteHandler onComplete) {
+        sendMsg(MSG_LOAD_EFFECTS, 0, 0, onComplete, 0);
+    }
+
+    /**
+     *  Unloads samples from the sound pool.
+     *  This method can be called to free some memory when
+     *  sound effects are disabled.
+     */
+    /*package*/ void unloadSoundEffects() {
+        sendMsg(MSG_UNLOAD_EFFECTS, 0, 0, null, 0);
+    }
+
+    /*package*/ void playSoundEffect(int effect, int volume) {
+        sendMsg(MSG_PLAY_EFFECT, effect, volume, null, 0);
+    }
+
+    /*package*/ void dump(PrintWriter pw, String prefix) {
+        if (mSfxHandler != null) {
+            pw.println(prefix + "Message handler (watch for unhandled messages):");
+            mSfxHandler.dump(new PrintWriterPrinter(pw), "  ");
+        } else {
+            pw.println(prefix + "Message handler is null");
+        }
+        pw.println(prefix + "Default attenuation (dB): " + mSfxAttenuationDb);
+        mSfxLogger.dump(pw);
+    }
+
+    private void startWorker() {
+        mSfxWorker = new SfxWorker();
+        mSfxWorker.start();
+        synchronized (this) {
+            while (mSfxHandler == null) {
+                try {
+                    wait();
+                } catch (InterruptedException e) {
+                    Log.w(TAG, "Interrupted while waiting " + mSfxWorker.getName() + " to start");
+                }
+            }
+        }
+    }
+
+    private void sendMsg(int msg, int arg1, int arg2, Object obj, int delayMs) {
+        mSfxHandler.sendMessageDelayed(mSfxHandler.obtainMessage(msg, arg1, arg2, obj), delayMs);
+    }
+
+    private void logEvent(String msg) {
+        mSfxLogger.log(new AudioEventLogger.StringEvent(msg));
+    }
+
+    // All the methods below run on the worker thread
+    private void onLoadSoundEffects(OnEffectsLoadCompleteHandler onComplete) {
+        if (mSoundPoolLoader != null) {
+            // Loading is ongoing.
+            mSoundPoolLoader.addHandler(onComplete);
+            return;
+        }
+        if (mSoundPool != null) {
+            if (onComplete != null) {
+                onComplete.run(true /*success*/);
+            }
+            return;
+        }
+
+        logEvent("effects loading started");
+        mSoundPool = new SoundPool.Builder()
+                .setMaxStreams(NUM_SOUNDPOOL_CHANNELS)
+                .setAudioAttributes(new AudioAttributes.Builder()
+                        .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
+                        .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
+                        .build())
+                .build();
+        loadTouchSoundAssets();
+
+        mSoundPoolLoader = new SoundPoolLoader();
+        mSoundPoolLoader.addHandler(new OnEffectsLoadCompleteHandler() {
+            @Override
+            public void run(boolean success) {
+                mSoundPoolLoader = null;
+                if (!success) {
+                    Log.w(TAG, "onLoadSoundEffects(), Error while loading samples");
+                    onUnloadSoundEffects();
+                }
+            }
+        });
+        mSoundPoolLoader.addHandler(onComplete);
+
+        int resourcesToLoad = 0;
+        for (Resource res : mResources) {
+            String filePath = getResourceFilePath(res);
+            int sampleId = mSoundPool.load(filePath, 0);
+            if (sampleId > 0) {
+                res.mSampleId = sampleId;
+                res.mLoaded = false;
+                resourcesToLoad++;
+            } else {
+                logEvent("effect " + filePath + " rejected by SoundPool");
+                Log.w(TAG, "SoundPool could not load file: " + filePath);
+            }
+        }
+
+        if (resourcesToLoad > 0) {
+            sendMsg(MSG_LOAD_EFFECTS_TIMEOUT, 0, 0, null, SOUND_EFFECTS_LOAD_TIMEOUT_MS);
+        } else {
+            logEvent("effects loading completed, no effects to load");
+            mSoundPoolLoader.onComplete(true /*success*/);
+        }
+    }
+
+    void onUnloadSoundEffects() {
+        if (mSoundPool == null) {
+            return;
+        }
+        if (mSoundPoolLoader != null) {
+            mSoundPoolLoader.addHandler(new OnEffectsLoadCompleteHandler() {
+                @Override
+                public void run(boolean success) {
+                    onUnloadSoundEffects();
+                }
+            });
+        }
+
+        logEvent("effects unloading started");
+        for (Resource res : mResources) {
+            if (res.mSampleId != EFFECT_NOT_IN_SOUND_POOL) {
+                mSoundPool.unload(res.mSampleId);
+            }
+        }
+        mSoundPool.release();
+        mSoundPool = null;
+        logEvent("effects unloading completed");
+    }
+
+    void onPlaySoundEffect(int effect, int volume) {
+        float volFloat;
+        // use default if volume is not specified by caller
+        if (volume < 0) {
+            volFloat = (float) Math.pow(10, (float) mSfxAttenuationDb / 20);
+        } else {
+            volFloat = volume / 1000.0f;
+        }
+
+        Resource res = mResources.get(mEffects[effect]);
+        if (res.mSampleId != EFFECT_NOT_IN_SOUND_POOL && res.mLoaded) {
+            mSoundPool.play(res.mSampleId, volFloat, volFloat, 0, 0, 1.0f);
+        } else {
+            MediaPlayer mediaPlayer = new MediaPlayer();
+            try {
+                String filePath = getResourceFilePath(res);
+                mediaPlayer.setDataSource(filePath);
+                mediaPlayer.setAudioStreamType(AudioSystem.STREAM_SYSTEM);
+                mediaPlayer.prepare();
+                mediaPlayer.setVolume(volFloat);
+                mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
+                    public void onCompletion(MediaPlayer mp) {
+                        cleanupPlayer(mp);
+                    }
+                });
+                mediaPlayer.setOnErrorListener(new OnErrorListener() {
+                    public boolean onError(MediaPlayer mp, int what, int extra) {
+                        cleanupPlayer(mp);
+                        return true;
+                    }
+                });
+                mediaPlayer.start();
+            } catch (IOException ex) {
+                Log.w(TAG, "MediaPlayer IOException: " + ex);
+            } catch (IllegalArgumentException ex) {
+                Log.w(TAG, "MediaPlayer IllegalArgumentException: " + ex);
+            } catch (IllegalStateException ex) {
+                Log.w(TAG, "MediaPlayer IllegalStateException: " + ex);
+            }
+        }
+    }
+
+    private static void cleanupPlayer(MediaPlayer mp) {
+        if (mp != null) {
+            try {
+                mp.stop();
+                mp.release();
+            } catch (IllegalStateException ex) {
+                Log.w(TAG, "MediaPlayer IllegalStateException: " + ex);
+            }
+        }
+    }
+
+    private static final String TAG_AUDIO_ASSETS = "audio_assets";
+    private static final String ATTR_VERSION = "version";
+    private static final String TAG_GROUP = "group";
+    private static final String ATTR_GROUP_NAME = "name";
+    private static final String TAG_ASSET = "asset";
+    private static final String ATTR_ASSET_ID = "id";
+    private static final String ATTR_ASSET_FILE = "file";
+
+    private static final String ASSET_FILE_VERSION = "1.0";
+    private static final String GROUP_TOUCH_SOUNDS = "touch_sounds";
+
+    private static final int SOUND_EFFECTS_LOAD_TIMEOUT_MS = 15000;
+
+    private String getResourceFilePath(Resource res) {
+        String filePath = Environment.getProductDirectory() + SOUND_EFFECTS_PATH + res.mFileName;
+        if (!new File(filePath).isFile()) {
+            filePath = Environment.getRootDirectory() + SOUND_EFFECTS_PATH + res.mFileName;
+        }
+        return filePath;
+    }
+
+    private void loadTouchSoundAssetDefaults() {
+        int defaultResourceIdx = mResources.size();
+        mResources.add(new Resource("Effect_Tick.ogg"));
+        for (int i = 0; i < mEffects.length; i++) {
+            mEffects[i] = defaultResourceIdx;
+        }
+    }
+
+    private void loadTouchSoundAssets() {
+        XmlResourceParser parser = null;
+
+        // only load assets once.
+        if (!mResources.isEmpty()) {
+            return;
+        }
+
+        loadTouchSoundAssetDefaults();
+
+        try {
+            parser = mContext.getResources().getXml(com.android.internal.R.xml.audio_assets);
+
+            XmlUtils.beginDocument(parser, TAG_AUDIO_ASSETS);
+            String version = parser.getAttributeValue(null, ATTR_VERSION);
+            boolean inTouchSoundsGroup = false;
+
+            if (ASSET_FILE_VERSION.equals(version)) {
+                while (true) {
+                    XmlUtils.nextElement(parser);
+                    String element = parser.getName();
+                    if (element == null) {
+                        break;
+                    }
+                    if (element.equals(TAG_GROUP)) {
+                        String name = parser.getAttributeValue(null, ATTR_GROUP_NAME);
+                        if (GROUP_TOUCH_SOUNDS.equals(name)) {
+                            inTouchSoundsGroup = true;
+                            break;
+                        }
+                    }
+                }
+                while (inTouchSoundsGroup) {
+                    XmlUtils.nextElement(parser);
+                    String element = parser.getName();
+                    if (element == null) {
+                        break;
+                    }
+                    if (element.equals(TAG_ASSET)) {
+                        String id = parser.getAttributeValue(null, ATTR_ASSET_ID);
+                        String file = parser.getAttributeValue(null, ATTR_ASSET_FILE);
+                        int fx;
+
+                        try {
+                            Field field = AudioManager.class.getField(id);
+                            fx = field.getInt(null);
+                        } catch (Exception e) {
+                            Log.w(TAG, "Invalid touch sound ID: " + id);
+                            continue;
+                        }
+
+                        mEffects[fx] = findOrAddResourceByFileName(file);
+                    } else {
+                        break;
+                    }
+                }
+            }
+        } catch (Resources.NotFoundException e) {
+            Log.w(TAG, "audio assets file not found", e);
+        } catch (XmlPullParserException e) {
+            Log.w(TAG, "XML parser exception reading touch sound assets", e);
+        } catch (IOException e) {
+            Log.w(TAG, "I/O exception reading touch sound assets", e);
+        } finally {
+            if (parser != null) {
+                parser.close();
+            }
+        }
+    }
+
+    private int findOrAddResourceByFileName(String fileName) {
+        for (int i = 0; i < mResources.size(); i++) {
+            if (mResources.get(i).mFileName.equals(fileName)) {
+                return i;
+            }
+        }
+        int result = mResources.size();
+        mResources.add(new Resource(fileName));
+        return result;
+    }
+
+    private Resource findResourceBySampleId(int sampleId) {
+        for (Resource res : mResources) {
+            if (res.mSampleId == sampleId) {
+                return res;
+            }
+        }
+        return null;
+    }
+
+    private class SfxWorker extends Thread {
+        SfxWorker() {
+            super("AS.SfxWorker");
+        }
+
+        @Override
+        public void run() {
+            Looper.prepare();
+            synchronized (SoundEffectsHelper.this) {
+                mSfxHandler = new SfxHandler();
+                SoundEffectsHelper.this.notify();
+            }
+            Looper.loop();
+        }
+    }
+
+    private class SfxHandler extends Handler {
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_LOAD_EFFECTS:
+                    onLoadSoundEffects((OnEffectsLoadCompleteHandler) msg.obj);
+                    break;
+                case MSG_UNLOAD_EFFECTS:
+                    onUnloadSoundEffects();
+                    break;
+                case MSG_PLAY_EFFECT:
+                    onLoadSoundEffects(new OnEffectsLoadCompleteHandler() {
+                        @Override
+                        public void run(boolean success) {
+                            if (success) {
+                                onPlaySoundEffect(msg.arg1 /*effect*/, msg.arg2 /*volume*/);
+                            }
+                        }
+                    });
+                    break;
+                case MSG_LOAD_EFFECTS_TIMEOUT:
+                    if (mSoundPoolLoader != null) {
+                        mSoundPoolLoader.onTimeout();
+                    }
+                    break;
+            }
+        }
+    }
+
+    private class SoundPoolLoader implements
+            android.media.SoundPool.OnLoadCompleteListener {
+
+        private List<OnEffectsLoadCompleteHandler> mLoadCompleteHandlers =
+                new ArrayList<OnEffectsLoadCompleteHandler>();
+
+        SoundPoolLoader() {
+            // SoundPool use the current Looper when creating its message handler.
+            // Since SoundPoolLoader is created on the SfxWorker thread, SoundPool's
+            // message handler ends up running on it (it's OK to have multiple
+            // handlers on the same Looper). Thus, onLoadComplete gets executed
+            // on the worker thread.
+            mSoundPool.setOnLoadCompleteListener(this);
+        }
+
+        void addHandler(OnEffectsLoadCompleteHandler handler) {
+            if (handler != null) {
+                mLoadCompleteHandlers.add(handler);
+            }
+        }
+
+        @Override
+        public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
+            if (status == 0) {
+                int remainingToLoad = 0;
+                for (Resource res : mResources) {
+                    if (res.mSampleId == sampleId && !res.mLoaded) {
+                        logEvent("effect " + res.mFileName + " loaded");
+                        res.mLoaded = true;
+                    }
+                    if (res.mSampleId != EFFECT_NOT_IN_SOUND_POOL && !res.mLoaded) {
+                        remainingToLoad++;
+                    }
+                }
+                if (remainingToLoad == 0) {
+                    onComplete(true);
+                }
+            } else {
+                Resource res = findResourceBySampleId(sampleId);
+                String filePath;
+                if (res != null) {
+                    filePath = getResourceFilePath(res);
+                } else {
+                    filePath = "with unknown sample ID " + sampleId;
+                }
+                logEvent("effect " + filePath + " loading failed, status " + status);
+                Log.w(TAG, "onLoadSoundEffects(), Error " + status + " while loading sample "
+                        + filePath);
+                onComplete(false);
+            }
+        }
+
+        void onTimeout() {
+            onComplete(false);
+        }
+
+        void onComplete(boolean success) {
+            mSoundPool.setOnLoadCompleteListener(null);
+            for (OnEffectsLoadCompleteHandler handler : mLoadCompleteHandlers) {
+                handler.run(success);
+            }
+            logEvent("effects loading " + (success ? "completed" : "failed"));
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/biometrics/BiometricServiceBase.java b/services/core/java/com/android/server/biometrics/BiometricServiceBase.java
index 0c4f0bd..f08423e 100644
--- a/services/core/java/com/android/server/biometrics/BiometricServiceBase.java
+++ b/services/core/java/com/android/server/biometrics/BiometricServiceBase.java
@@ -497,9 +497,9 @@
         }
     }
 
-    private final class BiometricTaskStackListener extends TaskStackListener {
+    private final Runnable mOnTaskStackChangedRunnable = new Runnable() {
         @Override
-        public void onTaskStackChanged() {
+        public void run() {
             try {
                 if (!(mCurrentClient instanceof AuthenticationClient)) {
                     return;
@@ -514,8 +514,8 @@
                     final String topPackage = runningTasks.get(0).topActivity.getPackageName();
                     if (!topPackage.contentEquals(currentClient)
                             && !mCurrentClient.isAlreadyDone()) {
-                        Slog.e(getTag(), "Stopping background authentication, top: " + topPackage
-                                + " currentClient: " + currentClient);
+                        Slog.e(getTag(), "Stopping background authentication, top: "
+                                + topPackage + " currentClient: " + currentClient);
                         mCurrentClient.stop(false /* initiatedByClient */);
                     }
                 }
@@ -523,6 +523,13 @@
                 Slog.e(getTag(), "Unable to get running tasks", e);
             }
         }
+    };
+
+    private final class BiometricTaskStackListener extends TaskStackListener {
+        @Override
+        public void onTaskStackChanged() {
+            mHandler.post(mOnTaskStackChangedRunnable);
+        }
     }
 
     private final class ResetClientStateRunnable implements Runnable {
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 99341d1..4f33ebb0 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -303,6 +303,8 @@
     private final Spline mMinimumBrightnessSpline;
     private final ColorSpace mWideColorSpace;
 
+    private SensorManager mSensorManager;
+
     public DisplayManagerService(Context context) {
         this(context, new Injector());
     }
@@ -430,7 +432,7 @@
         }
 
         mDisplayModeDirector.setListener(new AllowedDisplayModeObserver());
-        mDisplayModeDirector.start();
+        mDisplayModeDirector.start(mSensorManager);
 
         mHandler.sendEmptyMessage(MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS);
     }
@@ -2358,6 +2360,7 @@
                 };
                 mDisplayPowerController = new DisplayPowerController(
                         mContext, callbacks, handler, sensorManager, blanker);
+                mSensorManager = sensorManager;
             }
 
             mHandler.sendEmptyMessage(MSG_LOAD_BRIGHTNESS_CONFIGURATION);
diff --git a/services/core/java/com/android/server/display/DisplayModeDirector.java b/services/core/java/com/android/server/display/DisplayModeDirector.java
index 14bd2d8..78a48da 100644
--- a/services/core/java/com/android/server/display/DisplayModeDirector.java
+++ b/services/core/java/com/android/server/display/DisplayModeDirector.java
@@ -18,26 +18,41 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
 import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.res.Resources;
 import android.database.ContentObserver;
 import android.hardware.display.DisplayManager;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+
 import android.net.Uri;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
 import android.os.UserHandle;
+import android.os.PowerManager;
+import android.os.SystemClock;
 import android.provider.Settings;
+import android.text.TextUtils;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.view.Display;
 import android.view.DisplayInfo;
 
 import com.android.internal.R;
+import com.android.server.display.whitebalance.DisplayWhiteBalanceFactory;
+import com.android.server.display.whitebalance.AmbientFilter;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.List;
 import java.util.Objects;
 
 /**
@@ -74,7 +89,7 @@
     private final AppRequestObserver mAppRequestObserver;
     private final SettingsObserver mSettingsObserver;
     private final DisplayObserver mDisplayObserver;
-
+    private final BrightnessObserver mBrightnessObserver;
 
     private Listener mListener;
 
@@ -87,6 +102,8 @@
         mAppRequestObserver = new AppRequestObserver();
         mSettingsObserver = new SettingsObserver(context, handler);
         mDisplayObserver = new DisplayObserver(context, handler);
+        mBrightnessObserver = new BrightnessObserver(context, handler);
+
     }
 
     /**
@@ -96,15 +113,17 @@
      * This has to be deferred because the object may be constructed before the rest of the system
      * is ready.
      */
-    public void start() {
+    public void start(SensorManager sensorManager) {
         mSettingsObserver.observe();
         mDisplayObserver.observe();
         mSettingsObserver.observe();
+        mBrightnessObserver.observe(sensorManager);
         synchronized (mLock) {
             // We may have a listener already registered before the call to start, so go ahead and
             // notify them to pick up our newly initialized state.
             notifyAllowedModesChangedLocked();
         }
+
     }
 
     /**
@@ -315,6 +334,7 @@
             }
             mSettingsObserver.dumpLocked(pw);
             mAppRequestObserver.dumpLocked(pw);
+            mBrightnessObserver.dumpLocked(pw);
         }
     }
 
@@ -486,20 +506,15 @@
                 Settings.System.getUriFor(Settings.System.PEAK_REFRESH_RATE);
         private final Uri mLowPowerModeSetting =
                 Settings.Global.getUriFor(Settings.Global.LOW_POWER_MODE);
-        private final Uri mBrightnessSetting =
-                Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS);
 
         private final Context mContext;
         private final float mDefaultPeakRefreshRate;
-        private final int mBrightnessThreshold;
 
         SettingsObserver(@NonNull Context context, @NonNull Handler handler) {
             super(handler);
             mContext = context;
             mDefaultPeakRefreshRate = (float) context.getResources().getInteger(
                     R.integer.config_defaultPeakRefreshRate);
-            mBrightnessThreshold = context.getResources().getInteger(
-                    R.integer.config_brightnessThresholdOfPeakRefreshRate);
         }
 
         public void observe() {
@@ -508,14 +523,9 @@
                     UserHandle.USER_SYSTEM);
             cr.registerContentObserver(mLowPowerModeSetting, false /*notifyDescendants*/, this,
                     UserHandle.USER_SYSTEM);
-            if (mBrightnessThreshold >= 0) {
-                cr.registerContentObserver(mBrightnessSetting, false /*notifyDescendants*/, this,
-                    UserHandle.USER_SYSTEM);
-            }
             synchronized (mLock) {
                 updateRefreshRateSettingLocked();
                 updateLowPowerModeSettingLocked();
-                updateBrightnessSettingLocked();
             }
         }
 
@@ -526,8 +536,6 @@
                     updateRefreshRateSettingLocked();
                 } else if (mLowPowerModeSetting.equals(uri)) {
                     updateLowPowerModeSettingLocked();
-                } else if (mBrightnessThreshold >=0 && mBrightnessSetting.equals(uri)) {
-                    updateBrightnessSettingLocked();
                 }
             }
         }
@@ -542,6 +550,7 @@
                 vote = null;
             }
             updateVoteLocked(Vote.PRIORITY_LOW_POWER_MODE, vote);
+            mBrightnessObserver.onLowPowerModeEnabled(inLowPowerMode);
         }
 
         private void updateRefreshRateSettingLocked() {
@@ -549,23 +558,7 @@
                     Settings.System.PEAK_REFRESH_RATE, mDefaultPeakRefreshRate);
             Vote vote = Vote.forRefreshRates(0f, peakRefreshRate);
             updateVoteLocked(Vote.PRIORITY_USER_SETTING_REFRESH_RATE, vote);
-        }
-
-        private void updateBrightnessSettingLocked() {
-            int brightness = Settings.System.getInt(mContext.getContentResolver(),
-                    Settings.System.SCREEN_BRIGHTNESS, -1);
-
-            if (brightness < 0) {
-                return;
-            }
-
-            final Vote vote;
-            if (brightness <= mBrightnessThreshold) {
-                vote = Vote.forRefreshRates(0f, 60f);
-            } else {
-                vote = null;
-            }
-            updateVoteLocked(Vote.PRIORITY_LOW_BRIGHTNESS, vote);
+            mBrightnessObserver.onPeakRefreshRateEnabled(peakRefreshRate > 60f);
         }
 
         public void dumpLocked(PrintWriter pw) {
@@ -715,4 +708,240 @@
             }
         }
     }
+
+    /**
+     * This class manages brightness threshold for switching between 60 hz and higher refresh rate.
+     * See more information at the definition of
+     * {@link R.array#config_brightnessThresholdsOfPeakRefreshRate} and
+     * {@link R.array#config_ambientThresholdsOfPeakRefreshRate}.
+     */
+    private class BrightnessObserver extends ContentObserver {
+        private final Uri mDisplayBrightnessSetting =
+                Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS);
+
+        private final static int LIGHT_SENSOR_RATE_MS = 250;
+        private final int[] mDisplayBrightnessThresholds;
+        private final int[] mAmbientBrightnessThresholds;
+        // valid threshold if any item from the array >= 0
+        private boolean mShouldObserveDisplayChange;
+        private boolean mShouldObserveAmbientChange;
+
+        private SensorManager mSensorManager;
+        private Sensor mLightSensor;
+        // Take it as low brightness before valid sensor data comes
+        private float mAmbientLux = -1.0f;
+        private AmbientFilter mAmbientFilter;
+
+        private final Context mContext;
+        private ScreenStateReceiver mScreenStateReceiver;
+
+        // Enable light sensor only when screen is on, peak refresh rate enabled and low power mode
+        // off. After initialization, these states will be updated from the same handler thread.
+        private boolean mScreenOn = false;
+        private boolean mPeakRefreshRateEnabled = false;
+        private boolean mLowPowerModeEnabled = false;
+
+        BrightnessObserver(Context context, Handler handler) {
+            super(handler);
+            mContext = context;
+            mDisplayBrightnessThresholds = context.getResources().getIntArray(
+                    R.array.config_brightnessThresholdsOfPeakRefreshRate);
+            mAmbientBrightnessThresholds = context.getResources().getIntArray(
+                    R.array.config_ambientThresholdsOfPeakRefreshRate);
+            if (mDisplayBrightnessThresholds.length != mAmbientBrightnessThresholds.length) {
+                throw new RuntimeException("display brightness threshold array and ambient "
+                        + "brightness threshold array have different length");
+            }
+
+            mShouldObserveDisplayChange = checkShouldObserve(mDisplayBrightnessThresholds);
+            mShouldObserveAmbientChange = checkShouldObserve(mAmbientBrightnessThresholds);
+        }
+
+        public void observe(SensorManager sensorManager) {
+            if (mShouldObserveDisplayChange) {
+                final ContentResolver cr = mContext.getContentResolver();
+                cr.registerContentObserver(mDisplayBrightnessSetting,
+                        false /*notifyDescendants*/, this, UserHandle.USER_SYSTEM);
+            }
+
+            if (mShouldObserveAmbientChange) {
+                Resources resources = mContext.getResources();
+                String lightSensorType = resources.getString(
+                        com.android.internal.R.string.config_displayLightSensorType);
+
+                Sensor lightSensor = null;
+                if (!TextUtils.isEmpty(lightSensorType)) {
+                    List<Sensor> sensors = sensorManager.getSensorList(Sensor.TYPE_ALL);
+                    for (int i = 0; i < sensors.size(); i++) {
+                        Sensor sensor = sensors.get(i);
+                        if (lightSensorType.equals(sensor.getStringType())) {
+                            lightSensor = sensor;
+                            break;
+                        }
+                    }
+                }
+
+                if (lightSensor == null) {
+                    lightSensor = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
+                }
+
+                if (lightSensor != null) {
+                    final Resources res = mContext.getResources();
+
+                    mAmbientFilter = DisplayWhiteBalanceFactory.createBrightnessFilter(res);
+                    mSensorManager = sensorManager;
+                    mLightSensor = lightSensor;
+
+                    // Intent.ACTION_SCREEN_ON is not sticky. Check current screen status.
+                    if (mContext.getSystemService(PowerManager.class).isInteractive()) {
+                        onScreenOn(true);
+                    }
+                    mScreenStateReceiver = new ScreenStateReceiver(mContext);
+                }
+            }
+
+            if (mShouldObserveDisplayChange || mShouldObserveAmbientChange) {
+                synchronized (mLock) {
+                    onBrightnessChangedLocked();
+                }
+            }
+        }
+
+        public void onPeakRefreshRateEnabled(boolean b) {
+            if (mShouldObserveAmbientChange && mPeakRefreshRateEnabled != b) {
+                mPeakRefreshRateEnabled = b;
+                updateSensorStatus();
+            }
+        }
+
+        public void onLowPowerModeEnabled(boolean b) {
+            if (mShouldObserveAmbientChange && mLowPowerModeEnabled != b) {
+                mLowPowerModeEnabled = b;
+                updateSensorStatus();
+            }
+        }
+
+        public void dumpLocked(PrintWriter pw) {
+            pw.println("  BrightnessObserver");
+
+            for (int d: mDisplayBrightnessThresholds) {
+                pw.println("    mDisplayBrightnessThreshold: " + d);
+            }
+
+            for (int d: mAmbientBrightnessThresholds) {
+                pw.println("    mAmbientBrightnessThreshold: " + d);
+            }
+        }
+
+        @Override
+        public void onChange(boolean selfChange, Uri uri, int userId) {
+            synchronized (mLock) {
+                onBrightnessChangedLocked();
+            }
+        }
+
+        /**
+         * Checks to see if at least one value is positive, in which case it is necessary to listen
+         * to value changes.
+         */
+        private boolean checkShouldObserve(int[] a) {
+            for (int d: a) {
+                if (d >= 0) {
+                    return true;
+                }
+            }
+
+            return false;
+        }
+
+        private void onBrightnessChangedLocked() {
+            int brightness = Settings.System.getInt(mContext.getContentResolver(),
+                    Settings.System.SCREEN_BRIGHTNESS, -1);
+
+            Vote vote = null;
+            for (int i = 0; i < mDisplayBrightnessThresholds.length; i++) {
+                int disp = mDisplayBrightnessThresholds[i];
+                int ambi = mAmbientBrightnessThresholds[i];
+
+                if (disp >= 0 && ambi >= 0) {
+                    if (brightness <= disp && mAmbientLux <= ambi) {
+                        vote = Vote.forRefreshRates(0f, 60f);
+                    }
+                } else if (disp >= 0) {
+                    if (brightness <= disp) {
+                        vote = Vote.forRefreshRates(0f, 60f);
+                    }
+                } else if (ambi >= 0) {
+                    if (mAmbientLux <= ambi) {
+                        vote = Vote.forRefreshRates(0f, 60f);
+                    }
+                }
+
+                if (vote != null) {
+                    break;
+                }
+            }
+
+            if (DEBUG) {
+                Slog.d(TAG, "Display brightness " + brightness + ", ambient lux " +  mAmbientLux +
+                        (vote != null ? " 60hz only" : " no refresh rate limit"));
+            }
+            updateVoteLocked(Vote.PRIORITY_LOW_BRIGHTNESS, vote);
+        }
+
+        private void onScreenOn(boolean on) {
+            // Not check mShouldObserveAmbientChange because Screen status receiver is registered
+            // only when it is true.
+            if (mScreenOn != on) {
+                mScreenOn = on;
+                updateSensorStatus();
+            }
+        }
+
+        private void updateSensorStatus() {
+            if (mSensorManager == null || mLightSensorListener == null) {
+                return;
+            }
+
+            if (mScreenOn && !mLowPowerModeEnabled && mPeakRefreshRateEnabled) {
+                mSensorManager.registerListener(mLightSensorListener,
+                        mLightSensor, LIGHT_SENSOR_RATE_MS * 1000, mHandler);
+            } else {
+                mSensorManager.unregisterListener(mLightSensorListener);
+            }
+        }
+
+        private final SensorEventListener mLightSensorListener = new SensorEventListener() {
+            @Override
+            public void onSensorChanged(SensorEvent event) {
+                long now = SystemClock.uptimeMillis();
+                mAmbientFilter.addValue(now, event.values[0]);
+                mAmbientLux = mAmbientFilter.getEstimate(now);
+
+                synchronized (mLock) {
+                    onBrightnessChangedLocked();
+                }
+            }
+
+            @Override
+            public void onAccuracyChanged(Sensor sensor, int accuracy) {
+                // Not used.
+            }
+        };
+
+        private final class ScreenStateReceiver extends BroadcastReceiver {
+            public ScreenStateReceiver(Context context) {
+                IntentFilter filter = new IntentFilter();
+                filter.addAction(Intent.ACTION_SCREEN_OFF);
+                filter.addAction(Intent.ACTION_SCREEN_ON);
+                filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
+                context.registerReceiver(this, filter, null, mHandler);
+            }
+
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                onScreenOn(Intent.ACTION_SCREEN_ON.equals(intent.getAction()));
+            }
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/display/whitebalance/AmbientFilter.java b/services/core/java/com/android/server/display/whitebalance/AmbientFilter.java
index 123cd73..3580897 100644
--- a/services/core/java/com/android/server/display/whitebalance/AmbientFilter.java
+++ b/services/core/java/com/android/server/display/whitebalance/AmbientFilter.java
@@ -36,7 +36,7 @@
  * - {@link WeightedMovingAverageAmbientFilter}
  *   A weighted average prioritising recent changes.
  */
-abstract class AmbientFilter {
+abstract public class AmbientFilter {
 
     protected static final boolean DEBUG = false; // Enable for verbose logs.
 
@@ -156,8 +156,7 @@
     /**
      * A weighted average prioritising recent changes.
      */
-    @VisibleForTesting
-    public static class WeightedMovingAverageAmbientFilter extends AmbientFilter {
+    static class WeightedMovingAverageAmbientFilter extends AmbientFilter {
 
         // How long the latest ambient value change is predicted to last.
         private static final int PREDICTION_TIME = 100; // Milliseconds
diff --git a/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceFactory.java b/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceFactory.java
index 4df7d6b..bf0a1d1 100644
--- a/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceFactory.java
+++ b/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceFactory.java
@@ -115,8 +115,7 @@
      * Creates a BrightnessFilter which functions as a weighted moving average buffer for recent
      * brightness values.
      */
-    @VisibleForTesting
-    static AmbientFilter createBrightnessFilter(Resources resources) {
+    public static AmbientFilter createBrightnessFilter(Resources resources) {
         final int horizon = resources.getInteger(
                 com.android.internal.R.integer.config_displayWhiteBalanceBrightnessFilterHorizon);
         final float intercept = getFloat(resources,
@@ -129,7 +128,6 @@
                 + "expected config_displayWhiteBalanceBrightnessFilterIntercept");
     }
 
-
     /**
      * Creates an ambient color sensor instance to redirect sensor data to callbacks.
      */
diff --git a/services/core/java/com/android/server/infra/AbstractPerUserSystemService.java b/services/core/java/com/android/server/infra/AbstractPerUserSystemService.java
index c52921e..16cf7ee 100644
--- a/services/core/java/com/android/server/infra/AbstractPerUserSystemService.java
+++ b/services/core/java/com/android/server/infra/AbstractPerUserSystemService.java
@@ -75,6 +75,14 @@
         mMaster = master;
         mLock = lock;
         mUserId = userId;
+        updateIsSetupComplete(userId);
+    }
+
+    /** Updates whether setup is complete for current user */
+    private void updateIsSetupComplete(@UserIdInt int userId) {
+        final String setupComplete = Settings.Secure.getStringForUser(
+                getContext().getContentResolver(), Settings.Secure.USER_SETUP_COMPLETE, userId);
+        mSetupComplete = "1".equals(setupComplete);
     }
 
     /**
@@ -143,9 +151,7 @@
                     + ", disabled=" + disabled + ", mDisabled=" + mDisabled);
         }
 
-        final String setupComplete = Settings.Secure.getStringForUser(
-                getContext().getContentResolver(), Settings.Secure.USER_SETUP_COMPLETE, mUserId);
-        mSetupComplete = "1".equals(setupComplete);
+        updateIsSetupComplete(mUserId);
         mDisabled = disabled;
 
         updateServiceInfoLocked();
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 49b42df..09e9375 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -17,7 +17,6 @@
 
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Display.INVALID_DISPLAY;
-import static android.view.inputmethod.InputMethodSystemProperty.PER_PROFILE_IME_ENABLED;
 
 import static java.lang.annotation.RetentionPolicy.SOURCE;
 
@@ -1036,9 +1035,7 @@
                 // sender userId can be a real user ID or USER_ALL.
                 final int senderUserId = pendingResult.getSendingUserId();
                 if (senderUserId != UserHandle.USER_ALL) {
-                    final int resolvedUserId = PER_PROFILE_IME_ENABLED
-                            ? senderUserId : mUserManagerInternal.getProfileParentId(senderUserId);
-                    if (resolvedUserId != mSettings.getCurrentUserId()) {
+                    if (senderUserId != mSettings.getCurrentUserId()) {
                         // A background user is trying to hide the dialog. Ignore.
                         return;
                     }
@@ -1662,9 +1659,6 @@
         if (userId == mSettings.getCurrentUserId()) {
             return true;
         }
-        if (!PER_PROFILE_IME_ENABLED && mSettings.isCurrentProfile(userId)) {
-            return true;
-        }
 
         // Caveat: A process which has INTERACT_ACROSS_USERS_FULL gets results for the
         // foreground user, not for the user of that process. Accordingly InputMethodManagerService
@@ -3005,7 +2999,7 @@
             return InputBindResult.INVALID_USER;
         }
 
-        if (PER_PROFILE_IME_ENABLED && userId != mSettings.getCurrentUserId()) {
+        if (userId != mSettings.getCurrentUserId()) {
             switchUserLocked(userId);
         }
         // Master feature flag that overrides other conditions and forces IME preRendering.
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodUtils.java b/services/core/java/com/android/server/inputmethod/InputMethodUtils.java
index b5e19ae..77e2fbd 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodUtils.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodUtils.java
@@ -35,13 +35,11 @@
 import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
-import android.util.IntArray;
 import android.util.Pair;
 import android.util.Printer;
 import android.util.Slog;
 import android.view.inputmethod.InputMethodInfo;
 import android.view.inputmethod.InputMethodSubtype;
-import android.view.inputmethod.InputMethodSystemProperty;
 import android.view.textservice.SpellCheckerInfo;
 
 import com.android.internal.annotations.GuardedBy;
@@ -1303,9 +1301,6 @@
      * Converts a user ID, which can be a pseudo user ID such as {@link UserHandle#USER_ALL} to a
      * list of real user IDs.
      *
-     * <p>This method also converts profile user ID to profile parent user ID unless
-     * {@link InputMethodSystemProperty#PER_PROFILE_IME_ENABLED} is {@code true}.</p>
-     *
      * @param userIdToBeResolved A user ID. Two pseudo user ID {@link UserHandle#USER_CURRENT} and
      *                           {@link UserHandle#USER_ALL} are also supported
      * @param currentUserId A real user ID, which will be used when {@link UserHandle#USER_CURRENT}
@@ -1320,17 +1315,7 @@
                 LocalServices.getService(UserManagerInternal.class);
 
         if (userIdToBeResolved == UserHandle.USER_ALL) {
-            if (InputMethodSystemProperty.PER_PROFILE_IME_ENABLED) {
-                return userManagerInternal.getUserIds();
-            }
-            final IntArray result = new IntArray();
-            for (int userId : userManagerInternal.getUserIds()) {
-                final int parentUserId = userManagerInternal.getProfileParentId(userId);
-                if (result.indexOf(parentUserId) < 0) {
-                    result.add(parentUserId);
-                }
-            }
-            return result.toArray();
+            return userManagerInternal.getUserIds();
         }
 
         final int sourceUserId;
@@ -1353,8 +1338,6 @@
             }
             return new int[]{};
         }
-        final int resolvedUserId = InputMethodSystemProperty.PER_PROFILE_IME_ENABLED
-                ? sourceUserId : userManagerInternal.getProfileParentId(sourceUserId);
-        return new int[]{resolvedUserId};
+        return new int[]{sourceUserId};
     }
 }
diff --git a/services/core/java/com/android/server/job/controllers/TimeController.java b/services/core/java/com/android/server/job/controllers/TimeController.java
index ababad9..4c11947 100644
--- a/services/core/java/com/android/server/job/controllers/TimeController.java
+++ b/services/core/java/com/android/server/job/controllers/TimeController.java
@@ -18,20 +18,13 @@
 
 import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
 
-import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.AlarmManager;
 import android.app.AlarmManager.OnAlarmListener;
-import android.content.ContentResolver;
 import android.content.Context;
-import android.database.ContentObserver;
-import android.net.Uri;
-import android.os.Handler;
 import android.os.Process;
 import android.os.UserHandle;
 import android.os.WorkSource;
-import android.provider.Settings;
-import android.util.KeyValueListParser;
 import android.util.Log;
 import android.util.Slog;
 import android.util.TimeUtils;
@@ -39,7 +32,6 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.IndentingPrintWriter;
-import com.android.server.job.ConstantsProto;
 import com.android.server.job.JobSchedulerService;
 import com.android.server.job.StateControllerProto;
 
@@ -63,9 +55,6 @@
     /** Delay alarm tag for logging purposes */
     private final String DELAY_TAG = "*job.delay*";
 
-    private final Handler mHandler;
-    private final TcConstants mTcConstants;
-
     private long mNextJobExpiredElapsedMillis;
     private long mNextDelayExpiredElapsedMillis;
 
@@ -81,14 +70,6 @@
         mNextJobExpiredElapsedMillis = Long.MAX_VALUE;
         mNextDelayExpiredElapsedMillis = Long.MAX_VALUE;
         mChainedAttributionEnabled = mService.isChainedAttributionEnabled();
-
-        mHandler = new Handler(mContext.getMainLooper());
-        mTcConstants = new TcConstants(mHandler);
-    }
-
-    @Override
-    public void onSystemServicesReady() {
-        mTcConstants.start(mContext.getContentResolver());
     }
 
     /**
@@ -133,20 +114,16 @@
 
             job.setTrackingController(JobStatus.TRACKING_TIME);
             WorkSource ws = deriveWorkSource(job.getSourceUid(), job.getSourcePackageName());
-            final long deadlineExpiredElapsed =
-                    job.hasDeadlineConstraint() ? job.getLatestRunTimeElapsed() : Long.MAX_VALUE;
-            final long delayExpiredElapsed =
-                    job.hasTimingDelayConstraint() ? job.getEarliestRunTime() : Long.MAX_VALUE;
-            if (mTcConstants.SKIP_NOT_READY_JOBS) {
-                if (wouldBeReadyWithConstraintLocked(job, JobStatus.CONSTRAINT_TIMING_DELAY)) {
-                    maybeUpdateDelayAlarmLocked(delayExpiredElapsed, ws);
-                }
-                if (wouldBeReadyWithConstraintLocked(job, JobStatus.CONSTRAINT_DEADLINE)) {
-                    maybeUpdateDeadlineAlarmLocked(deadlineExpiredElapsed, ws);
-                }
-            } else {
-                maybeUpdateDelayAlarmLocked(delayExpiredElapsed, ws);
-                maybeUpdateDeadlineAlarmLocked(deadlineExpiredElapsed, ws);
+
+            // Only update alarms if the job would be ready with the relevant timing constraint
+            // satisfied.
+            if (job.hasTimingDelayConstraint()
+                    && wouldBeReadyWithConstraintLocked(job, JobStatus.CONSTRAINT_TIMING_DELAY)) {
+                maybeUpdateDelayAlarmLocked(job.getEarliestRunTime(), ws);
+            }
+            if (job.hasDeadlineConstraint()
+                    && wouldBeReadyWithConstraintLocked(job, JobStatus.CONSTRAINT_DEADLINE)) {
+                maybeUpdateDeadlineAlarmLocked(job.getLatestRunTimeElapsed(), ws);
             }
         }
     }
@@ -168,10 +145,6 @@
 
     @Override
     public void evaluateStateLocked(JobStatus job) {
-        if (!mTcConstants.SKIP_NOT_READY_JOBS) {
-            return;
-        }
-
         final long nowElapsedMillis = sElapsedRealtimeClock.millis();
 
         // Check deadline constraint first because if it's satisfied, we avoid a little bit of
@@ -261,9 +234,7 @@
                     }
                     it.remove();
                 } else {  // Sorted by expiry time, so take the next one and stop.
-                    if (mTcConstants.SKIP_NOT_READY_JOBS
-                            && !wouldBeReadyWithConstraintLocked(
-                            job, JobStatus.CONSTRAINT_DEADLINE)) {
+                    if (!wouldBeReadyWithConstraintLocked(job, JobStatus.CONSTRAINT_DEADLINE)) {
                         if (DEBUG) {
                             Slog.i(TAG,
                                     "Skipping " + job + " because deadline won't make it ready.");
@@ -321,9 +292,7 @@
                         ready = true;
                     }
                 } else {
-                    if (mTcConstants.SKIP_NOT_READY_JOBS
-                            && !wouldBeReadyWithConstraintLocked(
-                            job, JobStatus.CONSTRAINT_TIMING_DELAY)) {
+                    if (!wouldBeReadyWithConstraintLocked(job, JobStatus.CONSTRAINT_TIMING_DELAY)) {
                         if (DEBUG) {
                             Slog.i(TAG,
                                     "Skipping " + job + " because delay won't make it ready.");
@@ -458,81 +427,6 @@
         checkExpiredDelaysAndResetAlarm();
     }
 
-    @VisibleForTesting
-    class TcConstants extends ContentObserver {
-        private ContentResolver mResolver;
-        private final KeyValueListParser mParser = new KeyValueListParser(',');
-
-        private static final String KEY_SKIP_NOT_READY_JOBS = "skip_not_ready_jobs";
-
-        private static final boolean DEFAULT_SKIP_NOT_READY_JOBS = true;
-
-        /**
-         * Whether or not TimeController should skip setting wakeup alarms for jobs that aren't
-         * ready now.
-         */
-        public boolean SKIP_NOT_READY_JOBS = DEFAULT_SKIP_NOT_READY_JOBS;
-
-        /**
-         * Creates a content observer.
-         *
-         * @param handler The handler to run {@link #onChange} on, or null if none.
-         */
-        TcConstants(Handler handler) {
-            super(handler);
-        }
-
-        private void start(ContentResolver resolver) {
-            mResolver = resolver;
-            mResolver.registerContentObserver(Settings.Global.getUriFor(
-                    Settings.Global.JOB_SCHEDULER_TIME_CONTROLLER_CONSTANTS), false, this);
-            onChange(true, null);
-        }
-
-        @Override
-        public void onChange(boolean selfChange, Uri uri) {
-            final String constants = Settings.Global.getString(
-                    mResolver, Settings.Global.JOB_SCHEDULER_TIME_CONTROLLER_CONSTANTS);
-
-            try {
-                mParser.setString(constants);
-            } catch (Exception e) {
-                // Failed to parse the settings string, log this and move on with defaults.
-                Slog.e(TAG, "Bad jobscheduler time controller settings", e);
-            }
-
-            final boolean oldVal = SKIP_NOT_READY_JOBS;
-            SKIP_NOT_READY_JOBS = mParser.getBoolean(
-                    KEY_SKIP_NOT_READY_JOBS, DEFAULT_SKIP_NOT_READY_JOBS);
-
-            if (oldVal != SKIP_NOT_READY_JOBS) {
-                synchronized (mLock) {
-                    recheckAlarmsLocked();
-                }
-            }
-        }
-
-        private void dump(IndentingPrintWriter pw) {
-            pw.println();
-            pw.println("TimeController:");
-            pw.increaseIndent();
-            pw.printPair(KEY_SKIP_NOT_READY_JOBS, SKIP_NOT_READY_JOBS).println();
-            pw.decreaseIndent();
-        }
-
-        private void dump(ProtoOutputStream proto) {
-            final long tcToken = proto.start(ConstantsProto.TIME_CONTROLLER);
-            proto.write(ConstantsProto.TimeController.SKIP_NOT_READY_JOBS, SKIP_NOT_READY_JOBS);
-            proto.end(tcToken);
-        }
-    }
-
-    @VisibleForTesting
-    @NonNull
-    TcConstants getTcConstants() {
-        return mTcConstants;
-    }
-
     @Override
     public void dumpControllerStateLocked(IndentingPrintWriter pw,
             Predicate<JobStatus> predicate) {
@@ -607,14 +501,4 @@
         proto.end(mToken);
         proto.end(token);
     }
-
-    @Override
-    public void dumpConstants(IndentingPrintWriter pw) {
-        mTcConstants.dump(pw);
-    }
-
-    @Override
-    public void dumpConstants(ProtoOutputStream proto) {
-        mTcConstants.dump(proto);
-    }
 }
diff --git a/services/core/java/com/android/server/location/AbstractLocationProvider.java b/services/core/java/com/android/server/location/AbstractLocationProvider.java
index 8107e9f..c1a6394 100644
--- a/services/core/java/com/android/server/location/AbstractLocationProvider.java
+++ b/services/core/java/com/android/server/location/AbstractLocationProvider.java
@@ -77,20 +77,6 @@
     }
 
     /**
-     * Call this method to report a new location. May be called from any thread.
-     */
-    protected void reportLocation(Location location) {
-        mLocationProviderManager.onReportLocation(location);
-    }
-
-    /**
-     * Call this method to report a new location. May be called from any thread.
-     */
-    protected void reportLocation(List<Location> locations) {
-        mLocationProviderManager.onReportLocation(locations);
-    }
-
-    /**
      * Call this method to report a change in provider enabled/disabled status. May be called from
      * any thread.
      */
@@ -106,24 +92,50 @@
         mLocationProviderManager.onSetProperties(properties);
     }
 
-    /** Returns list of packages currently associated with this provider. */
+    /**
+     * Call this method to report a new location. May be called from any thread.
+     */
+    protected void reportLocation(Location location) {
+        mLocationProviderManager.onReportLocation(location);
+    }
+
+    /**
+     * Call this method to report a new location. May be called from any thread.
+     */
+    protected void reportLocation(List<Location> locations) {
+        mLocationProviderManager.onReportLocation(locations);
+    }
+
+    /**
+     * Invoked by the location service to return a list of packages currently associated with this
+     * provider. May be called from any thread.
+     */
     public List<String> getProviderPackages() {
         return Collections.singletonList(mContext.getPackageName());
     }
 
     /**
-     * Called when the location service delivers a new request for fulfillment to the provider.
-     * Replaces any previous requests completely.
+     * Invoked by the location service to deliver a new request for fulfillment to the provider.
+     * Replaces any previous requests completely. Will always be invoked from the location service
+     * thread with a cleared binder identity.
      */
-    public abstract void setRequest(ProviderRequest request, WorkSource source);
+    public abstract void onSetRequest(ProviderRequest request, WorkSource source);
 
     /**
-     * Called to dump debug or log information.
+     * Invoked by the location service to deliver a custom command to this provider. Will always be
+     * invoked from the location service thread with a cleared binder identity.
+     */
+    public void onSendExtraCommand(int uid, int pid, String command, Bundle extras) {}
+
+    /**
+     * Invoked by the location service to dump debug or log information. May be invoked from any
+     * thread.
      */
     public abstract void dump(FileDescriptor fd, PrintWriter pw, String[] args);
 
     /**
-     * Retrieves the current status of the provider.
+     * Invoked by the location service to retrieve the current status of the provider. May be
+     * invoked from any thread.
      *
      * @deprecated Will be removed in a future release.
      */
@@ -133,7 +145,8 @@
     }
 
     /**
-     * Retrieves the last update time of the status of the provider.
+     * Invoked by the location service to retrieve the last update time of the status of the
+     * provider. May be invoked from any thread.
      *
      * @deprecated Will be removed in a future release.
      */
@@ -141,10 +154,4 @@
     public long getStatusUpdateTime() {
         return 0;
     }
-
-    /**
-     * Sends a custom command to this provider. Called with the original binder identity of the
-     * caller.
-     */
-    public abstract void sendExtraCommand(String command, Bundle extras);
 }
diff --git a/services/core/java/com/android/server/location/GeofenceManager.java b/services/core/java/com/android/server/location/GeofenceManager.java
index fafe99c..a192206 100644
--- a/services/core/java/com/android/server/location/GeofenceManager.java
+++ b/services/core/java/com/android/server/location/GeofenceManager.java
@@ -16,11 +16,6 @@
 
 package com.android.server.location;
 
-import java.io.PrintWriter;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-
 import android.app.AppOpsManager;
 import android.app.PendingIntent;
 import android.content.ContentResolver;
@@ -44,6 +39,11 @@
 import com.android.server.LocationManagerService;
 import com.android.server.PendingIntentUtils;
 
+import java.io.PrintWriter;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
 public class GeofenceManager implements LocationListener, PendingIntent.OnFinished {
     private static final String TAG = "GeofenceManager";
     private static final boolean D = LocationManagerService.D;
@@ -79,13 +79,13 @@
     private final GeofenceHandler mHandler;
     private final LocationBlacklist mBlacklist;
 
-    private Object mLock = new Object();
+    private final Object mLock = new Object();
 
     // access to members below is synchronized on mLock
     /**
      * A list containing all registered geofences.
      */
-    private List<GeofenceState> mFences = new LinkedList<GeofenceState>();
+    private List<GeofenceState> mFences = new LinkedList<>();
 
     /**
      * This is set true when we have an active request for {@link Location} updates via
@@ -272,8 +272,8 @@
      */
     // Runs on the handler.
     private void updateFences() {
-        List<PendingIntent> enterIntents = new LinkedList<PendingIntent>();
-        List<PendingIntent> exitIntents = new LinkedList<PendingIntent>();
+        List<PendingIntent> enterIntents = new LinkedList<>();
+        List<PendingIntent> exitIntents = new LinkedList<>();
 
         synchronized (mLock) {
             mPendingUpdate = false;
@@ -446,14 +446,8 @@
     }
 
     public void dump(PrintWriter pw) {
-        pw.println("  Geofences:");
-
         for (GeofenceState state : mFences) {
-            pw.append("    ");
-            pw.append(state.mPackageName);
-            pw.append(" ");
-            pw.append(state.mFence.toString());
-            pw.append("\n");
+            pw.println(state.mPackageName + " " + state.mFence);
         }
     }
 
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 8857618..6911b7c 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -1028,7 +1028,7 @@
     }
 
     @Override
-    public void setRequest(ProviderRequest request, WorkSource source) {
+    public void onSetRequest(ProviderRequest request, WorkSource source) {
         sendMessage(SET_REQUEST, 0, new GpsRequest(request, source));
     }
 
@@ -1165,7 +1165,7 @@
     }
 
     @Override
-    public void sendExtraCommand(String command, Bundle extras) {
+    public void onSendExtraCommand(int uid, int pid, String command, Bundle extras) {
 
         long identity = Binder.clearCallingIdentity();
         try {
@@ -2171,18 +2171,18 @@
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         StringBuilder s = new StringBuilder();
-        s.append("  mStarted=").append(mStarted).append("   (changed ");
+        s.append("mStarted=").append(mStarted).append("   (changed ");
         TimeUtils.formatDuration(SystemClock.elapsedRealtime()
                 - mStartedChangedElapsedRealtime, s);
         s.append(" ago)").append('\n');
-        s.append("  mFixInterval=").append(mFixInterval).append('\n');
-        s.append("  mLowPowerMode=").append(mLowPowerMode).append('\n');
-        s.append("  mGnssMeasurementsProvider.isRegistered()=")
+        s.append("mFixInterval=").append(mFixInterval).append('\n');
+        s.append("mLowPowerMode=").append(mLowPowerMode).append('\n');
+        s.append("mGnssMeasurementsProvider.isRegistered()=")
                 .append(mGnssMeasurementsProvider.isRegistered()).append('\n');
-        s.append("  mGnssNavigationMessageProvider.isRegistered()=")
+        s.append("mGnssNavigationMessageProvider.isRegistered()=")
                 .append(mGnssNavigationMessageProvider.isRegistered()).append('\n');
-        s.append("  mDisableGpsForPowerManager=").append(mDisableGpsForPowerManager).append('\n');
-        s.append("  mTopHalCapabilities=0x").append(Integer.toHexString(mTopHalCapabilities));
+        s.append("mDisableGpsForPowerManager=").append(mDisableGpsForPowerManager).append('\n');
+        s.append("mTopHalCapabilities=0x").append(Integer.toHexString(mTopHalCapabilities));
         s.append(" ( ");
         if (hasCapability(GPS_CAPABILITY_SCHEDULING)) s.append("SCHEDULING ");
         if (hasCapability(GPS_CAPABILITY_MSB)) s.append("MSB ");
@@ -2199,12 +2199,13 @@
         }
         s.append(")\n");
         if (hasCapability(GPS_CAPABILITY_MEASUREMENT_CORRECTIONS)) {
-            s.append("  SubHal=MEASUREMENT_CORRECTIONS[");
+            s.append("SubHal=MEASUREMENT_CORRECTIONS[");
             s.append(mGnssMeasurementCorrectionsProvider.toStringCapabilities());
             s.append("]\n");
         }
         s.append(mGnssMetrics.dumpGnssMetricsAsText());
-        s.append("  native internal state: ").append(native_get_internal_state());
+        s.append("native internal state: \n");
+        s.append("  ").append(native_get_internal_state());
         s.append("\n");
         pw.append(s);
     }
diff --git a/services/core/java/com/android/server/location/LocationProviderProxy.java b/services/core/java/com/android/server/location/LocationProviderProxy.java
index ddbc203..09911ff 100644
--- a/services/core/java/com/android/server/location/LocationProviderProxy.java
+++ b/services/core/java/com/android/server/location/LocationProviderProxy.java
@@ -168,7 +168,7 @@
     }
 
     @Override
-    public void setRequest(ProviderRequest request, WorkSource source) {
+    public void onSetRequest(ProviderRequest request, WorkSource source) {
         synchronized (mRequestLock) {
             mRequest = request;
             mWorkSource = source;
@@ -181,10 +181,10 @@
 
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        pw.println("    service=" + mServiceWatcher);
+        pw.println("service=" + mServiceWatcher);
         synchronized (mProviderPackagesLock) {
             if (mProviderPackages.size() > 1) {
-                pw.println("    additional packages=" + mProviderPackages);
+                pw.println("additional packages=" + mProviderPackages);
             }
         }
     }
@@ -206,7 +206,7 @@
     }
 
     @Override
-    public void sendExtraCommand(String command, Bundle extras) {
+    public void onSendExtraCommand(int uid, int pid, String command, Bundle extras) {
         mServiceWatcher.runOnBinder(binder -> {
             ILocationProvider service = ILocationProvider.Stub.asInterface(binder);
             service.sendExtraCommand(command, extras);
diff --git a/services/core/java/com/android/server/location/MockProvider.java b/services/core/java/com/android/server/location/MockProvider.java
index 6accad8..b0c4c2e 100644
--- a/services/core/java/com/android/server/location/MockProvider.java
+++ b/services/core/java/com/android/server/location/MockProvider.java
@@ -81,11 +81,11 @@
 
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        pw.println(" last location=" + mLocation);
+        pw.println("last location=" + mLocation);
     }
 
     @Override
-    public void setRequest(ProviderRequest request, WorkSource source) {}
+    public void onSetRequest(ProviderRequest request, WorkSource source) {}
 
     @Override
     public int getStatus(Bundle extras) {
@@ -101,7 +101,4 @@
     public long getStatusUpdateTime() {
         return mStatusUpdateTime;
     }
-
-    @Override
-    public void sendExtraCommand(String command, Bundle extras) {}
 }
diff --git a/services/core/java/com/android/server/location/PassiveProvider.java b/services/core/java/com/android/server/location/PassiveProvider.java
index 3a841c9..639b1eb 100644
--- a/services/core/java/com/android/server/location/PassiveProvider.java
+++ b/services/core/java/com/android/server/location/PassiveProvider.java
@@ -19,7 +19,6 @@
 import android.content.Context;
 import android.location.Criteria;
 import android.location.Location;
-import android.os.Bundle;
 import android.os.WorkSource;
 
 import com.android.internal.location.ProviderProperties;
@@ -53,7 +52,7 @@
     }
 
     @Override
-    public void setRequest(ProviderRequest request, WorkSource source) {
+    public void onSetRequest(ProviderRequest request, WorkSource source) {
         mReportLocation = request.reportLocation;
     }
 
@@ -64,10 +63,7 @@
     }
 
     @Override
-    public void sendExtraCommand(String command, Bundle extras) {}
-
-    @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        pw.println(" report location=" + mReportLocation);
+        pw.println("report location=" + mReportLocation);
     }
 }
diff --git a/services/core/java/com/android/server/locksettings/PasswordSlotManager.java b/services/core/java/com/android/server/locksettings/PasswordSlotManager.java
index 5cbd237..4ef63c0 100644
--- a/services/core/java/com/android/server/locksettings/PasswordSlotManager.java
+++ b/services/core/java/com/android/server/locksettings/PasswordSlotManager.java
@@ -122,7 +122,7 @@
      */
     public void markSlotDeleted(int slot) throws RuntimeException {
         ensureSlotMapLoaded();
-        if (mSlotMap.containsKey(slot) && mSlotMap.get(slot) != getMode()) {
+        if (mSlotMap.containsKey(slot) && !mSlotMap.get(slot).equals(getMode())) {
             throw new RuntimeException("password slot " + slot + " cannot be deleted");
         }
         mSlotMap.remove(slot);
diff --git a/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java b/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java
index c13fcd6..9e34018 100644
--- a/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java
+++ b/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java
@@ -85,9 +85,16 @@
         mCallback = callback;
     }
 
-    public void setSelectedRoute(int uid, String routeId) {
+    public void selectRoute(String packageName, String routeId) {
         if (mConnectionReady) {
-            mActiveConnection.selectRoute(uid, routeId);
+            mActiveConnection.selectRoute(packageName, routeId);
+            updateBinding();
+        }
+    }
+
+    public void unselectRoute(String packageName, String routeId) {
+        if (mConnectionReady) {
+            mActiveConnection.unselectRotue(packageName, routeId);
             updateBinding();
         }
     }
@@ -235,17 +242,6 @@
         }
     }
 
-    private void onRouteSelected(Connection connection, int uid, String routeId) {
-        if (mActiveConnection != connection) {
-            return;
-        }
-
-        if (DEBUG) {
-            Slog.d(TAG, this + ": State changed ");
-        }
-        mHandler.post(mStateChanged);
-    }
-
     private void onProviderInfoUpdated(Connection connection, MediaRoute2ProviderInfo info) {
         if (mActiveConnection != connection) {
             return;
@@ -298,8 +294,8 @@
         public boolean register() {
             try {
                 mProvider.asBinder().linkToDeath(this, 0);
-                mProvider.registerClient(mClient);
-                mHandler.post((Runnable) () -> onConnectionReady(Connection.this));
+                mProvider.setClient(mClient);
+                mHandler.post(() -> onConnectionReady(Connection.this));
                 return true;
             } catch (RemoteException ex) {
                 binderDied();
@@ -312,23 +308,25 @@
             mClient.dispose();
         }
 
-        public void selectRoute(int uid, String id) {
-            if (mClient == null) {
-                return;
-            }
+        public void selectRoute(String packageName, String routeId) {
             try {
-                mProvider.selectRoute(mClient, uid, id);
+                mProvider.selectRoute(packageName, routeId);
             } catch (RemoteException ex) {
                 Slog.e(TAG, "Failed to deliver request to set discovery mode.", ex);
             }
         }
 
-        public void sendControlRequest(String id, Intent request) {
-            if (mClient == null) {
-                return;
-            }
+        public void unselectRotue(String packageName, String routeId) {
             try {
-                mProvider.notifyControlRequestSent(mClient, id, request);
+                mProvider.unselectRoute(packageName, routeId);
+            } catch (RemoteException ex) {
+                Slog.e(TAG, "Failed to deliver request to set discovery mode.", ex);
+            }
+        }
+
+        public void sendControlRequest(String routeId, Intent request) {
+            try {
+                mProvider.notifyControlRequestSent(routeId, request);
             } catch (RemoteException ex) {
                 Slog.e(TAG, "Failed to deliver request to send control request.", ex);
             }
@@ -339,10 +337,6 @@
             mHandler.post(() -> onConnectionDied(Connection.this));
         }
 
-        void postRouteSelected(int uid, String routeId) {
-            mHandler.post(() -> onRouteSelected(Connection.this, uid, routeId));
-        }
-
         void postProviderUpdated(MediaRoute2ProviderInfo info) {
             mHandler.post(() -> onProviderInfoUpdated(Connection.this, info));
         }
@@ -360,14 +354,6 @@
         }
 
         @Override
-        public void notifyRouteSelected(int uid, String routeId) throws RemoteException {
-            Connection connection = mConnectionRef.get();
-            if (connection != null) {
-                connection.postRouteSelected(uid, routeId);
-            }
-        }
-
-        @Override
         public void notifyProviderInfoUpdated(MediaRoute2ProviderInfo info) {
             Connection connection = mConnectionRef.get();
             if (connection != null) {
diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
index 0398658..12137fe 100644
--- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
@@ -32,16 +32,15 @@
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
-import android.os.Message;
 import android.os.RemoteException;
 import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.Log;
-import android.util.Pair;
 import android.util.Slog;
 import android.util.SparseArray;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.function.pooled.PooledLambda;
 
 import java.io.PrintWriter;
 import java.lang.ref.WeakReference;
@@ -183,11 +182,11 @@
     }
 
     public void selectClientRoute2(@NonNull IMediaRouter2Manager manager,
-            int clientUid, @Nullable MediaRoute2Info route) {
+            String packageName, @Nullable MediaRoute2Info route) {
         final long token = Binder.clearCallingIdentity();
         try {
             synchronized (mLock) {
-                selectClientRoute2Locked(manager, clientUid, route);
+                selectClientRoute2Locked(manager, packageName, route);
             }
         } finally {
             Binder.restoreCallingIdentity(token);
@@ -204,13 +203,15 @@
 
                 UserRecord oldUser = mUserRecords.get(oldUserId);
                 if (oldUser != null) {
-                    oldUser.mHandler.sendEmptyMessage(MediaRouterService.UserHandler.MSG_STOP);
+                    oldUser.mHandler.sendMessage(
+                            obtainMessage(UserHandler::stop, oldUser.mHandler));
                     disposeUserIfNeededLocked(oldUser); // since no longer current user
                 }
 
                 UserRecord newUser = mUserRecords.get(userId);
                 if (newUser != null) {
-                    newUser.mHandler.sendEmptyMessage(MediaRouterService.UserHandler.MSG_START);
+                    newUser.mHandler.sendMessage(
+                            obtainMessage(UserHandler::start, newUser.mHandler));
                 }
             }
         }
@@ -267,8 +268,7 @@
         }
     }
 
-    private void selectRoute2Locked(IMediaRouter2Client client,
-            MediaRoute2Info route) {
+    private void selectRoute2Locked(IMediaRouter2Client client, MediaRoute2Info route) {
         ClientRecord clientRecord = mAllClientRecords.get(client.asBinder());
         if (clientRecord != null) {
             MediaRoute2Info oldRoute = clientRecord.mSelectedRoute;
@@ -297,8 +297,9 @@
         if (clientRecord != null) {
             clientRecord.mControlCategories = categories;
 
-            clientRecord.mUserRecord.mHandler.obtainMessage(
-                    UserHandler.MSG_UPDATE_CLIENT_USAGE, clientRecord).sendToTarget();
+            clientRecord.mUserRecord.mHandler.sendMessage(
+                    obtainMessage(UserHandler::updateClientUsage,
+                            clientRecord.mUserRecord.mHandler, clientRecord));
         }
     }
 
@@ -308,9 +309,9 @@
         ClientRecord clientRecord = mAllClientRecords.get(binder);
 
         if (clientRecord != null) {
-            Pair<MediaRoute2Info, Intent> obj = new Pair<>(route, request);
-            clientRecord.mUserRecord.mHandler.obtainMessage(
-                    UserHandler.MSG_SEND_CONTROL_REQUEST, obj).sendToTarget();
+            clientRecord.mUserRecord.mHandler.sendMessage(
+                    obtainMessage(UserHandler::sendControlRequest,
+                            clientRecord.mUserRecord.mHandler, route, request));
         }
     }
 
@@ -347,8 +348,9 @@
             final int count = userRecord.mClientRecords.size();
             for (int i = 0; i < count; i++) {
                 ClientRecord clientRecord = userRecord.mClientRecords.get(i);
-                clientRecord.mUserRecord.mHandler.obtainMessage(
-                        UserHandler.MSG_UPDATE_CLIENT_USAGE, clientRecord).sendToTarget();
+                clientRecord.mUserRecord.mHandler.sendMessage(
+                        obtainMessage(UserHandler::updateClientUsage,
+                            clientRecord.mUserRecord.mHandler, clientRecord));
             }
         }
     }
@@ -364,10 +366,10 @@
     }
 
     private void selectClientRoute2Locked(IMediaRouter2Manager manager,
-            int clientUid, MediaRoute2Info route) {
+            String packageName, MediaRoute2Info route) {
         ManagerRecord managerRecord = mAllManagerRecords.get(manager.asBinder());
         if (managerRecord != null) {
-            ClientRecord clientRecord = managerRecord.mUserRecord.findClientRecordByUid(clientUid);
+            ClientRecord clientRecord = managerRecord.mUserRecord.findClientRecord(packageName);
             if (clientRecord == null) {
                 Slog.w(TAG, "Ignoring route selection for unknown client.");
             }
@@ -382,7 +384,8 @@
             Slog.d(TAG, userRecord + ": Initialized");
         }
         if (userRecord.mUserId == mCurrentUserId) {
-            userRecord.mHandler.sendEmptyMessage(UserHandler.MSG_START);
+            userRecord.mHandler.sendMessage(
+                    obtainMessage(UserHandler::start, userRecord.mHandler));
         }
     }
 
@@ -413,9 +416,11 @@
             mHandler = new UserHandler(MediaRouter2ServiceImpl.this, this);
         }
 
-        ClientRecord findClientRecordByUid(int uid) {
+        ClientRecord findClientRecord(String packageName) {
             for (ClientRecord clientRecord : mClientRecords) {
-                if (clientRecord.mUid == uid) return clientRecord;
+                if (TextUtils.equals(clientRecord.mPackageName, packageName)) {
+                    return clientRecord;
+                }
             }
             return null;
         }
@@ -496,14 +501,6 @@
             MediaRoute2ProviderWatcher.Callback,
             MediaRoute2ProviderProxy.Callback {
 
-        //TODO: Use PooledLambda instead.
-        static final int MSG_START = 1;
-        static final int MSG_STOP = 2;
-
-        static final int MSG_UPDATE_CLIENT_USAGE = 11;
-        static final int MSG_UPDATE_MANAGER_STATE = 12;
-        static final int MSG_SEND_CONTROL_REQUEST = 13;
-
         private final WeakReference<MediaRouter2ServiceImpl> mServiceRef;
         private final UserRecord mUserRecord;
         private final MediaRoute2ProviderWatcher mWatcher;
@@ -524,32 +521,6 @@
                     this, mUserRecord.mUserId);
         }
 
-        @Override
-        public void handleMessage(Message msg) {
-            switch (msg.what) {
-                case MSG_START: {
-                    start();
-                    break;
-                }
-                case MSG_STOP: {
-                    stop();
-                    break;
-                }
-                case MSG_UPDATE_CLIENT_USAGE: {
-                    updateClientUsage((ClientRecord) msg.obj);
-                    break;
-                }
-                case MSG_UPDATE_MANAGER_STATE: {
-                    updateManagerState();
-                    break;
-                }
-                case MSG_SEND_CONTROL_REQUEST: {
-                    Pair<MediaRoute2Info, Intent> obj = (Pair<MediaRoute2Info, Intent>) msg.obj;
-                    sendControlRequest(obj.first, obj.second);
-                }
-            }
-        }
-
         private void start() {
             if (!mRunning) {
                 mRunning = true;
@@ -585,20 +556,24 @@
             scheduleUpdateManagerState();
         }
 
-        private void unselectRoute(ClientRecord clientRecord, MediaRoute2Info route) {
+        private void selectRoute(ClientRecord clientRecord, MediaRoute2Info route) {
             if (route != null) {
                 MediaRoute2ProviderProxy provider = findProvider(route.getProviderId());
-                if (provider != null) {
-                    provider.setSelectedRoute(clientRecord.mUid, null);
+                if (provider == null) {
+                    Log.w(TAG, "Ignoring to select route of unknown provider " + route);
+                } else {
+                    provider.selectRoute(clientRecord.mPackageName, route.getId());
                 }
             }
         }
 
-        private void selectRoute(ClientRecord clientRecord, MediaRoute2Info route) {
+        private void unselectRoute(ClientRecord clientRecord, MediaRoute2Info route) {
             if (route != null) {
                 MediaRoute2ProviderProxy provider = findProvider(route.getProviderId());
-                if (provider != null) {
-                    provider.setSelectedRoute(clientRecord.mUid, route.getId());
+                if (provider == null) {
+                    Log.w(TAG, "Ignoring to unselect route of unknown provider " + route);
+                } else {
+                    provider.unselectRoute(clientRecord.mPackageName, route.getId());
                 }
             }
         }
@@ -613,7 +588,7 @@
         private void scheduleUpdateManagerState() {
             if (!mManagerStateUpdateScheduled) {
                 mManagerStateUpdateScheduled = true;
-                sendEmptyMessage(MSG_UPDATE_MANAGER_STATE);
+                sendMessage(PooledLambda.obtainMessage(UserHandler::updateManagerState, this));
             }
         }
 
@@ -670,8 +645,9 @@
             }
             for (IMediaRouter2Manager manager : managers) {
                 try {
-                    manager.notifyRouteSelected(clientRecord.mUid, clientRecord.mSelectedRoute);
-                    manager.notifyControlCategoriesChanged(clientRecord.mUid,
+                    manager.notifyRouteSelected(clientRecord.mPackageName,
+                            clientRecord.mSelectedRoute);
+                    manager.notifyControlCategoriesChanged(clientRecord.mPackageName,
                             clientRecord.mControlCategories);
                 } catch (RemoteException ex) {
                     Slog.w(TAG, "Failed to update client usage. Manager probably died.", ex);
diff --git a/services/core/java/com/android/server/media/MediaRouterService.java b/services/core/java/com/android/server/media/MediaRouterService.java
index 4577365..a43068b 100644
--- a/services/core/java/com/android/server/media/MediaRouterService.java
+++ b/services/core/java/com/android/server/media/MediaRouterService.java
@@ -482,8 +482,8 @@
     // Binder call
     @Override
     public void selectClientRoute2(IMediaRouter2Manager manager,
-            int clientUid, MediaRoute2Info route) {
-        mService2.selectClientRoute2(manager, clientUid, route);
+            String packageName, MediaRoute2Info route) {
+        mService2.selectClientRoute2(manager, packageName, route);
     }
 
     // Binder call
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 5bd4b20..c05655a 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -92,6 +92,7 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
 
 /**
@@ -748,6 +749,8 @@
 
         private final int mFullUserId;
         private final MediaSessionStack mPriorityStack;
+        private final HashMap<IBinder, CallbackRecord> mCallbacks = new HashMap<>();
+
         private PendingIntent mLastMediaButtonReceiver;
         private ComponentName mRestoredMediaButtonReceiver;
         private int mRestoredMediaButtonReceiverComponentType;
@@ -761,7 +764,6 @@
 
         private IOnMediaKeyListener mOnMediaKeyListener;
         private int mOnMediaKeyListenerUid;
-        private ICallback mCallback;
 
         FullUserRecord(int fullUserId) {
             mFullUserId = fullUserId;
@@ -793,6 +795,24 @@
             }
         }
 
+        public void registerCallbackLocked(ICallback callback, int uid) {
+            IBinder cbBinder = callback.asBinder();
+            CallbackRecord cr = new CallbackRecord(callback, uid);
+            mCallbacks.put(cbBinder, cr);
+            try {
+                cbBinder.linkToDeath(cr, 0);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed to register callback", e);
+                mCallbacks.remove(cbBinder);
+            }
+        }
+
+        public void unregisterCallbackLocked(ICallback callback) {
+            IBinder cbBinder = callback.asBinder();
+            CallbackRecord cr = mCallbacks.remove(cbBinder);
+            cbBinder.unlinkToDeath(cr, 0);
+        }
+
         public void dumpLocked(PrintWriter pw, String prefix) {
             pw.print(prefix + "Record for full_user=" + mFullUserId);
             // Dump managed profile user ids associated with this user.
@@ -811,7 +831,10 @@
             pw.println(indent + "Media key listener: " + mOnMediaKeyListener);
             pw.println(indent + "Media key listener package: "
                     + getCallingPackageName(mOnMediaKeyListenerUid));
-            pw.println(indent + "Callback: " + mCallback);
+            pw.println(indent + "Callbacks: registered " + mCallbacks.size() + " callback(s)");
+            for (CallbackRecord cr : mCallbacks.values()) {
+                pw.println(indent + "  from " + getCallingPackageName(cr.uid));
+            }
             pw.println(indent + "Last MediaButtonReceiver: " + mLastMediaButtonReceiver);
             pw.println(indent + "Restored MediaButtonReceiver: " + mRestoredMediaButtonReceiver);
             pw.println(indent + "Restored MediaButtonReceiverComponentType: "
@@ -871,21 +894,18 @@
                     mFullUserId);
         }
 
-        private void pushAddressedPlayerChangedLocked() {
-            if (mCallback == null) {
-                return;
-            }
+        private void pushAddressedPlayerChangedLocked(ICallback callback) {
             try {
                 MediaSessionRecord mediaButtonSession = getMediaButtonSessionLocked();
                 if (mediaButtonSession != null) {
-                    mCallback.onAddressedPlayerChangedToMediaSession(
+                    callback.onAddressedPlayerChangedToMediaSession(
                             mediaButtonSession.getSessionToken());
                 } else if (mCurrentFullUserRecord.mLastMediaButtonReceiver != null) {
-                    mCallback.onAddressedPlayerChangedToMediaButtonReceiver(
+                    callback.onAddressedPlayerChangedToMediaButtonReceiver(
                             mCurrentFullUserRecord.mLastMediaButtonReceiver
                                     .getIntent().getComponent());
                 } else if (mCurrentFullUserRecord.mRestoredMediaButtonReceiver != null) {
-                    mCallback.onAddressedPlayerChangedToMediaButtonReceiver(
+                    callback.onAddressedPlayerChangedToMediaButtonReceiver(
                             mCurrentFullUserRecord.mRestoredMediaButtonReceiver);
                 }
             } catch (RemoteException e) {
@@ -893,6 +913,12 @@
             }
         }
 
+        private void pushAddressedPlayerChangedLocked() {
+            for (CallbackRecord cr : mCallbacks.values()) {
+                pushAddressedPlayerChangedLocked(cr.callback);
+            }
+        }
+
         private MediaSessionRecord getMediaButtonSessionLocked() {
             return isGlobalPriorityActiveLocked()
                     ? mGlobalPrioritySession : mPriorityStack.getMediaButtonSession();
@@ -926,6 +952,23 @@
             // Pick legacy behavior for BroadcastReceiver or unknown.
             return COMPONENT_TYPE_BROADCAST;
         }
+
+        final class CallbackRecord implements IBinder.DeathRecipient {
+            public final ICallback callback;
+            public final int uid;
+
+            CallbackRecord(ICallback callback, int uid) {
+                this.callback = callback;
+                this.uid = uid;
+            }
+
+            @Override
+            public void binderDied() {
+                synchronized (mLock) {
+                    mCallbacks.remove(callback.asBinder());
+                }
+            }
+        }
     }
 
     final class SessionsListenerRecord implements IBinder.DeathRecipient {
@@ -1305,44 +1348,53 @@
         }
 
         @Override
-        public void setCallback(ICallback callback) {
+        public void registerCallback(final ICallback callback) {
             final int pid = Binder.getCallingPid();
             final int uid = Binder.getCallingUid();
+            final int userId = UserHandle.getUserId(uid);
             final long token = Binder.clearCallingIdentity();
             try {
-                if (!UserHandle.isSameApp(uid, Process.BLUETOOTH_UID)) {
-                    throw new SecurityException("Only Bluetooth service processes can set"
-                            + " Callback");
+                if (!hasMediaControlPermission(pid, uid)) {
+                    throw new SecurityException("MEDIA_CONTENT_CONTROL permission is required to"
+                            + "  register Callback");
                 }
                 synchronized (mLock) {
-                    int userId = UserHandle.getUserId(uid);
                     FullUserRecord user = getFullUserRecordLocked(userId);
                     if (user == null || user.mFullUserId != userId) {
-                        Log.w(TAG, "Only the full user can set the callback"
+                        Log.w(TAG, "Only the full user can register the callback"
                                 + ", userId=" + userId);
                         return;
                     }
-                    user.mCallback = callback;
-                    Log.d(TAG, "The callback " + user.mCallback
-                            + " is set by " + getCallingPackageName(uid));
-                    if (user.mCallback == null) {
+                    user.registerCallbackLocked(callback, uid);
+                    Log.d(TAG, "The callback (" + callback.asBinder()
+                            + ") is registered by " + getCallingPackageName(uid));
+                }
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        @Override
+        public void unregisterCallback(final ICallback callback) {
+            final int pid = Binder.getCallingPid();
+            final int uid = Binder.getCallingUid();
+            final int userId = UserHandle.getUserId(uid);
+            final long token = Binder.clearCallingIdentity();
+            try {
+                if (!hasMediaControlPermission(pid, uid)) {
+                    throw new SecurityException("MEDIA_CONTENT_CONTROL permission is required to"
+                            + "  unregister Callback");
+                }
+                synchronized (mLock) {
+                    FullUserRecord user = getFullUserRecordLocked(userId);
+                    if (user == null || user.mFullUserId != userId) {
+                        Log.w(TAG, "Only the full user can unregister the callback"
+                                + ", userId=" + userId);
                         return;
                     }
-                    try {
-                        user.mCallback.asBinder().linkToDeath(
-                                new IBinder.DeathRecipient() {
-                                    @Override
-                                    public void binderDied() {
-                                        synchronized (mLock) {
-                                            user.mCallback = null;
-                                        }
-                                    }
-                                }, 0);
-                        user.pushAddressedPlayerChangedLocked();
-                    } catch (RemoteException e) {
-                        Log.w(TAG, "Failed to set callback", e);
-                        user.mCallback = null;
-                    }
+                    user.unregisterCallbackLocked(callback);
+                    Log.d(TAG, "The callback (" + callback.asBinder()
+                            + ") is unregistered by " + getCallingPackageName(uid));
                 }
             } finally {
                 Binder.restoreCallingIdentity(token);
@@ -1771,6 +1823,7 @@
         public boolean isTrusted(String controllerPackageName, int controllerPid, int controllerUid)
                 throws RemoteException {
             final int uid = Binder.getCallingUid();
+            final int userId = UserHandle.getUserId(uid);
             final long token = Binder.clearCallingIdentity();
             try {
                 // Don't perform sanity check between controllerPackageName and controllerUid.
@@ -1781,8 +1834,8 @@
                 // Note that we can use Context#getOpPackageName() instead of
                 // Context#getPackageName() for getting package name that matches with the PID/UID,
                 // but it doesn't tell which package has created the MediaController, so useless.
-                return hasMediaControlPermission(UserHandle.getUserId(uid), controllerPackageName,
-                        controllerPid, controllerUid);
+                return hasMediaControlPermission(controllerPid, controllerUid)
+                        || hasEnabledNotificationListener(userId, controllerPackageName);
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -1808,13 +1861,7 @@
             return resolvedUserId;
         }
 
-        private boolean hasMediaControlPermission(int resolvedUserId, String packageName,
-                int pid, int uid) throws RemoteException {
-            // Allow API calls from the System UI and Settings
-            if (hasStatusBarServicePermission(pid, uid)) {
-                return true;
-            }
-
+        private boolean hasMediaControlPermission(int pid, int uid) {
             // Check if it's system server or has MEDIA_CONTENT_CONTROL.
             // Note that system server doesn't have MEDIA_CONTENT_CONTROL, so we need extra
             // check here.
@@ -1823,11 +1870,15 @@
                     == PackageManager.PERMISSION_GRANTED) {
                 return true;
             } else if (DEBUG) {
-                Log.d(TAG, packageName + " (uid=" + uid + ") hasn't granted MEDIA_CONTENT_CONTROL");
+                Log.d(TAG, "uid(" + uid + ") hasn't granted MEDIA_CONTENT_CONTROL");
             }
+            return false;
+        }
 
+        private boolean hasEnabledNotificationListener(int resolvedUserId, String packageName)
+                throws RemoteException {
             // You may not access another user's content as an enabled listener.
-            final int userId = UserHandle.getUserId(uid);
+            final int userId = UserHandle.getUserId(resolvedUserId);
             if (resolvedUserId != userId) {
                 return false;
             }
@@ -1845,7 +1896,7 @@
                 }
             }
             if (DEBUG) {
-                Log.d(TAG, packageName + " (uid=" + uid + ") doesn't have an enabled "
+                Log.d(TAG, packageName + " (uid=" + resolvedUserId + ") doesn't have an enabled "
                         + "notification listener");
             }
             return false;
@@ -1950,13 +2001,14 @@
                 session.sendMediaButton(packageName, pid, uid, asSystemService, keyEvent,
                         needWakeLock ? mKeyEventReceiver.mLastTimeoutId : -1,
                         mKeyEventReceiver);
-                if (mCurrentFullUserRecord.mCallback != null) {
-                    try {
-                        mCurrentFullUserRecord.mCallback.onMediaKeyEventDispatchedToMediaSession(
+                try {
+                    for (FullUserRecord.CallbackRecord cr
+                            : mCurrentFullUserRecord.mCallbacks.values()) {
+                        cr.callback.onMediaKeyEventDispatchedToMediaSession(
                                 keyEvent, session.getSessionToken());
-                    } catch (RemoteException e) {
-                        Log.w(TAG, "Failed to send callback", e);
                     }
+                } catch (RemoteException e) {
+                    Log.w(TAG, "Failed to send callback", e);
                 }
             } else if (mCurrentFullUserRecord.mLastMediaButtonReceiver != null
                     || mCurrentFullUserRecord.mRestoredMediaButtonReceiver != null) {
@@ -1980,12 +2032,12 @@
                         receiver.send(mContext,
                                 needWakeLock ? mKeyEventReceiver.mLastTimeoutId : -1,
                                 mediaButtonIntent, mKeyEventReceiver, mHandler);
-                        if (mCurrentFullUserRecord.mCallback != null) {
-                            ComponentName componentName = mCurrentFullUserRecord
-                                    .mLastMediaButtonReceiver.getIntent().getComponent();
-                            if (componentName != null) {
-                                mCurrentFullUserRecord.mCallback
-                                        .onMediaKeyEventDispatchedToMediaButtonReceiver(
+                        ComponentName componentName = mCurrentFullUserRecord
+                                .mLastMediaButtonReceiver.getIntent().getComponent();
+                        if (componentName != null) {
+                            for (FullUserRecord.CallbackRecord cr
+                                    : mCurrentFullUserRecord.mCallbacks.values()) {
+                                cr.callback.onMediaKeyEventDispatchedToMediaButtonReceiver(
                                                 keyEvent, componentName);
                             }
                         }
@@ -2018,9 +2070,9 @@
                             Log.w(TAG, "Error sending media button to the restored intent "
                                     + receiver + ", type=" + componentType, e);
                         }
-                        if (mCurrentFullUserRecord.mCallback != null) {
-                            mCurrentFullUserRecord.mCallback
-                                    .onMediaKeyEventDispatchedToMediaButtonReceiver(
+                        for (FullUserRecord.CallbackRecord cr
+                                : mCurrentFullUserRecord.mCallbacks.values()) {
+                            cr.callback.onMediaKeyEventDispatchedToMediaButtonReceiver(
                                             keyEvent, receiver);
                         }
                     }
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 6c34e13..5530b51 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -232,7 +232,6 @@
 import com.android.server.SystemConfig;
 
 import libcore.io.IoUtils;
-import libcore.util.EmptyArray;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlSerializer;
@@ -404,8 +403,10 @@
     private IConnectivityManager mConnManager;
     private PowerManagerInternal mPowerManagerInternal;
     private IDeviceIdleController mDeviceIdleController;
+
+    /** Current cached value of the current Battery Saver mode's setting for restrict background. */
     @GuardedBy("mUidRulesFirstLock")
-    private PowerSaveState mRestrictBackgroundPowerState;
+    private boolean mRestrictBackgroundLowPowerMode;
 
     // Store the status of restrict background before turning on battery saver.
     // Used to restore mRestrictBackground when battery saver is turned off.
@@ -540,7 +541,7 @@
     private final SparseArray<String> mSubIdToSubscriberId = new SparseArray<>();
     /** Set of all merged subscriberId as of last update */
     @GuardedBy("mNetworkPoliciesSecondLock")
-    private String[] mMergedSubscriberIds = EmptyArray.STRING;
+    private List<String[]> mMergedSubscriberIds = new ArrayList<>();
 
     /**
      * Indicates the uids restricted by admin from accessing metered data. It's a mapping from
@@ -772,11 +773,9 @@
 
                     // Update the restrictBackground if battery saver is turned on
                     mRestrictBackgroundBeforeBsm = mLoadedRestrictBackground;
-                    mRestrictBackgroundPowerState = mPowerManagerInternal
-                            .getLowPowerState(ServiceType.DATA_SAVER);
-                    final boolean localRestrictBackground =
-                            mRestrictBackgroundPowerState.batterySaverEnabled;
-                    if (localRestrictBackground && !mLoadedRestrictBackground) {
+                    mRestrictBackgroundLowPowerMode = mPowerManagerInternal
+                            .getLowPowerState(ServiceType.DATA_SAVER).batterySaverEnabled;
+                    if (mRestrictBackgroundLowPowerMode && !mLoadedRestrictBackground) {
                         mLoadedRestrictBackground = true;
                     }
                     mPowerManagerInternal.registerLowPowerModeObserver(
@@ -1801,7 +1800,7 @@
         final SubscriptionManager sm = mContext.getSystemService(SubscriptionManager.class);
 
         final int[] subIds = ArrayUtils.defeatNullable(sm.getActiveSubscriptionIdList());
-        final String[] mergedSubscriberIds = ArrayUtils.defeatNullable(tm.getMergedSubscriberIds());
+        final List<String[]> mergedSubscriberIdsList = new ArrayList();
 
         final SparseArray<String> subIdToSubscriberId = new SparseArray<>(subIds.length);
         for (int subId : subIds) {
@@ -1811,6 +1810,10 @@
             } else {
                 Slog.wtf(TAG, "Missing subscriberId for subId " + subId);
             }
+
+            String[] mergedSubscriberId = ArrayUtils.defeatNullable(
+                    tm.createForSubscriptionId(subId).getMergedSubscriberIdsFromGroup());
+            mergedSubscriberIdsList.add(mergedSubscriberId);
         }
 
         synchronized (mNetworkPoliciesSecondLock) {
@@ -1820,7 +1823,7 @@
                         subIdToSubscriberId.valueAt(i));
             }
 
-            mMergedSubscriberIds = mergedSubscriberIds;
+            mMergedSubscriberIds = mergedSubscriberIdsList;
         }
 
         Trace.traceEnd(TRACE_TAG_NETWORK);
@@ -2897,7 +2900,7 @@
             sendRestrictBackgroundChangedMsg();
             mLogger.restrictBackgroundChanged(oldRestrictBackground, mRestrictBackground);
 
-            if (mRestrictBackgroundPowerState.globalBatterySaverEnabled) {
+            if (mRestrictBackgroundLowPowerMode) {
                 mRestrictBackgroundChangedInBsm = true;
             }
             synchronized (mNetworkPoliciesSecondLock) {
@@ -3373,8 +3376,10 @@
                 fout.decreaseIndent();
 
                 fout.println();
-                fout.println("Merged subscriptions: "
-                        + Arrays.toString(NetworkIdentity.scrubSubscriberId(mMergedSubscriberIds)));
+                for (String[] mergedSubscribers : mMergedSubscriberIds) {
+                    fout.println("Merged subscriptions: " + Arrays.toString(
+                            NetworkIdentity.scrubSubscriberId(mergedSubscribers)));
+                }
 
                 fout.println();
                 fout.println("Policy for UIDs:");
@@ -4902,17 +4907,21 @@
     @GuardedBy("mUidRulesFirstLock")
     @VisibleForTesting
     void updateRestrictBackgroundByLowPowerModeUL(final PowerSaveState result) {
-        mRestrictBackgroundPowerState = result;
+        if (mRestrictBackgroundLowPowerMode == result.batterySaverEnabled) {
+            // Nothing changed. Nothing to do.
+            return;
+        }
+        mRestrictBackgroundLowPowerMode = result.batterySaverEnabled;
 
-        boolean restrictBackground = result.batterySaverEnabled;
+        boolean restrictBackground = mRestrictBackgroundLowPowerMode;
         boolean shouldInvokeRestrictBackground;
-        // store the temporary mRestrictBackgroundChangedInBsm and update it at last
+        // store the temporary mRestrictBackgroundChangedInBsm and update it at the end.
         boolean localRestrictBgChangedInBsm = mRestrictBackgroundChangedInBsm;
 
-        if (result.globalBatterySaverEnabled) {
+        if (mRestrictBackgroundLowPowerMode) {
             // Try to turn on restrictBackground if (1) it is off and (2) batter saver need to
             // turn it on.
-            shouldInvokeRestrictBackground = !mRestrictBackground && result.batterySaverEnabled;
+            shouldInvokeRestrictBackground = !mRestrictBackground;
             mRestrictBackgroundBeforeBsm = mRestrictBackground;
             localRestrictBgChangedInBsm = false;
         } else {
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index f032fa6..07fd322 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -25,9 +25,12 @@
 import static android.app.Notification.FLAG_ONGOING_EVENT;
 import static android.app.Notification.FLAG_ONLY_ALERT_ONCE;
 import static android.app.NotificationManager.ACTION_APP_BLOCK_STATE_CHANGED;
+import static android.app.NotificationManager.ACTION_AUTOMATIC_ZEN_RULE_STATUS_CHANGED;
 import static android.app.NotificationManager.ACTION_NOTIFICATION_CHANNEL_BLOCK_STATE_CHANGED;
 import static android.app.NotificationManager.ACTION_NOTIFICATION_CHANNEL_GROUP_BLOCK_STATE_CHANGED;
 import static android.app.NotificationManager.ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED;
+import static android.app.NotificationManager.EXTRA_AUTOMATIC_ZEN_RULE_ID;
+import static android.app.NotificationManager.EXTRA_AUTOMATIC_ZEN_RULE_STATUS;
 import static android.app.NotificationManager.IMPORTANCE_LOW;
 import static android.app.NotificationManager.IMPORTANCE_MIN;
 import static android.app.NotificationManager.IMPORTANCE_NONE;
@@ -207,6 +210,7 @@
 import android.util.proto.ProtoOutputStream;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
+import android.widget.RemoteViews;
 import android.widget.Toast;
 
 import com.android.internal.R;
@@ -463,6 +467,9 @@
     private boolean mIsAutomotive;
     private boolean mNotificationEffectsEnabledForAutomotive;
 
+    private int mWarnRemoteViewsSizeBytes;
+    private int mStripRemoteViewsSizeBytes;
+
     private MetricsLogger mMetricsLogger;
     private TriPredicate<String, Integer, String> mAllowedManagedServicePackages;
 
@@ -1641,6 +1648,15 @@
                 sendRegisteredOnlyBroadcast(NotificationManager.ACTION_NOTIFICATION_POLICY_CHANGED);
                 mRankingHandler.requestSort();
             }
+
+            @Override
+            void onAutomaticRuleStatusChanged(int userId, String pkg, String id, int status) {
+                Intent intent = new Intent(ACTION_AUTOMATIC_ZEN_RULE_STATUS_CHANGED);
+                intent.setPackage(pkg);
+                intent.putExtra(EXTRA_AUTOMATIC_ZEN_RULE_ID, id);
+                intent.putExtra(EXTRA_AUTOMATIC_ZEN_RULE_STATUS, status);
+                getContext().sendBroadcastAsUser(intent, UserHandle.of(userId));
+            }
         });
         mPreferencesHelper = new PreferencesHelper(getContext(),
                 mPackageManagerClient,
@@ -1723,6 +1739,11 @@
 
         mZenModeHelper.setPriorityOnlyDndExemptPackages(getContext().getResources().getStringArray(
                 com.android.internal.R.array.config_priorityOnlyDndExemptPackages));
+
+        mWarnRemoteViewsSizeBytes = getContext().getResources().getInteger(
+                com.android.internal.R.integer.config_notificationWarnRemoteViewSizeBytes);
+        mStripRemoteViewsSizeBytes = getContext().getResources().getInteger(
+                com.android.internal.R.integer.config_notificationStripRemoteViewSizeBytes);
     }
 
     @Override
@@ -4712,7 +4733,7 @@
 
         // Fix the notification as best we can.
         try {
-            fixNotification(notification, pkg, userId);
+            fixNotification(notification, pkg, tag, id, userId);
 
         } catch (NameNotFoundException e) {
             Slog.e(TAG, "Cannot create a context for sending app", e);
@@ -4817,8 +4838,8 @@
     }
 
     @VisibleForTesting
-    protected void fixNotification(Notification notification, String pkg, int userId)
-            throws NameNotFoundException {
+    protected void fixNotification(Notification notification, String pkg, String tag, int id,
+            int userId) throws NameNotFoundException {
         final ApplicationInfo ai = mPackageManagerClient.getApplicationInfoAsUser(
                 pkg, PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
                 (userId == UserHandle.USER_ALL) ? USER_SYSTEM : userId);
@@ -4841,6 +4862,50 @@
                         ": Use of fullScreenIntent requires the USE_FULL_SCREEN_INTENT permission");
             }
         }
+
+        // Remote views? Are they too big?
+        checkRemoteViews(pkg, tag, id, notification);
+    }
+
+    private void checkRemoteViews(String pkg, String tag, int id, Notification notification) {
+        if (removeRemoteView(pkg, tag, id, notification.contentView)) {
+            notification.contentView = null;
+        }
+        if (removeRemoteView(pkg, tag, id, notification.bigContentView)) {
+            notification.bigContentView = null;
+        }
+        if (removeRemoteView(pkg, tag, id, notification.headsUpContentView)) {
+            notification.headsUpContentView = null;
+        }
+        if (notification.publicVersion != null) {
+            if (removeRemoteView(pkg, tag, id, notification.publicVersion.contentView)) {
+                notification.publicVersion.contentView = null;
+            }
+            if (removeRemoteView(pkg, tag, id, notification.publicVersion.bigContentView)) {
+                notification.publicVersion.bigContentView = null;
+            }
+            if (removeRemoteView(pkg, tag, id, notification.publicVersion.headsUpContentView)) {
+                notification.publicVersion.headsUpContentView = null;
+            }
+        }
+    }
+
+    private boolean removeRemoteView(String pkg, String tag, int id, RemoteViews contentView) {
+        if (contentView == null) {
+            return false;
+        }
+        final int contentViewSize = contentView.estimateMemoryUsage();
+        if (contentViewSize > mWarnRemoteViewsSizeBytes
+                && contentViewSize < mStripRemoteViewsSizeBytes) {
+            Slog.w(TAG, "RemoteViews too large on tag: " + tag + " id: " + id
+                    + " this might be stripped in a future release");
+        }
+        if (contentViewSize >= mStripRemoteViewsSizeBytes) {
+            mUsageStats.registerImageRemoved(pkg);
+            Slog.w(TAG, "Removed too large RemoteViews on tag: " + tag + " id: " + id);
+            return true;
+        }
+        return false;
     }
 
     /**
@@ -5069,23 +5134,25 @@
             }
         }
 
-        // snoozed apps
-        if (mSnoozeHelper.isSnoozed(userId, pkg, r.getKey())) {
-            MetricsLogger.action(r.getLogMaker()
-                    .setType(MetricsProto.MetricsEvent.TYPE_UPDATE)
-                    .setCategory(MetricsProto.MetricsEvent.NOTIFICATION_SNOOZED));
-            if (DBG) {
-                Slog.d(TAG, "Ignored enqueue for snoozed notification " + r.getKey());
+        synchronized (mNotificationLock) {
+            // snoozed apps
+            if (mSnoozeHelper.isSnoozed(userId, pkg, r.getKey())) {
+                MetricsLogger.action(r.getLogMaker()
+                        .setType(MetricsProto.MetricsEvent.TYPE_UPDATE)
+                        .setCategory(MetricsProto.MetricsEvent.NOTIFICATION_SNOOZED));
+                if (DBG) {
+                    Slog.d(TAG, "Ignored enqueue for snoozed notification " + r.getKey());
+                }
+                mSnoozeHelper.update(userId, r);
+                handleSavePolicyFile();
+                return false;
             }
-            mSnoozeHelper.update(userId, r);
-            handleSavePolicyFile();
-            return false;
-        }
 
 
-        // blocked apps
-        if (isBlocked(r, mUsageStats)) {
-            return false;
+            // blocked apps
+            if (isBlocked(r, mUsageStats)) {
+                return false;
+            }
         }
 
         return true;
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index 6748f80..a126073 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -34,11 +34,8 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.PackageManagerInternal;
-import android.content.res.Resources;
 import android.graphics.Bitmap;
-import android.graphics.drawable.Icon;
 import android.media.AudioAttributes;
 import android.media.AudioSystem;
 import android.metrics.LogMaker;
@@ -453,16 +450,11 @@
 
     void dump(PrintWriter pw, String prefix, Context baseContext, boolean redact) {
         final Notification notification = sbn.getNotification();
-        final Icon icon = notification.getSmallIcon();
-        String iconStr = String.valueOf(icon);
-        if (icon != null && icon.getType() == Icon.TYPE_RESOURCE) {
-            iconStr += " / " + idDebugString(baseContext, icon.getResPackage(), icon.getResId());
-        }
         pw.println(prefix + this);
         prefix = prefix + "  ";
         pw.println(prefix + "uid=" + sbn.getUid() + " userId=" + sbn.getUserId());
         pw.println(prefix + "opPkg=" + sbn.getOpPkg());
-        pw.println(prefix + "icon=" + iconStr);
+        pw.println(prefix + "icon=" + notification.getSmallIcon());
         pw.println(prefix + "flags=0x" + Integer.toHexString(notification.flags));
         pw.println(prefix + "pri=" + notification.priority);
         pw.println(prefix + "key=" + sbn.getKey());
@@ -592,28 +584,6 @@
         pw.println(prefix + "mAdjustments=" + mAdjustments);
     }
 
-
-    static String idDebugString(Context baseContext, String packageName, int id) {
-        Context c;
-
-        if (packageName != null) {
-            try {
-                c = baseContext.createPackageContext(packageName, 0);
-            } catch (NameNotFoundException e) {
-                c = baseContext;
-            }
-        } else {
-            c = baseContext;
-        }
-
-        Resources r = c.getResources();
-        try {
-            return r.getResourceName(id);
-        } catch (Resources.NotFoundException e) {
-            return "<name unknown>";
-        }
-    }
-
     @Override
     public final String toString() {
         return String.format(
diff --git a/services/core/java/com/android/server/notification/NotificationUsageStats.java b/services/core/java/com/android/server/notification/NotificationUsageStats.java
index dd393b8..fe3d0eb 100644
--- a/services/core/java/com/android/server/notification/NotificationUsageStats.java
+++ b/services/core/java/com/android/server/notification/NotificationUsageStats.java
@@ -41,7 +41,6 @@
 import org.json.JSONObject;
 
 import java.io.PrintWriter;
-import java.lang.Math;
 import java.util.ArrayDeque;
 import java.util.Calendar;
 import java.util.GregorianCalendar;
@@ -263,6 +262,17 @@
         }
     }
 
+    /**
+     * Call this when RemoteViews object has been removed from a notification because the images
+     * it contains are too big (even after rescaling).
+     */
+    public synchronized void registerImageRemoved(String packageName) {
+        AggregatedStats[] aggregatedStatsArray = getAggregatedStatsLocked(packageName);
+        for (AggregatedStats stats : aggregatedStatsArray) {
+            stats.numImagesRemoved++;
+        }
+    }
+
     // Locked by this.
     private AggregatedStats[] getAggregatedStatsLocked(NotificationRecord record) {
         return getAggregatedStatsLocked(record.sbn.getPackageName());
@@ -405,6 +415,7 @@
         public int numAlertViolations;
         public int numQuotaViolations;
         public long mLastAccessTime;
+        public int numImagesRemoved;
 
         public AggregatedStats(Context context, String key) {
             this.key = key;
@@ -529,6 +540,7 @@
             maybeCount("note_over_rate", (numRateViolations - previous.numRateViolations));
             maybeCount("note_over_alert_rate", (numAlertViolations - previous.numAlertViolations));
             maybeCount("note_over_quota", (numQuotaViolations - previous.numQuotaViolations));
+            maybeCount("note_images_removed", (numImagesRemoved - previous.numImagesRemoved));
             noisyImportance.maybeCount(previous.noisyImportance);
             quietImportance.maybeCount(previous.quietImportance);
             finalImportance.maybeCount(previous.finalImportance);
@@ -562,6 +574,7 @@
             previous.numRateViolations = numRateViolations;
             previous.numAlertViolations = numAlertViolations;
             previous.numQuotaViolations = numQuotaViolations;
+            previous.numImagesRemoved = numImagesRemoved;
             noisyImportance.update(previous.noisyImportance);
             quietImportance.update(previous.quietImportance);
             finalImportance.update(previous.finalImportance);
@@ -667,6 +680,8 @@
             output.append("numAlertViolations=").append(numAlertViolations).append("\n");
             output.append(indentPlusTwo);
             output.append("numQuotaViolations=").append(numQuotaViolations).append("\n");
+            output.append(indentPlusTwo);
+            output.append("numImagesRemoved=").append(numImagesRemoved).append("\n");
             output.append(indentPlusTwo).append(noisyImportance.toString()).append("\n");
             output.append(indentPlusTwo).append(quietImportance.toString()).append("\n");
             output.append(indentPlusTwo).append(finalImportance.toString()).append("\n");
@@ -709,6 +724,7 @@
             maybePut(dump, "numQuotaLViolations", numQuotaViolations);
             maybePut(dump, "notificationEnqueueRate", getEnqueueRate());
             maybePut(dump, "numAlertViolations", numAlertViolations);
+            maybePut(dump, "numImagesRemoved", numImagesRemoved);
             noisyImportance.maybePut(dump, previous.noisyImportance);
             quietImportance.maybePut(dump, previous.quietImportance);
             finalImportance.maybePut(dump, previous.finalImportance);
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index f81015d..ee948b2 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -16,6 +16,10 @@
 
 package com.android.server.notification;
 
+import static android.app.NotificationManager.AUTOMATIC_RULE_STATUS_DISABLED;
+import static android.app.NotificationManager.AUTOMATIC_RULE_STATUS_ENABLED;
+import static android.app.NotificationManager.AUTOMATIC_RULE_STATUS_REMOVED;
+
 import android.app.AppOpsManager;
 import android.app.AutomaticZenRule;
 import android.app.Notification;
@@ -351,6 +355,12 @@
                             "Cannot update rules not owned by your condition provider");
                 }
             }
+            if (rule.enabled != automaticZenRule.isEnabled()) {
+                dispatchOnAutomaticRuleStatusChanged(mConfig.user, rule.pkg, ruleId,
+                        automaticZenRule.isEnabled()
+                                ? AUTOMATIC_RULE_STATUS_ENABLED : AUTOMATIC_RULE_STATUS_DISABLED);
+            }
+
             populateZenRule(automaticZenRule, rule, false);
             return setConfigLocked(newConfig, reason, rule.component, true);
         }
@@ -370,6 +380,8 @@
                 throw new SecurityException(
                         "Cannot delete rules not owned by your condition provider");
             }
+            dispatchOnAutomaticRuleStatusChanged(
+                    mConfig.user, rule.pkg, id, AUTOMATIC_RULE_STATUS_REMOVED);
             return setConfigLocked(newConfig, reason, null, true);
         }
     }
@@ -1120,6 +1132,13 @@
         }
     }
 
+    private void dispatchOnAutomaticRuleStatusChanged(int userId, String pkg, String id,
+            int status) {
+        for (Callback callback : mCallbacks) {
+            callback.onAutomaticRuleStatusChanged(userId, pkg, id, status);
+        }
+    }
+
     private ZenModeConfig readDefaultConfig(Resources resources) {
         XmlResourceParser parser = null;
         try {
@@ -1509,5 +1528,6 @@
         void onZenModeChanged() {}
         void onPolicyChanged() {}
         void onConsolidatedPolicyChanged() {}
+        void onAutomaticRuleStatusChanged(int userId, String pkg, String id, int status) {}
     }
 }
diff --git a/services/core/java/com/android/server/pm/ApexManager.java b/services/core/java/com/android/server/pm/ApexManager.java
index 2301e3f..dd099b1 100644
--- a/services/core/java/com/android/server/pm/ApexManager.java
+++ b/services/core/java/com/android/server/pm/ApexManager.java
@@ -158,9 +158,9 @@
      * applied at next reboot.
      *
      * @param sessionId the identifier of the {@link PackageInstallerSession} being marked as ready.
-     * @return true upon success, false if the session is unknown.
+     * @throws PackageManagerException if call to apexd fails
      */
-    abstract boolean markStagedSessionReady(int sessionId);
+    abstract void markStagedSessionReady(int sessionId) throws PackageManagerException;
 
     /**
      * Marks a staged session as successful.
@@ -402,12 +402,16 @@
         }
 
         @Override
-        boolean markStagedSessionReady(int sessionId) {
+        void markStagedSessionReady(int sessionId) throws PackageManagerException {
             try {
-                return mApexService.markStagedSessionReady(sessionId);
+                mApexService.markStagedSessionReady(sessionId);
             } catch (RemoteException re) {
                 Slog.e(TAG, "Unable to contact apexservice", re);
                 throw new RuntimeException(re);
+            } catch (Exception e) {
+                throw new PackageManagerException(
+                        PackageInstaller.SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
+                        "Failed to mark apexd session as ready : " + e.getMessage());
             }
         }
 
@@ -576,7 +580,7 @@
         }
 
         @Override
-        boolean markStagedSessionReady(int sessionId) {
+        void markStagedSessionReady(int sessionId) {
             throw new UnsupportedOperationException();
         }
 
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index b14f481..8660d19 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -37,11 +37,11 @@
 import static android.content.pm.PackageManager.DELETE_KEEP_DATA;
 import static android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
 import static android.content.pm.PackageManager.FLAG_PERMISSION_POLICY_FIXED;
-import static android.content.pm.PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
 import static android.content.pm.PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE;
 import static android.content.pm.PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
 import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_FIXED;
 import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET;
+import static android.content.pm.PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER;
 import static android.content.pm.PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
 import static android.content.pm.PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
 import static android.content.pm.PackageManager.INSTALL_FAILED_DUPLICATE_PERMISSION;
@@ -90,6 +90,7 @@
 import static android.os.storage.StorageManager.FLAG_STORAGE_CE;
 import static android.os.storage.StorageManager.FLAG_STORAGE_DE;
 import static android.os.storage.StorageManager.FLAG_STORAGE_EXTERNAL;
+import static android.permission.PermissionManager.KILL_APP_REASON_GIDS_CHANGED;
 
 import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_MANAGED_PROFILE;
 import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_PARENT;
@@ -144,7 +145,6 @@
 import android.content.pm.FallbackCategoryProvider;
 import android.content.pm.FeatureInfo;
 import android.content.pm.IDexModuleRegisterCallback;
-import android.content.pm.IOnPermissionsChangeListener;
 import android.content.pm.IPackageDataObserver;
 import android.content.pm.IPackageDeleteObserver;
 import android.content.pm.IPackageDeleteObserver2;
@@ -168,9 +168,7 @@
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.LegacyPackageDeleteObserver;
 import android.content.pm.PackageManager.ModuleInfoFlags;
-import android.content.pm.PackageManager.PermissionWhitelistFlags;
 import android.content.pm.PackageManagerInternal;
-import android.content.pm.PackageManagerInternal.CheckPermissionDelegate;
 import android.content.pm.PackageManagerInternal.PackageListObserver;
 import android.content.pm.PackageParser;
 import android.content.pm.PackageParser.ActivityIntentInfo;
@@ -291,7 +289,6 @@
 import com.android.internal.util.DumpUtils;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.IndentingPrintWriter;
-import com.android.internal.util.IntPair;
 import com.android.internal.util.Preconditions;
 import com.android.server.AttributeCache;
 import com.android.server.DeviceIdleController;
@@ -317,7 +314,6 @@
 import com.android.server.pm.permission.DefaultPermissionGrantPolicy;
 import com.android.server.pm.permission.PermissionManagerService;
 import com.android.server.pm.permission.PermissionManagerServiceInternal;
-import com.android.server.pm.permission.PermissionManagerServiceInternal.PermissionCallback;
 import com.android.server.pm.permission.PermissionsState;
 import com.android.server.security.VerityUtils;
 import com.android.server.storage.DeviceStorageMonitorInternal;
@@ -580,12 +576,6 @@
 
     public static final String PLATFORM_PACKAGE_NAME = "android";
 
-    private static final String KILL_APP_REASON_GIDS_CHANGED =
-            "permission grant or revoke changed gids";
-
-    private static final String KILL_APP_REASON_PERMISSIONS_REVOKED =
-            "permissions revoked";
-
     private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";
 
     private static final String PACKAGE_SCHEME = "package";
@@ -915,8 +905,6 @@
     private AtomicInteger mNextMoveId = new AtomicInteger();
     private final MoveCallbacks mMoveCallbacks;
 
-    private final OnPermissionChangeListeners mOnPermissionChangeListeners;
-
     // Cache of users who need badging.
     private final SparseBooleanArray mUserNeedsBadging = new SparseBooleanArray();
 
@@ -1005,9 +993,6 @@
     }
 
     @GuardedBy("mPackages")
-    private CheckPermissionDelegate mCheckPermissionDelegate;
-
-    @GuardedBy("mPackages")
     private PackageManagerInternal.DefaultBrowserProvider mDefaultBrowserProvider;
 
     @GuardedBy("mPackages")
@@ -1766,66 +1751,6 @@
         }
     }
 
-    private PermissionCallback mPermissionCallback = new PermissionCallback() {
-        @Override
-        public void onGidsChanged(int appId, int userId) {
-            mHandler.post(() -> killUid(appId, userId, KILL_APP_REASON_GIDS_CHANGED));
-        }
-        @Override
-        public void onPermissionGranted(int uid, int userId) {
-            mOnPermissionChangeListeners.onPermissionsChanged(uid);
-
-            // Not critical; if this is lost, the application has to request again.
-            synchronized (mPackages) {
-                mSettings.writeRuntimePermissionsForUserLPr(userId, false);
-            }
-        }
-        @Override
-        public void onInstallPermissionGranted() {
-            synchronized (mPackages) {
-                scheduleWriteSettingsLocked();
-            }
-        }
-        @Override
-        public void onPermissionRevoked(int uid, int userId) {
-            mOnPermissionChangeListeners.onPermissionsChanged(uid);
-
-            synchronized (mPackages) {
-                // Critical; after this call the application should never have the permission
-                mSettings.writeRuntimePermissionsForUserLPr(userId, true);
-            }
-
-            final int appId = UserHandle.getAppId(uid);
-            killUid(appId, userId, KILL_APP_REASON_PERMISSIONS_REVOKED);
-        }
-        @Override
-        public void onInstallPermissionRevoked() {
-            synchronized (mPackages) {
-                scheduleWriteSettingsLocked();
-            }
-        }
-        @Override
-        public void onPermissionUpdated(int[] updatedUserIds, boolean sync) {
-            synchronized (mPackages) {
-                for (int userId : updatedUserIds) {
-                    mSettings.writeRuntimePermissionsForUserLPr(userId, sync);
-                }
-            }
-        }
-        @Override
-        public void onInstallPermissionUpdated() {
-            synchronized (mPackages) {
-                scheduleWriteSettingsLocked();
-            }
-        }
-        @Override
-        public void onPermissionRemoved() {
-            synchronized (mPackages) {
-                mSettings.writeLPr();
-            }
-        }
-    };
-
     private void handlePackagePostInstall(PackageInstalledInfo res, boolean grantPermissions,
             boolean killApp, boolean virtualPreload,
             String[] grantedPermissions, List<String> whitelistedRestrictedPermissions,
@@ -1846,8 +1771,7 @@
                     && !whitelistedRestrictedPermissions.isEmpty()) {
                 mPermissionManager.setWhitelistedRestrictedPermissions(
                         res.pkg, res.newUsers, whitelistedRestrictedPermissions,
-                        Process.myUid(), PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER,
-                        mPermissionCallback);
+                        Process.myUid(), FLAG_PERMISSION_WHITELIST_INSTALLER);
             }
 
             // Now that we successfully installed the package, grant runtime
@@ -1858,8 +1782,7 @@
             if (grantPermissions) {
                 final int callingUid = Binder.getCallingUid();
                 mPermissionManager.grantRequestedRuntimePermissions(
-                        res.pkg, res.newUsers, grantedPermissions, callingUid,
-                        mPermissionCallback);
+                        res.pkg, res.newUsers, grantedPermissions, callingUid);
             }
 
             final String installerPackageName =
@@ -1875,7 +1798,7 @@
             if (res.pkg.parentPackage != null) {
                 final int callingUid = Binder.getCallingUid();
                 mPermissionManager.grantRuntimePermissionsGrantedToDisabledPackage(
-                        res.pkg, callingUid, mPermissionCallback);
+                        res.pkg, callingUid);
             }
 
             synchronized (mPackages) {
@@ -2477,9 +2400,6 @@
 
         mViewCompiler = new ViewCompiler(mInstallLock, mInstaller);
 
-        mOnPermissionChangeListeners = new OnPermissionChangeListeners(
-                FgThread.get().getLooper());
-
         getDefaultDisplayMetrics(context, mMetrics);
 
         t.traceBegin("get system config");
@@ -3180,8 +3100,7 @@
                         + mSdkVersion + "; regranting permissions for internal storage");
             }
             mPermissionManager.updateAllPermissions(
-                    StorageManager.UUID_PRIVATE_INTERNAL, sdkUpdated, mPackages.values(),
-                    mPermissionCallback);
+                    StorageManager.UUID_PRIVATE_INTERNAL, sdkUpdated);
             ver.sdkVersion = mSdkVersion;
 
             // If this is the first boot or an update from pre-M, and it is a normal
@@ -3477,8 +3396,7 @@
                     } catch (PackageManagerException e) {
                         Slog.e(TAG, "updateAllSharedLibrariesLPw failed: ", e);
                     }
-                    mPermissionManager.updatePermissions(pkg.packageName, pkg, mPackages.values(),
-                            mPermissionCallback);
+                    mPermissionManager.updatePermissions(pkg.packageName, pkg);
                     mSettings.writeLPr();
                 }
             } catch (PackageManagerException e) {
@@ -4549,55 +4467,6 @@
         return -1;
     }
 
-    /**
-     * Check if any package sharing/holding a uid has a low enough target SDK.
-     *
-     * @param uid The uid of the packages
-     * @param higherTargetSDK The target SDK that might be higher than the searched package
-     *
-     * @return {@code true} if there is a package sharing/holding the uid with
-     * {@code package.targetSDK < higherTargetSDK}
-     */
-    private boolean hasTargetSdkInUidLowerThan(int uid, int higherTargetSDK) {
-        int userId = UserHandle.getUserId(uid);
-
-        synchronized (mPackages) {
-            Object obj = mSettings.getSettingLPr(UserHandle.getAppId(uid));
-            if (obj == null) {
-                return false;
-            }
-
-            if (obj instanceof PackageSetting) {
-                final PackageSetting ps = (PackageSetting) obj;
-
-                if (!ps.getInstalled(userId)) {
-                    return false;
-                }
-
-                return ps.pkg.applicationInfo.targetSdkVersion < higherTargetSDK;
-            } else if (obj instanceof SharedUserSetting) {
-                final SharedUserSetting sus = (SharedUserSetting) obj;
-
-                final int numPkgs = sus.packages.size();
-                for (int i = 0; i < numPkgs; i++) {
-                    final PackageSetting ps = sus.packages.valueAt(i);
-
-                    if (!ps.getInstalled(userId)) {
-                        continue;
-                    }
-
-                    if (ps.pkg.applicationInfo.targetSdkVersion < higherTargetSDK) {
-                        return true;
-                    }
-                }
-
-                return false;
-            } else {
-                return false;
-            }
-        }
-    }
-
     @Override
     public int[] getPackageGids(String packageName, int flags, int userId) {
         if (!sUserManager.exists(userId)) return null;
@@ -5607,46 +5476,26 @@
         }
     }
 
+    // NOTE: Can't remove due to unsupported app usage
     @Override
     public int checkPermission(String permName, String pkgName, int userId) {
-        final CheckPermissionDelegate checkPermissionDelegate;
-        synchronized (mPackages) {
-            if (mCheckPermissionDelegate == null)  {
-                return checkPermissionImpl(permName, pkgName, userId);
-            }
-            checkPermissionDelegate = mCheckPermissionDelegate;
-        }
-        return checkPermissionDelegate.checkPermission(permName, pkgName, userId,
-                PackageManagerService.this::checkPermissionImpl);
+        try {
+            // Because this is accessed via the package manager service AIDL,
+            // go through the permission manager service AIDL
+            return mPermissionManagerService.checkPermission(permName, pkgName, userId);
+        } catch (RemoteException ignore) { }
+        return PackageManager.PERMISSION_DENIED;
     }
 
-    private int checkPermissionImpl(String permName, String pkgName, int userId) {
-        return mPermissionManager.checkPermission(permName, pkgName, getCallingUid(), userId);
-    }
-
+    // NOTE: Can't remove without a major refactor. Keep around for now.
     @Override
     public int checkUidPermission(String permName, int uid) {
-        final CheckPermissionDelegate checkPermissionDelegate;
-        synchronized (mPackages) {
-            if (mCheckPermissionDelegate == null)  {
-                return checkUidPermissionImpl(permName, uid);
-            }
-            checkPermissionDelegate = mCheckPermissionDelegate;
-        }
-        return checkPermissionDelegate.checkUidPermission(permName, uid,
-                PackageManagerService.this::checkUidPermissionImpl);
-    }
-
-    private int checkUidPermissionImpl(String permName, int uid) {
-        synchronized (mPackages) {
-            final String[] packageNames = getPackagesForUid(uid);
-            PackageParser.Package pkg = null;
-            final int N = packageNames == null ? 0 : packageNames.length;
-            for (int i = 0; pkg == null && i < N; i++) {
-                pkg = mPackages.get(packageNames[i]);
-            }
-            return mPermissionManager.checkUidPermission(permName, pkg, uid, getCallingUid());
-        }
+        try {
+            // Because this is accessed via the package manager service AIDL,
+            // go through the permission manager service AIDL
+            return mPermissionManagerService.checkUidPermission(permName, uid);
+        } catch (RemoteException ignore) { }
+        return PackageManager.PERMISSION_DENIED;
     }
 
     @Override
@@ -5675,7 +5524,8 @@
 
         final long identity = Binder.clearCallingIdentity();
         try {
-            final int flags = getPermissionFlags(permission, packageName, userId);
+            final int flags = mPermissionManager
+                    .getPermissionFlags(permission, packageName, Binder.getCallingUid(), userId);
             return (flags & PackageManager.FLAG_PERMISSION_POLICY_FIXED) != 0;
         } finally {
             Binder.restoreCallingIdentity(identity);
@@ -5727,338 +5577,18 @@
         } catch (RemoteException ignore) { }
     }
 
+    // NOTE: Can't remove due to unsupported app usage
     @Override
     public void grantRuntimePermission(String packageName, String permName, final int userId) {
-        boolean overridePolicy = (checkUidPermission(
-                Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY, Binder.getCallingUid())
-                == PackageManager.PERMISSION_GRANTED);
-
-        mPermissionManager.grantRuntimePermission(permName, packageName, overridePolicy,
-                getCallingUid(), userId, mPermissionCallback);
-    }
-
-    @Override
-    public void revokeRuntimePermission(String packageName, String permName, int userId) {
-        boolean overridePolicy = (checkUidPermission(
-                Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY, Binder.getCallingUid())
-                == PackageManager.PERMISSION_GRANTED);
-
-        mPermissionManager.revokeRuntimePermission(permName, packageName, overridePolicy,
-                userId, mPermissionCallback);
-    }
-
-    @Override
-    public void resetRuntimePermissions() {
-        mContext.enforceCallingOrSelfPermission(
-                android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS,
-                "revokeRuntimePermission");
-
-        int callingUid = Binder.getCallingUid();
-        if (callingUid != Process.SYSTEM_UID && callingUid != 0) {
-            mContext.enforceCallingOrSelfPermission(
-                    android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
-                    "resetRuntimePermissions");
-        }
-
-        synchronized (mPackages) {
-            mPermissionManager.updateAllPermissions(
-                    StorageManager.UUID_PRIVATE_INTERNAL, false, mPackages.values(),
-                    mPermissionCallback);
-            for (int userId : UserManagerService.getInstance().getUserIds()) {
-                final int packageCount = mPackages.size();
-                for (int i = 0; i < packageCount; i++) {
-                    PackageParser.Package pkg = mPackages.valueAt(i);
-                    if (!(pkg.mExtras instanceof PackageSetting)) {
-                        continue;
-                    }
-                    PackageSetting ps = (PackageSetting) pkg.mExtras;
-                    resetUserChangesToRuntimePermissionsAndFlagsLPw(ps, userId);
-                }
-            }
-        }
-    }
-
-    @Override
-    public int getPermissionFlags(String permName, String packageName, int userId) {
-        return mPermissionManager.getPermissionFlags(
-                permName, packageName, getCallingUid(), userId);
-    }
-
-    @Override
-    public void updatePermissionFlags(String permName, String packageName, int flagMask,
-            int flagValues, boolean checkAdjustPolicyFlagPermission, int userId) {
-        int callingUid = getCallingUid();
-        boolean overridePolicy = false;
-
-        if (callingUid != Process.SYSTEM_UID && callingUid != Process.ROOT_UID) {
-            long callingIdentity = Binder.clearCallingIdentity();
-            try {
-                if ((flagMask & FLAG_PERMISSION_POLICY_FIXED) != 0) {
-                    if (checkAdjustPolicyFlagPermission) {
-                        mContext.enforceCallingOrSelfPermission(
-                                Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY,
-                                "Need " + Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY
-                                        + " to change policy flags");
-                    } else if (!hasTargetSdkInUidLowerThan(callingUid, Build.VERSION_CODES.Q)) {
-                        throw new IllegalArgumentException(
-                                Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY + " needs "
-                                        + " to be checked for packages targeting "
-                                        + Build.VERSION_CODES.Q + " or later when changing policy "
-                                        + "flags");
-                    }
-
-                    overridePolicy = true;
-                }
-            } finally {
-                Binder.restoreCallingIdentity(callingIdentity);
-            }
-        }
-
-        mPermissionManager.updatePermissionFlags(
-                permName, packageName, flagMask, flagValues, callingUid, userId,
-                overridePolicy, mPermissionCallback);
-    }
-
-    /**
-     * Update the permission flags for all packages and runtime permissions of a user in order
-     * to allow device or profile owner to remove POLICY_FIXED.
-     */
-    @Override
-    public void updatePermissionFlagsForAllApps(int flagMask, int flagValues, int userId) {
-        synchronized (mPackages) {
-            final boolean changed = mPermissionManager.updatePermissionFlagsForAllApps(
-                    flagMask, flagValues, getCallingUid(), userId, mPackages.values(),
-                    mPermissionCallback);
-            if (changed) {
-                mSettings.writeRuntimePermissionsForUserLPr(userId, false);
-            }
-        }
-    }
-
-    @Override
-    public @Nullable List<String> getWhitelistedRestrictedPermissions(@NonNull String packageName,
-            @PermissionWhitelistFlags int whitelistFlags, @UserIdInt int userId) {
-        Preconditions.checkNotNull(packageName);
-        Preconditions.checkFlagsArgument(whitelistFlags,
-                PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE
-                        | PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM
-                        | PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER);
-        Preconditions.checkArgumentNonNegative(userId, null);
-
-        if (UserHandle.getCallingUserId() != userId) {
-            mContext.enforceCallingOrSelfPermission(
-                    android.Manifest.permission.INTERACT_ACROSS_USERS,
-                    "getWhitelistedRestrictedPermissions for user " + userId);
-        }
-
-        final PackageParser.Package pkg;
-
-        synchronized (mPackages) {
-            final PackageSetting packageSetting = mSettings.mPackages.get(packageName);
-            if (packageSetting == null) {
-                Slog.w(TAG, "Unknown package: " + packageName);
-                return null;
-            }
-
-            pkg = packageSetting.pkg;
-
-            final boolean isCallerPrivileged = mContext.checkCallingOrSelfPermission(
-                    Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS)
-                            == PackageManager.PERMISSION_GRANTED;
-            final PackageSetting installerPackageSetting = mSettings.mPackages.get(
-                    packageSetting.installerPackageName);
-            final boolean isCallerInstallerOnRecord = installerPackageSetting != null
-                    && UserHandle.isSameApp(installerPackageSetting.appId, Binder.getCallingUid());
-
-            if ((whitelistFlags & PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM) != 0
-                    && !isCallerPrivileged) {
-                throw new SecurityException("Querying system whitelist requires "
-                        + Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS);
-            }
-
-            if ((whitelistFlags & (PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE
-                    | PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER)) != 0) {
-                if (!isCallerPrivileged && !isCallerInstallerOnRecord) {
-                    throw new SecurityException("Querying upgrade or installer whitelist"
-                            + " requires being installer on record or "
-                            + Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS);
-                }
-            }
-
-            if (filterAppAccessLPr(packageSetting, Binder.getCallingUid(),
-                    UserHandle.getCallingUserId())) {
-                return null;
-            }
-        }
-
-        final long identity = Binder.clearCallingIdentity();
         try {
-            return mPermissionManager.getWhitelistedRestrictedPermissions(
-                    pkg, whitelistFlags, userId);
-        } finally {
-            Binder.restoreCallingIdentity(identity);
-        }
+            // Because this is accessed via the package manager service AIDL,
+            // go through the permission manager service AIDL
+            mPermissionManagerService.grantRuntimePermission(packageName, permName, userId);
+        } catch (RemoteException ignore) { }
     }
 
     @Override
-    public boolean addWhitelistedRestrictedPermission(@NonNull String packageName,
-            @NonNull String permission, @PermissionWhitelistFlags int whitelistFlags,
-            @UserIdInt int userId) {
-        // Other argument checks are done in get/setWhitelistedRestrictedPermissions
-        Preconditions.checkNotNull(permission);
-
-        if (!checkExistsAndEnforceCannotModifyImmutablyRestrictedPermission(permission)) {
-            return false;
-        }
-
-        List<String> permissions = getWhitelistedRestrictedPermissions(packageName,
-                whitelistFlags, userId);
-        if (permissions == null) {
-            permissions = new ArrayList<>(1);
-        }
-        if (permissions.indexOf(permission) < 0) {
-            permissions.add(permission);
-            return setWhitelistedRestrictedPermissions(packageName, permissions,
-                    whitelistFlags, userId);
-        }
-        return false;
-    }
-
-    private boolean checkExistsAndEnforceCannotModifyImmutablyRestrictedPermission(
-            @NonNull String permission) {
-        synchronized (mPackages) {
-            final BasePermission bp = mPermissionManager.getPermissionTEMP(permission);
-            if (bp == null) {
-                Slog.w(TAG, "No such permissions: " + permission);
-                return false;
-            }
-            if (bp.isHardOrSoftRestricted() && bp.isImmutablyRestricted()
-                    && mContext.checkCallingOrSelfPermission(
-                    Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS)
-                    != PackageManager.PERMISSION_GRANTED) {
-                throw new SecurityException("Cannot modify whitelisting of an immutably "
-                        + "restricted permission: " + permission);
-            }
-            return true;
-        }
-    }
-
-    @Override
-    public boolean removeWhitelistedRestrictedPermission(@NonNull String packageName,
-            @NonNull String permission, @PermissionWhitelistFlags int whitelistFlags,
-            @UserIdInt int userId) {
-        // Other argument checks are done in get/setWhitelistedRestrictedPermissions
-        Preconditions.checkNotNull(permission);
-
-        if (!checkExistsAndEnforceCannotModifyImmutablyRestrictedPermission(permission)) {
-            return false;
-        }
-
-        final List<String> permissions = getWhitelistedRestrictedPermissions(packageName,
-                whitelistFlags, userId);
-        if (permissions != null && permissions.remove(permission)) {
-            return setWhitelistedRestrictedPermissions(packageName, permissions,
-                    whitelistFlags, userId);
-        }
-        return false;
-    }
-
-    private boolean setWhitelistedRestrictedPermissions(@NonNull String packageName,
-            @Nullable List<String> permissions, @PermissionWhitelistFlags int whitelistFlag,
-            @UserIdInt int userId) {
-        Preconditions.checkNotNull(packageName);
-        Preconditions.checkFlagsArgument(whitelistFlag,
-                PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE
-                        | PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM
-                        | PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER);
-        Preconditions.checkArgument(Integer.bitCount(whitelistFlag) == 1);
-        Preconditions.checkArgumentNonNegative(userId, null);
-
-        if (UserHandle.getCallingUserId() != userId) {
-            mContext.enforceCallingOrSelfPermission(
-                    Manifest.permission.INTERACT_ACROSS_USERS,
-                    "setWhitelistedRestrictedPermissions for user " + userId);
-        }
-
-        final PackageParser.Package pkg;
-
-        synchronized (mPackages) {
-            final PackageSetting packageSetting = mSettings.mPackages.get(packageName);
-            if (packageSetting == null) {
-                Slog.w(TAG, "Unknown package: " + packageName);
-                return false;
-            }
-
-            pkg = packageSetting.pkg;
-
-            final boolean isCallerPrivileged = mContext.checkCallingOrSelfPermission(
-                    Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS)
-                            == PackageManager.PERMISSION_GRANTED;
-            final PackageSetting installerPackageSetting = mSettings.mPackages.get(
-                    packageSetting.installerPackageName);
-            final boolean isCallerInstallerOnRecord = installerPackageSetting != null
-                    && UserHandle.isSameApp(installerPackageSetting.appId, Binder.getCallingUid());
-
-            if ((whitelistFlag & PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM) != 0
-                    && !isCallerPrivileged) {
-                throw new SecurityException("Modifying system whitelist requires "
-                        + Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS);
-            }
-
-            if ((whitelistFlag & PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE) != 0) {
-                if (!isCallerPrivileged && !isCallerInstallerOnRecord) {
-                    throw new SecurityException("Modifying upgrade whitelist requires"
-                            + " being installer on record or "
-                            + Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS);
-                }
-                final List<String> whitelistedPermissions = getWhitelistedRestrictedPermissions(
-                        packageName, whitelistFlag, userId);
-                if (permissions == null || permissions.isEmpty()) {
-                    if (whitelistedPermissions == null || whitelistedPermissions.isEmpty()) {
-                        return true;
-                    }
-                } else {
-                    // Only the system can add and remove while the installer can only remove.
-                    final int permissionCount = permissions.size();
-                    for (int i = 0; i < permissionCount; i++) {
-                        if ((whitelistedPermissions == null
-                                || !whitelistedPermissions.contains(permissions.get(i)))
-                                && !isCallerPrivileged) {
-                            throw new SecurityException("Adding to upgrade whitelist requires"
-                                    + Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS);
-                        }
-                    }
-                }
-            }
-
-            if ((whitelistFlag & PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER) != 0) {
-                if (!isCallerPrivileged && !isCallerInstallerOnRecord) {
-                    throw new SecurityException("Modifying installer whitelist requires"
-                            + " being installer on record or "
-                            + Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS);
-                }
-            }
-
-            if (filterAppAccessLPr(packageSetting, Binder.getCallingUid(),
-                    UserHandle.getCallingUserId())) {
-                return false;
-            }
-        }
-
-        final long identity = Binder.clearCallingIdentity();
-        try {
-            mPermissionManager.setWhitelistedRestrictedPermissions(pkg,
-                    new int[]{userId}, permissions, Process.myUid(), whitelistFlag,
-                    mPermissionCallback);
-        } finally {
-            Binder.restoreCallingIdentity(identity);
-        }
-
-        return true;
-    }
-
-    @Override
-    public boolean shouldShowRequestPermissionRationale(String permissionName,
+    public boolean shouldShowRequestPermissionRationale(String permName,
             String packageName, int userId) {
         if (UserHandle.getCallingUserId() != userId) {
             mContext.enforceCallingPermission(
@@ -6071,7 +5601,7 @@
             return false;
         }
 
-        if (checkPermission(permissionName, packageName, userId)
+        if (checkPermission(permName, packageName, userId)
                 == PackageManager.PERMISSION_GRANTED) {
             return false;
         }
@@ -6080,8 +5610,8 @@
 
         final long identity = Binder.clearCallingIdentity();
         try {
-            flags = getPermissionFlags(permissionName,
-                    packageName, userId);
+            flags = mPermissionManager
+                    .getPermissionFlags(permName, packageName, Binder.getCallingUid(), userId);
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
@@ -6098,27 +5628,6 @@
     }
 
     @Override
-    public void addOnPermissionsChangeListener(IOnPermissionsChangeListener listener) {
-        mContext.enforceCallingOrSelfPermission(
-                Manifest.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS,
-                "addOnPermissionsChangeListener");
-
-        synchronized (mPackages) {
-            mOnPermissionChangeListeners.addListenerLocked(listener);
-        }
-    }
-
-    @Override
-    public void removeOnPermissionsChangeListener(IOnPermissionsChangeListener listener) {
-        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
-            throw new SecurityException("Instant applications don't have access to this method");
-        }
-        synchronized (mPackages) {
-            mOnPermissionChangeListeners.removeListenerLocked(listener);
-        }
-    }
-
-    @Override
     public boolean isProtectedBroadcast(String actionName) {
         // allow instant applications
         synchronized (mProtectedBroadcasts) {
@@ -6280,29 +5789,6 @@
     }
 
     /**
-     * This method should typically only be used when granting or revoking
-     * permissions, since the app may immediately restart after this call.
-     * <p>
-     * If you're doing surgery on app code/data, use {@link PackageFreezer} to
-     * guard your work against the app being relaunched.
-     */
-    private void killUid(int appId, int userId, String reason) {
-        final long identity = Binder.clearCallingIdentity();
-        try {
-            IActivityManager am = ActivityManager.getService();
-            if (am != null) {
-                try {
-                    am.killUid(appId, userId, reason);
-                } catch (RemoteException e) {
-                    /* ignore - same process */
-                }
-            }
-        } finally {
-            Binder.restoreCallingIdentity(identity);
-        }
-    }
-
-    /**
      * If the database version for this type of package (internal storage or
      * external storage) is less than the version where package signatures
      * were updated, return true.
@@ -9850,16 +9336,6 @@
     }
 
     @GuardedBy("mPackages")
-    public CheckPermissionDelegate getCheckPermissionDelegateLocked() {
-        return mCheckPermissionDelegate;
-    }
-
-    @GuardedBy("mPackages")
-    public void setCheckPermissionDelegateLocked(CheckPermissionDelegate delegate) {
-        mCheckPermissionDelegate = delegate;
-    }
-
-    @GuardedBy("mPackages")
     private void notifyPackageUseLocked(String packageName, int reason) {
         final PackageParser.Package p = mPackages.get(packageName);
         if (p == null) {
@@ -12316,7 +11792,7 @@
 
                 AsyncTask.execute(() ->
                         mPermissionManager.revokeRuntimePermissionsIfGroupChanged(pkg, oldPkg,
-                                allPackageNames, mPermissionCallback));
+                                allPackageNames));
             }
         }
 
@@ -13562,8 +13038,8 @@
                         != 0 && pkgSetting.pkg != null) {
                     whiteListedPermissions = pkgSetting.pkg.requestedPermissions;
                 }
-                setWhitelistedRestrictedPermissions(packageName, whiteListedPermissions,
-                        PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER, userId);
+                mPermissionManager.setWhitelistedRestrictedPermissions(packageName,
+                        whiteListedPermissions, FLAG_PERMISSION_WHITELIST_INSTALLER, userId);
 
                 if (pkgSetting.pkg != null) {
                     synchronized (mInstallLock) {
@@ -16229,8 +15705,7 @@
         if (DEBUG_INSTALL) Slog.d(TAG, "New package installed in " + pkg.codePath);
         synchronized (mPackages) {
 // NOTE: This changes slightly to include UPDATE_PERMISSIONS_ALL regardless of the size of pkg.permissions
-            mPermissionManager.updatePermissions(pkg.packageName, pkg, mPackages.values(),
-                    mPermissionCallback);
+            mPermissionManager.updatePermissions(pkg.packageName, pkg);
             // For system-bundled packages, we assume that installing an upgraded version
             // of the package implies that the user actually wants to run that new code,
             // so we enable the package.
@@ -18899,8 +18374,7 @@
                     if (outInfo != null) {
                         outInfo.removedAppId = removedAppId;
                     }
-                    mPermissionManager.updatePermissions(
-                            deletedPs.name, null, mPackages.values(), mPermissionCallback);
+                    mPermissionManager.updatePermissions(deletedPs.name, null);
                     if (deletedPs.sharedUser != null) {
                         // Remove permissions associated with package. Since runtime
                         // permissions are per user we have to kill the removed package
@@ -19178,8 +18652,7 @@
             if (origPermissionState != null) {
                 ps.getPermissionsState().copyFrom(origPermissionState);
             }
-            mPermissionManager.updatePermissions(pkg.packageName, pkg, mPackages.values(),
-                    mPermissionCallback);
+            mPermissionManager.updatePermissions(pkg.packageName, pkg);
 
             final boolean applyUserRestrictions
                     = (allUserHandles != null) && (origUserHandles != null);
@@ -19641,9 +19114,7 @@
                     scheduleWritePackageRestrictionsLocked(nextUserId);
                 }
             }
-            synchronized (mPackages) {
-                resetUserChangesToRuntimePermissionsAndFlagsLPw(ps, nextUserId);
-            }
+            mPermissionManager.resetRuntimePermissions(pkg, nextUserId);
             // Also delete contributed media, when requested
             if ((flags & PackageManager.DELETE_CONTRIBUTED_MEDIA) != 0) {
                 try {
@@ -19754,15 +19225,12 @@
                     pkg = ps.pkg;
                 }
             }
-
-            if (pkg == null) {
-                Slog.w(TAG, "Package named '" + packageName + "' doesn't exist.");
-                return false;
-            }
-
-            PackageSetting ps = (PackageSetting) pkg.mExtras;
-            resetUserChangesToRuntimePermissionsAndFlagsLPw(ps, userId);
         }
+        if (pkg == null) {
+            Slog.w(TAG, "Package named '" + packageName + "' doesn't exist.");
+            return false;
+        }
+        mPermissionManager.resetRuntimePermissions(pkg, userId);
 
         clearAppDataLIF(pkg, userId,
                 FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL);
@@ -19784,201 +19252,11 @@
         return true;
     }
 
-    /**
-     * Reverts user permission state changes (permissions and flags) in
-     * all packages for a given user.
-     *
-     * @param userId The device user for which to do a reset.
-     */
-    @GuardedBy("mPackages")
-    private void resetUserChangesToRuntimePermissionsAndFlagsLPw(int userId) {
-        final int packageCount = mPackages.size();
-        for (int i = 0; i < packageCount; i++) {
-            PackageParser.Package pkg = mPackages.valueAt(i);
-            PackageSetting ps = (PackageSetting) pkg.mExtras;
-            resetUserChangesToRuntimePermissionsAndFlagsLPw(ps, userId);
-        }
-    }
-
     private void resetNetworkPolicies(int userId) {
         LocalServices.getService(NetworkPolicyManagerInternal.class).resetUserState(userId);
     }
 
     /**
-     * Reverts user permission state changes (permissions and flags).
-     *
-     * @param ps The package for which to reset.
-     * @param userId The device user for which to do a reset.
-     */
-    @GuardedBy("mPackages")
-    private void resetUserChangesToRuntimePermissionsAndFlagsLPw(
-            final PackageSetting ps, final int userId) {
-        if (ps.pkg == null) {
-            return;
-        }
-
-        final String packageName = ps.pkg.packageName;
-
-        // These are flags that can change base on user actions.
-        final int userSettableMask = FLAG_PERMISSION_USER_SET
-                | FLAG_PERMISSION_USER_FIXED
-                | FLAG_PERMISSION_REVOKE_ON_UPGRADE
-                | FLAG_PERMISSION_REVIEW_REQUIRED;
-
-        final int policyOrSystemFlags = FLAG_PERMISSION_SYSTEM_FIXED
-                | FLAG_PERMISSION_POLICY_FIXED;
-
-        // Delay and combine non-async permission callbacks
-        final boolean[] permissionRemoved = new boolean[1];
-        final ArraySet<Long> revokedPermissions = new ArraySet<>();
-        final SparseBooleanArray updatedUsers = new SparseBooleanArray();
-
-        PermissionCallback delayingPermCallback = new PermissionCallback() {
-            public void onGidsChanged(int appId, int userId) {
-                mPermissionCallback.onGidsChanged(appId, userId);
-            }
-
-            public void onPermissionChanged() {
-                mPermissionCallback.onPermissionChanged();
-            }
-
-            public void onPermissionGranted(int uid, int userId) {
-                mPermissionCallback.onPermissionGranted(uid, userId);
-            }
-
-            public void onInstallPermissionGranted() {
-                mPermissionCallback.onInstallPermissionGranted();
-            }
-
-            public void onPermissionRevoked(int uid, int userId) {
-                revokedPermissions.add(IntPair.of(uid, userId));
-
-                updatedUsers.put(userId, true);
-            }
-
-            public void onInstallPermissionRevoked() {
-                mPermissionCallback.onInstallPermissionRevoked();
-            }
-
-            public void onPermissionUpdated(int[] updatedUserIds, boolean sync) {
-                for (int userId : updatedUserIds) {
-                    if (sync) {
-                        updatedUsers.put(userId, true);
-                    } else {
-                        // Don't override sync=true by sync=false
-                        if (!updatedUsers.get(userId)) {
-                            updatedUsers.put(userId, false);
-                        }
-                    }
-                }
-            }
-
-            public void onPermissionRemoved() {
-                permissionRemoved[0] = true;
-            }
-
-            public void onInstallPermissionUpdated() {
-                mPermissionCallback.onInstallPermissionUpdated();
-            }
-        };
-
-        final int permissionCount = ps.pkg.requestedPermissions.size();
-        for (int i = 0; i < permissionCount; i++) {
-            final String permName = ps.pkg.requestedPermissions.get(i);
-            final BasePermission bp =
-                    (BasePermission) mPermissionManager.getPermissionTEMP(permName);
-            if (bp == null) {
-                continue;
-            }
-
-            if (bp.isRemoved()) {
-                continue;
-            }
-
-            // If shared user we just reset the state to which only this app contributed.
-            if (ps.sharedUser != null) {
-                boolean used = false;
-                final int packageCount = ps.sharedUser.packages.size();
-                for (int j = 0; j < packageCount; j++) {
-                    PackageSetting pkg = ps.sharedUser.packages.valueAt(j);
-                    if (pkg.pkg != null && !pkg.pkg.packageName.equals(ps.pkg.packageName)
-                            && pkg.pkg.requestedPermissions.contains(permName)) {
-                        used = true;
-                        break;
-                    }
-                }
-                if (used) {
-                    continue;
-                }
-            }
-
-            final int oldFlags = mPermissionManager.getPermissionFlags(permName, packageName,
-                    Process.SYSTEM_UID, userId);
-
-            // Always clear the user settable flags.
-            // If permission review is enabled and this is a legacy app, mark the
-            // permission as requiring a review as this is the initial state.
-            int flags = 0;
-            if (ps.pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M && bp.isRuntime()) {
-                flags |= FLAG_PERMISSION_REVIEW_REQUIRED | FLAG_PERMISSION_REVOKE_ON_UPGRADE;
-            }
-
-            mPermissionManager.updatePermissionFlags(permName, packageName,
-                    userSettableMask, flags, Process.SYSTEM_UID, userId, false,
-                    delayingPermCallback);
-
-            // Below is only runtime permission handling.
-            if (!bp.isRuntime()) {
-                continue;
-            }
-
-            // Never clobber system or policy.
-            if ((oldFlags & policyOrSystemFlags) != 0) {
-                continue;
-            }
-
-            // If this permission was granted by default, make sure it is.
-            if ((oldFlags & FLAG_PERMISSION_GRANTED_BY_DEFAULT) != 0) {
-                mPermissionManager.grantRuntimePermission(permName, packageName, false,
-                        Process.SYSTEM_UID, userId, delayingPermCallback);
-            // If permission review is enabled the permissions for a legacy apps
-            // are represented as constantly granted runtime ones, so don't revoke.
-            } else if ((flags & FLAG_PERMISSION_REVIEW_REQUIRED) == 0) {
-                // Otherwise, reset the permission.
-                mPermissionManager.revokeRuntimePermission(permName, packageName, false, userId,
-                        delayingPermCallback);
-            }
-        }
-
-        // Execute delayed callbacks
-        if (permissionRemoved[0]) {
-            mPermissionCallback.onPermissionRemoved();
-        }
-
-        // Slight variation on the code in mPermissionCallback.onPermissionRevoked() as we cannot
-        // kill uid while holding mPackages-lock
-        if (!revokedPermissions.isEmpty()) {
-            int numRevokedPermissions = revokedPermissions.size();
-            for (int i = 0; i < numRevokedPermissions; i++) {
-                int revocationUID = IntPair.first(revokedPermissions.valueAt(i));
-                int revocationUserId = IntPair.second(revokedPermissions.valueAt(i));
-
-                mOnPermissionChangeListeners.onPermissionsChanged(revocationUID);
-
-                // Kill app later as we are holding mPackages
-                mHandler.post(() -> killUid(UserHandle.getAppId(revocationUID), revocationUserId,
-                        KILL_APP_REASON_PERMISSIONS_REVOKED));
-            }
-        }
-
-        int numUpdatedUsers = updatedUsers.size();
-        for (int i = 0; i < numUpdatedUsers; i++) {
-            mSettings.writeRuntimePermissionsForUserLPr(updatedUsers.keyAt(i),
-                    updatedUsers.valueAt(i));
-        }
-    }
-
-    /**
      * Remove entries from the keystore daemon. Will only remove it if the
      * {@code appId} is valid.
      */
@@ -20434,8 +19712,8 @@
                 mSettings.applyDefaultPreferredAppsLPw(userId);
                 clearIntentFilterVerificationsLPw(userId);
                 primeDomainVerificationsLPw(userId);
-                resetUserChangesToRuntimePermissionsAndFlagsLPw(userId);
             }
+            mPermissionManager.resetAllRuntimePermissions(userId);
             updateDefaultHomeNotLocked(userId);
             // TODO: We have to reset the default SMS and Phone. This requires
             // significant refactoring to keep all default apps in the package
@@ -21647,9 +20925,7 @@
         // permissions, ensure permissions are updated. Beware of dragons if you
         // try optimizing this.
         synchronized (mPackages) {
-            mPermissionManager.updateAllPermissions(
-                    StorageManager.UUID_PRIVATE_INTERNAL, false, mPackages.values(),
-                    mPermissionCallback);
+            mPermissionManager.updateAllPermissions(StorageManager.UUID_PRIVATE_INTERNAL, false);
         }
 
         // Watch for external volumes that come and go over time
@@ -22642,8 +21918,7 @@
                 logCriticalInfo(Log.INFO, "Platform changed from " + ver.sdkVersion + " to "
                         + mSdkVersion + "; regranting permissions for " + volumeUuid);
             }
-            mPermissionManager.updateAllPermissions(volumeUuid, sdkUpdated, mPackages.values(),
-                    mPermissionCallback);
+            mPermissionManager.updateAllPermissions(volumeUuid, sdkUpdated);
 
             // Yay, everything is now upgraded
             ver.forceCurrent();
@@ -23671,9 +22946,7 @@
         mDefaultPermissionPolicy.grantDefaultPermissions(userId);
         synchronized(mPackages) {
             // NOTE: This adds UPDATE_PERMISSIONS_REPLACE_PKG
-            mPermissionManager.updateAllPermissions(
-                    StorageManager.UUID_PRIVATE_INTERNAL, true, mPackages.values(),
-                    mPermissionCallback);
+            mPermissionManager.updateAllPermissions(StorageManager.UUID_PRIVATE_INTERNAL, true);
         }
     }
 
@@ -24007,59 +23280,6 @@
         }
     }
 
-    private final static class OnPermissionChangeListeners extends Handler {
-        private static final int MSG_ON_PERMISSIONS_CHANGED = 1;
-
-        private final RemoteCallbackList<IOnPermissionsChangeListener> mPermissionListeners =
-                new RemoteCallbackList<>();
-
-        public OnPermissionChangeListeners(Looper looper) {
-            super(looper);
-        }
-
-        @Override
-        public void handleMessage(Message msg) {
-            switch (msg.what) {
-                case MSG_ON_PERMISSIONS_CHANGED: {
-                    final int uid = msg.arg1;
-                    handleOnPermissionsChanged(uid);
-                } break;
-            }
-        }
-
-        public void addListenerLocked(IOnPermissionsChangeListener listener) {
-            mPermissionListeners.register(listener);
-
-        }
-
-        public void removeListenerLocked(IOnPermissionsChangeListener listener) {
-            mPermissionListeners.unregister(listener);
-        }
-
-        public void onPermissionsChanged(int uid) {
-            if (mPermissionListeners.getRegisteredCallbackCount() > 0) {
-                obtainMessage(MSG_ON_PERMISSIONS_CHANGED, uid, 0).sendToTarget();
-            }
-        }
-
-        private void handleOnPermissionsChanged(int uid) {
-            final int count = mPermissionListeners.beginBroadcast();
-            try {
-                for (int i = 0; i < count; i++) {
-                    IOnPermissionsChangeListener callback = mPermissionListeners
-                            .getBroadcastItem(i);
-                    try {
-                        callback.onPermissionsChanged(uid);
-                    } catch (RemoteException e) {
-                        Log.e(TAG, "Permission listener is dead", e);
-                    }
-                }
-            } finally {
-                mPermissionListeners.finishBroadcast();
-            }
-        }
-    }
-
     private class PackageManagerNative extends IPackageManagerNative.Stub {
         @Override
         public String[] getNamesForUids(int[] uids) throws RemoteException {
@@ -24151,13 +23371,6 @@
 
     private class PackageManagerInternalImpl extends PackageManagerInternal {
         @Override
-        public void updatePermissionFlagsTEMP(String permName, String packageName, int flagMask,
-                int flagValues, int userId) {
-            PackageManagerService.this.updatePermissionFlags(
-                    permName, packageName, flagMask, flagValues, true, userId);
-        }
-
-        @Override
         public List<ApplicationInfo> getInstalledApplications(int flags, int userId,
                 int callingUid) {
             return PackageManagerService.this.getInstalledApplicationsListInternal(flags, userId,
@@ -24238,11 +23451,6 @@
         }
 
         @Override
-        public int getPermissionFlagsTEMP(String permName, String packageName, int userId) {
-            return PackageManagerService.this.getPermissionFlags(permName, packageName, userId);
-        }
-
-        @Override
         public boolean isInstantApp(String packageName, int userId) {
             return PackageManagerService.this.isInstantApp(packageName, userId);
         }
@@ -24270,6 +23478,19 @@
         }
 
         @Override
+        public PackageParser.Package getPackage(int uid) {
+            synchronized (mPackages) {
+                final String[] packageNames = getPackagesForUid(uid);
+                PackageParser.Package pkg = null;
+                final int numPackages = packageNames == null ? 0 : packageNames.length;
+                for (int i = 0; pkg == null && i < numPackages; i++) {
+                    pkg = mPackages.get(packageNames[i]);
+                }
+                return pkg;
+            }
+        }
+
+        @Override
         public PackageList getPackageList(PackageListObserver observer) {
             synchronized (mPackages) {
                 final int N = mPackages.size();
@@ -24575,22 +23796,6 @@
         }
 
         @Override
-        public void grantRuntimePermission(String packageName, String permName, int userId,
-                boolean overridePolicy) {
-            PackageManagerService.this.mPermissionManager.grantRuntimePermission(
-                    permName, packageName, overridePolicy, getCallingUid(), userId,
-                    mPermissionCallback);
-        }
-
-        @Override
-        public void revokeRuntimePermission(String packageName, String permName, int userId,
-                boolean overridePolicy) {
-            mPermissionManager.revokeRuntimePermission(
-                    permName, packageName, overridePolicy, userId,
-                    mPermissionCallback);
-        }
-
-        @Override
         public String getNameForUid(int uid) {
             return PackageManagerService.this.getNameForUid(uid);
         }
@@ -24793,20 +23998,6 @@
         }
 
         @Override
-        public CheckPermissionDelegate getCheckPermissionDelegate() {
-            synchronized (mPackages) {
-                return PackageManagerService.this.getCheckPermissionDelegateLocked();
-            }
-        }
-
-        @Override
-        public void setCheckPermissionDelegate(CheckPermissionDelegate delegate) {
-            synchronized (mPackages) {
-                PackageManagerService.this.setCheckPermissionDelegateLocked(delegate);
-            }
-        }
-
-        @Override
         public SparseArray<String> getAppsWithSharedUserIds() {
             synchronized (mPackages) {
                 return getAppsWithSharedUserIdsLocked();
@@ -25016,6 +24207,65 @@
                 }
             }
         }
+
+        @Override
+        public void writePermissionSettings(int[] userIds, boolean async) {
+            synchronized (mPackages) {
+                for (int userId : userIds) {
+                    mSettings.writeRuntimePermissionsForUserLPr(userId, !async);
+                }
+            }
+        }
+
+        @Override
+        public int getTargetSdk(int uid) {
+            int userId = UserHandle.getUserId(uid);
+
+            synchronized (mPackages) {
+                final Object obj = mSettings.getSettingLPr(UserHandle.getAppId(uid));
+                if (obj instanceof PackageSetting) {
+                    final PackageSetting ps = (PackageSetting) obj;
+                    if (!ps.getInstalled(userId)) {
+                        return 0;
+                    }
+                    return ps.pkg.applicationInfo.targetSdkVersion;
+                } else if (obj instanceof SharedUserSetting) {
+                    int maxTargetSdk = 0;
+                    final SharedUserSetting sus = (SharedUserSetting) obj;
+                    final int numPkgs = sus.packages.size();
+                    for (int i = 0; i < numPkgs; i++) {
+                        final PackageSetting ps = sus.packages.valueAt(i);
+                        if (!ps.getInstalled(userId)) {
+                            continue;
+                        }
+                        if (ps.pkg.applicationInfo.targetSdkVersion < maxTargetSdk) {
+                            continue;
+                        }
+                        maxTargetSdk = ps.pkg.applicationInfo.targetSdkVersion;
+                    }
+                    return maxTargetSdk;
+                }
+                return 0;
+            }
+        }
+
+        @Override
+        public boolean isCallerInstallerOfRecord(
+                @NonNull PackageParser.Package pkg, int callingUid) {
+            synchronized (mPackages) {
+                if (pkg == null) {
+                    return false;
+                }
+                final PackageSetting packageSetting = (PackageSetting) pkg.mExtras;
+                if (packageSetting == null) {
+                    return false;
+                }
+                final PackageSetting installerPackageSetting =
+                        mSettings.mPackages.get(packageSetting.installerPackageName);
+                return installerPackageSetting != null
+                        && UserHandle.isSameApp(installerPackageSetting.appId, callingUid);
+            }
+        }
     }
 
     @GuardedBy("mPackages")
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
index 45b6834..f56e1ef 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
@@ -62,6 +62,7 @@
 import com.android.server.EventLogTags;
 import com.android.server.pm.dex.DexManager;
 import com.android.server.pm.dex.PackageDexUsage;
+import com.android.server.pm.permission.PermissionsState;
 
 import dalvik.system.VMRuntime;
 
@@ -885,4 +886,16 @@
             IoUtils.closeQuietly(source);
         }
     }
+
+    /**
+     * Returns the {@link PermissionsState} for the given package. If the {@link PermissionsState}
+     * could not be found, {@code null} will be returned.
+     */
+    public static PermissionsState getPermissionsState(PackageParser.Package pkg) {
+        final PackageSetting packageSetting = (PackageSetting) pkg.mExtras;
+        if (packageSetting == null) {
+            return null;
+        }
+        return packageSetting.getPermissionsState();
+    }
 }
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index a25c68f..53c1c1f 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -1997,15 +1997,15 @@
         }
 
         if (grant) {
-            mInterface.grantRuntimePermission(pkg, perm, userId);
+            mPermissionManager.grantRuntimePermission(pkg, perm, userId);
         } else {
-            mInterface.revokeRuntimePermission(pkg, perm, userId);
+            mPermissionManager.revokeRuntimePermission(pkg, perm, userId);
         }
         return 0;
     }
 
     private int runResetPermissions() throws RemoteException {
-        mInterface.resetRuntimePermissions();
+        mPermissionManager.resetRuntimePermissions();
         return 0;
     }
 
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index 404b515..bf141a0 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -242,11 +242,11 @@
         }
 
         if (sessionContainsApk(session)) {
-            if (!installApksInSession(session, /* preReboot */ true)) {
-                session.setStagedSessionFailed(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
-                        "APK verification failed. Check logcat messages for "
-                                + "more information.");
+            try {
+                installApksInSession(session, /* preReboot */ true);
                 // TODO(b/118865310): abort the session on apexd.
+            } catch (PackageManagerException e) {
+                session.setStagedSessionFailed(e.error, e.getMessage());
                 return;
             }
         }
@@ -278,10 +278,14 @@
         // session as ready), then if a device gets rebooted right after the call to apexd, only
         // apex part of the train will be applied, leaving device in an inconsistent state.
         session.setStagedSessionReady();
-        if (hasApex && !mApexManager.markStagedSessionReady(session.sessionId)) {
-            session.setStagedSessionFailed(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
-                            "APEX staging failed, check logcat messages from apexd for more "
-                            + "details.");
+        if (!hasApex) {
+            // Session doesn't contain apex, nothing to do.
+            return;
+        }
+        try {
+            mApexManager.markStagedSessionReady(session.sessionId);
+        } catch (PackageManagerException e) {
+            session.setStagedSessionFailed(e.error, e.getMessage());
         }
     }
 
@@ -311,7 +315,7 @@
     }
 
     private void resumeSession(@NonNull PackageInstallerSession session) {
-        boolean hasApex = sessionContainsApex(session);
+        final boolean hasApex = sessionContainsApex(session);
         if (hasApex) {
             // Check with apexservice whether the apex packages have been activated.
             ApexSessionInfo apexSessionInfo = mApexManager.getStagedSessionInfo(session.sessionId);
@@ -346,10 +350,10 @@
             }
         }
         // The APEX part of the session is activated, proceed with the installation of APKs.
-        if (!installApksInSession(session, /* preReboot */ false)) {
-            session.setStagedSessionFailed(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED,
-                    "Staged installation of APKs failed. Check logcat messages for"
-                        + "more information.");
+        try {
+            installApksInSession(session, /* preReboot */ false);
+        } catch (PackageManagerException e) {
+            session.setStagedSessionFailed(e.error, e.getMessage());
 
             if (!hasApex) {
                 return;
@@ -384,16 +388,22 @@
         return ret;
     }
 
+    @NonNull
     private PackageInstallerSession createAndWriteApkSession(
-            @NonNull PackageInstallerSession originalSession, boolean preReboot) {
+            @NonNull PackageInstallerSession originalSession, boolean preReboot)
+            throws PackageManagerException {
+        final int errorCode = preReboot ? SessionInfo.STAGED_SESSION_VERIFICATION_FAILED
+                : SessionInfo.STAGED_SESSION_ACTIVATION_FAILED;
         if (originalSession.stageDir == null) {
             Slog.wtf(TAG, "Attempting to install a staged APK session with no staging dir");
-            return null;
+            throw new PackageManagerException(errorCode,
+                    "Attempting to install a staged APK session with no staging dir");
         }
         List<String> apkFilePaths = findAPKsInDir(originalSession.stageDir);
         if (apkFilePaths.isEmpty()) {
             Slog.w(TAG, "Can't find staged APK in " + originalSession.stageDir.getAbsolutePath());
-            return null;
+            throw new PackageManagerException(errorCode,
+                    "Can't find staged APK in " + originalSession.stageDir.getAbsolutePath());
         }
 
         PackageInstaller.SessionParams params = originalSession.params.copy();
@@ -420,20 +430,22 @@
                 long sizeBytes = pfd.getStatSize();
                 if (sizeBytes < 0) {
                     Slog.e(TAG, "Unable to get size of: " + apkFilePath);
-                    return null;
+                    throw new PackageManagerException(errorCode,
+                            "Unable to get size of: " + apkFilePath);
                 }
                 apkSession.write(apkFile.getName(), 0, sizeBytes, pfd);
             }
         } catch (IOException e) {
             Slog.e(TAG, "Failure to install APK staged session " + originalSession.sessionId, e);
-            return null;
+            throw new PackageManagerException(errorCode, "Failed to write APK session", e);
         }
         return apkSession;
     }
 
-    private boolean commitApkSession(@NonNull PackageInstallerSession apkSession,
-                                     int originalSessionId, boolean preReboot) {
-
+    private void commitApkSession(@NonNull PackageInstallerSession apkSession,
+            int originalSessionId, boolean preReboot) throws PackageManagerException {
+        final int errorCode = preReboot ? SessionInfo.STAGED_SESSION_VERIFICATION_FAILED
+                : SessionInfo.STAGED_SESSION_ACTIVATION_FAILED;
         if (!preReboot) {
             if ((apkSession.params.installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0) {
                 // If rollback is available for this session, notify the rollback
@@ -453,23 +465,24 @@
         final Intent result = receiver.getResult();
         final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
                 PackageInstaller.STATUS_FAILURE);
-        if (status == PackageInstaller.STATUS_SUCCESS) {
-            return true;
+        if (status != PackageInstaller.STATUS_SUCCESS) {
+
+            final String errorMessage = result.getStringExtra(
+                    PackageInstaller.EXTRA_STATUS_MESSAGE);
+            Slog.e(TAG, "Failure to install APK staged session " + originalSessionId + " ["
+                    + errorMessage + "]");
+            throw new PackageManagerException(errorCode, errorMessage);
         }
-        Slog.e(TAG, "Failure to install APK staged session " + originalSessionId + " ["
-                + result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + "]");
-        return false;
     }
 
-    private boolean installApksInSession(@NonNull PackageInstallerSession session,
-                                         boolean preReboot) {
+    private void installApksInSession(@NonNull PackageInstallerSession session,
+                                         boolean preReboot) throws PackageManagerException {
+        final int errorCode = preReboot ? SessionInfo.STAGED_SESSION_VERIFICATION_FAILED
+                : SessionInfo.STAGED_SESSION_ACTIVATION_FAILED;
         if (!session.isMultiPackage() && !isApexSession(session)) {
             // APK single-packaged staged session. Do a regular install.
             PackageInstallerSession apkSession = createAndWriteApkSession(session, preReboot);
-            if (apkSession == null) {
-                return false;
-            }
-            return commitApkSession(apkSession, session.sessionId, preReboot);
+            commitApkSession(apkSession, session.sessionId, preReboot);
         } else if (session.isMultiPackage()) {
             // For multi-package staged sessions containing APKs, we identify which child sessions
             // contain an APK, and with those then create a new multi-package group of sessions,
@@ -487,7 +500,7 @@
             }
             if (childSessions.isEmpty()) {
                 // APEX-only multi-package staged session, nothing to do.
-                return true;
+                return;
             }
             PackageInstaller.SessionParams params = session.params.copy();
             params.isStaged = false;
@@ -504,26 +517,24 @@
             } catch (IOException e) {
                 Slog.e(TAG, "Unable to prepare multi-package session for staged session "
                         + session.sessionId);
-                return false;
+                throw new PackageManagerException(errorCode,
+                        "Unable to prepare multi-package session for staged session");
             }
 
             for (PackageInstallerSession sessionToClone : childSessions) {
                 PackageInstallerSession apkChildSession =
                         createAndWriteApkSession(sessionToClone, preReboot);
-                if (apkChildSession == null) {
-                    return false;
-                }
                 try {
                     apkParentSession.addChildSessionId(apkChildSession.sessionId);
                 } catch (IllegalStateException e) {
                     Slog.e(TAG, "Failed to add a child session for installing the APK files", e);
-                    return false;
+                    throw new PackageManagerException(errorCode,
+                            "Failed to add a child session " + apkChildSession.sessionId);
                 }
             }
-            return commitApkSession(apkParentSession, session.sessionId, preReboot);
+            commitApkSession(apkParentSession, session.sessionId, preReboot);
         }
         // APEX single-package staged session, nothing to do.
-        return true;
     }
 
     void commitSession(@NonNull PackageInstallerSession session) {
diff --git a/services/core/java/com/android/server/pm/TEST_MAPPING b/services/core/java/com/android/server/pm/TEST_MAPPING
index 15dc6ae..e375fa4 100644
--- a/services/core/java/com/android/server/pm/TEST_MAPPING
+++ b/services/core/java/com/android/server/pm/TEST_MAPPING
@@ -8,6 +8,14 @@
     },
     {
       "name": "CtsCompilationTestCases"
+    },
+    {
+      "name": "CtsPermissionTestCases",
+      "options": [
+        {
+            "include-filter": "android.permission.cts.PermissionUpdateListenerTest"
+        }
+      ]
     }
   ],
   "imports": [
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 230b221..9d0b427 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -16,6 +16,7 @@
 
 package com.android.server.pm.permission;
 
+import static android.Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY;
 import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
 import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
 import static android.content.pm.PackageManager.FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT;
@@ -33,12 +34,15 @@
 import static android.content.pm.PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE;
 import static android.content.pm.PackageManager.MASK_PERMISSION_FLAGS_ALL;
 import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
+import static android.permission.PermissionManager.KILL_APP_REASON_GIDS_CHANGED;
+import static android.permission.PermissionManager.KILL_APP_REASON_PERMISSIONS_REVOKED;
 
 import static com.android.server.pm.PackageManagerService.DEBUG_INSTALL;
 import static com.android.server.pm.PackageManagerService.DEBUG_PACKAGE_SCANNING;
 import static com.android.server.pm.PackageManagerService.DEBUG_PERMISSIONS;
 import static com.android.server.pm.PackageManagerService.DEBUG_REMOVE;
 import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
+import static com.android.server.pm.permission.PermissionManagerService.killUid;
 import static com.android.server.pm.permission.PermissionsState.PERMISSION_OPERATION_FAILURE;
 
 import static java.util.concurrent.TimeUnit.SECONDS;
@@ -48,7 +52,9 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
+import android.app.ActivityManager;
 import android.app.ApplicationPackageManager;
+import android.app.IActivityManager;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.PermissionGroupInfoFlags;
@@ -65,7 +71,11 @@
 import android.os.Build;
 import android.os.Handler;
 import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.Message;
 import android.os.Process;
+import android.os.RemoteCallbackList;
+import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.Trace;
 import android.os.UserHandle;
@@ -73,16 +83,19 @@
 import android.os.UserManagerInternal;
 import android.os.storage.StorageManager;
 import android.os.storage.StorageManagerInternal;
+import android.permission.IOnPermissionsChangeListener;
 import android.permission.IPermissionManager;
 import android.permission.PermissionControllerManager;
 import android.permission.PermissionManager;
 import android.permission.PermissionManagerInternal;
+import android.permission.PermissionManagerInternal.CheckPermissionDelegate;
 import android.permission.PermissionManagerInternal.OnRuntimePermissionStateChangedListener;
 import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.DebugUtils;
 import android.util.EventLog;
+import android.util.IntArray;
 import android.util.Log;
 import android.util.Slog;
 import android.util.SparseArray;
@@ -93,6 +106,8 @@
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.os.RoSystemProperties;
 import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.IntPair;
+import com.android.internal.util.Preconditions;
 import com.android.internal.util.function.pooled.PooledLambda;
 import com.android.server.FgThread;
 import com.android.server.LocalServices;
@@ -112,7 +127,6 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
@@ -123,6 +137,7 @@
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
+import java.util.function.Consumer;
 
 /**
  * Manages all permissions and handles permissions related tasks.
@@ -229,6 +244,70 @@
     final private ArrayList<OnRuntimePermissionStateChangedListener>
             mRuntimePermissionStateChangedListeners = new ArrayList<>();
 
+    @GuardedBy("mLock")
+    private CheckPermissionDelegate mCheckPermissionDelegate;
+
+    @GuardedBy("mLock")
+    private final OnPermissionChangeListeners mOnPermissionChangeListeners;
+
+    // TODO: Take a look at the methods defined in the callback.
+    // The callback was initially created to support the split between permission
+    // manager and the package manager. However, it's started to be used for other
+    // purposes. It may make sense to keep as an abstraction, but, the methods
+    // necessary to be overridden may be different than what was initially needed
+    // for the split.
+    private PermissionCallback mDefaultPermissionCallback = new PermissionCallback() {
+        @Override
+        public void onGidsChanged(int appId, int userId) {
+            mHandler.post(() -> killUid(appId, userId, KILL_APP_REASON_GIDS_CHANGED));
+        }
+        @Override
+        public void onPermissionGranted(int uid, int userId) {
+            mOnPermissionChangeListeners.onPermissionsChanged(uid);
+
+            // Not critical; if this is lost, the application has to request again.
+            mPackageManagerInt.writeSettings(true);
+        }
+        @Override
+        public void onInstallPermissionGranted() {
+            mPackageManagerInt.writeSettings(true);
+        }
+        @Override
+        public void onPermissionRevoked(int uid, int userId) {
+            mOnPermissionChangeListeners.onPermissionsChanged(uid);
+
+            // Critical; after this call the application should never have the permission
+            mPackageManagerInt.writeSettings(false);
+            final int appId = UserHandle.getAppId(uid);
+            killUid(appId, userId, KILL_APP_REASON_PERMISSIONS_REVOKED);
+        }
+        @Override
+        public void onInstallPermissionRevoked() {
+            mPackageManagerInt.writeSettings(true);
+        }
+        @Override
+        public void onPermissionUpdated(int[] userIds, boolean sync) {
+            mPackageManagerInt.writePermissionSettings(userIds, !sync);
+        }
+        @Override
+        public void onInstallPermissionUpdated() {
+            mPackageManagerInt.writeSettings(true);
+        }
+        @Override
+        public void onPermissionRemoved() {
+            mPackageManagerInt.writeSettings(false);
+        }
+        public void onPermissionUpdatedNotifyListener(@UserIdInt int[] updatedUserIds, boolean sync,
+                int uid) {
+            onPermissionUpdated(updatedUserIds, sync);
+            mOnPermissionChangeListeners.onPermissionsChanged(uid);
+        }
+        public void onInstallPermissionUpdatedNotifyListener(int uid) {
+            onInstallPermissionUpdated();
+            mOnPermissionChangeListeners.onPermissionsChanged(uid);
+        }
+    };
+
     PermissionManagerService(Context context,
             @NonNull Object externalLock) {
         mContext = context;
@@ -248,6 +327,7 @@
         SystemConfig systemConfig = SystemConfig.getInstance();
         mSystemPermissions = systemConfig.getSystemPermissions();
         mGlobalGids = systemConfig.getGlobalGids();
+        mOnPermissionChangeListeners = new OnPermissionChangeListeners(FgThread.get().getLooper());
 
         // propagate permission configuration
         final ArrayMap<String, SystemConfig.PermissionEntry> permConfig =
@@ -298,6 +378,29 @@
         return LocalServices.getService(PermissionManagerServiceInternal.class);
     }
 
+    /**
+     * This method should typically only be used when granting or revoking
+     * permissions, since the app may immediately restart after this call.
+     * <p>
+     * If you're doing surgery on app code/data, use {@link PackageFreezer} to
+     * guard your work against the app being relaunched.
+     */
+    public static void killUid(int appId, int userId, String reason) {
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            IActivityManager am = ActivityManager.getService();
+            if (am != null) {
+                try {
+                    am.killUid(appId, userId, reason);
+                } catch (RemoteException e) {
+                    /* ignore - same process */
+                }
+            }
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
     @Nullable BasePermission getPermission(String permName) {
         synchronized (mLock) {
             return mSettings.getPermissionLocked(permName);
@@ -456,12 +559,232 @@
         }
     }
 
-    private int checkPermission(String permName, String pkgName, int callingUid, int userId) {
+    @Override
+    public int getPermissionFlags(String permName, String packageName, int userId) {
+        final int callingUid = getCallingUid();
+        return getPermissionFlagsInternal(permName, packageName, callingUid, userId);
+    }
+
+    private int getPermissionFlagsInternal(
+            String permName, String packageName, int callingUid, int userId) {
+        if (!mUserManagerInt.exists(userId)) {
+            return 0;
+        }
+
+        enforceGrantRevokeGetRuntimePermissionPermissions("getPermissionFlags");
+        enforceCrossUserPermission(callingUid, userId,
+                true,  // requireFullPermission
+                false, // checkShell
+                false, // requirePermissionWhenSameUser
+                "getPermissionFlags");
+
+        final PackageParser.Package pkg = mPackageManagerInt.getPackage(packageName);
+        if (pkg == null || pkg.mExtras == null) {
+            return 0;
+        }
+        synchronized (mLock) {
+            if (mSettings.getPermissionLocked(permName) == null) {
+                return 0;
+            }
+        }
+        if (mPackageManagerInt.filterAppAccess(pkg, callingUid, userId)) {
+            return 0;
+        }
+        final PackageSetting ps = (PackageSetting) pkg.mExtras;
+        PermissionsState permissionsState = ps.getPermissionsState();
+        return permissionsState.getPermissionFlags(permName, userId);
+    }
+
+    @Override
+    public void updatePermissionFlags(String permName, String packageName, int flagMask,
+            int flagValues, boolean checkAdjustPolicyFlagPermission, int userId) {
+        final int callingUid = getCallingUid();
+        boolean overridePolicy = false;
+
+        if (callingUid != Process.SYSTEM_UID && callingUid != Process.ROOT_UID) {
+            long callingIdentity = Binder.clearCallingIdentity();
+            try {
+                if ((flagMask & FLAG_PERMISSION_POLICY_FIXED) != 0) {
+                    if (checkAdjustPolicyFlagPermission) {
+                        mContext.enforceCallingOrSelfPermission(
+                                Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY,
+                                "Need " + Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY
+                                        + " to change policy flags");
+                    } else if (mPackageManagerInt.getTargetSdk(callingUid)
+                            >= Build.VERSION_CODES.Q) {
+                        throw new IllegalArgumentException(
+                                Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY + " needs "
+                                        + " to be checked for packages targeting "
+                                        + Build.VERSION_CODES.Q + " or later when changing policy "
+                                        + "flags");
+                    }
+                    overridePolicy = true;
+                }
+            } finally {
+                Binder.restoreCallingIdentity(callingIdentity);
+            }
+        }
+
+        updatePermissionFlagsInternal(
+                permName, packageName, flagMask, flagValues, callingUid, userId,
+                overridePolicy, mDefaultPermissionCallback);
+    }
+
+    private void updatePermissionFlagsInternal(String permName, String packageName, int flagMask,
+            int flagValues, int callingUid, int userId, boolean overridePolicy,
+            PermissionCallback callback) {
+        if (ApplicationPackageManager.DEBUG_TRACE_GRANTS
+                && ApplicationPackageManager.shouldTraceGrant(packageName, permName, userId)) {
+            Log.i(TAG, "System is updating flags for "
+                            + permName + " for user " + userId  + " "
+                            + DebugUtils.flagsToString(
+                                    PackageManager.class, "FLAG_PERMISSION_", flagMask)
+                            + " := "
+                            + DebugUtils.flagsToString(
+                                    PackageManager.class, "FLAG_PERMISSION_", flagValues)
+                            + " on behalf of uid " + callingUid
+                            + " " + mPackageManagerInt.getNameForUid(callingUid),
+                    new RuntimeException());
+        }
+
+        if (!mUserManagerInt.exists(userId)) {
+            return;
+        }
+
+        enforceGrantRevokeRuntimePermissionPermissions("updatePermissionFlags");
+
+        enforceCrossUserPermission(callingUid, userId,
+                true,  // requireFullPermission
+                true,  // checkShell
+                false, // requirePermissionWhenSameUser
+                "updatePermissionFlags");
+
+        if ((flagMask & FLAG_PERMISSION_POLICY_FIXED) != 0 && !overridePolicy) {
+            throw new SecurityException("updatePermissionFlags requires "
+                    + Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY);
+        }
+
+        // Only the system can change these flags and nothing else.
+        if (callingUid != Process.SYSTEM_UID) {
+            flagMask &= ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
+            flagValues &= ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
+            flagMask &= ~PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
+            flagValues &= ~PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
+            flagValues &= ~PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
+            flagValues &= ~PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT;
+            flagValues &= ~PackageManager.FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
+            flagValues &= ~PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
+            flagValues &= ~PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION;
+        }
+
+        final PackageParser.Package pkg = mPackageManagerInt.getPackage(packageName);
+        if (pkg == null || pkg.mExtras == null) {
+            Log.e(TAG, "Unknown package: " + packageName);
+            return;
+        }
+        if (mPackageManagerInt.filterAppAccess(pkg, callingUid, userId)) {
+            throw new IllegalArgumentException("Unknown package: " + packageName);
+        }
+
+        final BasePermission bp;
+        synchronized (mLock) {
+            bp = mSettings.getPermissionLocked(permName);
+        }
+        if (bp == null) {
+            throw new IllegalArgumentException("Unknown permission: " + permName);
+        }
+
+        final PackageSetting ps = (PackageSetting) pkg.mExtras;
+        final PermissionsState permissionsState = ps.getPermissionsState();
+        final boolean hadState =
+                permissionsState.getRuntimePermissionState(permName, userId) != null;
+        final boolean permissionUpdated =
+                permissionsState.updatePermissionFlags(bp, userId, flagMask, flagValues);
+        if (permissionUpdated && bp.isRuntime()) {
+            notifyRuntimePermissionStateChanged(packageName, userId);
+        }
+        if (permissionUpdated && callback != null) {
+            // Install and runtime permissions are stored in different places,
+            // so figure out what permission changed and persist the change.
+            if (permissionsState.getInstallPermissionState(permName) != null) {
+                callback.onInstallPermissionUpdatedNotifyListener(pkg.applicationInfo.uid);
+            } else if (permissionsState.getRuntimePermissionState(permName, userId) != null
+                    || hadState) {
+                callback.onPermissionUpdatedNotifyListener(new int[] { userId }, false,
+                        pkg.applicationInfo.uid);
+            }
+        }
+    }
+
+    /**
+     * Update the permission flags for all packages and runtime permissions of a user in order
+     * to allow device or profile owner to remove POLICY_FIXED.
+     */
+    @Override
+    public void updatePermissionFlagsForAllApps(int flagMask, int flagValues,
+            final int userId) {
+        final int callingUid = getCallingUid();
+        if (!mUserManagerInt.exists(userId)) {
+            return;
+        }
+
+        enforceGrantRevokeRuntimePermissionPermissions(
+                "updatePermissionFlagsForAllApps");
+        enforceCrossUserPermission(callingUid, userId,
+                true,  // requireFullPermission
+                true,  // checkShell
+                false, // requirePermissionWhenSameUser
+                "updatePermissionFlagsForAllApps");
+
+        // Only the system can change system fixed flags.
+        final int effectiveFlagMask = (callingUid != Process.SYSTEM_UID)
+                ? flagMask : flagMask & ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
+        final int effectiveFlagValues = (callingUid != Process.SYSTEM_UID)
+                ? flagValues : flagValues & ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
+
+        final boolean[] changed = new boolean[1];
+        mPackageManagerInt.forEachPackage(new Consumer<PackageParser.Package>() {
+            @Override
+            public void accept(Package pkg) {
+                final PackageSetting ps = (PackageSetting) pkg.mExtras;
+                if (ps == null) {
+                    return;
+                }
+                final PermissionsState permissionsState = ps.getPermissionsState();
+                changed[0] |= permissionsState.updatePermissionFlagsForAllPermissions(
+                        userId, effectiveFlagMask, effectiveFlagValues);
+                mOnPermissionChangeListeners.onPermissionsChanged(pkg.applicationInfo.uid);
+            }
+        });
+
+        if (changed[0]) {
+            mPackageManagerInt.writePermissionSettings(new int[] { userId }, true);
+        }
+    }
+
+    @Override
+    public int checkPermission(String permName, String pkgName, int userId) {
+        final CheckPermissionDelegate checkPermissionDelegate;
+        synchronized (mLock) {
+            if (mCheckPermissionDelegate == null)  {
+                return checkPermissionImpl(permName, pkgName, userId);
+            }
+            checkPermissionDelegate = mCheckPermissionDelegate;
+        }
+        return checkPermissionDelegate.checkPermission(permName, pkgName, userId,
+                PermissionManagerService.this::checkPermissionImpl);
+    }
+
+    private int checkPermissionImpl(String permName, String pkgName, int userId) {
+        return checkPermissionInternal(permName, pkgName, getCallingUid(), userId);
+    }
+
+    private int checkPermissionInternal(String permName, String packageName, int callingUid,
+            int userId) {
         if (!mUserManagerInt.exists(userId)) {
             return PackageManager.PERMISSION_DENIED;
         }
-
-        final PackageParser.Package pkg = mPackageManagerInt.getPackage(pkgName);
+        final PackageParser.Package pkg = mPackageManagerInt.getPackage(packageName);
         if (pkg != null && pkg.mExtras != null) {
             if (mPackageManagerInt.filterAppAccess(pkg, callingUid, userId)) {
                 return PackageManager.PERMISSION_DENIED;
@@ -485,12 +808,38 @@
                 return PackageManager.PERMISSION_GRANTED;
             }
         }
-
         return PackageManager.PERMISSION_DENIED;
     }
 
-    private int checkUidPermission(String permName, PackageParser.Package pkg, int uid,
-            int callingUid) {
+    @Override
+    public int checkUidPermission(String permName, int uid) {
+        final CheckPermissionDelegate checkPermissionDelegate;
+        synchronized (mLock) {
+            if (mCheckPermissionDelegate == null)  {
+                return checkUidPermissionImpl(permName, uid);
+            }
+            checkPermissionDelegate = mCheckPermissionDelegate;
+        }
+        return checkPermissionDelegate.checkUidPermission(permName, uid,
+                PermissionManagerService.this::checkUidPermissionImpl);
+    }
+
+    private int checkUidPermissionImpl(@NonNull String permName, int uid) {
+        final PackageParser.Package pkg = mPackageManagerInt.getPackage(uid);
+        synchronized (mLock) {
+            return checkUidPermissionInternal(permName, pkg, uid, getCallingUid());
+        }
+    }
+
+    /**
+     * Checks whether or not the given package has been granted the specified
+     * permission. If the given package is {@code null}, we instead check the
+     * system permissions for the given UID.
+     *
+     * @see SystemConfig#getSystemPermissions()
+     */
+    private int checkUidPermissionInternal(@NonNull String permName,
+            @Nullable PackageParser.Package pkg, int uid, int callingUid) {
         final int callingUserId = UserHandle.getUserId(callingUid);
         final boolean isCallerInstantApp =
                 mPackageManagerInt.getInstantAppPackageName(callingUid) != null;
@@ -538,6 +887,728 @@
         return PackageManager.PERMISSION_DENIED;
     }
 
+    @Override
+    public void addOnPermissionsChangeListener(IOnPermissionsChangeListener listener) {
+        mContext.enforceCallingOrSelfPermission(
+                Manifest.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS,
+                "addOnPermissionsChangeListener");
+
+        synchronized (mLock) {
+            mOnPermissionChangeListeners.addListenerLocked(listener);
+        }
+    }
+
+    @Override
+    public void removeOnPermissionsChangeListener(IOnPermissionsChangeListener listener) {
+        if (mPackageManagerInt.getInstantAppPackageName(Binder.getCallingUid()) != null) {
+            throw new SecurityException("Instant applications don't have access to this method");
+        }
+        synchronized (mLock) {
+            mOnPermissionChangeListeners.removeListenerLocked(listener);
+        }
+    }
+
+    @Override
+    @Nullable public List<String> getWhitelistedRestrictedPermissions(@NonNull String packageName,
+            @PermissionWhitelistFlags int flags, @UserIdInt int userId) {
+        Preconditions.checkNotNull(packageName);
+        Preconditions.checkFlagsArgument(flags,
+                PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE
+                        | PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM
+                        | PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER);
+        Preconditions.checkArgumentNonNegative(userId, null);
+
+        if (UserHandle.getCallingUserId() != userId) {
+            mContext.enforceCallingOrSelfPermission(
+                    android.Manifest.permission.INTERACT_ACROSS_USERS,
+                    "getWhitelistedRestrictedPermissions for user " + userId);
+        }
+
+        final PackageParser.Package pkg = mPackageManagerInt.getPackage(packageName);
+        if (pkg == null) {
+            return null;
+        }
+
+        final int callingUid = Binder.getCallingUid();
+        if (mPackageManagerInt.filterAppAccess(pkg, callingUid, UserHandle.getCallingUserId())) {
+            return null;
+        }
+        final boolean isCallerPrivileged = mContext.checkCallingOrSelfPermission(
+                Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS)
+                        == PackageManager.PERMISSION_GRANTED;
+        final boolean isCallerInstallerOnRecord =
+                mPackageManagerInt.isCallerInstallerOfRecord(pkg, callingUid);
+
+        if ((flags & PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM) != 0
+                && !isCallerPrivileged) {
+            throw new SecurityException("Querying system whitelist requires "
+                    + Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS);
+        }
+
+        if ((flags & (PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE
+                | PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER)) != 0) {
+            if (!isCallerPrivileged && !isCallerInstallerOnRecord) {
+                throw new SecurityException("Querying upgrade or installer whitelist"
+                        + " requires being installer on record or "
+                        + Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS);
+            }
+        }
+
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            final PermissionsState permissionsState =
+                    PackageManagerServiceUtils.getPermissionsState(pkg);
+            if (permissionsState == null) {
+                return null;
+            }
+
+            int queryFlags = 0;
+            if ((flags & PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM) != 0) {
+                queryFlags |= PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT;
+            }
+            if ((flags & PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE) != 0) {
+                queryFlags |= PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
+            }
+            if ((flags & PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER) != 0) {
+                queryFlags |=  PackageManager.FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
+            }
+
+            ArrayList<String> whitelistedPermissions = null;
+
+            final int permissionCount = pkg.requestedPermissions.size();
+            for (int i = 0; i < permissionCount; i++) {
+                final String permissionName = pkg.requestedPermissions.get(i);
+                final int currentFlags =
+                        permissionsState.getPermissionFlags(permissionName, userId);
+                if ((currentFlags & queryFlags) != 0) {
+                    if (whitelistedPermissions == null) {
+                        whitelistedPermissions = new ArrayList<>();
+                    }
+                    whitelistedPermissions.add(permissionName);
+                }
+            }
+
+            return whitelistedPermissions;
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    @Override
+    public boolean addWhitelistedRestrictedPermission(@NonNull String packageName,
+            @NonNull String permName, @PermissionWhitelistFlags int flags,
+            @UserIdInt int userId) {
+        // Other argument checks are done in get/setWhitelistedRestrictedPermissions
+        Preconditions.checkNotNull(permName);
+
+        if (!checkExistsAndEnforceCannotModifyImmutablyRestrictedPermission(permName)) {
+            return false;
+        }
+
+        List<String> permissions =
+                getWhitelistedRestrictedPermissions(packageName, flags, userId);
+        if (permissions == null) {
+            permissions = new ArrayList<>(1);
+        }
+        if (permissions.indexOf(permName) < 0) {
+            permissions.add(permName);
+            return setWhitelistedRestrictedPermissionsInternal(packageName, permissions,
+                    flags, userId);
+        }
+        return false;
+    }
+
+    private boolean checkExistsAndEnforceCannotModifyImmutablyRestrictedPermission(
+            @NonNull String permName) {
+        synchronized (mLock) {
+            final BasePermission bp = mSettings.getPermissionLocked(permName);
+            if (bp == null) {
+                Slog.w(TAG, "No such permissions: " + permName);
+                return false;
+            }
+            if (bp.isHardOrSoftRestricted() && bp.isImmutablyRestricted()
+                    && mContext.checkCallingOrSelfPermission(
+                    Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS)
+                    != PackageManager.PERMISSION_GRANTED) {
+                throw new SecurityException("Cannot modify whitelisting of an immutably "
+                        + "restricted permission: " + permName);
+            }
+            return true;
+        }
+    }
+
+    @Override
+    public boolean removeWhitelistedRestrictedPermission(@NonNull String packageName,
+            @NonNull String permName, @PermissionWhitelistFlags int flags,
+            @UserIdInt int userId) {
+        // Other argument checks are done in get/setWhitelistedRestrictedPermissions
+        Preconditions.checkNotNull(permName);
+
+        if (!checkExistsAndEnforceCannotModifyImmutablyRestrictedPermission(permName)) {
+            return false;
+        }
+
+        final List<String> permissions =
+                getWhitelistedRestrictedPermissions(packageName, flags, userId);
+        if (permissions != null && permissions.remove(permName)) {
+            return setWhitelistedRestrictedPermissionsInternal(packageName, permissions,
+                    flags, userId);
+        }
+        return false;
+    }
+
+    private boolean setWhitelistedRestrictedPermissionsInternal(@NonNull String packageName,
+            @Nullable List<String> permissions, @PermissionWhitelistFlags int flags,
+            @UserIdInt int userId) {
+        Preconditions.checkNotNull(packageName);
+        Preconditions.checkFlagsArgument(flags,
+                PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE
+                        | PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM
+                        | PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER);
+        Preconditions.checkArgument(Integer.bitCount(flags) == 1);
+        Preconditions.checkArgumentNonNegative(userId, null);
+
+        if (UserHandle.getCallingUserId() != userId) {
+            mContext.enforceCallingOrSelfPermission(
+                    Manifest.permission.INTERACT_ACROSS_USERS,
+                    "setWhitelistedRestrictedPermissions for user " + userId);
+        }
+
+        final PackageParser.Package pkg = mPackageManagerInt.getPackage(packageName);
+        if (pkg == null) {
+            return false;
+        }
+
+        final int callingUid = Binder.getCallingUid();
+        if (mPackageManagerInt.filterAppAccess(pkg, callingUid, UserHandle.getCallingUserId())) {
+            return false;
+        }
+
+        final boolean isCallerPrivileged = mContext.checkCallingOrSelfPermission(
+                Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS)
+                        == PackageManager.PERMISSION_GRANTED;
+        final boolean isCallerInstallerOnRecord =
+                mPackageManagerInt.isCallerInstallerOfRecord(pkg, callingUid);
+
+        if ((flags & PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM) != 0
+                && !isCallerPrivileged) {
+            throw new SecurityException("Modifying system whitelist requires "
+                    + Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS);
+        }
+
+        if ((flags & PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE) != 0) {
+            if (!isCallerPrivileged && !isCallerInstallerOnRecord) {
+                throw new SecurityException("Modifying upgrade whitelist requires"
+                        + " being installer on record or "
+                        + Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS);
+            }
+            final List<String> whitelistedPermissions =
+                    getWhitelistedRestrictedPermissions(pkg.packageName, flags, userId);
+            if (permissions == null || permissions.isEmpty()) {
+                if (whitelistedPermissions == null || whitelistedPermissions.isEmpty()) {
+                    return true;
+                }
+            } else {
+                // Only the system can add and remove while the installer can only remove.
+                final int permissionCount = permissions.size();
+                for (int i = 0; i < permissionCount; i++) {
+                    if ((whitelistedPermissions == null
+                            || !whitelistedPermissions.contains(permissions.get(i)))
+                            && !isCallerPrivileged) {
+                        throw new SecurityException("Adding to upgrade whitelist requires"
+                                + Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS);
+                    }
+                }
+            }
+
+            if ((flags & PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER) != 0) {
+                if (!isCallerPrivileged && !isCallerInstallerOnRecord) {
+                    throw new SecurityException("Modifying installer whitelist requires"
+                            + " being installer on record or "
+                            + Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS);
+                }
+            }
+        }
+
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            setWhitelistedRestrictedPermissionsForUser(
+                    pkg, userId, permissions, Process.myUid(), flags, mDefaultPermissionCallback);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+
+        return true;
+    }
+
+    @Override
+    public void grantRuntimePermission(String packageName, String permName, final int userId) {
+        final int callingUid = Binder.getCallingUid();
+        final boolean overridePolicy =
+                checkUidPermission(ADJUST_RUNTIME_PERMISSIONS_POLICY, callingUid)
+                        == PackageManager.PERMISSION_GRANTED;
+
+        grantRuntimePermissionInternal(permName, packageName, overridePolicy,
+                callingUid, userId, mDefaultPermissionCallback);
+    }
+
+    // TODO swap permission name and package name
+    private void grantRuntimePermissionInternal(String permName, String packageName,
+            boolean overridePolicy, int callingUid, final int userId, PermissionCallback callback) {
+        if (ApplicationPackageManager.DEBUG_TRACE_GRANTS
+                && ApplicationPackageManager.shouldTraceGrant(packageName, permName, userId)) {
+            Log.i(TAG, "System is granting "
+                    + permName + " for user " + userId + " on behalf of uid " + callingUid
+                    + " " + mPackageManagerInt.getNameForUid(callingUid),
+                    new RuntimeException());
+        }
+        if (!mUserManagerInt.exists(userId)) {
+            Log.e(TAG, "No such user:" + userId);
+            return;
+        }
+
+        mContext.enforceCallingOrSelfPermission(
+                android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
+                "grantRuntimePermission");
+
+        enforceCrossUserPermission(callingUid, userId,
+                true,  // requireFullPermission
+                true,  // checkShell
+                false, // requirePermissionWhenSameUser
+                "grantRuntimePermission");
+
+        final PackageParser.Package pkg = mPackageManagerInt.getPackage(packageName);
+        if (pkg == null || pkg.mExtras == null) {
+            throw new IllegalArgumentException("Unknown package: " + packageName);
+        }
+        final BasePermission bp;
+        synchronized (mLock) {
+            bp = mSettings.getPermissionLocked(permName);
+        }
+        if (bp == null) {
+            throw new IllegalArgumentException("Unknown permission: " + permName);
+        }
+        if (mPackageManagerInt.filterAppAccess(pkg, callingUid, userId)) {
+            throw new IllegalArgumentException("Unknown package: " + packageName);
+        }
+
+        bp.enforceDeclaredUsedAndRuntimeOrDevelopment(pkg);
+
+        // If a permission review is required for legacy apps we represent
+        // their permissions as always granted runtime ones since we need
+        // to keep the review required permission flag per user while an
+        // install permission's state is shared across all users.
+        if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M
+                && bp.isRuntime()) {
+            return;
+        }
+
+        final int uid = UserHandle.getUid(userId, pkg.applicationInfo.uid);
+
+        final PackageSetting ps = (PackageSetting) pkg.mExtras;
+        final PermissionsState permissionsState = ps.getPermissionsState();
+
+        final int flags = permissionsState.getPermissionFlags(permName, userId);
+        if ((flags & PackageManager.FLAG_PERMISSION_SYSTEM_FIXED) != 0) {
+            Log.e(TAG, "Cannot grant system fixed permission "
+                    + permName + " for package " + packageName);
+            return;
+        }
+        if (!overridePolicy && (flags & PackageManager.FLAG_PERMISSION_POLICY_FIXED) != 0) {
+            Log.e(TAG, "Cannot grant policy fixed permission "
+                    + permName + " for package " + packageName);
+            return;
+        }
+
+        if (bp.isHardRestricted()
+                && (flags & PackageManager.FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT) == 0) {
+            Log.e(TAG, "Cannot grant hard restricted non-exempt permission "
+                    + permName + " for package " + packageName);
+            return;
+        }
+
+        if (bp.isSoftRestricted() && !SoftRestrictedPermissionPolicy.forPermission(mContext,
+                pkg.applicationInfo, UserHandle.of(userId), permName).canBeGranted()) {
+            Log.e(TAG, "Cannot grant soft restricted permission " + permName + " for package "
+                    + packageName);
+            return;
+        }
+
+        if (bp.isDevelopment()) {
+            // Development permissions must be handled specially, since they are not
+            // normal runtime permissions.  For now they apply to all users.
+            if (permissionsState.grantInstallPermission(bp)
+                    != PERMISSION_OPERATION_FAILURE) {
+                if (callback != null) {
+                    callback.onInstallPermissionGranted();
+                }
+            }
+            return;
+        }
+
+        if (ps.getInstantApp(userId) && !bp.isInstant()) {
+            throw new SecurityException("Cannot grant non-ephemeral permission"
+                    + permName + " for package " + packageName);
+        }
+
+        if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) {
+            Slog.w(TAG, "Cannot grant runtime permission to a legacy app");
+            return;
+        }
+
+        final int result = permissionsState.grantRuntimePermission(bp, userId);
+        switch (result) {
+            case PERMISSION_OPERATION_FAILURE: {
+                return;
+            }
+
+            case PermissionsState.PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED: {
+                if (callback != null) {
+                    callback.onGidsChanged(UserHandle.getAppId(pkg.applicationInfo.uid), userId);
+                }
+            }
+            break;
+        }
+
+        if (bp.isRuntime()) {
+            logPermission(MetricsEvent.ACTION_PERMISSION_GRANTED, permName, packageName);
+        }
+
+        if (callback != null) {
+            callback.onPermissionGranted(uid, userId);
+        }
+
+        if (bp.isRuntime()) {
+            notifyRuntimePermissionStateChanged(packageName, userId);
+        }
+
+        // Only need to do this if user is initialized. Otherwise it's a new user
+        // and there are no processes running as the user yet and there's no need
+        // to make an expensive call to remount processes for the changed permissions.
+        if (READ_EXTERNAL_STORAGE.equals(permName)
+                || WRITE_EXTERNAL_STORAGE.equals(permName)) {
+            final long token = Binder.clearCallingIdentity();
+            try {
+                if (mUserManagerInt.isUserInitialized(userId)) {
+                    StorageManagerInternal storageManagerInternal = LocalServices.getService(
+                            StorageManagerInternal.class);
+                    storageManagerInternal.onExternalStoragePolicyChanged(uid, packageName);
+                }
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+    }
+
+    @Override
+    public void revokeRuntimePermission(String packageName, String permName, int userId) {
+        final int callingUid = Binder.getCallingUid();
+        final boolean overridePolicy =
+                checkUidPermission(ADJUST_RUNTIME_PERMISSIONS_POLICY, callingUid)
+                        == PackageManager.PERMISSION_GRANTED;
+
+        revokeRuntimePermissionInternal(permName, packageName, overridePolicy, callingUid, userId,
+                mDefaultPermissionCallback);
+    }
+
+    // TODO swap permission name and package name
+    private void revokeRuntimePermissionInternal(String permName, String packageName,
+            boolean overridePolicy, int callingUid, final int userId, PermissionCallback callback) {
+        if (ApplicationPackageManager.DEBUG_TRACE_GRANTS
+                && ApplicationPackageManager.shouldTraceGrant(packageName, permName, userId)) {
+            Log.i(TAG, "System is revoking "
+                            + permName + " for user " + userId + " on behalf of uid " + callingUid
+                            + " " + mPackageManagerInt.getNameForUid(callingUid),
+                    new RuntimeException());
+        }
+        if (!mUserManagerInt.exists(userId)) {
+            Log.e(TAG, "No such user:" + userId);
+            return;
+        }
+
+        mContext.enforceCallingOrSelfPermission(
+                android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS,
+                "revokeRuntimePermission");
+
+        enforceCrossUserPermission(callingUid, userId,
+                true,  // requireFullPermission
+                true,  // checkShell
+                false, // requirePermissionWhenSameUser
+                "revokeRuntimePermission");
+
+        final PackageParser.Package pkg = mPackageManagerInt.getPackage(packageName);
+        if (pkg == null || pkg.mExtras == null) {
+            throw new IllegalArgumentException("Unknown package: " + packageName);
+        }
+        if (mPackageManagerInt.filterAppAccess(pkg, callingUid, userId)) {
+            throw new IllegalArgumentException("Unknown package: " + packageName);
+        }
+        final BasePermission bp = mSettings.getPermissionLocked(permName);
+        if (bp == null) {
+            throw new IllegalArgumentException("Unknown permission: " + permName);
+        }
+
+        bp.enforceDeclaredUsedAndRuntimeOrDevelopment(pkg);
+
+        // If a permission review is required for legacy apps we represent
+        // their permissions as always granted runtime ones since we need
+        // to keep the review required permission flag per user while an
+        // install permission's state is shared across all users.
+        if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M
+                && bp.isRuntime()) {
+            return;
+        }
+
+        final PackageSetting ps = (PackageSetting) pkg.mExtras;
+        final PermissionsState permissionsState = ps.getPermissionsState();
+
+        final int flags = permissionsState.getPermissionFlags(permName, userId);
+        // Only the system may revoke SYSTEM_FIXED permissions.
+        if ((flags & PackageManager.FLAG_PERMISSION_SYSTEM_FIXED) != 0
+                && UserHandle.getCallingAppId() != Process.SYSTEM_UID) {
+            throw new SecurityException("Non-System UID cannot revoke system fixed permission "
+                    + permName + " for package " + packageName);
+        }
+        if (!overridePolicy && (flags & PackageManager.FLAG_PERMISSION_POLICY_FIXED) != 0) {
+            throw new SecurityException("Cannot revoke policy fixed permission "
+                    + permName + " for package " + packageName);
+        }
+
+        if (bp.isDevelopment()) {
+            // Development permissions must be handled specially, since they are not
+            // normal runtime permissions.  For now they apply to all users.
+            if (permissionsState.revokeInstallPermission(bp)
+                    != PERMISSION_OPERATION_FAILURE) {
+                if (callback != null) {
+                    mDefaultPermissionCallback.onInstallPermissionRevoked();
+                }
+            }
+            return;
+        }
+
+        // Permission is already revoked, no need to do anything.
+        if (!permissionsState.hasRuntimePermission(permName, userId)) {
+            return;
+        }
+
+        if (permissionsState.revokeRuntimePermission(bp, userId)
+                == PERMISSION_OPERATION_FAILURE) {
+            return;
+        }
+
+        if (bp.isRuntime()) {
+            logPermission(MetricsEvent.ACTION_PERMISSION_REVOKED, permName, packageName);
+        }
+
+        if (callback != null) {
+            callback.onPermissionRevoked(pkg.applicationInfo.uid, userId);
+        }
+
+        if (bp.isRuntime()) {
+            notifyRuntimePermissionStateChanged(packageName, userId);
+        }
+    }
+
+    @Override
+    public void resetRuntimePermissions() {
+        mContext.enforceCallingOrSelfPermission(
+                android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS,
+                "revokeRuntimePermission");
+
+        final int callingUid = Binder.getCallingUid();
+        if (callingUid != Process.SYSTEM_UID && callingUid != 0) {
+            mContext.enforceCallingOrSelfPermission(
+                    android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+                    "resetRuntimePermissions");
+        }
+
+        updateAllPermissions(
+                StorageManager.UUID_PRIVATE_INTERNAL, false, mDefaultPermissionCallback);
+        for (final int userId : UserManagerService.getInstance().getUserIds()) {
+            mPackageManagerInt.forEachPackage(
+                    (PackageParser.Package pkg) -> resetRuntimePermissionsInternal(pkg, userId));
+        }
+    }
+
+    /**
+     * Reverts user permission state changes (permissions and flags).
+     *
+     * @param ps The package for which to reset.
+     * @param userId The device user for which to do a reset.
+     */
+    @GuardedBy("mPackages")
+    private void resetRuntimePermissionsInternal(final PackageParser.Package pkg,
+            final int userId) {
+        final String packageName = pkg.packageName;
+
+        // These are flags that can change base on user actions.
+        final int userSettableMask = FLAG_PERMISSION_USER_SET
+                | FLAG_PERMISSION_USER_FIXED
+                | FLAG_PERMISSION_REVOKE_ON_UPGRADE
+                | FLAG_PERMISSION_REVIEW_REQUIRED;
+
+        final int policyOrSystemFlags = FLAG_PERMISSION_SYSTEM_FIXED
+                | FLAG_PERMISSION_POLICY_FIXED;
+
+        // Delay and combine non-async permission callbacks
+        final int permissionCount = pkg.requestedPermissions.size();
+        final boolean[] permissionRemoved = new boolean[1];
+        final ArraySet<Long> revokedPermissions = new ArraySet<>();
+        final IntArray syncUpdatedUsers = new IntArray(permissionCount);
+        final IntArray asyncUpdatedUsers = new IntArray(permissionCount);
+
+        PermissionCallback delayingPermCallback = new PermissionCallback() {
+            public void onGidsChanged(int appId, int userId) {
+                mDefaultPermissionCallback.onGidsChanged(appId, userId);
+            }
+
+            public void onPermissionChanged() {
+                mDefaultPermissionCallback.onPermissionChanged();
+            }
+
+            public void onPermissionGranted(int uid, int userId) {
+                mDefaultPermissionCallback.onPermissionGranted(uid, userId);
+            }
+
+            public void onInstallPermissionGranted() {
+                mDefaultPermissionCallback.onInstallPermissionGranted();
+            }
+
+            public void onPermissionRevoked(int uid, int userId) {
+                revokedPermissions.add(IntPair.of(uid, userId));
+
+                syncUpdatedUsers.add(userId);
+            }
+
+            public void onInstallPermissionRevoked() {
+                mDefaultPermissionCallback.onInstallPermissionRevoked();
+            }
+
+            public void onPermissionUpdated(int[] updatedUserIds, boolean sync) {
+                for (int userId : updatedUserIds) {
+                    if (sync) {
+                        syncUpdatedUsers.add(userId);
+                        asyncUpdatedUsers.remove(userId);
+                    } else {
+                        // Don't override sync=true by sync=false
+                        if (syncUpdatedUsers.indexOf(userId) == -1) {
+                            asyncUpdatedUsers.add(userId);
+                        }
+                    }
+                }
+            }
+
+            public void onPermissionRemoved() {
+                permissionRemoved[0] = true;
+            }
+
+            public void onInstallPermissionUpdated() {
+                mDefaultPermissionCallback.onInstallPermissionUpdated();
+            }
+        };
+
+        for (int i = 0; i < permissionCount; i++) {
+            final String permName = pkg.requestedPermissions.get(i);
+            final BasePermission bp;
+            synchronized (mLock) {
+                bp = mSettings.getPermissionLocked(permName);
+            }
+            if (bp == null) {
+                continue;
+            }
+
+            if (bp.isRemoved()) {
+                continue;
+            }
+
+            // If shared user we just reset the state to which only this app contributed.
+            final String sharedUserId =
+                    mPackageManagerInt.getSharedUserIdForPackage(pkg.packageName);
+            final String[] pkgNames =
+                    mPackageManagerInt.getPackagesForSharedUserId(sharedUserId, userId);
+            if (pkgNames != null && pkgNames.length > 0) {
+                boolean used = false;
+                final int packageCount = pkgNames.length;
+                for (int j = 0; j < packageCount; j++) {
+                    final String sharedPkgName = pkgNames[j];
+                    final PackageParser.Package sharedPkg =
+                            mPackageManagerInt.getPackage(sharedPkgName);
+                    if (sharedPkg != null && !sharedPkg.packageName.equals(packageName)
+                            && sharedPkg.requestedPermissions.contains(permName)) {
+                        used = true;
+                        break;
+                    }
+                }
+                if (used) {
+                    continue;
+                }
+            }
+
+            final int oldFlags =
+                    getPermissionFlagsInternal(permName, packageName, Process.SYSTEM_UID, userId);
+
+            // Always clear the user settable flags.
+            // If permission review is enabled and this is a legacy app, mark the
+            // permission as requiring a review as this is the initial state.
+            final int uid = mPackageManagerInt.getPackageUid(packageName, 0, userId);
+            final int targetSdk = mPackageManagerInt.getTargetSdk(uid);
+            final int flags = (targetSdk < Build.VERSION_CODES.M && bp.isRuntime())
+                    ? FLAG_PERMISSION_REVIEW_REQUIRED | FLAG_PERMISSION_REVOKE_ON_UPGRADE
+                    : 0;
+
+            updatePermissionFlagsInternal(
+                    permName, packageName, userSettableMask, flags, Process.SYSTEM_UID, userId,
+                    false, delayingPermCallback);
+
+            // Below is only runtime permission handling.
+            if (!bp.isRuntime()) {
+                continue;
+            }
+
+            // Never clobber system or policy.
+            if ((oldFlags & policyOrSystemFlags) != 0) {
+                continue;
+            }
+
+            // If this permission was granted by default, make sure it is.
+            if ((oldFlags & FLAG_PERMISSION_GRANTED_BY_DEFAULT) != 0) {
+                grantRuntimePermissionInternal(permName, packageName, false,
+                        Process.SYSTEM_UID, userId, delayingPermCallback);
+            // If permission review is enabled the permissions for a legacy apps
+            // are represented as constantly granted runtime ones, so don't revoke.
+            } else if ((flags & FLAG_PERMISSION_REVIEW_REQUIRED) == 0) {
+                // Otherwise, reset the permission.
+                revokeRuntimePermissionInternal(permName, packageName, false, Process.SYSTEM_UID,
+                        userId, delayingPermCallback);
+            }
+        }
+
+        // Execute delayed callbacks
+        if (permissionRemoved[0]) {
+            mDefaultPermissionCallback.onPermissionRemoved();
+        }
+
+        // Slight variation on the code in mPermissionCallback.onPermissionRevoked() as we cannot
+        // kill uid while holding mPackages-lock
+        if (!revokedPermissions.isEmpty()) {
+            int numRevokedPermissions = revokedPermissions.size();
+            for (int i = 0; i < numRevokedPermissions; i++) {
+                int revocationUID = IntPair.first(revokedPermissions.valueAt(i));
+                int revocationUserId = IntPair.second(revokedPermissions.valueAt(i));
+
+                mOnPermissionChangeListeners.onPermissionsChanged(revocationUID);
+
+                // Kill app later as we are holding mPackages
+                mHandler.post(() -> killUid(UserHandle.getAppId(revocationUID), revocationUserId,
+                        KILL_APP_REASON_PERMISSIONS_REVOKED));
+            }
+        }
+
+        mPackageManagerInt.writePermissionSettings(syncUpdatedUsers.toArray(), false);
+        mPackageManagerInt.writePermissionSettings(asyncUpdatedUsers.toArray(), true);
+    }
+
     /**
      * Get the state of the runtime permissions as xml file.
      *
@@ -717,6 +1788,7 @@
             }
         }
 
+        final int callingUid = Binder.getCallingUid();
         final int numNewPackagePermissions = newPackage.permissions.size();
         for (int newPermissionNum = 0; newPermissionNum < numNewPackagePermissions;
                 newPermissionNum++) {
@@ -741,9 +1813,9 @@
                         final int numPackages = allPackageNames.size();
                         for (int packageNum = 0; packageNum < numPackages; packageNum++) {
                             final String packageName = allPackageNames.get(packageNum);
-
-                            if (checkPermission(permissionName, packageName, UserHandle.USER_SYSTEM,
-                                    userId) == PackageManager.PERMISSION_GRANTED) {
+                            final int permissionState = checkPermissionInternal(
+                                    permissionName, packageName, UserHandle.USER_SYSTEM, userId);
+                            if (permissionState == PackageManager.PERMISSION_GRANTED) {
                                 EventLog.writeEvent(0x534e4554, "72710897",
                                         newPackage.applicationInfo.uid,
                                         "Revoking permission " + permissionName +
@@ -752,8 +1824,8 @@
                                         " to " + newPermissionGroupName);
 
                                 try {
-                                    revokeRuntimePermission(permissionName, packageName, false,
-                                            userId, permissionCallback);
+                                    revokeRuntimePermissionInternal(permissionName, packageName,
+                                            false, callingUid, userId, permissionCallback);
                                 } catch (IllegalArgumentException e) {
                                     Slog.e(TAG, "Could not revoke " + permissionName + " from "
                                             + packageName, e);
@@ -2001,7 +3073,7 @@
             }
             for (int userId : mUserManagerInt.getUserIds()) {
                 if (disabledPs.getPermissionsState().hasRuntimePermission(permission, userId)) {
-                    grantRuntimePermission(
+                    grantRuntimePermissionInternal(
                             permission, pkg.packageName, false, callingUid, userId, callback);
                 }
             }
@@ -2016,54 +3088,6 @@
         }
     }
 
-    private @Nullable List<String> getWhitelistedRestrictedPermissions(
-            @NonNull PackageParser.Package pkg, @PermissionWhitelistFlags int whitelistFlags,
-            @UserIdInt int userId) {
-        final PackageSetting packageSetting = (PackageSetting) pkg.mExtras;
-        if (packageSetting == null) {
-            return null;
-        }
-
-        final PermissionsState permissionsState = packageSetting.getPermissionsState();
-
-        int queryFlags = 0;
-        if ((whitelistFlags & PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM) != 0) {
-            queryFlags |= PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT;
-        }
-        if ((whitelistFlags & PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE) != 0) {
-            queryFlags |= PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
-        }
-        if ((whitelistFlags & PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER) != 0) {
-            queryFlags |=  PackageManager.FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
-        }
-
-        ArrayList<String> whitelistedPermissions = null;
-
-        final int permissionCount = pkg.requestedPermissions.size();
-        for (int i = 0; i < permissionCount; i++) {
-            final String permissionName = pkg.requestedPermissions.get(i);
-            final int currentFlags = permissionsState.getPermissionFlags(permissionName, userId);
-            if ((currentFlags & queryFlags) != 0) {
-                if (whitelistedPermissions == null) {
-                    whitelistedPermissions = new ArrayList<>();
-                }
-                whitelistedPermissions.add(permissionName);
-            }
-        }
-
-        return whitelistedPermissions;
-    }
-
-    private void setWhitelistedRestrictedPermissions(@NonNull PackageParser.Package pkg,
-            @NonNull int[] userIds, @Nullable List<String> permissions, int callingUid,
-            @PackageManager.PermissionWhitelistFlags int whitelistFlags,
-            @NonNull PermissionCallback callback) {
-        for (int userId : userIds) {
-            setWhitelistedRestrictedPermissionsForUser(pkg, userId, permissions,
-                    callingUid, whitelistFlags, callback);
-        }
-    }
-
     private void grantRequestedRuntimePermissionsForUser(PackageParser.Package pkg, int userId,
             String[] grantedPermissions, int callingUid, PermissionCallback callback) {
         PackageSetting ps = (PackageSetting) pkg.mExtras;
@@ -2095,14 +3119,14 @@
                 if (supportsRuntimePermissions) {
                     // Installer cannot change immutable permissions.
                     if ((flags & immutableFlags) == 0) {
-                        grantRuntimePermission(permission, pkg.packageName, false, callingUid,
-                                userId, callback);
+                        grantRuntimePermissionInternal(permission, pkg.packageName, false,
+                                callingUid, userId, callback);
                     }
                 } else {
                     // In permission review mode we clear the review flag when we
                     // are asked to install the app with all permissions granted.
                     if ((flags & PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) != 0) {
-                        updatePermissionFlags(permission, pkg.packageName,
+                        updatePermissionFlagsInternal(permission, pkg.packageName,
                                 PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED, 0, callingUid,
                                 userId, false, callback);
                     }
@@ -2111,262 +3135,15 @@
         }
     }
 
-    private void grantRuntimePermission(String permName, String packageName, boolean overridePolicy,
-            int callingUid, final int userId, PermissionCallback callback) {
-        if (ApplicationPackageManager.DEBUG_TRACE_GRANTS
-                && ApplicationPackageManager.shouldTraceGrant(packageName, permName, userId)) {
-            Log.i(TAG, "System is granting "
-                    + permName + " for user " + userId + " on behalf of uid " + callingUid
-                    + " " + mPackageManagerInt.getNameForUid(callingUid),
-                    new RuntimeException());
-        }
-        if (!mUserManagerInt.exists(userId)) {
-            Log.e(TAG, "No such user:" + userId);
-            return;
-        }
-
-        mContext.enforceCallingOrSelfPermission(
-                android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
-                "grantRuntimePermission");
-
-        enforceCrossUserPermission(callingUid, userId,
-                true,  // requireFullPermission
-                true,  // checkShell
-                false, // requirePermissionWhenSameUser
-                "grantRuntimePermission");
-
-        final PackageParser.Package pkg = mPackageManagerInt.getPackage(packageName);
-        if (pkg == null || pkg.mExtras == null) {
-            throw new IllegalArgumentException("Unknown package: " + packageName);
-        }
-        final BasePermission bp;
-        synchronized(mLock) {
-            bp = mSettings.getPermissionLocked(permName);
-        }
-        if (bp == null) {
-            throw new IllegalArgumentException("Unknown permission: " + permName);
-        }
-        if (mPackageManagerInt.filterAppAccess(pkg, callingUid, userId)) {
-            throw new IllegalArgumentException("Unknown package: " + packageName);
-        }
-
-        bp.enforceDeclaredUsedAndRuntimeOrDevelopment(pkg);
-
-        // If a permission review is required for legacy apps we represent
-        // their permissions as always granted runtime ones since we need
-        // to keep the review required permission flag per user while an
-        // install permission's state is shared across all users.
-        if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M
-                && bp.isRuntime()) {
-            return;
-        }
-
-        final int uid = UserHandle.getUid(userId, pkg.applicationInfo.uid);
-
-        final PackageSetting ps = (PackageSetting) pkg.mExtras;
-        final PermissionsState permissionsState = ps.getPermissionsState();
-
-        final int flags = permissionsState.getPermissionFlags(permName, userId);
-        if ((flags & PackageManager.FLAG_PERMISSION_SYSTEM_FIXED) != 0) {
-            Log.e(TAG, "Cannot grant system fixed permission "
-                    + permName + " for package " + packageName);
-            return;
-        }
-        if (!overridePolicy && (flags & PackageManager.FLAG_PERMISSION_POLICY_FIXED) != 0) {
-            Log.e(TAG, "Cannot grant policy fixed permission "
-                    + permName + " for package " + packageName);
-            return;
-        }
-
-        if (bp.isHardRestricted()
-                && (flags & PackageManager.FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT) == 0) {
-            Log.e(TAG, "Cannot grant hard restricted non-exempt permission "
-                    + permName + " for package " + packageName);
-            return;
-        }
-
-        if (bp.isSoftRestricted() && !SoftRestrictedPermissionPolicy.forPermission(mContext,
-                pkg.applicationInfo, UserHandle.of(userId), permName).canBeGranted()) {
-            Log.e(TAG, "Cannot grant soft restricted permission " + permName + " for package "
-                    + packageName);
-            return;
-        }
-
-        if (bp.isDevelopment()) {
-            // Development permissions must be handled specially, since they are not
-            // normal runtime permissions.  For now they apply to all users.
-            if (permissionsState.grantInstallPermission(bp) !=
-                    PERMISSION_OPERATION_FAILURE) {
-                if (callback != null) {
-                    callback.onInstallPermissionGranted();
-                }
-            }
-            return;
-        }
-
-        if (ps.getInstantApp(userId) && !bp.isInstant()) {
-            throw new SecurityException("Cannot grant non-ephemeral permission"
-                    + permName + " for package " + packageName);
-        }
-
-        if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) {
-            Slog.w(TAG, "Cannot grant runtime permission to a legacy app");
-            return;
-        }
-
-        final int result = permissionsState.grantRuntimePermission(bp, userId);
-        switch (result) {
-            case PERMISSION_OPERATION_FAILURE: {
-                return;
-            }
-
-            case PermissionsState.PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED: {
-                if (callback != null) {
-                    callback.onGidsChanged(UserHandle.getAppId(pkg.applicationInfo.uid), userId);
-                }
-            }
-            break;
-        }
-
-        if (bp.isRuntime()) {
-            logPermission(MetricsEvent.ACTION_PERMISSION_GRANTED, permName, packageName);
-        }
-
-        if (callback != null) {
-            callback.onPermissionGranted(uid, userId);
-        }
-
-        if (bp.isRuntime()) {
-            notifyRuntimePermissionStateChanged(packageName, userId);
-        }
-
-        // Only need to do this if user is initialized. Otherwise it's a new user
-        // and there are no processes running as the user yet and there's no need
-        // to make an expensive call to remount processes for the changed permissions.
-        if (READ_EXTERNAL_STORAGE.equals(permName)
-                || WRITE_EXTERNAL_STORAGE.equals(permName)) {
-            final long token = Binder.clearCallingIdentity();
-            try {
-                if (mUserManagerInt.isUserInitialized(userId)) {
-                    StorageManagerInternal storageManagerInternal = LocalServices.getService(
-                            StorageManagerInternal.class);
-                    storageManagerInternal.onExternalStoragePolicyChanged(uid, packageName);
-                }
-            } finally {
-                Binder.restoreCallingIdentity(token);
-            }
-        }
-
-    }
-
-    private void revokeRuntimePermission(String permName, String packageName,
-            boolean overridePolicy, int userId, PermissionCallback callback) {
-        int callingUid = Binder.getCallingUid();
-        if (ApplicationPackageManager.DEBUG_TRACE_GRANTS
-                && ApplicationPackageManager.shouldTraceGrant(packageName, permName, userId)) {
-            Log.i(TAG, "System is revoking "
-                            + permName + " for user " + userId + " on behalf of uid " + callingUid
-                            + " " + mPackageManagerInt.getNameForUid(callingUid),
-                    new RuntimeException());
-        }
-        if (!mUserManagerInt.exists(userId)) {
-            Log.e(TAG, "No such user:" + userId);
-            return;
-        }
-
-        mContext.enforceCallingOrSelfPermission(
-                android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS,
-                "revokeRuntimePermission");
-
-        enforceCrossUserPermission(callingUid, userId,
-                true,  // requireFullPermission
-                true,  // checkShell
-                false, // requirePermissionWhenSameUser
-                "revokeRuntimePermission");
-
-        final PackageParser.Package pkg = mPackageManagerInt.getPackage(packageName);
-        if (pkg == null || pkg.mExtras == null) {
-            throw new IllegalArgumentException("Unknown package: " + packageName);
-        }
-        if (mPackageManagerInt.filterAppAccess(pkg, callingUid, userId)) {
-            throw new IllegalArgumentException("Unknown package: " + packageName);
-        }
-        final BasePermission bp = mSettings.getPermissionLocked(permName);
-        if (bp == null) {
-            throw new IllegalArgumentException("Unknown permission: " + permName);
-        }
-
-        bp.enforceDeclaredUsedAndRuntimeOrDevelopment(pkg);
-
-        // If a permission review is required for legacy apps we represent
-        // their permissions as always granted runtime ones since we need
-        // to keep the review required permission flag per user while an
-        // install permission's state is shared across all users.
-        if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M
-                && bp.isRuntime()) {
-            return;
-        }
-
-        final PackageSetting ps = (PackageSetting) pkg.mExtras;
-        final PermissionsState permissionsState = ps.getPermissionsState();
-
-        final int flags = permissionsState.getPermissionFlags(permName, userId);
-        // Only the system may revoke SYSTEM_FIXED permissions.
-        if ((flags & PackageManager.FLAG_PERMISSION_SYSTEM_FIXED) != 0
-                && UserHandle.getCallingAppId() != Process.SYSTEM_UID) {
-            throw new SecurityException("Non-System UID cannot revoke system fixed permission "
-                    + permName + " for package " + packageName);
-        }
-        if (!overridePolicy && (flags & PackageManager.FLAG_PERMISSION_POLICY_FIXED) != 0) {
-            throw new SecurityException("Cannot revoke policy fixed permission "
-                    + permName + " for package " + packageName);
-        }
-
-        if (bp.isDevelopment()) {
-            // Development permissions must be handled specially, since they are not
-            // normal runtime permissions.  For now they apply to all users.
-            if (permissionsState.revokeInstallPermission(bp) !=
-                    PERMISSION_OPERATION_FAILURE) {
-                if (callback != null) {
-                    callback.onInstallPermissionRevoked();
-                }
-            }
-            return;
-        }
-
-        // Permission is already revoked, no need to do anything.
-        if (!permissionsState.hasRuntimePermission(permName, userId)) {
-            return;
-        }
-
-        if (permissionsState.revokeRuntimePermission(bp, userId) ==
-                PERMISSION_OPERATION_FAILURE) {
-            return;
-        }
-
-        if (bp.isRuntime()) {
-            logPermission(MetricsEvent.ACTION_PERMISSION_REVOKED, permName, packageName);
-        }
-
-        if (callback != null) {
-            callback.onPermissionRevoked(pkg.applicationInfo.uid, userId);
-        }
-
-        if (bp.isRuntime()) {
-            notifyRuntimePermissionStateChanged(packageName, userId);
-        }
-    }
-
     private void setWhitelistedRestrictedPermissionsForUser(@NonNull PackageParser.Package pkg,
             @UserIdInt int userId, @Nullable List<String> permissions, int callingUid,
             @PermissionWhitelistFlags int whitelistFlags, PermissionCallback callback) {
-        final PackageSetting ps = (PackageSetting) pkg.mExtras;
-        if (ps == null) {
+        final PermissionsState permissionsState =
+                PackageManagerServiceUtils.getPermissionsState(pkg);
+        if (permissionsState == null) {
             return;
         }
 
-        final PermissionsState permissionsState = ps.getPermissionsState();
-
         ArraySet<String> oldGrantedRestrictedPermissions = null;
         boolean updatePermissions = false;
 
@@ -2454,7 +3231,7 @@
                 newFlags |= PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
             }
 
-            updatePermissionFlags(permissionName, pkg.packageName, mask, newFlags,
+            updatePermissionFlagsInternal(permissionName, pkg.packageName, mask, newFlags,
                     callingUid, userId, false, null /*callback*/);
         }
 
@@ -2468,7 +3245,9 @@
                 for (int i = 0; i < oldGrantedCount; i++) {
                     final String permission = oldGrantedRestrictedPermissions.valueAt(i);
                     // Sometimes we create a new permission state instance during update.
-                    if (!ps.getPermissionsState().hasPermission(permission, userId)) {
+                    final PermissionsState newPermissionsState =
+                            PackageManagerServiceUtils.getPermissionsState(pkg);
+                    if (!newPermissionsState.hasPermission(permission, userId)) {
                         callback.onPermissionRevoked(pkg.applicationInfo.uid, userId);
                         break;
                     }
@@ -2541,37 +3320,6 @@
         return runtimePermissionChangedUserIds;
     }
 
-    private int getPermissionFlags(
-            String permName, String packageName, int callingUid, int userId) {
-        if (!mUserManagerInt.exists(userId)) {
-            return 0;
-        }
-
-        enforceGrantRevokeGetRuntimePermissionPermissions("getPermissionFlags");
-
-        enforceCrossUserPermission(callingUid, userId,
-                true,  // requireFullPermission
-                false, // checkShell
-                false, // requirePermissionWhenSameUser
-                "getPermissionFlags");
-
-        final PackageParser.Package pkg = mPackageManagerInt.getPackage(packageName);
-        if (pkg == null || pkg.mExtras == null) {
-            return 0;
-        }
-        synchronized (mLock) {
-            if (mSettings.getPermissionLocked(permName) == null) {
-                return 0;
-            }
-        }
-        if (mPackageManagerInt.filterAppAccess(pkg, callingUid, userId)) {
-            return 0;
-        }
-        final PackageSetting ps = (PackageSetting) pkg.mExtras;
-        PermissionsState permissionsState = ps.getPermissionsState();
-        return permissionsState.getPermissionFlags(permName, userId);
-    }
-
     /**
      * Update permissions when a package changed.
      *
@@ -2586,16 +3334,15 @@
      * @param callback Callback to call after permission changes
      */
     private void updatePermissions(@NonNull String packageName, @Nullable PackageParser.Package pkg,
-            @NonNull Collection<PackageParser.Package> allPackages,
             @NonNull PermissionCallback callback) {
         final int flags =
                 (pkg != null ? UPDATE_PERMISSIONS_ALL | UPDATE_PERMISSIONS_REPLACE_PKG : 0);
         updatePermissions(
-                packageName, pkg, getVolumeUuidForPackage(pkg), flags, allPackages, callback);
+                packageName, pkg, getVolumeUuidForPackage(pkg), flags, callback);
         if (pkg != null && pkg.childPackages != null) {
             for (PackageParser.Package childPkg : pkg.childPackages) {
                 updatePermissions(childPkg.packageName, childPkg,
-                        getVolumeUuidForPackage(childPkg), flags, allPackages, callback);
+                        getVolumeUuidForPackage(childPkg), flags, callback);
             }
         }
     }
@@ -2613,13 +3360,12 @@
      * @param callback Callback to call after permission changes
      */
     private void updateAllPermissions(@Nullable String volumeUuid, boolean sdkUpdated,
-            @NonNull Collection<PackageParser.Package> allPackages,
             @NonNull PermissionCallback callback) {
         final int flags = UPDATE_PERMISSIONS_ALL |
                 (sdkUpdated
                         ? UPDATE_PERMISSIONS_REPLACE_PKG | UPDATE_PERMISSIONS_REPLACE_ALL
                         : 0);
-        updatePermissions(null, null, volumeUuid, flags, allPackages, callback);
+        updatePermissions(null, null, volumeUuid, flags, callback);
     }
 
     /**
@@ -2697,11 +3443,11 @@
      * @param allPackages All currently known packages
      * @param callback Callback to call after permission changes
      */
-    private void updatePermissions(@Nullable String changingPkgName,
-            @Nullable PackageParser.Package changingPkg, @Nullable String replaceVolumeUuid,
+    private void updatePermissions(final @Nullable String changingPkgName,
+            final @Nullable PackageParser.Package changingPkg,
+            final @Nullable String replaceVolumeUuid,
             @UpdatePermissionFlags int flags,
-            @NonNull Collection<PackageParser.Package> allPackages,
-            @Nullable PermissionCallback callback) {
+            final @Nullable PermissionCallback callback) {
         // TODO: Most of the methods exposing BasePermission internals [source package name,
         // etc..] shouldn't be needed. Instead, when we've parsed a permission that doesn't
         // have package settings, we should make note of it elsewhere [map between
@@ -2730,15 +3476,16 @@
         Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "restorePermissionState");
         // Now update the permissions for all packages.
         if ((flags & UPDATE_PERMISSIONS_ALL) != 0) {
-            for (PackageParser.Package pkg : allPackages) {
-                if (pkg != changingPkg) {
-                    // Only replace for packages on requested volume
-                    final String volumeUuid = getVolumeUuidForPackage(pkg);
-                    final boolean replace = ((flags & UPDATE_PERMISSIONS_REPLACE_ALL) != 0)
-                            && Objects.equals(replaceVolumeUuid, volumeUuid);
-                    restorePermissionState(pkg, replace, changingPkgName, callback);
+            final boolean replaceAll = ((flags & UPDATE_PERMISSIONS_REPLACE_ALL) != 0);
+            mPackageManagerInt.forEachPackage((Package pkg) -> {
+                if (pkg == changingPkg) {
+                    return;
                 }
-            }
+                // Only replace for packages on requested volume
+                final String volumeUuid = getVolumeUuidForPackage(pkg);
+                final boolean replace = replaceAll && Objects.equals(replaceVolumeUuid, volumeUuid);
+                restorePermissionState(pkg, replace, changingPkgName, callback);
+            });
         }
 
         if (changingPkg != null) {
@@ -2880,124 +3627,6 @@
         return changed;
     }
 
-    private void updatePermissionFlags(String permName, String packageName, int flagMask,
-            int flagValues, int callingUid, int userId, boolean overridePolicy,
-            PermissionCallback callback) {
-        if (ApplicationPackageManager.DEBUG_TRACE_GRANTS
-                && ApplicationPackageManager.shouldTraceGrant(packageName, permName, userId)) {
-            Log.i(TAG, "System is updating flags for "
-                            + permName + " for user " + userId  + " "
-                            + DebugUtils.flagsToString(
-                                    PackageManager.class, "FLAG_PERMISSION_", flagMask)
-                            + " := "
-                            + DebugUtils.flagsToString(
-                                    PackageManager.class, "FLAG_PERMISSION_", flagValues)
-                            + " on behalf of uid " + callingUid
-                            + " " + mPackageManagerInt.getNameForUid(callingUid),
-                    new RuntimeException());
-        }
-
-        if (!mUserManagerInt.exists(userId)) {
-            return;
-        }
-
-        enforceGrantRevokeRuntimePermissionPermissions("updatePermissionFlags");
-
-        enforceCrossUserPermission(callingUid, userId,
-                true,  // requireFullPermission
-                true,  // checkShell
-                false, // requirePermissionWhenSameUser
-                "updatePermissionFlags");
-
-        if ((flagMask & FLAG_PERMISSION_POLICY_FIXED) != 0 && !overridePolicy) {
-            throw new SecurityException("updatePermissionFlags requires "
-                    + Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY);
-        }
-
-        // Only the system can change these flags and nothing else.
-        if (callingUid != Process.SYSTEM_UID) {
-            flagMask &= ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
-            flagValues &= ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
-            flagMask &= ~PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
-            flagValues &= ~PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
-            flagValues &= ~PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
-            flagValues &= ~PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT;
-            flagValues &= ~PackageManager.FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
-            flagValues &= ~PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
-            flagValues &= ~PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION;
-        }
-
-        final PackageParser.Package pkg = mPackageManagerInt.getPackage(packageName);
-        if (pkg == null || pkg.mExtras == null) {
-            Log.e(TAG, "Unknown package: " + packageName);
-            return;
-        }
-        if (mPackageManagerInt.filterAppAccess(pkg, callingUid, userId)) {
-            throw new IllegalArgumentException("Unknown package: " + packageName);
-        }
-
-        final BasePermission bp;
-        synchronized (mLock) {
-            bp = mSettings.getPermissionLocked(permName);
-        }
-        if (bp == null) {
-            throw new IllegalArgumentException("Unknown permission: " + permName);
-        }
-
-        final PackageSetting ps = (PackageSetting) pkg.mExtras;
-        final PermissionsState permissionsState = ps.getPermissionsState();
-        final boolean hadState =
-                permissionsState.getRuntimePermissionState(permName, userId) != null;
-        final boolean permissionUpdated =
-                permissionsState.updatePermissionFlags(bp, userId, flagMask, flagValues);
-        if (permissionUpdated && bp.isRuntime()) {
-            notifyRuntimePermissionStateChanged(packageName, userId);
-        }
-        if (permissionUpdated && callback != null) {
-            // Install and runtime permissions are stored in different places,
-            // so figure out what permission changed and persist the change.
-            if (permissionsState.getInstallPermissionState(permName) != null) {
-                callback.onInstallPermissionUpdated();
-            } else if (permissionsState.getRuntimePermissionState(permName, userId) != null
-                    || hadState) {
-                callback.onPermissionUpdated(new int[] { userId }, false);
-            }
-        }
-    }
-
-    private boolean updatePermissionFlagsForAllApps(int flagMask, int flagValues, int callingUid,
-            int userId, Collection<Package> packages, PermissionCallback callback) {
-        if (!mUserManagerInt.exists(userId)) {
-            return false;
-        }
-
-        enforceGrantRevokeRuntimePermissionPermissions(
-                "updatePermissionFlagsForAllApps");
-        enforceCrossUserPermission(callingUid, userId,
-                true,  // requireFullPermission
-                true,  // checkShell
-                false, // requirePermissionWhenSameUser
-                "updatePermissionFlagsForAllApps");
-
-        // Only the system can change system fixed flags.
-        if (callingUid != Process.SYSTEM_UID) {
-            flagMask &= ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
-            flagValues &= ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
-        }
-
-        boolean changed = false;
-        for (PackageParser.Package pkg : packages) {
-            final PackageSetting ps = (PackageSetting) pkg.mExtras;
-            if (ps == null) {
-                continue;
-            }
-            PermissionsState permissionsState = ps.getPermissionsState();
-            changed |= permissionsState.updatePermissionFlagsForAllPermissions(
-                    userId, flagMask, flagValues);
-        }
-        return changed;
-    }
-
     private void enforceGrantRevokeRuntimePermissionPermissions(String message) {
         if (mContext.checkCallingOrSelfPermission(Manifest.permission.GRANT_RUNTIME_PERMISSIONS)
                 != PackageManager.PERMISSION_GRANTED
@@ -3150,10 +3779,9 @@
         public void revokeRuntimePermissionsIfGroupChanged(
                 @NonNull PackageParser.Package newPackage,
                 @NonNull PackageParser.Package oldPackage,
-                @NonNull ArrayList<String> allPackageNames,
-                @NonNull PermissionCallback permissionCallback) {
+                @NonNull ArrayList<String> allPackageNames) {
             PermissionManagerService.this.revokeRuntimePermissionsIfGroupChanged(newPackage,
-                    oldPackage, allPackageNames, permissionCallback);
+                    oldPackage, allPackageNames, mDefaultPermissionCallback);
         }
         @Override
         public void addAllPermissions(Package pkg, boolean chatty) {
@@ -3168,57 +3796,50 @@
             PermissionManagerService.this.removeAllPermissions(pkg, chatty);
         }
         @Override
-        public void grantRuntimePermission(String permName, String packageName,
-                boolean overridePolicy, int callingUid, int userId,
-                PermissionCallback callback) {
-            PermissionManagerService.this.grantRuntimePermission(
-                    permName, packageName, overridePolicy, callingUid, userId, callback);
-        }
-        @Override
         public void grantRequestedRuntimePermissions(PackageParser.Package pkg, int[] userIds,
-                String[] grantedPermissions, int callingUid, PermissionCallback callback) {
+                String[] grantedPermissions, int callingUid) {
             PermissionManagerService.this.grantRequestedRuntimePermissions(
-                    pkg, userIds, grantedPermissions, callingUid, callback);
-        }
-        @Override
-        public List<String> getWhitelistedRestrictedPermissions(PackageParser.Package pkg,
-                @PackageManager.PermissionWhitelistFlags int whitelistFlags, int userId) {
-            return PermissionManagerService.this.getWhitelistedRestrictedPermissions(pkg,
-                    whitelistFlags, userId);
+                    pkg, userIds, grantedPermissions, callingUid, mDefaultPermissionCallback);
         }
         @Override
         public void setWhitelistedRestrictedPermissions(@NonNull PackageParser.Package pkg,
                 @NonNull int[] userIds, @Nullable List<String> permissions, int callingUid,
-                @PackageManager.PermissionWhitelistFlags int whitelistFlags,
-                @NonNull PermissionCallback callback) {
-            PermissionManagerService.this.setWhitelistedRestrictedPermissions(
-                    pkg, userIds, permissions, callingUid, whitelistFlags, callback);
+                @PackageManager.PermissionWhitelistFlags int flags) {
+            for (int userId : userIds) {
+                setWhitelistedRestrictedPermissionsForUser(pkg, userId, permissions,
+                        callingUid, flags, mDefaultPermissionCallback);
+            }
+        }
+        @Override
+        public void setWhitelistedRestrictedPermissions(String packageName,
+                List<String> permissions, int flags, int userId) {
+            PermissionManagerService.this.setWhitelistedRestrictedPermissionsInternal(
+                    packageName, permissions, flags, userId);
         }
         @Override
         public void grantRuntimePermissionsGrantedToDisabledPackage(PackageParser.Package pkg,
-                int callingUid, PermissionCallback callback) {
+                int callingUid) {
             PermissionManagerService.this.grantRuntimePermissionsGrantedToDisabledPackageLocked(
-                    pkg, callingUid, callback);
+                    pkg, callingUid, mDefaultPermissionCallback);
         }
         @Override
-        public void revokeRuntimePermission(String permName, String packageName,
-                boolean overridePolicy, int userId, PermissionCallback callback) {
-            PermissionManagerService.this.revokeRuntimePermission(permName, packageName,
-                    overridePolicy, userId, callback);
+        public void updatePermissions(@NonNull String packageName, @Nullable Package pkg) {
+            PermissionManagerService.this
+                    .updatePermissions(packageName, pkg, mDefaultPermissionCallback);
         }
         @Override
-        public void updatePermissions(@NonNull String packageName, @Nullable Package pkg,
-                @NonNull Collection<PackageParser.Package> allPackages,
-                @NonNull PermissionCallback callback) {
-            PermissionManagerService.this.updatePermissions(
-                    packageName, pkg, allPackages, callback);
+        public void updateAllPermissions(@Nullable String volumeUuid, boolean sdkUpdated) {
+            PermissionManagerService.this
+                    .updateAllPermissions(volumeUuid, sdkUpdated, mDefaultPermissionCallback);
         }
         @Override
-        public void updateAllPermissions(@Nullable String volumeUuid, boolean sdkUpdated,
-                @NonNull Collection<PackageParser.Package> allPackages,
-                @NonNull PermissionCallback callback) {
-            PermissionManagerService.this.updateAllPermissions(
-                    volumeUuid, sdkUpdated, allPackages, callback);
+        public void resetRuntimePermissions(Package pkg, int userId) {
+            PermissionManagerService.this.resetRuntimePermissionsInternal(pkg, userId);
+        }
+        @Override
+        public void resetAllRuntimePermissions(final int userId) {
+            mPackageManagerInt.forEachPackage(
+                    (PackageParser.Package pkg) -> resetRuntimePermissionsInternal(pkg, userId));
         }
         @Override
         public String[] getAppOpPermissionPackages(String permName, int callingUid) {
@@ -3228,24 +3849,18 @@
         @Override
         public int getPermissionFlags(String permName, String packageName, int callingUid,
                 int userId) {
-            return PermissionManagerService.this.getPermissionFlags(permName, packageName,
-                    callingUid, userId);
+            return PermissionManagerService.this
+                    .getPermissionFlagsInternal(permName, packageName, callingUid, userId);
         }
         @Override
         public void updatePermissionFlags(String permName, String packageName, int flagMask,
                 int flagValues, int callingUid, int userId, boolean overridePolicy,
                 PermissionCallback callback) {
-            PermissionManagerService.this.updatePermissionFlags(
+            PermissionManagerService.this.updatePermissionFlagsInternal(
                     permName, packageName, flagMask, flagValues, callingUid, userId,
                     overridePolicy, callback);
         }
         @Override
-        public boolean updatePermissionFlagsForAllApps(int flagMask, int flagValues, int callingUid,
-                int userId, Collection<Package> packages, PermissionCallback callback) {
-            return PermissionManagerService.this.updatePermissionFlagsForAllApps(
-                    flagMask, flagValues, callingUid, userId, packages, callback);
-        }
-        @Override
         public void enforceCrossUserPermission(int callingUid, int userId,
                 boolean requireFullPermission, boolean checkShell, String message) {
             PermissionManagerService.this.enforceCrossUserPermission(callingUid, userId,
@@ -3263,17 +3878,6 @@
             PermissionManagerService.this.enforceGrantRevokeRuntimePermissionPermissions(message);
         }
         @Override
-        public int checkPermission(String permName, String packageName, int callingUid,
-                int userId) {
-            return PermissionManagerService.this.checkPermission(
-                    permName, packageName, callingUid, userId);
-        }
-        @Override
-        public int checkUidPermission(String permName, PackageParser.Package pkg, int uid,
-                int callingUid) {
-            return PermissionManagerService.this.checkUidPermission(permName, pkg, uid, callingUid);
-        }
-        @Override
         public PermissionSettings getPermissionSettings() {
             return mSettings;
         }
@@ -3338,5 +3942,76 @@
             PermissionManagerService.this.removeOnRuntimePermissionStateChangedListener(
                     listener);
         }
+
+        @Override
+        public CheckPermissionDelegate getCheckPermissionDelegate() {
+            synchronized (mLock) {
+                return mCheckPermissionDelegate;
+            }
+        }
+
+        @Override
+        public void setCheckPermissionDelegate(CheckPermissionDelegate delegate) {
+            synchronized (mLock) {
+                mCheckPermissionDelegate = delegate;
+            }
+        }
+        @Override
+        public void notifyPermissionsChangedTEMP(int uid) {
+            mOnPermissionChangeListeners.onPermissionsChanged(uid);
+        }
+    }
+
+    private static final class OnPermissionChangeListeners extends Handler {
+        private static final int MSG_ON_PERMISSIONS_CHANGED = 1;
+
+        private final RemoteCallbackList<IOnPermissionsChangeListener> mPermissionListeners =
+                new RemoteCallbackList<>();
+
+        OnPermissionChangeListeners(Looper looper) {
+            super(looper);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_ON_PERMISSIONS_CHANGED: {
+                    final int uid = msg.arg1;
+                    handleOnPermissionsChanged(uid);
+                } break;
+            }
+        }
+
+        public void addListenerLocked(IOnPermissionsChangeListener listener) {
+            mPermissionListeners.register(listener);
+
+        }
+
+        public void removeListenerLocked(IOnPermissionsChangeListener listener) {
+            mPermissionListeners.unregister(listener);
+        }
+
+        public void onPermissionsChanged(int uid) {
+            if (mPermissionListeners.getRegisteredCallbackCount() > 0) {
+                obtainMessage(MSG_ON_PERMISSIONS_CHANGED, uid, 0).sendToTarget();
+            }
+        }
+
+        private void handleOnPermissionsChanged(int uid) {
+            final int count = mPermissionListeners.beginBroadcast();
+            try {
+                for (int i = 0; i < count; i++) {
+                    IOnPermissionsChangeListener callback = mPermissionListeners
+                            .getBroadcastItem(i);
+                    try {
+                        callback.onPermissionsChanged(uid);
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "Permission listener is dead", e);
+                    }
+                }
+            } finally {
+                mPermissionListeners.finishBroadcast();
+            }
+        }
     }
 }
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 23d0114..2fdab4d 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
@@ -16,6 +16,7 @@
 
 package com.android.server.pm.permission;
 
+import android.annotation.AppIdInt;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
@@ -25,7 +26,6 @@
 import android.permission.PermissionManagerInternal;
 
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.List;
 
 /**
@@ -42,24 +42,29 @@
      * callback methods.
      */
     public static class PermissionCallback {
-        public void onGidsChanged(int appId, int userId) {
+        public void onGidsChanged(@AppIdInt int appId, @UserIdInt int userId) {
         }
         public void onPermissionChanged() {
         }
-        public void onPermissionGranted(int uid, int userId) {
+        public void onPermissionGranted(int uid, @UserIdInt int userId) {
         }
         public void onInstallPermissionGranted() {
         }
-        public void onPermissionRevoked(int uid, int userId) {
+        public void onPermissionRevoked(int uid, @UserIdInt int userId) {
         }
         public void onInstallPermissionRevoked() {
         }
-        public void onPermissionUpdated(int[] updatedUserIds, boolean sync) {
+        public void onPermissionUpdated(@UserIdInt int[] updatedUserIds, boolean sync) {
+        }
+        public void onPermissionUpdatedNotifyListener(@UserIdInt int[] updatedUserIds, boolean sync,
+                int uid) {
         }
         public void onPermissionRemoved() {
         }
         public void onInstallPermissionUpdated() {
         }
+        public void onInstallPermissionUpdatedNotifyListener(int uid) {
+        }
     }
 
     public abstract void systemReady();
@@ -67,27 +72,19 @@
     public abstract boolean isPermissionsReviewRequired(@NonNull PackageParser.Package pkg,
             @UserIdInt int userId);
 
-    public abstract void grantRuntimePermission(
-            @NonNull String permName, @NonNull String packageName, boolean overridePolicy,
-            int callingUid, int userId, @Nullable PermissionCallback callback);
     public abstract void grantRuntimePermissionsGrantedToDisabledPackage(
-            @NonNull PackageParser.Package pkg, int callingUid,
-            @Nullable PermissionCallback callback);
+            @NonNull PackageParser.Package pkg, int callingUid);
     public abstract void grantRequestedRuntimePermissions(
             @NonNull PackageParser.Package pkg, @NonNull int[] userIds,
-            @NonNull String[] grantedPermissions, int callingUid,
-            @Nullable PermissionCallback callback);
-    public abstract @Nullable List<String> getWhitelistedRestrictedPermissions(
-            @NonNull PackageParser.Package pkg,
-            @PackageManager.PermissionWhitelistFlags int whitelistFlags, int userId);
+            @NonNull String[] grantedPermissions, int callingUid);
     public abstract void setWhitelistedRestrictedPermissions(
             @NonNull PackageParser.Package pkg, @NonNull int[] userIds,
             @NonNull List<String> permissions, int callingUid,
-            @PackageManager.PermissionWhitelistFlags int whitelistFlags,
-            @Nullable PermissionCallback callback);
-    public abstract void revokeRuntimePermission(@NonNull String permName,
-            @NonNull String packageName, boolean overridePolicy, int userId,
-            @Nullable PermissionCallback callback);
+            @PackageManager.PermissionWhitelistFlags int whitelistFlags);
+    /** Sets the whitelisted, restricted permissions for the given package. */
+    public abstract void setWhitelistedRestrictedPermissions(
+            @NonNull String packageName, @NonNull List<String> permissions,
+            @PackageManager.PermissionWhitelistFlags int flags, @NonNull int userId);
 
     /**
      * Update permissions when a package changed.
@@ -103,9 +100,7 @@
      * @param callback Callback to call after permission changes
      */
     public abstract void updatePermissions(@NonNull String packageName,
-            @Nullable PackageParser.Package pkg,
-            @NonNull Collection<PackageParser.Package> allPackages,
-            @NonNull PermissionCallback callback);
+            @Nullable PackageParser.Package pkg);
 
     /**
      * Update all permissions for all apps.
@@ -119,9 +114,22 @@
      * @param allPackages All currently known packages
      * @param callback Callback to call after permission changes
      */
-    public abstract void updateAllPermissions(@Nullable String volumeUuid, boolean sdkUpdate,
-            @NonNull Collection<PackageParser.Package> allPackages,
-            @NonNull PermissionCallback callback);
+    public abstract void updateAllPermissions(@Nullable String volumeUuid, boolean sdkUpdate);
+
+    /**
+     * Resets any user permission state changes (eg. permissions and flags) of all
+     * packages installed for the given user.
+     *
+     * @see #resetRuntimePermissions(android.content.pm.PackageParser.Package, int)
+     */
+    public abstract void resetAllRuntimePermissions(@UserIdInt int userId);
+
+    /**
+     * Resets any user permission state changes (eg. permissions and flags) of the
+     * specified package for the given user.
+     */
+    public abstract void resetRuntimePermissions(@NonNull PackageParser.Package pkg,
+            @UserIdInt int userId);
 
     /**
      * We might auto-grant permissions if any permission of the group is already granted. Hence if
@@ -131,13 +139,11 @@
      * @param newPackage The new package that was installed
      * @param oldPackage The old package that was updated
      * @param allPackageNames All packages
-     * @param permissionCallback Callback for permission changed
      */
     public abstract void revokeRuntimePermissionsIfGroupChanged(
             @NonNull PackageParser.Package newPackage,
             @NonNull PackageParser.Package oldPackage,
-            @NonNull ArrayList<String> allPackageNames,
-            @NonNull PermissionCallback permissionCallback);
+            @NonNull ArrayList<String> allPackageNames);
 
     /**
      * Add all permissions in the given package.
@@ -163,18 +169,6 @@
     public abstract void updatePermissionFlags(@NonNull String permName,
             @NonNull String packageName, int flagMask, int flagValues, int callingUid, int userId,
             boolean overridePolicy, @Nullable PermissionCallback callback);
-    /**
-     * Updates the flags for all applications by replacing the flags in the specified mask
-     * with the provided flag values.
-     */
-    public abstract boolean updatePermissionFlagsForAllApps(int flagMask, int flagValues,
-            int callingUid, int userId, @NonNull Collection<PackageParser.Package> packages,
-            @Nullable PermissionCallback callback);
-
-    public abstract int checkPermission(@NonNull String permName, @NonNull String packageName,
-            int callingUid, int userId);
-    public abstract int checkUidPermission(@NonNull String permName,
-            @Nullable PackageParser.Package pkg, int uid, int callingUid);
 
     /**
      * Enforces the request is from the system or an app that has INTERACT_ACROSS_USERS
@@ -199,8 +193,25 @@
 
     /** HACK HACK methods to allow for partial migration of data to the PermissionManager class */
     public abstract @Nullable BasePermission getPermissionTEMP(@NonNull String permName);
+    /** HACK HACK notify the permission listener; this shouldn't be needed after permissions
+     *  are fully removed from the package manager */
+    public abstract void notifyPermissionsChangedTEMP(int uid);
 
     /** Get all permission that have a certain protection level */
     public abstract @NonNull ArrayList<PermissionInfo> getAllPermissionWithProtectionLevel(
             @PermissionInfo.Protection int protectionLevel);
+
+    /**
+     * Returns the delegate used to influence permission checking.
+     *
+     * @return The delegate instance.
+     */
+    public abstract @Nullable CheckPermissionDelegate getCheckPermissionDelegate();
+
+    /**
+     * Sets the delegate used to influence permission checking.
+     *
+     * @param delegate A delegate instance or {@code null} to clear.
+     */
+    public abstract void setCheckPermissionDelegate(@Nullable CheckPermissionDelegate delegate);
 }
diff --git a/services/core/java/com/android/server/pm/permission/TEST_MAPPING b/services/core/java/com/android/server/pm/permission/TEST_MAPPING
index 3f9eb2d..ee7a098 100644
--- a/services/core/java/com/android/server/pm/permission/TEST_MAPPING
+++ b/services/core/java/com/android/server/pm/permission/TEST_MAPPING
@@ -14,6 +14,9 @@
                 },
                 {
                     "include-filter": "android.permission.cts.SharedUidPermissionsTest"
+                },
+                {
+                    "include-filter": "android.permission.cts.PermissionUpdateListenerTest"
                 }
             ]
         },
diff --git a/services/core/java/com/android/server/policy/PermissionPolicyService.java b/services/core/java/com/android/server/policy/PermissionPolicyService.java
index 037293f..a569bff 100644
--- a/services/core/java/com/android/server/policy/PermissionPolicyService.java
+++ b/services/core/java/com/android/server/policy/PermissionPolicyService.java
@@ -798,7 +798,7 @@
         @Override
         public boolean checkStartActivity(@NonNull Intent intent, int callingUid,
                 @Nullable String callingPackage) {
-            if (callingPackage != null && isActionRemovedForCallingPackage(intent.getAction(),
+            if (callingPackage != null && isActionRemovedForCallingPackage(intent, callingUid,
                     callingPackage)) {
                 Slog.w(LOG_TAG, "Action Removed: starting " + intent.toString() + " from "
                         + callingPackage + " (uid=" + callingUid + ")");
@@ -811,8 +811,9 @@
          * Check if the intent action is removed for the calling package (often based on target SDK
          * version). If the action is removed, we'll silently cancel the activity launch.
          */
-        private boolean isActionRemovedForCallingPackage(@Nullable String action,
+        private boolean isActionRemovedForCallingPackage(@NonNull Intent intent, int callingUid,
                 @NonNull String callingPackage) {
+            String action = intent.getAction();
             if (action == null) {
                 return false;
             }
@@ -821,15 +822,19 @@
                 case Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT: {
                     ApplicationInfo applicationInfo;
                     try {
-                        applicationInfo = getContext().getPackageManager().getApplicationInfo(
-                                callingPackage, 0);
+                        applicationInfo = getContext().getPackageManager().getApplicationInfoAsUser(
+                                callingPackage, 0, UserHandle.getUserId(callingUid));
+                        if (applicationInfo.targetSdkVersion >= Build.VERSION_CODES.Q) {
+                            // Applications targeting Q or higher should use
+                            // RoleManager.createRequestRoleIntent() instead.
+                            return true;
+                        }
                     } catch (PackageManager.NameNotFoundException e) {
                         Slog.i(LOG_TAG, "Cannot find application info for " + callingPackage);
-                        return false;
                     }
-                    // Applications targeting Q should use RoleManager.createRequestRoleIntent()
-                    // instead.
-                    return applicationInfo.targetSdkVersion >= Build.VERSION_CODES.Q;
+                    // Make sure RequestRoleActivity can know the calling package if we allow it.
+                    intent.putExtra(Intent.EXTRA_CALLING_PACKAGE, callingPackage);
+                    return false;
                 }
                 default:
                     return false;
diff --git a/services/core/java/com/android/server/role/RoleManagerService.java b/services/core/java/com/android/server/role/RoleManagerService.java
index c6a1867..b503ce8 100644
--- a/services/core/java/com/android/server/role/RoleManagerService.java
+++ b/services/core/java/com/android/server/role/RoleManagerService.java
@@ -17,6 +17,7 @@
 package com.android.server.role;
 
 import android.Manifest;
+import android.annotation.AnyThread;
 import android.annotation.CheckResult;
 import android.annotation.MainThread;
 import android.annotation.NonNull;
@@ -49,7 +50,6 @@
 import android.os.ShellCallback;
 import android.os.UserHandle;
 import android.os.UserManagerInternal;
-import android.provider.Telephony;
 import android.service.sms.FinancialSmsService;
 import android.telephony.IFinancialSmsCallback;
 import android.text.TextUtils;
@@ -61,6 +61,8 @@
 import android.util.proto.ProtoOutputStream;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.infra.AndroidFuture;
+import com.android.internal.infra.ThrottledRunnable;
 import com.android.internal.telephony.SmsApplication;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.BitUtils;
@@ -82,7 +84,6 @@
 import java.util.Collections;
 import java.util.List;
 import java.util.Objects;
-import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
@@ -99,6 +100,8 @@
 
     private static final boolean DEBUG = false;
 
+    private static final long GRANT_DEFAULT_ROLES_INTERVAL_MILLIS = 1000;
+
     @NonNull
     private final UserManagerInternal mUserManagerInternal;
     @NonNull
@@ -142,6 +145,14 @@
     @NonNull
     private final Handler mListenerHandler = FgThread.getHandler();
 
+    /**
+     * Maps user id to its throttled runnable for granting default roles.
+     */
+    @GuardedBy("mLock")
+    @NonNull
+    private final SparseArray<ThrottledRunnable> mGrantDefaultRolesThrottledRunnables =
+            new SparseArray<>();
+
     public RoleManagerService(@NonNull Context context,
             @NonNull RoleHoldersResolver legacyRoleResolver) {
         super(context);
@@ -182,8 +193,6 @@
     public void onStart() {
         publishBinderService(Context.ROLE_SERVICE, new Stub());
 
-        //TODO add watch for new user creation and run default grants for them
-
         IntentFilter intentFilter = new IntentFilter();
         intentFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
         intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
@@ -203,64 +212,78 @@
                     // Package is being upgraded - we're about to get ACTION_PACKAGE_ADDED
                     return;
                 }
-                performInitialGrantsIfNecessaryAsync(userId);
+                maybeGrantDefaultRolesAsync(userId);
             }
         }, UserHandle.ALL, intentFilter, null, null);
     }
 
     @Override
     public void onStartUser(@UserIdInt int userId) {
-        performInitialGrantsIfNecessary(userId);
-    }
-
-    private CompletableFuture<Void> performInitialGrantsIfNecessaryAsync(@UserIdInt int userId) {
-        RoleUserState userState;
-        userState = getOrCreateUserState(userId);
-
-        String packagesHash = computeComponentStateHash(userId);
-        String oldPackagesHash = userState.getPackagesHash();
-        boolean needGrant = !Objects.equals(packagesHash, oldPackagesHash);
-        if (needGrant) {
-
-            //TODO gradually add more role migrations statements here for remaining roles
-            // Make sure to implement LegacyRoleResolutionPolicy#getRoleHolders
-            // for a given role before adding a migration statement for it here
-            migrateRoleIfNecessary(RoleManager.ROLE_SMS, userId);
-            migrateRoleIfNecessary(RoleManager.ROLE_ASSISTANT, userId);
-            migrateRoleIfNecessary(RoleManager.ROLE_DIALER, userId);
-            migrateRoleIfNecessary(RoleManager.ROLE_EMERGENCY, userId);
-
-            // Some vital packages state has changed since last role grant
-            // Run grants again
-            Slog.i(LOG_TAG, "Granting default permissions...");
-            CompletableFuture<Void> result = new CompletableFuture<>();
-            getOrCreateController(userId).grantDefaultRoles(FgThread.getExecutor(),
-                    successful -> {
-                        if (successful) {
-                            userState.setPackagesHash(packagesHash);
-                            result.complete(null);
-                        } else {
-                            result.completeExceptionally(new RuntimeException());
-                        }
-                    });
-            return result;
-        } else if (DEBUG) {
-            Slog.i(LOG_TAG, "Already ran grants for package state " + packagesHash);
-        }
-        return CompletableFuture.completedFuture(null);
+        maybeGrantDefaultRolesSync(userId);
     }
 
     @MainThread
-    private void performInitialGrantsIfNecessary(@UserIdInt int userId) {
-        CompletableFuture<Void> result = performInitialGrantsIfNecessaryAsync(userId);
+    private void maybeGrantDefaultRolesSync(@UserIdInt int userId) {
+        AndroidFuture<Void> future = maybeGrantDefaultRolesInternal(userId);
         try {
-            result.get(30, TimeUnit.SECONDS);
+            future.get(30, TimeUnit.SECONDS);
         } catch (InterruptedException | ExecutionException | TimeoutException e) {
-            Slog.e(LOG_TAG, "Failed to grant defaults for user " + userId, e);
+            Slog.e(LOG_TAG, "Failed to grant default roles for user " + userId, e);
         }
     }
 
-    private void migrateRoleIfNecessary(String role, @UserIdInt int userId) {
+    private void maybeGrantDefaultRolesAsync(@UserIdInt int userId) {
+        ThrottledRunnable runnable;
+        synchronized (mLock) {
+            runnable = mGrantDefaultRolesThrottledRunnables.get(userId);
+            if (runnable == null) {
+                runnable = new ThrottledRunnable(FgThread.getHandler(),
+                        GRANT_DEFAULT_ROLES_INTERVAL_MILLIS,
+                        () -> maybeGrantDefaultRolesInternal(userId));
+                mGrantDefaultRolesThrottledRunnables.put(userId, runnable);
+            }
+        }
+        runnable.run();
+    }
+
+    @AnyThread
+    @NonNull
+    private AndroidFuture<Void> maybeGrantDefaultRolesInternal(@UserIdInt int userId) {
+        RoleUserState userState = getOrCreateUserState(userId);
+        String oldPackagesHash = userState.getPackagesHash();
+        String newPackagesHash = computeComponentStateHash(userId);
+        if (Objects.equals(oldPackagesHash, newPackagesHash)) {
+            if (DEBUG) {
+                Slog.i(LOG_TAG, "Already granted default roles for packages hash "
+                        + newPackagesHash);
+            }
+            return AndroidFuture.completedFuture(null);
+        }
+
+        //TODO gradually add more role migrations statements here for remaining roles
+        // Make sure to implement LegacyRoleResolutionPolicy#getRoleHolders
+        // for a given role before adding a migration statement for it here
+        maybeMigrateRole(RoleManager.ROLE_SMS, userId);
+        maybeMigrateRole(RoleManager.ROLE_ASSISTANT, userId);
+        maybeMigrateRole(RoleManager.ROLE_DIALER, userId);
+        maybeMigrateRole(RoleManager.ROLE_EMERGENCY, userId);
+
+        // Some package state has changed, so grant default roles again.
+        Slog.i(LOG_TAG, "Granting default roles...");
+        AndroidFuture<Void> future = new AndroidFuture<>();
+        getOrCreateController(userId).grantDefaultRoles(FgThread.getExecutor(),
+                successful -> {
+                    if (successful) {
+                        userState.setPackagesHash(newPackagesHash);
+                        future.complete(null);
+                    } else {
+                        future.completeExceptionally(new RuntimeException());
+                    }
+                });
+        return future;
+    }
+
+    private void maybeMigrateRole(String role, @UserIdInt int userId) {
         // Any role for which we have a record are already migrated
         RoleUserState userState = getOrCreateUserState(userId);
         if (!userState.isRoleAvailable(role)) {
@@ -366,6 +389,7 @@
         RemoteCallbackList<IOnRoleHoldersChangedListener> listeners;
         RoleUserState userState;
         synchronized (mLock) {
+            mGrantDefaultRolesThrottledRunnables.remove(userId);
             listeners = mListeners.removeReturnOld(userId);
             mControllers.remove(userId);
             userState = mUserStates.removeReturnOld(userId);
@@ -742,7 +766,7 @@
 
         @Override
         public boolean setDefaultBrowser(@Nullable String packageName, @UserIdInt int userId) {
-            CompletableFuture<Void> future = new CompletableFuture<>();
+            AndroidFuture<Void> future = new AndroidFuture<>();
             RemoteCallback callback = new RemoteCallback(result -> {
                 boolean successful = result != null;
                 if (successful) {
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index 82eab63..cfa370b 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -86,9 +86,9 @@
 
     private static final String TAG = "RollbackManager";
 
-    // Rollbacks expire after 48 hours.
+    // Rollbacks expire after 14 days.
     private static final long DEFAULT_ROLLBACK_LIFETIME_DURATION_MILLIS =
-            TimeUnit.HOURS.toMillis(48);
+            TimeUnit.DAYS.toMillis(14);
 
     // Lock used to synchronize accesses to in-memory rollback data
     // structures. By convention, methods with the suffix "Locked" require
@@ -1247,7 +1247,8 @@
 
 
     private boolean packageVersionsEqual(VersionedPackage a, VersionedPackage b) {
-        return a.getPackageName().equals(b.getPackageName())
+        return a != null && b != null
+            && a.getPackageName().equals(b.getPackageName())
             && a.getLongVersionCode() == b.getLongVersionCode();
     }
 
diff --git a/services/core/java/com/android/server/textservices/LazyIntToIntMap.java b/services/core/java/com/android/server/textservices/LazyIntToIntMap.java
deleted file mode 100644
index 2e7f2a9..0000000
--- a/services/core/java/com/android/server/textservices/LazyIntToIntMap.java
+++ /dev/null
@@ -1,64 +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 com.android.server.textservices;
-
-import android.annotation.NonNull;
-import android.util.SparseIntArray;
-
-import java.util.function.IntUnaryOperator;
-
-/**
- * Simple int-to-int key-value-store that is to be lazily initialized with the given
- * {@link IntUnaryOperator}.
- */
-final class LazyIntToIntMap {
-
-    private final SparseIntArray mMap = new SparseIntArray();
-
-    @NonNull
-    private final IntUnaryOperator mMappingFunction;
-
-    /**
-     * @param mappingFunction int to int mapping rules to be (lazily) evaluated
-     */
-    public LazyIntToIntMap(@NonNull IntUnaryOperator mappingFunction) {
-        mMappingFunction = mappingFunction;
-    }
-
-    /**
-     * Deletes {@code key} and associated value.
-     * @param key key to be deleted
-     */
-    public void delete(int key) {
-        mMap.delete(key);
-    }
-
-    /**
-     * @param key key associated with the value
-     * @return value associated with the {@code key}. If this is the first time to access
-     * {@code key}, then {@code mappingFunction} passed to the constructor will be evaluated
-     */
-    public int get(int key) {
-        final int index = mMap.indexOfKey(key);
-        if (index >= 0) {
-            return mMap.valueAt(index);
-        }
-        final int value = mMappingFunction.applyAsInt(key);
-        mMap.append(key, value);
-        return value;
-    }
-}
diff --git a/services/core/java/com/android/server/textservices/TextServicesManagerService.java b/services/core/java/com/android/server/textservices/TextServicesManagerService.java
index d4aa59d..e0bac93 100644
--- a/services/core/java/com/android/server/textservices/TextServicesManagerService.java
+++ b/services/core/java/com/android/server/textservices/TextServicesManagerService.java
@@ -43,7 +43,6 @@
 import android.text.TextUtils;
 import android.util.Slog;
 import android.util.SparseArray;
-import android.view.inputmethod.InputMethodSystemProperty;
 import android.view.textservice.SpellCheckerInfo;
 import android.view.textservice.SpellCheckerSubtype;
 
@@ -86,10 +85,6 @@
     private final UserManager mUserManager;
     private final Object mLock = new Object();
 
-    @NonNull
-    @GuardedBy("mLock")
-    private final LazyIntToIntMap mSpellCheckerOwnerUserIdMap;
-
     private static class TextServicesData {
         @UserIdInt
         private final int mUserId;
@@ -312,9 +307,6 @@
 
     void onStopUser(@UserIdInt int userId) {
         synchronized (mLock) {
-            // Clear user ID mapping table.
-            mSpellCheckerOwnerUserIdMap.delete(userId);
-
             // Clean per-user data
             TextServicesData tsd = mUserData.get(userId);
             if (tsd == null) return;
@@ -334,33 +326,12 @@
     public TextServicesManagerService(Context context) {
         mContext = context;
         mUserManager = mContext.getSystemService(UserManager.class);
-        mSpellCheckerOwnerUserIdMap = new LazyIntToIntMap(callingUserId -> {
-            if (!InputMethodSystemProperty.PER_PROFILE_IME_ENABLED) {
-                final long token = Binder.clearCallingIdentity();
-                try {
-                    final UserInfo parent = mUserManager.getProfileParent(callingUserId);
-                    return (parent != null) ? parent.id : callingUserId;
-                } finally {
-                    Binder.restoreCallingIdentity(token);
-                }
-            } else {
-                return callingUserId;
-            }
-        });
-
         mMonitor = new TextServicesMonitor();
         mMonitor.register(context, null, UserHandle.ALL, true);
     }
 
     @GuardedBy("mLock")
     private void initializeInternalStateLocked(@UserIdInt int userId) {
-        // When DISABLE_PER_PROFILE_SPELL_CHECKER is true, we make sure here that work profile users
-        // will never have non-null TextServicesData for their user ID.
-        if (!InputMethodSystemProperty.PER_PROFILE_IME_ENABLED
-                && userId != mSpellCheckerOwnerUserIdMap.get(userId)) {
-            return;
-        }
-
         TextServicesData tsd = mUserData.get(userId);
         if (tsd == null) {
             tsd = new TextServicesData(userId, mContext);
@@ -506,8 +477,7 @@
     @Nullable
     private SpellCheckerInfo getCurrentSpellCheckerForUser(@UserIdInt int userId) {
         synchronized (mLock) {
-            final int spellCheckerOwnerUserId = mSpellCheckerOwnerUserIdMap.get(userId);
-            final TextServicesData data = mUserData.get(spellCheckerOwnerUserId);
+            final TextServicesData data = mUserData.get(userId);
             return data != null ? data.getCurrentSpellChecker() : null;
         }
     }
@@ -790,27 +760,7 @@
     @GuardedBy("mLock")
     @Nullable
     private TextServicesData getDataFromCallingUserIdLocked(@UserIdInt int callingUserId) {
-        final int spellCheckerOwnerUserId = mSpellCheckerOwnerUserIdMap.get(callingUserId);
-        final TextServicesData data = mUserData.get(spellCheckerOwnerUserId);
-        if (!InputMethodSystemProperty.PER_PROFILE_IME_ENABLED) {
-            if (spellCheckerOwnerUserId != callingUserId) {
-                // Calling process is running under child profile.
-                if (data == null) {
-                    return null;
-                }
-                final SpellCheckerInfo info = data.getCurrentSpellChecker();
-                if (info == null) {
-                    return null;
-                }
-                final ServiceInfo serviceInfo = info.getServiceInfo();
-                if ((serviceInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
-                    // To be conservative, non pre-installed spell checker services are not allowed
-                    // to be used for child profiles.
-                    return null;
-                }
-            }
-        }
-        return data;
+        return mUserData.get(callingUserId);
     }
 
     private static final class SessionRequest {
diff --git a/services/core/java/com/android/server/updates/CertificateTransparencyLogInstallReceiver.java b/services/core/java/com/android/server/updates/CertificateTransparencyLogInstallReceiver.java
index ec65f8d..bf32045 100644
--- a/services/core/java/com/android/server/updates/CertificateTransparencyLogInstallReceiver.java
+++ b/services/core/java/com/android/server/updates/CertificateTransparencyLogInstallReceiver.java
@@ -16,25 +16,30 @@
 
 package com.android.server.updates;
 
-import com.android.internal.util.HexDump;
 import android.os.FileUtils;
-import android.system.Os;
 import android.system.ErrnoException;
+import android.system.Os;
 import android.util.Base64;
 import android.util.Slog;
+
+import com.android.internal.util.HexDump;
+
+import libcore.io.Streams;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.FileFilter;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.OutputStreamWriter;
-import java.io.StringBufferInputStream;
 import java.nio.charset.StandardCharsets;
 import java.security.MessageDigest;
-import java.security.PublicKey;
 import java.security.NoSuchAlgorithmException;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
 
 public class CertificateTransparencyLogInstallReceiver extends ConfigUpdateInstallReceiver {
 
@@ -46,14 +51,13 @@
     }
 
     @Override
-    protected void install(byte[] content, int version) throws IOException {
+    protected void install(InputStream inputStream, int version) throws IOException {
         /* Install is complicated here because we translate the input, which is a JSON file
          * containing log information to a directory with a file per log. To support atomically
          * replacing the old configuration directory with the new there's a bunch of steps. We
          * create a new directory with the logs and then do an atomic update of the current symlink
          * to point to the new directory.
          */
-
         // 1. Ensure that the update dir exists and is readable
         updateDir.mkdir();
         if (!updateDir.isDirectory()) {
@@ -72,7 +76,8 @@
             // and so we cannot delete the directory since its in use. Instead just bump the version
             // and return.
             if (newVersion.getCanonicalPath().equals(currentSymlink.getCanonicalPath())) {
-                writeUpdate(updateDir, updateVersion, Long.toString(version).getBytes());
+                writeUpdate(updateDir, updateVersion,
+                        new ByteArrayInputStream(Long.toString(version).getBytes()));
                 deleteOldLogDirectories();
                 return;
             } else {
@@ -92,6 +97,7 @@
 
             // 4. For each log in the log file create the corresponding file in <new_version>/ .
             try {
+                byte[] content = Streams.readFullyNoClose(inputStream);
                 JSONObject json = new JSONObject(new String(content, StandardCharsets.UTF_8));
                 JSONArray logs = json.getJSONArray("logs");
                 for (int i = 0; i < logs.length(); i++) {
@@ -119,7 +125,8 @@
         }
         Slog.i(TAG, "CT log directory updated to " + newVersion.getAbsolutePath());
         // 7. Update the current version information
-        writeUpdate(updateDir, updateVersion, Long.toString(version).getBytes());
+        writeUpdate(updateDir, updateVersion,
+                new ByteArrayInputStream(Long.toString(version).getBytes()));
         // 8. Cleanup
         deleteOldLogDirectories();
     }
diff --git a/services/core/java/com/android/server/updates/ConfigUpdateInstallReceiver.java b/services/core/java/com/android/server/updates/ConfigUpdateInstallReceiver.java
index c3c841c..73bb4bf 100644
--- a/services/core/java/com/android/server/updates/ConfigUpdateInstallReceiver.java
+++ b/services/core/java/com/android/server/updates/ConfigUpdateInstallReceiver.java
@@ -16,9 +16,6 @@
 
 package com.android.server.updates;
 
-import com.android.server.EventLogTags;
-import com.android.internal.util.HexDump;
-
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -26,6 +23,14 @@
 import android.util.EventLog;
 import android.util.Slog;
 
+import com.android.internal.util.HexDump;
+import com.android.server.EventLogTags;
+
+import libcore.io.IoUtils;
+import libcore.io.Streams;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
@@ -33,9 +38,6 @@
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 
-import libcore.io.IoUtils;
-import libcore.io.Streams;
-
 public class ConfigUpdateInstallReceiver extends BroadcastReceiver {
 
     private static final String TAG = "ConfigUpdateInstallReceiver";
@@ -61,8 +63,6 @@
             @Override
             public void run() {
                 try {
-                    // get the content path from the extras
-                    byte[] altContent = getAltContent(context, intent);
                     // get the version from the extras
                     int altVersion = getVersionFromIntent(intent);
                     // get the previous value from the extras
@@ -75,11 +75,13 @@
                         Slog.i(TAG, "Not installing, new version is <= current version");
                     } else if (!verifyPreviousHash(currentHash, altRequiredHash)) {
                         EventLog.writeEvent(EventLogTags.CONFIG_INSTALL_FAILED,
-                                            "Current hash did not match required value");
+                                "Current hash did not match required value");
                     } else {
                         // install the new content
                         Slog.i(TAG, "Found new update, installing...");
-                        install(altContent, altVersion);
+                        try (BufferedInputStream altContent = getAltContent(context, intent)) {
+                            install(altContent, altVersion);
+                        }
                         Slog.i(TAG, "Installation successful");
                         postInstall(context, intent);
                     }
@@ -130,14 +132,9 @@
         }
     }
 
-    private byte[] getAltContent(Context c, Intent i) throws IOException {
+    private BufferedInputStream getAltContent(Context c, Intent i) throws IOException {
         Uri content = getContentFromIntent(i);
-        InputStream is = c.getContentResolver().openInputStream(content);
-        try {
-            return Streams.readFullyNoClose(is);
-        } finally {
-            is.close();
-        }
+        return new BufferedInputStream(c.getContentResolver().openInputStream(content));
     }
 
     private byte[] getCurrentContent() {
@@ -175,7 +172,7 @@
         return current.equals(required);
     }
 
-    protected void writeUpdate(File dir, File file, byte[] content) throws IOException {
+    protected void writeUpdate(File dir, File file, InputStream inputStream) throws IOException {
         FileOutputStream out = null;
         File tmp = null;
         try {
@@ -192,7 +189,7 @@
             tmp.setReadable(true, false);
             // write to it
             out = new FileOutputStream(tmp);
-            out.write(content);
+            Streams.copy(inputStream, out);
             // sync to disk
             out.getFD().sync();
             // atomic rename
@@ -207,9 +204,10 @@
         }
     }
 
-    protected void install(byte[] content, int version) throws IOException {
-        writeUpdate(updateDir, updateContent, content);
-        writeUpdate(updateDir, updateVersion, Long.toString(version).getBytes());
+    protected void install(InputStream inputStream, int version) throws IOException {
+        writeUpdate(updateDir, updateContent, inputStream);
+        writeUpdate(updateDir, updateVersion,
+                new ByteArrayInputStream(Long.toString(version).getBytes()));
     }
 
     protected void postInstall(Context context, Intent intent) {
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 971a24d..ed7790c 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -4912,7 +4912,7 @@
     }
 
     void dumpActivityContainersLocked(PrintWriter pw) {
-        pw.println("ACTIVITY MANAGER STARTER (dumpsys activity containers)");
+        pw.println("ACTIVITY MANAGER CONTAINERS (dumpsys activity containers)");
         mRootActivityContainer.dumpChildrenNames(pw, " ");
         pw.println(" ");
     }
diff --git a/services/core/java/com/android/server/wm/HighRefreshRateBlacklist.java b/services/core/java/com/android/server/wm/HighRefreshRateBlacklist.java
index c0f53b8..315de91 100644
--- a/services/core/java/com/android/server/wm/HighRefreshRateBlacklist.java
+++ b/services/core/java/com/android/server/wm/HighRefreshRateBlacklist.java
@@ -16,60 +16,102 @@
 
 package com.android.server.wm;
 
+import static android.provider.DeviceConfig.WindowManager.KEY_HIGH_REFRESH_RATE_BLACKLIST;
+
 import android.annotation.NonNull;
-import android.os.SystemProperties;
+import android.annotation.Nullable;
+import android.content.res.Resources;
+import android.provider.DeviceConfig;
 import android.util.ArraySet;
 
+import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.os.BackgroundThread;
+
+import java.io.PrintWriter;
+import java.util.concurrent.Executor;
 
 /**
  * A Blacklist for packages that should force the display out of high refresh rate.
  */
 class HighRefreshRateBlacklist {
 
-    private static final String SYSPROP_KEY = "ro.window_manager.high_refresh_rate_blacklist";
-    private static final String SYSPROP_KEY_LENGTH_SUFFIX = "_length";
-    private static final String SYSPROP_KEY_ENTRY_SUFFIX = "_entry";
-    private static final int MAX_ENTRIES = 50;
+    private final ArraySet<String> mBlacklistedPackages = new ArraySet<>();
+    @NonNull
+    private final String[] mDefaultBlacklist;
+    private final Object mLock = new Object();
 
-    private ArraySet<String> mBlacklistedPackages = new ArraySet<>();
-
-    static HighRefreshRateBlacklist create() {
-        return new HighRefreshRateBlacklist(new SystemPropertyGetter() {
+    static HighRefreshRateBlacklist create(@NonNull Resources r) {
+        return new HighRefreshRateBlacklist(r, new DeviceConfigInterface() {
             @Override
-            public int getInt(String key, int def) {
-                return SystemProperties.getInt(key, def);
+            public @Nullable String getProperty(@NonNull String namespace, @NonNull String name) {
+                return DeviceConfig.getProperty(namespace, name);
             }
-
-            @Override
-            public String get(String key) {
-                return SystemProperties.get(key);
+            public void addOnPropertiesChangedListener(@NonNull String namespace,
+                    @NonNull Executor executor,
+                    @NonNull DeviceConfig.OnPropertiesChangedListener listener) {
+                DeviceConfig.addOnPropertiesChangedListener(namespace, executor, listener);
             }
         });
     }
 
     @VisibleForTesting
-    HighRefreshRateBlacklist(SystemPropertyGetter propertyGetter) {
+    HighRefreshRateBlacklist(Resources r, DeviceConfigInterface deviceConfig) {
+        mDefaultBlacklist = r.getStringArray(R.array.config_highRefreshRateBlacklist);
+        deviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
+                BackgroundThread.getExecutor(), new OnPropertiesChangedListener());
+        final String property = deviceConfig.getProperty(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
+                KEY_HIGH_REFRESH_RATE_BLACKLIST);
+        updateBlacklist(property);
+    }
 
-        // Read and populate the blacklist
-        final int length = Math.min(
-                propertyGetter.getInt(SYSPROP_KEY + SYSPROP_KEY_LENGTH_SUFFIX, 0),
-                MAX_ENTRIES);
-        for (int i = 1; i <= length; i++) {
-            final String packageName = propertyGetter.get(
-                    SYSPROP_KEY + SYSPROP_KEY_ENTRY_SUFFIX + i);
-            if (!packageName.isEmpty()) {
-                mBlacklistedPackages.add(packageName);
+    private void updateBlacklist(@Nullable String property) {
+        synchronized (mLock) {
+            mBlacklistedPackages.clear();
+            if (property != null) {
+                String[] packages = property.split(",");
+                for (String pkg : packages) {
+                    String pkgName = pkg.trim();
+                    if (!pkgName.isEmpty()) {
+                        mBlacklistedPackages.add(pkgName);
+                    }
+                }
+            } else {
+                // If there's no config, or the config has been deleted, fallback to the device's
+                // default blacklist
+                for (String pkg : mDefaultBlacklist) {
+                    mBlacklistedPackages.add(pkg);
+                }
             }
         }
     }
 
     boolean isBlacklisted(String packageName) {
-        return mBlacklistedPackages.contains(packageName);
+        synchronized (mLock) {
+            return mBlacklistedPackages.contains(packageName);
+        }
+    }
+    void dump(PrintWriter pw) {
+        pw.println("High Refresh Rate Blacklist");
+        pw.println("  Packages:");
+        synchronized (mLock) {
+            for (String pkg : mBlacklistedPackages) {
+                pw.println("    " + pkg);
+            }
+        }
     }
 
-    interface SystemPropertyGetter {
-        int getInt(String key, int def);
-        @NonNull String get(String key);
+    interface DeviceConfigInterface {
+        @Nullable String getProperty(@NonNull String namespace, @NonNull String name);
+        void addOnPropertiesChangedListener(@NonNull String namespace, @NonNull Executor executor,
+                @NonNull DeviceConfig.OnPropertiesChangedListener listener);
+    }
+
+    private class OnPropertiesChangedListener implements DeviceConfig.OnPropertiesChangedListener {
+        public void onPropertiesChanged(@NonNull DeviceConfig.Properties properties) {
+            updateBlacklist(
+                    properties.getString(KEY_HIGH_REFRESH_RATE_BLACKLIST, null /*default*/));
+        }
     }
 }
+
diff --git a/services/core/java/com/android/server/wm/PinnedStackController.java b/services/core/java/com/android/server/wm/PinnedStackController.java
index af72931..ef0049b 100644
--- a/services/core/java/com/android/server/wm/PinnedStackController.java
+++ b/services/core/java/com/android/server/wm/PinnedStackController.java
@@ -350,7 +350,7 @@
             // Calculate the stack bounds in the new orientation to the same same fraction along the
             // rotated movement bounds.
             final Rect postChangeMovementBounds = getMovementBounds(postChangeStackBounds,
-                    false /* adjustForIme */, false /* adjustForShelf */);
+                    false /* adjustForIme */);
             mSnapAlgorithm.applySnapFraction(postChangeStackBounds, postChangeMovementBounds,
                     snapFraction);
             if (mIsMinimized) {
@@ -540,8 +540,7 @@
      */
     private Rect getMovementBounds(Rect stackBounds) {
         synchronized (mService.mGlobalLock) {
-            return getMovementBounds(stackBounds, true /* adjustForIme */,
-                    true /* adjustForShelf */);
+            return getMovementBounds(stackBounds, true /* adjustForIme */);
         }
     }
 
@@ -549,15 +548,16 @@
      * @return the movement bounds for the given {@param stackBounds} and the current state of the
      *         controller.
      */
-    private Rect getMovementBounds(Rect stackBounds, boolean adjustForIme, boolean adjustForShelf) {
+    private Rect getMovementBounds(Rect stackBounds, boolean adjustForIme) {
         synchronized (mService.mGlobalLock) {
             final Rect movementBounds = new Rect();
             getInsetBounds(movementBounds);
 
-            // Apply the movement bounds adjustments based on the current state
+            // Apply the movement bounds adjustments based on the current state.
+            // Note that shelf offset does not affect the movement bounds here
+            // since it's been taken care of in system UI.
             mSnapAlgorithm.getMovementBounds(stackBounds, movementBounds, movementBounds,
-                    Math.max((adjustForIme && mIsImeShowing) ? mImeHeight : 0,
-                            (adjustForShelf && mIsShelfShowing) ? mShelfHeight : 0));
+                    (adjustForIme && mIsImeShowing) ? mImeHeight : 0);
             return movementBounds;
         }
     }
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index cc9853b..f52bde9 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -856,7 +856,7 @@
 
     final Configuration mTempConfiguration = new Configuration();
 
-    final HighRefreshRateBlacklist mHighRefreshRateBlacklist = HighRefreshRateBlacklist.create();
+    final HighRefreshRateBlacklist mHighRefreshRateBlacklist;
 
     // If true, only the core apps and services are being launched because the device
     // is in a special boot mode, such as being encrypted or waiting for a decryption password.
@@ -1143,6 +1143,8 @@
                 this, mInputManager, mActivityTaskManager, mH.getLooper());
         mDragDropController = new DragDropController(this, mH.getLooper());
 
+        mHighRefreshRateBlacklist = HighRefreshRateBlacklist.create(context.getResources());
+
         mSystemGestureExclusionLimitDp = Math.max(MIN_GESTURE_EXCLUSION_LIMIT_DP,
                 DeviceConfig.getInt(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
                         KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP, 0));
@@ -5897,6 +5899,12 @@
         mRoot.dumpTokens(pw, dumpAll);
     }
 
+
+    private void dumpHighRefreshRateBlacklist(PrintWriter pw) {
+        pw.println("WINDOW MANAGER HIGH REFRESH RATE BLACKLIST (dumpsys window refresh)");
+        mHighRefreshRateBlacklist.dump(pw);
+    }
+
     private void dumpTraceStatus(PrintWriter pw) {
         pw.println("WINDOW MANAGER TRACE (dumpsys window trace)");
         pw.print(mWindowTracing.getStatus() + "\n");
@@ -6297,6 +6305,9 @@
             } else if ("trace".equals(cmd)) {
                 dumpTraceStatus(pw);
                 return;
+            } else if ("refresh".equals(cmd)) {
+                dumpHighRefreshRateBlacklist(pw);
+                return;
             } else {
                 // Dumping a single name?
                 if (!dumpWindows(pw, cmd, args, opti, dumpAll)) {
@@ -6352,6 +6363,10 @@
                 pw.println(separator);
             }
             dumpTraceStatus(pw);
+            if (dumpAll) {
+                pw.println(separator);
+            }
+            dumpHighRefreshRateBlacklist(pw);
         }
     }
 
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index fb3076b..1c8c46c 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -826,18 +826,19 @@
         }
     }
 
-    uint32_t changes = 0;
+    bool pointerGesturesEnabledChanged = false;
     { // acquire lock
         AutoMutex _l(mLock);
 
         if (mLocked.pointerGesturesEnabled != newPointerGesturesEnabled) {
             mLocked.pointerGesturesEnabled = newPointerGesturesEnabled;
-            changes |= InputReaderConfiguration::CHANGE_POINTER_GESTURE_ENABLEMENT;
+            pointerGesturesEnabledChanged = true;
         }
     } // release lock
 
-    if (changes) {
-        mInputManager->getReader()->requestRefreshConfiguration(changes);
+    if (pointerGesturesEnabledChanged) {
+        mInputManager->getReader()->requestRefreshConfiguration(
+                InputReaderConfiguration::CHANGE_POINTER_GESTURE_ENABLEMENT);
     }
 }
 
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 48921ea..68c9bad 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -196,6 +196,7 @@
 import android.os.UserManagerInternal;
 import android.os.UserManagerInternal.UserRestrictionsListener;
 import android.os.storage.StorageManager;
+import android.permission.IPermissionManager;
 import android.permission.PermissionControllerManager;
 import android.provider.CalendarContract;
 import android.provider.ContactsContract.QuickContact;
@@ -228,7 +229,6 @@
 import android.view.accessibility.AccessibilityManager;
 import android.view.accessibility.IAccessibilityManager;
 import android.view.inputmethod.InputMethodInfo;
-import android.view.inputmethod.InputMethodSystemProperty;
 
 import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
@@ -493,6 +493,7 @@
     final Context mContext;
     final Injector mInjector;
     final IPackageManager mIPackageManager;
+    final IPermissionManager mIPermissionManager;
     final UserManager mUserManager;
     final UserManagerInternal mUserManagerInternal;
     final UsageStatsManagerInternal mUsageStatsManagerInternal;
@@ -1975,6 +1976,10 @@
             return AppGlobals.getPackageManager();
         }
 
+        IPermissionManager getIPermissionManager() {
+            return AppGlobals.getPermissionManager();
+        }
+
         IBackupManager getIBackupManager() {
             return IBackupManager.Stub.asInterface(
                     ServiceManager.getService(Context.BACKUP_SERVICE));
@@ -2218,6 +2223,7 @@
         mUsageStatsManagerInternal = Preconditions.checkNotNull(
                 injector.getUsageStatsManagerInternal());
         mIPackageManager = Preconditions.checkNotNull(injector.getIPackageManager());
+        mIPermissionManager = Preconditions.checkNotNull(injector.getIPermissionManager());
         mTelephonyManager = Preconditions.checkNotNull(injector.getTelephonyManager());
 
         mLocalService = new LocalService();
@@ -8218,7 +8224,7 @@
         saveSettingsLocked(userId);
 
         try {
-            mIPackageManager.updatePermissionFlagsForAllApps(
+            mIPermissionManager.updatePermissionFlagsForAllApps(
                     PackageManager.FLAG_PERMISSION_POLICY_FIXED,
                     0  /* flagValues */, userId);
             pushUserRestrictions(userId);
@@ -9403,12 +9409,6 @@
             return false;
         }
         Preconditions.checkNotNull(who, "ComponentName is null");
-
-        // TODO When InputMethodManager supports per user calls remove this restriction.
-        if (!InputMethodSystemProperty.PER_PROFILE_IME_ENABLED
-                && !checkCallerIsCurrentUserOrProfile()) {
-            return false;
-        }
         final int callingUserId = mInjector.userHandleGetCallingUserId();
         if (packageList != null) {
             List<InputMethodInfo> enabledImes = InputMethodManagerInternal.get()
@@ -9464,26 +9464,16 @@
         final int callingUserId = mInjector.userHandleGetCallingUserId();
         synchronized (getLockObject()) {
             List<String> result = null;
-            // If we have multiple profiles we return the intersection of the
-            // permitted lists. This can happen in cases where we have a device
-            // and profile owner.
-            int[] profileIds = InputMethodSystemProperty.PER_PROFILE_IME_ENABLED
-                    ? new int[]{callingUserId}
-                    : mUserManager.getProfileIdsWithDisabled(callingUserId);
-            for (int profileId : profileIds) {
-                // Just loop though all admins, only device or profiles
-                // owners can have permitted lists set.
-                DevicePolicyData policy = getUserDataUnchecked(profileId);
-                final int N = policy.mAdminList.size();
-                for (int j = 0; j < N; j++) {
-                    ActiveAdmin admin = policy.mAdminList.get(j);
-                    List<String> fromAdmin = admin.permittedInputMethods;
-                    if (fromAdmin != null) {
-                        if (result == null) {
-                            result = new ArrayList<String>(fromAdmin);
-                        } else {
-                            result.retainAll(fromAdmin);
-                        }
+            // Only device or profile owners can have permitted lists set.
+            DevicePolicyData policy = getUserDataUnchecked(callingUserId);
+            for (int i = 0; i < policy.mAdminList.size(); i++) {
+                ActiveAdmin admin = policy.mAdminList.get(i);
+                List<String> fromAdmin = admin.permittedInputMethods;
+                if (fromAdmin != null) {
+                    if (result == null) {
+                        result = new ArrayList<String>(fromAdmin);
+                    } else {
+                        result.retainAll(fromAdmin);
                     }
                 }
             }
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/OverlayPackagesProvider.java b/services/devicepolicy/java/com/android/server/devicepolicy/OverlayPackagesProvider.java
index 699bec2..261a83c 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/OverlayPackagesProvider.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/OverlayPackagesProvider.java
@@ -33,7 +33,6 @@
 import android.content.pm.ResolveInfo;
 import android.util.ArraySet;
 import android.view.inputmethod.InputMethodInfo;
-import android.view.inputmethod.InputMethodSystemProperty;
 
 import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
@@ -61,17 +60,11 @@
 
     @VisibleForTesting
     interface Injector {
-        boolean isPerProfileImeEnabled();
         @NonNull
         List<InputMethodInfo> getInputMethodListAsUser(@UserIdInt int userId);
     }
 
     private static final class DefaultInjector implements Injector {
-        @Override
-        public boolean isPerProfileImeEnabled() {
-            return InputMethodSystemProperty.PER_PROFILE_IME_ENABLED;
-        }
-
         @NonNull
         @Override
         public List<InputMethodInfo> getInputMethodListAsUser(@UserIdInt int userId) {
@@ -108,13 +101,7 @@
         // Newly installed system apps are uninstalled when they are not required and are either
         // disallowed or have a launcher icon.
         nonRequiredApps.removeAll(getRequiredApps(provisioningAction, admin.getPackageName()));
-        if (mInjector.isPerProfileImeEnabled()) {
-            nonRequiredApps.removeAll(getSystemInputMethods(userId));
-        } else if (ACTION_PROVISION_MANAGED_DEVICE.equals(provisioningAction)
-                || ACTION_PROVISION_MANAGED_USER.equals(provisioningAction)) {
-            // Don't delete the system input method packages in case of Device owner provisioning.
-            nonRequiredApps.removeAll(getSystemInputMethods(userId));
-        }
+        nonRequiredApps.removeAll(getSystemInputMethods(userId));
         nonRequiredApps.addAll(getDisallowedApps(provisioningAction));
         return nonRequiredApps;
     }
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/TimeControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/TimeControllerTest.java
index 70b7bb6..3614763 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/TimeControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/TimeControllerTest.java
@@ -71,7 +71,6 @@
     private static final String SOURCE_PACKAGE = "com.android.frameworks.mockingservicestests";
     private static final int SOURCE_USER_ID = 0;
 
-    private TimeController.TcConstants mConstants;
     private TimeController mTimeController;
 
     private MockitoSession mMockingSession;
@@ -111,7 +110,6 @@
 
         // Initialize real objects.
         mTimeController = new TimeController(mJobSchedulerService);
-        mConstants = mTimeController.getTcConstants();
         spyOn(mTimeController);
     }
 
@@ -159,18 +157,7 @@
     }
 
     @Test
-    public void testMaybeStartTrackingJobLocked_DelayInOrder_NoSkipping() {
-        mConstants.SKIP_NOT_READY_JOBS = false;
-        mTimeController.onConstantsUpdatedLocked();
-
-        runTestMaybeStartTrackingJobLocked_DelayInOrder();
-    }
-
-    @Test
-    public void testMaybeStartTrackingJobLocked_DelayInOrder_WithSkipping_AllReady() {
-        mConstants.SKIP_NOT_READY_JOBS = true;
-        mTimeController.onConstantsUpdatedLocked();
-
+    public void testMaybeStartTrackingJobLocked_DelayInOrder_AllReady() {
         doReturn(true).when(mTimeController).wouldBeReadyWithConstraintLocked(any(), anyInt());
 
         runTestMaybeStartTrackingJobLocked_DelayInOrder();
@@ -201,9 +188,7 @@
     }
 
     @Test
-    public void testMaybeStartTrackingJobLocked_DelayInOrder_WithSkipping_SomeNotReady() {
-        mConstants.SKIP_NOT_READY_JOBS = true;
-        mTimeController.onConstantsUpdatedLocked();
+    public void testMaybeStartTrackingJobLocked_DelayInOrder_SomeNotReady() {
         final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
 
         JobStatus jobLatest = createJobStatus("testMaybeStartTrackingJobLocked_DelayInOrder",
@@ -235,18 +220,7 @@
     }
 
     @Test
-    public void testMaybeStartTrackingJobLocked_DelayReverseOrder_NoSkipping() {
-        mConstants.SKIP_NOT_READY_JOBS = false;
-        mTimeController.onConstantsUpdatedLocked();
-
-        runTestMaybeStartTrackingJobLocked_DelayReverseOrder();
-    }
-
-    @Test
-    public void testMaybeStartTrackingJobLocked_DelayReverseOrder_WithSkipping_AllReady() {
-        mConstants.SKIP_NOT_READY_JOBS = true;
-        mTimeController.onConstantsUpdatedLocked();
-
+    public void testMaybeStartTrackingJobLocked_DelayReverseOrder_AllReady() {
         doReturn(true).when(mTimeController).wouldBeReadyWithConstraintLocked(any(), anyInt());
 
         runTestMaybeStartTrackingJobLocked_DelayReverseOrder();
@@ -279,9 +253,7 @@
     }
 
     @Test
-    public void testMaybeStartTrackingJobLocked_DelayReverseOrder_WithSkipping_SomeNotReady() {
-        mConstants.SKIP_NOT_READY_JOBS = true;
-        mTimeController.onConstantsUpdatedLocked();
+    public void testMaybeStartTrackingJobLocked_DelayReverseOrder_SomeNotReady() {
         final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
 
         JobStatus jobLatest = createJobStatus("testMaybeStartTrackingJobLocked_DelayReverseOrder",
@@ -315,18 +287,7 @@
     }
 
     @Test
-    public void testMaybeStartTrackingJobLocked_DeadlineInOrder_NoSkipping() {
-        mConstants.SKIP_NOT_READY_JOBS = false;
-        mTimeController.onConstantsUpdatedLocked();
-
-        runTestMaybeStartTrackingJobLocked_DeadlineInOrder();
-    }
-
-    @Test
-    public void testMaybeStartTrackingJobLocked_DeadlineInOrder_WithSkipping_AllReady() {
-        mConstants.SKIP_NOT_READY_JOBS = true;
-        mTimeController.onConstantsUpdatedLocked();
-
+    public void testMaybeStartTrackingJobLocked_DeadlineInOrder_AllReady() {
         doReturn(true).when(mTimeController).wouldBeReadyWithConstraintLocked(any(), anyInt());
 
         runTestMaybeStartTrackingJobLocked_DeadlineInOrder();
@@ -357,9 +318,7 @@
     }
 
     @Test
-    public void testMaybeStartTrackingJobLocked_DeadlineInOrder_WithSkipping_SomeNotReady() {
-        mConstants.SKIP_NOT_READY_JOBS = true;
-        mTimeController.onConstantsUpdatedLocked();
+    public void testMaybeStartTrackingJobLocked_DeadlineInOrder_SomeNotReady() {
         final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
 
         JobStatus jobLatest = createJobStatus("testMaybeStartTrackingJobLocked_DeadlineInOrder",
@@ -391,18 +350,7 @@
     }
 
     @Test
-    public void testMaybeStartTrackingJobLocked_DeadlineReverseOrder_NoSkipping() {
-        mConstants.SKIP_NOT_READY_JOBS = false;
-        mTimeController.onConstantsUpdatedLocked();
-
-        runTestMaybeStartTrackingJobLocked_DeadlineReverseOrder();
-    }
-
-    @Test
-    public void testMaybeStartTrackingJobLocked_DeadlineReverseOrder_WithSkipping_AllReady() {
-        mConstants.SKIP_NOT_READY_JOBS = true;
-        mTimeController.onConstantsUpdatedLocked();
-
+    public void testMaybeStartTrackingJobLocked_DeadlineReverseOrder_AllReady() {
         doReturn(true).when(mTimeController).wouldBeReadyWithConstraintLocked(any(), anyInt());
 
         runTestMaybeStartTrackingJobLocked_DeadlineReverseOrder();
@@ -438,9 +386,7 @@
     }
 
     @Test
-    public void testMaybeStartTrackingJobLocked_DeadlineReverseOrder_WithSkipping_SomeNotReady() {
-        mConstants.SKIP_NOT_READY_JOBS = true;
-        mTimeController.onConstantsUpdatedLocked();
+    public void testMaybeStartTrackingJobLocked_DeadlineReverseOrder_SomeNotReady() {
         final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
 
         JobStatus jobLatest = createJobStatus(
@@ -478,62 +424,7 @@
     }
 
     @Test
-    public void testJobSkipToggling() {
-        final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
-
-        JobStatus jobLatest = createJobStatus(
-                "testMaybeStartTrackingJobLocked_DeadlineReverseOrder",
-                createJob().setOverrideDeadline(HOUR_IN_MILLIS));
-        JobStatus jobEarliest = createJobStatus(
-                "testMaybeStartTrackingJobLocked_DeadlineReverseOrder",
-                createJob().setOverrideDeadline(5 * MINUTE_IN_MILLIS));
-
-        doReturn(true).when(mTimeController)
-                .wouldBeReadyWithConstraintLocked(eq(jobLatest), anyInt());
-        doReturn(false).when(mTimeController)
-                .wouldBeReadyWithConstraintLocked(eq(jobEarliest), anyInt());
-
-        // Starting off with the skipping off, we should still set an alarm for the earlier job.
-        mConstants.SKIP_NOT_READY_JOBS = false;
-        mTimeController.recheckAlarmsLocked();
-        InOrder inOrder = inOrder(mAlarmManager);
-
-        mTimeController.maybeStartTrackingJobLocked(jobEarliest, null);
-        mTimeController.maybeStartTrackingJobLocked(jobLatest, null);
-        inOrder.verify(mAlarmManager, times(1))
-                .set(anyInt(), eq(now + 5 * MINUTE_IN_MILLIS), anyLong(), anyLong(),
-                        eq(TAG_DEADLINE), any(), any(), any());
-
-        // Turn it on, use alarm for later job.
-        mConstants.SKIP_NOT_READY_JOBS = true;
-        mTimeController.recheckAlarmsLocked();
-
-        inOrder.verify(mAlarmManager, times(1))
-                .set(anyInt(), eq(now + HOUR_IN_MILLIS), anyLong(), anyLong(), eq(TAG_DEADLINE),
-                        any(), any(), any());
-
-        // Back off, use alarm for earlier job.
-        mConstants.SKIP_NOT_READY_JOBS = false;
-        mTimeController.recheckAlarmsLocked();
-
-        inOrder.verify(mAlarmManager, times(1))
-                .set(anyInt(), eq(now + 5 * MINUTE_IN_MILLIS), anyLong(), anyLong(),
-                        eq(TAG_DEADLINE), any(), any(), any());
-    }
-
-    @Test
-    public void testCheckExpiredDelaysAndResetAlarm_NoSkipping() {
-        mConstants.SKIP_NOT_READY_JOBS = false;
-        mTimeController.recheckAlarmsLocked();
-
-        runTestCheckExpiredDelaysAndResetAlarm();
-    }
-
-    @Test
-    public void testCheckExpiredDelaysAndResetAlarm_WithSkipping_AllReady() {
-        mConstants.SKIP_NOT_READY_JOBS = true;
-        mTimeController.recheckAlarmsLocked();
-
+    public void testCheckExpiredDelaysAndResetAlarm_AllReady() {
         doReturn(true).when(mTimeController).wouldBeReadyWithConstraintLocked(any(), anyInt());
 
         runTestCheckExpiredDelaysAndResetAlarm();
@@ -589,9 +480,7 @@
     }
 
     @Test
-    public void testCheckExpiredDelaysAndResetAlarm_WithSkipping_SomeNotReady() {
-        mConstants.SKIP_NOT_READY_JOBS = true;
-        mTimeController.recheckAlarmsLocked();
+    public void testCheckExpiredDelaysAndResetAlarm_SomeNotReady() {
         final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
 
         JobStatus jobLatest = createJobStatus("testCheckExpiredDelaysAndResetAlarm",
@@ -639,18 +528,7 @@
     }
 
     @Test
-    public void testCheckExpiredDeadlinesAndResetAlarm_NoSkipping() {
-        mConstants.SKIP_NOT_READY_JOBS = false;
-        mTimeController.recheckAlarmsLocked();
-
-        runTestCheckExpiredDeadlinesAndResetAlarm();
-    }
-
-    @Test
-    public void testCheckExpiredDeadlinesAndResetAlarm_WithSkipping_AllReady() {
-        mConstants.SKIP_NOT_READY_JOBS = true;
-        mTimeController.recheckAlarmsLocked();
-
+    public void testCheckExpiredDeadlinesAndResetAlarm_AllReady() {
         doReturn(true).when(mTimeController).wouldBeReadyWithConstraintLocked(any(), anyInt());
 
         runTestCheckExpiredDeadlinesAndResetAlarm();
@@ -706,9 +584,7 @@
     }
 
     @Test
-    public void testCheckExpiredDeadlinesAndResetAlarm_WithSkipping_SomeNotReady() {
-        mConstants.SKIP_NOT_READY_JOBS = true;
-        mTimeController.recheckAlarmsLocked();
+    public void testCheckExpiredDeadlinesAndResetAlarm_SomeNotReady() {
         final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
 
         JobStatus jobLatest = createJobStatus("testCheckExpiredDeadlinesAndResetAlarm",
@@ -756,28 +632,14 @@
     }
 
     @Test
-    public void testEvaluateStateLocked_SkippingOff() {
-        mConstants.SKIP_NOT_READY_JOBS = false;
-        mTimeController.recheckAlarmsLocked();
-        JobStatus job = createJobStatus("testEvaluateStateLocked_SkippingOff",
-                createJob().setOverrideDeadline(HOUR_IN_MILLIS));
-
-        mTimeController.evaluateStateLocked(job);
-        verify(mAlarmManager, never())
-                .set(anyInt(), anyLong(), anyLong(), anyLong(), anyString(), any(), any(), any());
-    }
-
-    @Test
-    public void testEvaluateStateLocked_SkippingOn_Delay() {
-        mConstants.SKIP_NOT_READY_JOBS = true;
-        mTimeController.recheckAlarmsLocked();
+    public void testEvaluateStateLocked_Delay() {
         final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
 
-        JobStatus jobLatest = createJobStatus("testEvaluateStateLocked_SkippingOn_Delay",
+        JobStatus jobLatest = createJobStatus("testEvaluateStateLocked_Delay",
                 createJob().setMinimumLatency(HOUR_IN_MILLIS));
-        JobStatus jobMiddle = createJobStatus("testEvaluateStateLocked_SkippingOn_Delay",
+        JobStatus jobMiddle = createJobStatus("testEvaluateStateLocked_Delay",
                 createJob().setMinimumLatency(30 * MINUTE_IN_MILLIS));
-        JobStatus jobEarliest = createJobStatus("testEvaluateStateLocked_SkippingOn_Delay",
+        JobStatus jobEarliest = createJobStatus("testEvaluateStateLocked_Delay",
                 createJob().setMinimumLatency(5 * MINUTE_IN_MILLIS));
 
         doReturn(false).when(mTimeController)
@@ -827,16 +689,14 @@
     }
 
     @Test
-    public void testEvaluateStateLocked_SkippingOn_Deadline() {
-        mConstants.SKIP_NOT_READY_JOBS = true;
-        mTimeController.recheckAlarmsLocked();
+    public void testEvaluateStateLocked_Deadline() {
         final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
 
-        JobStatus jobLatest = createJobStatus("testEvaluateStateLocked_SkippingOn_Deadline",
+        JobStatus jobLatest = createJobStatus("testEvaluateStateLocked_Deadline",
                 createJob().setOverrideDeadline(HOUR_IN_MILLIS));
-        JobStatus jobMiddle = createJobStatus("testEvaluateStateLocked_SkippingOn_Deadline",
+        JobStatus jobMiddle = createJobStatus("testEvaluateStateLocked_Deadline",
                 createJob().setOverrideDeadline(30 * MINUTE_IN_MILLIS));
-        JobStatus jobEarliest = createJobStatus("testEvaluateStateLocked_SkippingOn_Deadline",
+        JobStatus jobEarliest = createJobStatus("testEvaluateStateLocked_Deadline",
                 createJob().setOverrideDeadline(5 * MINUTE_IN_MILLIS));
 
         doReturn(false).when(mTimeController)
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
index 2ce4c54..ce83df7 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
@@ -37,6 +37,7 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.os.UserManagerInternal;
+import android.permission.IPermissionManager;
 import android.security.KeyChain;
 import android.telephony.TelephonyManager;
 import android.util.ArrayMap;
@@ -199,6 +200,11 @@
         }
 
         @Override
+        IPermissionManager getIPermissionManager() {
+            return services.ipermissionManager;
+        }
+
+        @Override
         IBackupManager getIBackupManager() {
             return services.ibackupManager;
         }
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java b/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java
index 8f0aeea..f6f365e 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java
@@ -52,6 +52,7 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.os.UserManagerInternal;
+import android.permission.IPermissionManager;
 import android.provider.Settings;
 import android.security.KeyChain;
 import android.telephony.TelephonyManager;
@@ -97,6 +98,7 @@
     public ActivityManagerInternal activityManagerInternal;
     public ActivityTaskManagerInternal activityTaskManagerInternal;
     public final IPackageManager ipackageManager;
+    public final IPermissionManager ipermissionManager;
     public final IBackupManager ibackupManager;
     public final IAudioService iaudioService;
     public final LockPatternUtils lockPatternUtils;
@@ -137,6 +139,7 @@
         activityManagerInternal = mock(ActivityManagerInternal.class);
         activityTaskManagerInternal = mock(ActivityTaskManagerInternal.class);
         ipackageManager = mock(IPackageManager.class);
+        ipermissionManager = mock(IPermissionManager.class);
         ibackupManager = mock(IBackupManager.class);
         iaudioService = mock(IAudioService.class);
         lockPatternUtils = mock(LockPatternUtils.class);
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/OverlayPackagesProviderTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/OverlayPackagesProviderTest.java
index 757a046..a3cc915 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/OverlayPackagesProviderTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/OverlayPackagesProviderTest.java
@@ -79,7 +79,6 @@
                 InstrumentationRegistry.getTargetContext().getCacheDir());
 
         setSystemInputMethods();
-        setIsPerProfileModeEnabled(false);
         setRequiredAppsManagedDevice();
         setVendorRequiredAppsManagedDevice();
         setDisallowedAppsManagedDevice();
@@ -164,15 +163,6 @@
     }
 
     @Test
-    public void testProfileOwnerImesAreRequiredForPerProfileImeMode() {
-        setSystemAppsWithLauncher("app.a", "app.b");
-        setSystemInputMethods("app.a");
-        setIsPerProfileModeEnabled(true);
-
-        verifyAppsAreNonRequired(ACTION_PROVISION_MANAGED_PROFILE, "app.b");
-    }
-
-    @Test
     public void testManagedUserImesAreRequired() {
         setSystemAppsWithLauncher("app.a", "app.b");
         setSystemInputMethods("app.a");
@@ -344,10 +334,6 @@
         when(mInjector.getInputMethodListAsUser(eq(TEST_USER_ID))).thenReturn(inputMethods);
     }
 
-    private void setIsPerProfileModeEnabled(boolean enabled) {
-        when(mInjector.isPerProfileImeEnabled()).thenReturn(enabled);
-    }
-
     private void setSystemAppsWithLauncher(String... apps) {
         mSystemAppsWithLauncher = apps;
     }
diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
index ce1edcd..09ae3a2 100644
--- a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
@@ -559,7 +559,25 @@
                 .build();
         mService.updateRestrictBackgroundByLowPowerModeUL(stateOff);
 
-        // RestrictBackground should be on, following its previous state
+        // RestrictBackground should be on, as before.
+        assertTrue(mService.getRestrictBackground());
+
+        stateOn = new PowerSaveState.Builder()
+                .setGlobalBatterySaverEnabled(true)
+                .setBatterySaverEnabled(true)
+                .build();
+        mService.updateRestrictBackgroundByLowPowerModeUL(stateOn);
+
+        // RestrictBackground should be on.
+        assertTrue(mService.getRestrictBackground());
+
+        stateOff = new PowerSaveState.Builder()
+                .setGlobalBatterySaverEnabled(false)
+                .setBatterySaverEnabled(false)
+                .build();
+        mService.updateRestrictBackgroundByLowPowerModeUL(stateOff);
+
+        // RestrictBackground should be on, as it was enabled manually before battery saver.
         assertTrue(mService.getRestrictBackground());
     }
 
@@ -585,6 +603,20 @@
 
         // RestrictBackground should be off, following its previous state
         assertFalse(mService.getRestrictBackground());
+
+        PowerSaveState stateOnRestrictOff = new PowerSaveState.Builder()
+                .setGlobalBatterySaverEnabled(true)
+                .setBatterySaverEnabled(false)
+                .build();
+
+        mService.updateRestrictBackgroundByLowPowerModeUL(stateOnRestrictOff);
+
+        assertFalse(mService.getRestrictBackground());
+
+        mService.updateRestrictBackgroundByLowPowerModeUL(stateOff);
+
+        // RestrictBackground should still be off.
+        assertFalse(mService.getRestrictBackground());
     }
 
     @Test
@@ -602,11 +634,49 @@
 
         // User turns off RestrictBackground manually
         setRestrictBackground(false);
-        PowerSaveState stateOff = new PowerSaveState.Builder().setBatterySaverEnabled(
-                false).build();
+        // RestrictBackground should be off because user changed it manually
+        assertFalse(mService.getRestrictBackground());
+
+        PowerSaveState stateOff = new PowerSaveState.Builder()
+                .setGlobalBatterySaverEnabled(false)
+                .setBatterySaverEnabled(false)
+                .build();
         mService.updateRestrictBackgroundByLowPowerModeUL(stateOff);
 
-        // RestrictBackground should be off because user changes it manually
+        // RestrictBackground should remain off.
+        assertFalse(mService.getRestrictBackground());
+    }
+
+    @Test
+    public void updateRestrictBackgroundByLowPowerMode_RestrictOnWithGlobalOff()
+            throws Exception {
+        setRestrictBackground(false);
+        PowerSaveState stateOn = new PowerSaveState.Builder()
+                .setGlobalBatterySaverEnabled(false)
+                .setBatterySaverEnabled(true)
+                .build();
+
+        mService.updateRestrictBackgroundByLowPowerModeUL(stateOn);
+
+        // RestrictBackground should be turned on because of battery saver.
+        assertTrue(mService.getRestrictBackground());
+
+        PowerSaveState stateRestrictOff = new PowerSaveState.Builder()
+                .setGlobalBatterySaverEnabled(true)
+                .setBatterySaverEnabled(false)
+                .build();
+        mService.updateRestrictBackgroundByLowPowerModeUL(stateRestrictOff);
+
+        // RestrictBackground should be off, returning to its state before battery saver's change.
+        assertFalse(mService.getRestrictBackground());
+
+        PowerSaveState stateOff = new PowerSaveState.Builder()
+                .setGlobalBatterySaverEnabled(false)
+                .setBatterySaverEnabled(false)
+                .build();
+        mService.updateRestrictBackgroundByLowPowerModeUL(stateOff);
+
+        // RestrictBackground should still be off, back in its pre-battery saver state.
         assertFalse(mService.getRestrictBackground());
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/textservices/LazyIntToIntMapTest.java b/services/tests/servicestests/src/com/android/server/textservices/LazyIntToIntMapTest.java
deleted file mode 100644
index f80afb2..0000000
--- a/services/tests/servicestests/src/com/android/server/textservices/LazyIntToIntMapTest.java
+++ /dev/null
@@ -1,92 +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 com.android.server.textservices;
-
-import static org.junit.Assert.assertEquals;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.function.IntUnaryOperator;
-
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class LazyIntToIntMapTest {
-    @Test
-    public void testLaziness() {
-        final IntUnaryOperator func = mock(IntUnaryOperator.class);
-        when(func.applyAsInt(eq(1))).thenReturn(11);
-        when(func.applyAsInt(eq(2))).thenReturn(22);
-
-        final LazyIntToIntMap map = new LazyIntToIntMap(func);
-
-        verify(func, never()).applyAsInt(anyInt());
-
-        assertEquals(22, map.get(2));
-        verify(func, times(0)).applyAsInt(eq(1));
-        verify(func, times(1)).applyAsInt(eq(2));
-
-        // Accessing to the same key does not evaluate the function again.
-        assertEquals(22, map.get(2));
-        verify(func, times(0)).applyAsInt(eq(1));
-        verify(func, times(1)).applyAsInt(eq(2));
-    }
-
-    @Test
-    public void testDelete() {
-        final IntUnaryOperator func1 = mock(IntUnaryOperator.class);
-        when(func1.applyAsInt(eq(1))).thenReturn(11);
-        when(func1.applyAsInt(eq(2))).thenReturn(22);
-
-        final IntUnaryOperator func2 = mock(IntUnaryOperator.class);
-        when(func2.applyAsInt(eq(1))).thenReturn(111);
-        when(func2.applyAsInt(eq(2))).thenReturn(222);
-
-        final AtomicReference<IntUnaryOperator> funcRef = new AtomicReference<>(func1);
-        final LazyIntToIntMap map = new LazyIntToIntMap(i -> funcRef.get().applyAsInt(i));
-
-        verify(func1, never()).applyAsInt(anyInt());
-        verify(func2, never()).applyAsInt(anyInt());
-
-        assertEquals(22, map.get(2));
-        verify(func1, times(1)).applyAsInt(eq(2));
-        verify(func2, times(0)).applyAsInt(eq(2));
-
-        // Swap func1 with func2 then invalidate the key=2
-        funcRef.set(func2);
-        map.delete(2);
-
-        // Calling get(2) again should re-evaluate the value.
-        assertEquals(222, map.get(2));
-        verify(func1, times(1)).applyAsInt(eq(2));
-        verify(func2, times(1)).applyAsInt(eq(2));
-
-        // Trying to delete non-existing keys does nothing.
-        map.delete(1);
-    }
-}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 9ecf198..f14e8d2 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -132,6 +132,7 @@
 import android.util.ArraySet;
 import android.util.AtomicFile;
 import android.util.Xml;
+import android.widget.RemoteViews;
 
 import androidx.annotation.Nullable;
 import androidx.test.InstrumentationRegistry;
@@ -174,6 +175,7 @@
 import java.util.Map;
 import java.util.function.Consumer;
 
+
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 @RunWithLooper
@@ -348,12 +350,17 @@
         mHandler = mService.new WorkerHandler(mTestableLooper.getLooper());
         // MockPackageManager - default returns ApplicationInfo with matching calling UID
         mContext.setMockPackageManager(mPackageManagerClient);
-        final ApplicationInfo applicationInfo = new ApplicationInfo();
-        applicationInfo.uid = mUid;
+
         when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt()))
-                .thenReturn(applicationInfo);
+                .thenAnswer((Answer<ApplicationInfo>) invocation -> {
+                    Object[] args = invocation.getArguments();
+                    return getApplicationInfo((String) args[0], mUid);
+                });
         when(mPackageManagerClient.getApplicationInfoAsUser(anyString(), anyInt(), anyInt()))
-                .thenReturn(applicationInfo);
+                .thenAnswer((Answer<ApplicationInfo>) invocation -> {
+                    Object[] args = invocation.getArguments();
+                    return getApplicationInfo((String) args[0], mUid);
+                });
         when(mPackageManagerClient.getPackageUidAsUser(any(), anyInt())).thenReturn(mUid);
         final LightsManager mockLightsManager = mock(LightsManager.class);
         when(mockLightsManager.getLight(anyInt())).thenReturn(mock(Light.class));
@@ -389,7 +396,6 @@
 
         when(mAssistants.isAdjustmentAllowed(anyString())).thenReturn(true);
 
-
         mService.init(mTestableLooper.getLooper(),
                 mPackageManager, mPackageManagerClient, mockLightsManager,
                 mListeners, mAssistants, mConditionProviders,
@@ -413,12 +419,32 @@
 
     @After
     public void tearDown() throws Exception {
-        mFile.delete();
+        if (mFile != null) mFile.delete();
         clearDeviceConfig();
         InstrumentationRegistry.getInstrumentation()
                 .getUiAutomation().dropShellPermissionIdentity();
     }
 
+    private ApplicationInfo getApplicationInfo(String pkg, int uid) {
+        final ApplicationInfo applicationInfo = new ApplicationInfo();
+        applicationInfo.uid = uid;
+        switch (pkg) {
+            case PKG_N_MR1:
+                applicationInfo.targetSdkVersion = Build.VERSION_CODES.N_MR1;
+                break;
+            case PKG_O:
+                applicationInfo.targetSdkVersion = Build.VERSION_CODES.O;
+                break;
+            case PKG_P:
+                applicationInfo.targetSdkVersion = Build.VERSION_CODES.P;
+                break;
+            default:
+                applicationInfo.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;
+                break;
+        }
+        return applicationInfo;
+    }
+
     public void waitForIdle() {
         mTestableLooper.processAllMessages();
     }
@@ -5122,4 +5148,66 @@
         assertEquals(1, notifsAfter.length);
         assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0);
     }
+
+    @Test
+    public void testRemoveLargeRemoteViews() throws Exception {
+        int removeSize = mContext.getResources().getInteger(
+                com.android.internal.R.integer.config_notificationStripRemoteViewSizeBytes);
+
+        RemoteViews rv = mock(RemoteViews.class);
+        when(rv.estimateMemoryUsage()).thenReturn(removeSize);
+        when(rv.clone()).thenReturn(rv);
+        RemoteViews rv1 = mock(RemoteViews.class);
+        when(rv1.estimateMemoryUsage()).thenReturn(removeSize);
+        when(rv1.clone()).thenReturn(rv1);
+        RemoteViews rv2 = mock(RemoteViews.class);
+        when(rv2.estimateMemoryUsage()).thenReturn(removeSize);
+        when(rv2.clone()).thenReturn(rv2);
+        RemoteViews rv3 = mock(RemoteViews.class);
+        when(rv3.estimateMemoryUsage()).thenReturn(removeSize);
+        when(rv3.clone()).thenReturn(rv3);
+        RemoteViews rv4 = mock(RemoteViews.class);
+        when(rv4.estimateMemoryUsage()).thenReturn(removeSize);
+        when(rv4.clone()).thenReturn(rv4);
+        // note: different!
+        RemoteViews rv5 = mock(RemoteViews.class);
+        when(rv5.estimateMemoryUsage()).thenReturn(removeSize - 1);
+        when(rv5.clone()).thenReturn(rv5);
+
+        Notification np = new Notification.Builder(mContext, "test")
+                .setSmallIcon(android.R.drawable.sym_def_app_icon)
+                .setContentText("test")
+                .setCustomContentView(rv)
+                .setCustomBigContentView(rv1)
+                .setCustomHeadsUpContentView(rv2)
+                .build();
+        Notification n = new Notification.Builder(mContext, "test")
+                .setSmallIcon(android.R.drawable.sym_def_app_icon)
+                .setContentText("test")
+                .setCustomContentView(rv3)
+                .setCustomBigContentView(rv4)
+                .setCustomHeadsUpContentView(rv5)
+                .setPublicVersion(np)
+                .build();
+
+        assertNotNull(np.contentView);
+        assertNotNull(np.bigContentView);
+        assertNotNull(np.headsUpContentView);
+
+        assertTrue(n.publicVersion.extras.containsKey(Notification.EXTRA_CONTAINS_CUSTOM_VIEW));
+        assertNotNull(n.publicVersion.contentView);
+        assertNotNull(n.publicVersion.bigContentView);
+        assertNotNull(n.publicVersion.headsUpContentView);
+
+        mService.fixNotification(n, PKG, "tag", 9, 0);
+
+        assertNull(n.contentView);
+        assertNull(n.bigContentView);
+        assertNotNull(n.headsUpContentView);
+        assertNull(n.publicVersion.contentView);
+        assertNull(n.publicVersion.bigContentView);
+        assertNull(n.publicVersion.headsUpContentView);
+
+        verify(mUsageStats, times(5)).registerImageRemoved(PKG);
+    }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/HighRefreshRateBlacklistTest.java b/services/tests/wmtests/src/com/android/server/wm/HighRefreshRateBlacklistTest.java
index 5586726..daee911 100644
--- a/services/tests/wmtests/src/com/android/server/wm/HighRefreshRateBlacklistTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/HighRefreshRateBlacklistTest.java
@@ -16,71 +16,168 @@
 
 package com.android.server.wm;
 
+import static android.provider.DeviceConfig.WindowManager.KEY_HIGH_REFRESH_RATE_BLACKLIST;
+
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
+import android.content.res.Resources;
 import android.platform.test.annotations.Presubmit;
+import android.provider.DeviceConfig;
+import android.util.Pair;
 
-import androidx.test.filters.FlakyTest;
 import androidx.test.filters.SmallTest;
 
-import com.android.server.wm.HighRefreshRateBlacklist.SystemPropertyGetter;
+import com.android.internal.R;
+import com.android.server.wm.HighRefreshRateBlacklist.DeviceConfigInterface;
 
 import org.junit.Test;
 
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executor;
+import java.util.concurrent.TimeUnit;
+
 /**
  * Build/Install/Run:
- *  atest WmTests:HighRefreshRateBlacklistTest
+ * atest WmTests:HighRefreshRateBlacklistTest
  */
 @SmallTest
 @Presubmit
-@FlakyTest
 public class HighRefreshRateBlacklistTest {
 
     @Test
-    public void testBlacklist() {
-        HighRefreshRateBlacklist blacklist = new HighRefreshRateBlacklist(
-                new SystemPropertyGetter() {
-
-                    @Override
-                    public int getInt(String key, int def) {
-                        if ("ro.window_manager.high_refresh_rate_blacklist_length".equals(key)) {
-                            return 2;
-                        }
-                        return def;
-                    }
-
-                    @Override
-                    public String get(String key) {
-                        if ("ro.window_manager.high_refresh_rate_blacklist_entry1".equals(key)) {
-                            return "com.android.sample1";
-                        }
-                        if ("ro.window_manager.high_refresh_rate_blacklist_entry2".equals(key)) {
-                            return "com.android.sample2";
-                        }
-                        return "";
-                    }
-                });
+    public void testDefaultBlacklist() {
+        final Resources r = createResources("com.android.sample1", "com.android.sample2");
+        HighRefreshRateBlacklist blacklist =
+                new HighRefreshRateBlacklist(r, new FakeDeviceConfigInterface());
         assertTrue(blacklist.isBlacklisted("com.android.sample1"));
         assertTrue(blacklist.isBlacklisted("com.android.sample2"));
         assertFalse(blacklist.isBlacklisted("com.android.sample3"));
     }
 
     @Test
-    public void testNoBlacklist() {
-        HighRefreshRateBlacklist blacklist = new HighRefreshRateBlacklist(
-                new SystemPropertyGetter() {
-
-                    @Override
-                    public int getInt(String key, int def) {
-                        return def;
-                    }
-
-                    @Override
-                    public String get(String key) {
-                        return "";
-                    }
-                });
+    public void testNoDefaultBlacklist() {
+        final Resources r = createResources();
+        HighRefreshRateBlacklist blacklist =
+                new HighRefreshRateBlacklist(r, new FakeDeviceConfigInterface());
         assertFalse(blacklist.isBlacklisted("com.android.sample1"));
     }
+
+    @Test
+    public void testDefaultBlacklistIsOverriddenByDeviceConfig() {
+        final Resources r = createResources("com.android.sample1");
+        final FakeDeviceConfigInterface config = new FakeDeviceConfigInterface();
+        config.setBlacklist("com.android.sample2,com.android.sample3");
+        HighRefreshRateBlacklist blacklist = new HighRefreshRateBlacklist(r, config);
+        assertFalse(blacklist.isBlacklisted("com.android.sample1"));
+        assertTrue(blacklist.isBlacklisted("com.android.sample2"));
+        assertTrue(blacklist.isBlacklisted("com.android.sample3"));
+    }
+
+    @Test
+    public void testDefaultBlacklistIsOverriddenByEmptyDeviceConfig() {
+        final Resources r = createResources("com.android.sample1");
+        final FakeDeviceConfigInterface config = new FakeDeviceConfigInterface();
+        config.setBlacklist("");
+        HighRefreshRateBlacklist blacklist = new HighRefreshRateBlacklist(r, config);
+        assertFalse(blacklist.isBlacklisted("com.android.sample1"));
+    }
+
+    @Test
+    public void testDefaultBlacklistIsOverriddenByDeviceConfigUpdate() {
+        final Resources r = createResources("com.android.sample1");
+        final FakeDeviceConfigInterface config = new FakeDeviceConfigInterface();
+        HighRefreshRateBlacklist blacklist = new HighRefreshRateBlacklist(r, config);
+
+        // First check that the default blacklist is in effect
+        assertTrue(blacklist.isBlacklisted("com.android.sample1"));
+        assertFalse(blacklist.isBlacklisted("com.android.sample2"));
+        assertFalse(blacklist.isBlacklisted("com.android.sample3"));
+
+        //  Then confirm that the DeviceConfig list has propagated and taken effect.
+        config.setBlacklist("com.android.sample2,com.android.sample3");
+        assertFalse(blacklist.isBlacklisted("com.android.sample1"));
+        assertTrue(blacklist.isBlacklisted("com.android.sample2"));
+        assertTrue(blacklist.isBlacklisted("com.android.sample3"));
+
+        //  Finally make sure we go back to the default list if the DeviceConfig gets deleted.
+        config.setBlacklist(null);
+        assertTrue(blacklist.isBlacklisted("com.android.sample1"));
+        assertFalse(blacklist.isBlacklisted("com.android.sample2"));
+        assertFalse(blacklist.isBlacklisted("com.android.sample3"));
+    }
+
+    private Resources createResources(String... defaultBlacklist) {
+        Resources r = mock(Resources.class);
+        when(r.getStringArray(R.array.config_highRefreshRateBlacklist))
+                .thenReturn(defaultBlacklist);
+        return r;
+    }
+
+
+    class FakeDeviceConfigInterface implements DeviceConfigInterface {
+        private List<Pair<DeviceConfig.OnPropertiesChangedListener, Executor>> mListeners =
+                new ArrayList<>();
+        private String mBlacklist;
+
+        @Override
+        public String getProperty(String namespace, String name) {
+            if (!DeviceConfig.NAMESPACE_WINDOW_MANAGER.equals(namespace)
+                    || !KEY_HIGH_REFRESH_RATE_BLACKLIST.equals(name)) {
+                throw new IllegalArgumentException("Only things in NAMESPACE_WINDOW_MANAGER "
+                        + "supported.");
+            }
+            return mBlacklist;
+        }
+
+        @Override
+        public void addOnPropertiesChangedListener(String namespace, Executor executor,
+                DeviceConfig.OnPropertiesChangedListener listener) {
+
+            if (!DeviceConfig.NAMESPACE_WINDOW_MANAGER.equals(namespace)) {
+                throw new IllegalArgumentException("Only things in NAMESPACE_WINDOW_MANAGER "
+                        + "supported.");
+            }
+            mListeners.add(new Pair<>(listener, executor));
+        }
+
+        void setBlacklist(String blacklist) {
+            mBlacklist = blacklist;
+            CountDownLatch latch = new CountDownLatch(mListeners.size());
+            for (Pair<DeviceConfig.OnPropertiesChangedListener, Executor> listenerInfo :
+                    mListeners) {
+                final Executor executor = listenerInfo.second;
+                final DeviceConfig.OnPropertiesChangedListener listener = listenerInfo.first;
+                DeviceConfig.Properties properties = createBlacklistProperties(blacklist);
+                executor.execute(() -> {
+                    listener.onPropertiesChanged(properties);
+                    latch.countDown();
+                });
+            }
+            try {
+                latch.await(10, TimeUnit.SECONDS);
+            } catch (InterruptedException e) {
+                throw new RuntimeException("Failed to notify all blacklist listeners in time.", e);
+            }
+        }
+
+        private DeviceConfig.Properties createBlacklistProperties(final String blacklist) {
+            DeviceConfig.Properties properties = mock(DeviceConfig.Properties.class);
+            when(properties.getString(anyString(), any())).thenAnswer(invocation -> {
+                final Object[] args = invocation.getArguments();
+                if (KEY_HIGH_REFRESH_RATE_BLACKLIST.equals(args[0])) {
+                    return blacklist;
+                } else {
+                    return args[1];
+                }
+            });
+            return properties;
+        }
+    }
 }
diff --git a/services/usage/java/com/android/server/usage/UsageStatsProto.java b/services/usage/java/com/android/server/usage/UsageStatsProto.java
index 63bf7e7..3e88d93 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsProto.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsProto.java
@@ -44,7 +44,7 @@
 
         final long token = proto.start(IntervalStatsProto.STRINGPOOL);
         List<String> stringPool;
-        if (proto.isNextField(IntervalStatsProto.StringPool.SIZE)) {
+        if (proto.nextField(IntervalStatsProto.StringPool.SIZE)) {
             stringPool = new ArrayList(proto.readInt(IntervalStatsProto.StringPool.SIZE));
         } else {
             stringPool = new ArrayList();
@@ -66,12 +66,12 @@
 
         final long token = proto.start(fieldId);
         UsageStats stats;
-        if (proto.isNextField(IntervalStatsProto.UsageStats.PACKAGE_INDEX)) {
+        if (proto.nextField(IntervalStatsProto.UsageStats.PACKAGE_INDEX)) {
             // Fast path reading the package name index. Most cases this should work since it is
             // written first
             stats = statsOut.getOrCreateUsageStats(
                     stringPool.get(proto.readInt(IntervalStatsProto.UsageStats.PACKAGE_INDEX) - 1));
-        } else if (proto.isNextField(IntervalStatsProto.UsageStats.PACKAGE)) {
+        } else if (proto.nextField(IntervalStatsProto.UsageStats.PACKAGE)) {
             // No package index, try package name instead
             stats = statsOut.getOrCreateUsageStats(
                     proto.readString(IntervalStatsProto.UsageStats.PACKAGE));
@@ -177,7 +177,7 @@
         }
         String action = null;
         ArrayMap<String, Integer> counts;
-        if (proto.isNextField(IntervalStatsProto.UsageStats.ChooserAction.NAME)) {
+        if (proto.nextField(IntervalStatsProto.UsageStats.ChooserAction.NAME)) {
             // Fast path reading the action name. Most cases this should work since it is written
             // first
             action = proto.readString(IntervalStatsProto.UsageStats.ChooserAction.NAME);
@@ -244,7 +244,7 @@
         boolean configActive = false;
         final Configuration config = new Configuration();
         ConfigurationStats configStats;
-        if (proto.isNextField(IntervalStatsProto.Configuration.CONFIG)) {
+        if (proto.nextField(IntervalStatsProto.Configuration.CONFIG)) {
             // Fast path reading the configuration. Most cases this should work since it is
             // written first
             config.readFromProto(proto, IntervalStatsProto.Configuration.CONFIG);
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 7c41988..7f7a78b 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -909,6 +909,8 @@
                     if (!mScreenLocked && mScreenUnlockedFunctions != UsbManager.FUNCTION_NONE) {
                         // If the screen is unlocked, also set current functions.
                         setScreenUnlockedFunctions();
+                    } else {
+                        setEnabledFunctions(UsbManager.FUNCTION_NONE, false);
                     }
                     break;
                 case MSG_UPDATE_SCREEN_LOCK:
diff --git a/startop/apps/ColorChanging/.gitignore b/startop/apps/ColorChanging/.gitignore
new file mode 100644
index 0000000..2b75303
--- /dev/null
+++ b/startop/apps/ColorChanging/.gitignore
@@ -0,0 +1,13 @@
+*.iml
+.gradle
+/local.properties
+/.idea/caches
+/.idea/libraries
+/.idea/modules.xml
+/.idea/workspace.xml
+/.idea/navEditor.xml
+/.idea/assetWizardSettings.xml
+.DS_Store
+/build
+/captures
+.externalNativeBuild
diff --git a/startop/apps/ColorChanging/.idea/encodings.xml b/startop/apps/ColorChanging/.idea/encodings.xml
new file mode 100644
index 0000000..15a15b2
--- /dev/null
+++ b/startop/apps/ColorChanging/.idea/encodings.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="Encoding" addBOMForNewFiles="with NO BOM" />
+</project>
\ No newline at end of file
diff --git a/startop/apps/ColorChanging/.idea/gradle.xml b/startop/apps/ColorChanging/.idea/gradle.xml
new file mode 100644
index 0000000..2996d53
--- /dev/null
+++ b/startop/apps/ColorChanging/.idea/gradle.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="GradleSettings">
+    <option name="linkedExternalProjectsSettings">
+      <GradleProjectSettings>
+        <compositeConfiguration>
+          <compositeBuild compositeDefinitionSource="SCRIPT" />
+        </compositeConfiguration>
+        <option name="distributionType" value="DEFAULT_WRAPPED" />
+        <option name="externalProjectPath" value="$PROJECT_DIR$" />
+        <option name="resolveModulePerSourceSet" value="false" />
+      </GradleProjectSettings>
+    </option>
+  </component>
+</project>
\ No newline at end of file
diff --git a/startop/apps/ColorChanging/.idea/misc.xml b/startop/apps/ColorChanging/.idea/misc.xml
new file mode 100644
index 0000000..37a7509
--- /dev/null
+++ b/startop/apps/ColorChanging/.idea/misc.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" project-jdk-name="1.8" project-jdk-type="JavaSDK">
+    <output url="file://$PROJECT_DIR$/build/classes" />
+  </component>
+  <component name="ProjectType">
+    <option name="id" value="Android" />
+  </component>
+</project>
\ No newline at end of file
diff --git a/startop/apps/ColorChanging/.idea/runConfigurations.xml b/startop/apps/ColorChanging/.idea/runConfigurations.xml
new file mode 100644
index 0000000..7f68460
--- /dev/null
+++ b/startop/apps/ColorChanging/.idea/runConfigurations.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="RunConfigurationProducerService">
+    <option name="ignoredProducers">
+      <set>
+        <option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
+        <option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
+        <option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
+      </set>
+    </option>
+  </component>
+</project>
\ No newline at end of file
diff --git a/startop/apps/ColorChanging/README.md b/startop/apps/ColorChanging/README.md
new file mode 100644
index 0000000..eb8b9cc
--- /dev/null
+++ b/startop/apps/ColorChanging/README.md
@@ -0,0 +1,5 @@
+This directory contains a simple Android app that is meant to help in 
+syncing a trace along with a video in Perfetto.
+
+This app changes the colors of the screen that has traces to go along
+with the colors.
diff --git a/startop/apps/ColorChanging/app/.gitignore b/startop/apps/ColorChanging/app/.gitignore
new file mode 100644
index 0000000..796b96d
--- /dev/null
+++ b/startop/apps/ColorChanging/app/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/startop/apps/ColorChanging/app/build.gradle b/startop/apps/ColorChanging/app/build.gradle
new file mode 100644
index 0000000..ab955aa
--- /dev/null
+++ b/startop/apps/ColorChanging/app/build.gradle
@@ -0,0 +1,29 @@
+apply plugin: 'com.android.application'
+
+android {
+    compileSdkVersion 29
+    buildToolsVersion "29.0.0"
+    defaultConfig {
+        applicationId "com.android.startop.colorchanging"
+        minSdkVersion 15
+        targetSdkVersion 29
+        versionCode 1
+        versionName "1.0"
+        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+    }
+    buildTypes {
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+        }
+    }
+}
+
+dependencies {
+    implementation fileTree(dir: 'libs', include: ['*.jar'])
+    implementation 'androidx.appcompat:appcompat:1.0.2'
+    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
+    testImplementation 'junit:junit:4.12'
+    androidTestImplementation 'androidx.test:runner:1.2.0'
+    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
+}
diff --git a/startop/apps/ColorChanging/app/proguard-rules.pro b/startop/apps/ColorChanging/app/proguard-rules.pro
new file mode 100644
index 0000000..f1b4245
--- /dev/null
+++ b/startop/apps/ColorChanging/app/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
diff --git a/startop/apps/ColorChanging/app/src/androidTest/java/com/android/startop/colorchanging/ExampleInstrumentedTest.java b/startop/apps/ColorChanging/app/src/androidTest/java/com/android/startop/colorchanging/ExampleInstrumentedTest.java
new file mode 100644
index 0000000..31736f3
--- /dev/null
+++ b/startop/apps/ColorChanging/app/src/androidTest/java/com/android/startop/colorchanging/ExampleInstrumentedTest.java
@@ -0,0 +1,27 @@
+package com.android.startop.colorchanging;
+
+import android.content.Context;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+    @Test
+    public void useAppContext() {
+        // Context of the app under test.
+        Context appContext = InstrumentationRegistry.getTargetContext();
+
+        assertEquals("com.android.startop.colorchanging", appContext.getPackageName());
+    }
+}
diff --git a/startop/apps/ColorChanging/app/src/main/AndroidManifest.xml b/startop/apps/ColorChanging/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..37193b5
--- /dev/null
+++ b/startop/apps/ColorChanging/app/src/main/AndroidManifest.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.startop.colorchanging">
+
+    <application
+        android:allowBackup="true"
+        android:icon="@mipmap/ic_launcher"
+        android:label="@string/app_name"
+        android:roundIcon="@mipmap/ic_launcher_round"
+        android:supportsRtl="true"
+        android:theme="@style/AppTheme">
+        <activity android:name="com.android.startop.colorchanging.MainActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+
+</manifest>
\ No newline at end of file
diff --git a/startop/apps/ColorChanging/app/src/main/java/com/android/startop/colorchanging/MainActivity.java b/startop/apps/ColorChanging/app/src/main/java/com/android/startop/colorchanging/MainActivity.java
new file mode 100644
index 0000000..b8f4faf
--- /dev/null
+++ b/startop/apps/ColorChanging/app/src/main/java/com/android/startop/colorchanging/MainActivity.java
@@ -0,0 +1,91 @@
+/*
+ * 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.colorchanging;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+import android.os.Bundle;
+import android.os.Trace;
+import android.view.View;
+
+public class MainActivity extends AppCompatActivity {
+    View view;
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_main);
+
+        view = this.getWindow().getDecorView();
+        view.setBackgroundResource(R.color.gray);
+        Trace.beginSection("gray");
+    }
+
+    public void goRed(View v) {
+        Trace.endSection();
+        view.setBackgroundResource(R.color.red);
+        Trace.beginSection("red");
+    }
+
+    public void goOrange(View v) {
+        Trace.endSection();
+        view.setBackgroundResource(R.color.orange);
+        Trace.beginSection("orange");
+    }
+
+    public void goYellow(View v) {
+        Trace.endSection();
+        view.setBackgroundResource(R.color.yellow);
+        Trace.beginSection("yellow");
+    }
+
+    public void goGreen(View v) {
+        Trace.endSection();
+        view.setBackgroundResource(R.color.green);
+        Trace.beginSection("green");
+    }
+
+    public void goBlue(View v) {
+        Trace.endSection();
+        view.setBackgroundResource(R.color.blue);
+        Trace.beginSection("blue");
+    }
+
+    public void goIndigo(View v) {
+        Trace.endSection();
+        view.setBackgroundResource(R.color.indigo);
+        Trace.beginSection("indigo");
+    }
+
+    public void goViolet(View v) {
+        Trace.endSection();
+        view.setBackgroundResource(R.color.violet);
+        Trace.beginSection("violet");
+    }
+
+    public void goCyan(View v) {
+        Trace.endSection();
+        view.setBackgroundResource(R.color.cyan);
+        Trace.beginSection("cyan");
+    }
+
+    public void goBlack(View v) {
+        Trace.endSection();
+        view.setBackgroundResource(R.color.black);
+        Trace.beginSection("black");
+    }
+
+}
diff --git a/startop/apps/ColorChanging/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/startop/apps/ColorChanging/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
new file mode 100644
index 0000000..1f6bb29
--- /dev/null
+++ b/startop/apps/ColorChanging/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
@@ -0,0 +1,34 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:aapt="http://schemas.android.com/aapt"
+    android:width="108dp"
+    android:height="108dp"
+    android:viewportWidth="108"
+    android:viewportHeight="108">
+    <path
+        android:fillType="evenOdd"
+        android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
+        android:strokeWidth="1"
+        android:strokeColor="#00000000">
+        <aapt:attr name="android:fillColor">
+            <gradient
+                android:endX="78.5885"
+                android:endY="90.9159"
+                android:startX="48.7653"
+                android:startY="61.0927"
+                android:type="linear">
+                <item
+                    android:color="#44000000"
+                    android:offset="0.0" />
+                <item
+                    android:color="#00000000"
+                    android:offset="1.0" />
+            </gradient>
+        </aapt:attr>
+    </path>
+    <path
+        android:fillColor="#FFFFFF"
+        android:fillType="nonZero"
+        android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
+        android:strokeWidth="1"
+        android:strokeColor="#00000000" />
+</vector>
diff --git a/startop/apps/ColorChanging/app/src/main/res/drawable/ic_launcher_background.xml b/startop/apps/ColorChanging/app/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 0000000..0d025f9
--- /dev/null
+++ b/startop/apps/ColorChanging/app/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="108dp"
+    android:height="108dp"
+    android:viewportWidth="108"
+    android:viewportHeight="108">
+    <path
+        android:fillColor="#008577"
+        android:pathData="M0,0h108v108h-108z" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M9,0L9,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,0L19,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M29,0L29,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M39,0L39,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M49,0L49,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M59,0L59,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M69,0L69,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M79,0L79,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M89,0L89,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M99,0L99,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,9L108,9"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,19L108,19"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,29L108,29"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,39L108,39"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,49L108,49"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,59L108,59"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,69L108,69"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,79L108,79"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,89L108,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,99L108,99"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,29L89,29"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,39L89,39"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,49L89,49"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,59L89,59"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,69L89,69"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,79L89,79"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M29,19L29,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M39,19L39,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M49,19L49,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M59,19L59,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M69,19L69,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M79,19L79,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+</vector>
diff --git a/startop/apps/ColorChanging/app/src/main/res/layout/activity_main.xml b/startop/apps/ColorChanging/app/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000..fb18df7
--- /dev/null
+++ b/startop/apps/ColorChanging/app/src/main/res/layout/activity_main.xml
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    tools:context=".MainActivity">
+
+    <Button
+        android:id="@+id/button"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="16dp"
+        android:layout_marginLeft="16dp"
+        android:layout_marginTop="16dp"
+        android:onClick="goRed"
+        android:text="red"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <Button
+        android:id="@+id/button4"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="16dp"
+        android:layout_marginEnd="16dp"
+        android:layout_marginRight="16dp"
+        android:onClick="goYellow"
+        android:text="YELLOW"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <Button
+        android:id="@+id/button6"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="16dp"
+        android:layout_marginLeft="16dp"
+        android:layout_marginTop="32dp"
+        android:onClick="goGreen"
+        android:text="GREEN"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@+id/button" />
+
+    <Button
+        android:id="@+id/button7"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="165dp"
+        android:layout_marginLeft="165dp"
+        android:layout_marginTop="115dp"
+        android:layout_marginEnd="165dp"
+        android:layout_marginRight="165dp"
+        android:onClick="goViolet"
+        android:text="VIOLET"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintHorizontal_bias="0.428"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@+id/button8" />
+
+    <Button
+        android:id="@+id/button10"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="165dp"
+        android:layout_marginLeft="165dp"
+        android:layout_marginTop="32dp"
+        android:layout_marginEnd="165dp"
+        android:layout_marginRight="165dp"
+        android:onClick="goBlue"
+        android:text="BLUE"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@+id/button8" />
+
+    <Button
+        android:id="@+id/button8"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="165dp"
+        android:layout_marginLeft="165dp"
+        android:layout_marginTop="16dp"
+        android:layout_marginEnd="165dp"
+        android:layout_marginRight="165dp"
+        android:onClick="goOrange"
+        android:text="ORANGE"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <Button
+        android:id="@+id/button11"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="32dp"
+        android:layout_marginEnd="16dp"
+        android:layout_marginRight="16dp"
+        android:onClick="goIndigo"
+        android:text="INDIGO"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintTop_toBottomOf="@+id/button4" />
+
+    <Button
+        android:id="@+id/button12"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="162dp"
+        android:layout_marginLeft="162dp"
+        android:layout_marginTop="25dp"
+        android:layout_marginEnd="161dp"
+        android:layout_marginRight="161dp"
+        android:onClick="goCyan"
+        android:text="CYAN"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@+id/button7" />
+
+    <Button
+        android:id="@+id/button13"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="162dp"
+        android:layout_marginLeft="162dp"
+        android:layout_marginTop="25dp"
+        android:layout_marginEnd="161dp"
+        android:layout_marginRight="161dp"
+        android:onClick="goBlack"
+        android:text="BLACK"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@+id/button12" />
+</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
diff --git a/startop/apps/ColorChanging/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/startop/apps/ColorChanging/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
new file mode 100644
index 0000000..eca70cf
--- /dev/null
+++ b/startop/apps/ColorChanging/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+    <background android:drawable="@drawable/ic_launcher_background" />
+    <foreground android:drawable="@drawable/ic_launcher_foreground" />
+</adaptive-icon>
\ No newline at end of file
diff --git a/startop/apps/ColorChanging/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/startop/apps/ColorChanging/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 0000000..eca70cf
--- /dev/null
+++ b/startop/apps/ColorChanging/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+    <background android:drawable="@drawable/ic_launcher_background" />
+    <foreground android:drawable="@drawable/ic_launcher_foreground" />
+</adaptive-icon>
\ No newline at end of file
diff --git a/startop/apps/ColorChanging/app/src/main/res/mipmap-hdpi/ic_launcher.png b/startop/apps/ColorChanging/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..898f3ed
--- /dev/null
+++ b/startop/apps/ColorChanging/app/src/main/res/mipmap-hdpi/ic_launcher.png
Binary files differ
diff --git a/startop/apps/ColorChanging/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/startop/apps/ColorChanging/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644
index 0000000..dffca36
--- /dev/null
+++ b/startop/apps/ColorChanging/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
Binary files differ
diff --git a/startop/apps/ColorChanging/app/src/main/res/mipmap-mdpi/ic_launcher.png b/startop/apps/ColorChanging/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..64ba76f
--- /dev/null
+++ b/startop/apps/ColorChanging/app/src/main/res/mipmap-mdpi/ic_launcher.png
Binary files differ
diff --git a/startop/apps/ColorChanging/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/startop/apps/ColorChanging/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100644
index 0000000..dae5e08
--- /dev/null
+++ b/startop/apps/ColorChanging/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
Binary files differ
diff --git a/startop/apps/ColorChanging/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/startop/apps/ColorChanging/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..e5ed465
--- /dev/null
+++ b/startop/apps/ColorChanging/app/src/main/res/mipmap-xhdpi/ic_launcher.png
Binary files differ
diff --git a/startop/apps/ColorChanging/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/startop/apps/ColorChanging/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..14ed0af
--- /dev/null
+++ b/startop/apps/ColorChanging/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
Binary files differ
diff --git a/startop/apps/ColorChanging/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/startop/apps/ColorChanging/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..b0907ca
--- /dev/null
+++ b/startop/apps/ColorChanging/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/startop/apps/ColorChanging/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/startop/apps/ColorChanging/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..d8ae031
--- /dev/null
+++ b/startop/apps/ColorChanging/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
Binary files differ
diff --git a/startop/apps/ColorChanging/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/startop/apps/ColorChanging/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..2c18de9
--- /dev/null
+++ b/startop/apps/ColorChanging/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Binary files differ
diff --git a/startop/apps/ColorChanging/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/startop/apps/ColorChanging/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..beed3cd
--- /dev/null
+++ b/startop/apps/ColorChanging/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
Binary files differ
diff --git a/startop/apps/ColorChanging/app/src/main/res/values/colors.xml b/startop/apps/ColorChanging/app/src/main/res/values/colors.xml
new file mode 100644
index 0000000..209790f
--- /dev/null
+++ b/startop/apps/ColorChanging/app/src/main/res/values/colors.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <color name="colorPrimary">#008577</color>
+    <color name="colorPrimaryDark">#00574B</color>
+    <color name="colorAccent">#D81B60</color>
+    <color name="black">#000000</color>
+    <color name="red">#F44336</color>
+    <color name="green">#2CF035</color>
+    <color name="blue">#2C70F0</color>
+    <color name="yellow">#F0EA2C</color>
+    <color name="gray">#D3D3D3</color>
+    <color name="orange">#E57E0A</color>
+    <color name="indigo">#4B0082</color>
+    <color name="violet">#EE82EE</color>
+    <color name="cyan">#00E8FF</color>
+</resources>
diff --git a/startop/apps/ColorChanging/app/src/main/res/values/strings.xml b/startop/apps/ColorChanging/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..ff062fb
--- /dev/null
+++ b/startop/apps/ColorChanging/app/src/main/res/values/strings.xml
@@ -0,0 +1,3 @@
+<resources>
+    <string name="app_name">ColorChanging</string>
+</resources>
diff --git a/startop/apps/ColorChanging/app/src/main/res/values/styles.xml b/startop/apps/ColorChanging/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..5885930
--- /dev/null
+++ b/startop/apps/ColorChanging/app/src/main/res/values/styles.xml
@@ -0,0 +1,11 @@
+<resources>
+
+    <!-- Base application theme. -->
+    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
+        <!-- Customize your theme here. -->
+        <item name="colorPrimary">@color/colorPrimary</item>
+        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
+        <item name="colorAccent">@color/colorAccent</item>
+    </style>
+
+</resources>
diff --git a/startop/apps/ColorChanging/app/src/test/java/com/android/startop/colorchanging/ExampleUnitTest.java b/startop/apps/ColorChanging/app/src/test/java/com/android/startop/colorchanging/ExampleUnitTest.java
new file mode 100644
index 0000000..8423674
--- /dev/null
+++ b/startop/apps/ColorChanging/app/src/test/java/com/android/startop/colorchanging/ExampleUnitTest.java
@@ -0,0 +1,17 @@
+package com.android.startop.colorchanging;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+public class ExampleUnitTest {
+    @Test
+    public void addition_isCorrect() {
+        assertEquals(4, 2 + 2);
+    }
+}
\ No newline at end of file
diff --git a/startop/apps/ColorChanging/build.gradle b/startop/apps/ColorChanging/build.gradle
new file mode 100644
index 0000000..a960ab3
--- /dev/null
+++ b/startop/apps/ColorChanging/build.gradle
@@ -0,0 +1,24 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+
+buildscript {
+    repositories {
+        google()
+        jcenter()
+    }
+    dependencies {
+        classpath 'com.android.tools.build:gradle:3.4.1'
+        // NOTE: Do not place your application dependencies here; they belong
+        // in the individual module build.gradle files
+    }
+}
+
+allprojects {
+    repositories {
+        google()
+        jcenter()
+    }
+}
+
+task clean(type: Delete) {
+    delete rootProject.buildDir
+}
diff --git a/startop/apps/ColorChanging/gradle.properties b/startop/apps/ColorChanging/gradle.properties
new file mode 100644
index 0000000..199d16e
--- /dev/null
+++ b/startop/apps/ColorChanging/gradle.properties
@@ -0,0 +1,20 @@
+# Project-wide Gradle settings.
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx1536m
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
+# AndroidX package structure to make it clearer which packages are bundled with the
+# Android operating system, and which are packaged with your app's APK
+# https://developer.android.com/topic/libraries/support-library/androidx-rn
+android.useAndroidX=true
+# Automatically convert third-party libraries to use AndroidX
+android.enableJetifier=true
+
diff --git a/startop/apps/ColorChanging/gradle/wrapper/gradle-wrapper.jar b/startop/apps/ColorChanging/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..f6b961f
--- /dev/null
+++ b/startop/apps/ColorChanging/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/startop/apps/ColorChanging/gradle/wrapper/gradle-wrapper.properties b/startop/apps/ColorChanging/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..09f2718
--- /dev/null
+++ b/startop/apps/ColorChanging/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Mon Jun 17 13:40:58 PDT 2019
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip
diff --git a/startop/apps/ColorChanging/gradlew b/startop/apps/ColorChanging/gradlew
new file mode 100755
index 0000000..cccdd3d
--- /dev/null
+++ b/startop/apps/ColorChanging/gradlew
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+##  Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+        PRG="$link"
+    else
+        PRG=`dirname "$PRG"`"/$link"
+    fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+    echo "$*"
+}
+
+die () {
+    echo
+    echo "$*"
+    echo
+    exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+  CYGWIN* )
+    cygwin=true
+    ;;
+  Darwin* )
+    darwin=true
+    ;;
+  MINGW* )
+    msys=true
+    ;;
+  NONSTOP* )
+    nonstop=true
+    ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+        JAVACMD="$JAVA_HOME/bin/java"
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD="java"
+    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+    MAX_FD_LIMIT=`ulimit -H -n`
+    if [ $? -eq 0 ] ; then
+        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+            MAX_FD="$MAX_FD_LIMIT"
+        fi
+        ulimit -n $MAX_FD
+        if [ $? -ne 0 ] ; then
+            warn "Could not set maximum file descriptor limit: $MAX_FD"
+        fi
+    else
+        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+    fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+    JAVACMD=`cygpath --unix "$JAVACMD"`
+
+    # We build the pattern for arguments to be converted via cygpath
+    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+    SEP=""
+    for dir in $ROOTDIRSRAW ; do
+        ROOTDIRS="$ROOTDIRS$SEP$dir"
+        SEP="|"
+    done
+    OURCYGPATTERN="(^($ROOTDIRS))"
+    # Add a user-defined pattern to the cygpath arguments
+    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+    fi
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    i=0
+    for arg in "$@" ; do
+        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
+
+        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
+            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+        else
+            eval `echo args$i`="\"$arg\""
+        fi
+        i=$((i+1))
+    done
+    case $i in
+        (0) set -- ;;
+        (1) set -- "$args0" ;;
+        (2) set -- "$args0" "$args1" ;;
+        (3) set -- "$args0" "$args1" "$args2" ;;
+        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+    esac
+fi
+
+# Escape application args
+save () {
+    for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+    echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+  cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/startop/apps/ColorChanging/gradlew.bat b/startop/apps/ColorChanging/gradlew.bat
new file mode 100644
index 0000000..e95643d
--- /dev/null
+++ b/startop/apps/ColorChanging/gradlew.bat
@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off

+@rem ##########################################################################

+@rem

+@rem  Gradle startup script for Windows

+@rem

+@rem ##########################################################################

+

+@rem Set local scope for the variables with windows NT shell

+if "%OS%"=="Windows_NT" setlocal

+

+set DIRNAME=%~dp0

+if "%DIRNAME%" == "" set DIRNAME=.

+set APP_BASE_NAME=%~n0

+set APP_HOME=%DIRNAME%

+

+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.

+set DEFAULT_JVM_OPTS=

+

+@rem Find java.exe

+if defined JAVA_HOME goto findJavaFromJavaHome

+

+set JAVA_EXE=java.exe

+%JAVA_EXE% -version >NUL 2>&1

+if "%ERRORLEVEL%" == "0" goto init

+

+echo.

+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.

+echo.

+echo Please set the JAVA_HOME variable in your environment to match the

+echo location of your Java installation.

+

+goto fail

+

+:findJavaFromJavaHome

+set JAVA_HOME=%JAVA_HOME:"=%

+set JAVA_EXE=%JAVA_HOME%/bin/java.exe

+

+if exist "%JAVA_EXE%" goto init

+

+echo.

+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%

+echo.

+echo Please set the JAVA_HOME variable in your environment to match the

+echo location of your Java installation.

+

+goto fail

+

+:init

+@rem Get command-line arguments, handling Windows variants

+

+if not "%OS%" == "Windows_NT" goto win9xME_args

+

+:win9xME_args

+@rem Slurp the command line arguments.

+set CMD_LINE_ARGS=

+set _SKIP=2

+

+:win9xME_args_slurp

+if "x%~1" == "x" goto execute

+

+set CMD_LINE_ARGS=%*

+

+:execute

+@rem Setup the command line

+

+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar

+

+@rem Execute Gradle

+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%

+

+:end

+@rem End local scope for the variables with windows NT shell

+if "%ERRORLEVEL%"=="0" goto mainEnd

+

+:fail

+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of

+rem the _cmd.exe /c_ return code!

+if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1

+exit /b 1

+

+:mainEnd

+if "%OS%"=="Windows_NT" endlocal

+

+:omega

diff --git a/startop/apps/ColorChanging/settings.gradle b/startop/apps/ColorChanging/settings.gradle
new file mode 100644
index 0000000..e7b4def
--- /dev/null
+++ b/startop/apps/ColorChanging/settings.gradle
@@ -0,0 +1 @@
+include ':app'
diff --git a/startop/iorap/DISABLED_TEST_MAPPING b/startop/iorap/TEST_MAPPING
similarity index 100%
rename from startop/iorap/DISABLED_TEST_MAPPING
rename to startop/iorap/TEST_MAPPING
diff --git a/startop/iorap/tests/AndroidTest.xml b/startop/iorap/tests/AndroidTest.xml
index bcd1103..6102c44 100644
--- a/startop/iorap/tests/AndroidTest.xml
+++ b/startop/iorap/tests/AndroidTest.xml
@@ -33,18 +33,34 @@
     <target_preparer class="com.android.tradefed.targetprep.DisableSELinuxTargetPreparer">
     </target_preparer>
 
+    <!-- do not use DeviceSetup#set-property because it reboots the device b/136200738.
+         furthermore the changes in /data/local.prop don't actually seem to get picked up.
+    -->
     <target_preparer
         class="com.android.tradefed.targetprep.DeviceSetup">
+        <!-- we need this magic flag, otherwise it always reboots and breaks the selinux -->
+        <option name="force-skip-system-props" value="true" />
+
         <!-- Crash instead of using Log.wtf within the system_server iorap code. -->
-        <option name="set-property" key="iorapd.forwarding_service.wtf_crash" value="true" />
+        <option name="run-command" value="setprop iorapd.forwarding_service.wtf_crash true" />
         <!-- IIorapd has fake behavior: it doesn't do anything but reply with 'DONE' status -->
-        <option name="set-property" key="iorapd.binder.fake" value="true" />
-        <option name="restore-properties" value="true" />
+        <option name="run-command" value="setprop iorapd.binder.fake true" />
+
+        <!-- iorapd does not pick up the above changes until we restart it -->
+        <option name="run-command" value="stop iorapd" />
+        <option name="run-command" value="start iorapd" />
+        <!-- give it some time to restart the service; otherwise the first unit test might fail -->
+        <option name="run-command" value="sleep 1" />
     </target_preparer>
 
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="com.google.android.startop.iorap.tests" />
         <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
     </test>
+
+    <!-- using DeviceSetup again does not work. we simply leave the device in a semi-bad
+         state. there is no way to clean this up as far as I know.
+         -->
+
 </configuration>
 
diff --git a/startop/iorap/tests/src/com/google/android/startop/iorap/IIorapIntegrationTest.kt b/startop/iorap/tests/src/com/google/android/startop/iorap/IIorapIntegrationTest.kt
index 883d094..460add8 100644
--- a/startop/iorap/tests/src/com/google/android/startop/iorap/IIorapIntegrationTest.kt
+++ b/startop/iorap/tests/src/com/google/android/startop/iorap/IIorapIntegrationTest.kt
@@ -14,6 +14,7 @@
 
 package com.google.android.startop.iorap
 
+import android.net.Uri
 import android.os.ServiceManager
 import androidx.test.filters.MediumTest
 import org.junit.Test
@@ -85,6 +86,9 @@
 
     @Test
     fun testOnPackageEvent() {
+        // FIXME (b/137134253): implement PackageEvent parsing on the C++ side.
+        // This is currently (silently: b/137135024) failing because IIorap is 'oneway' and the
+        // C++ PackageEvent un-parceling fails since its not implemented fully.
         /*
         testAnyMethod { requestId : RequestId ->
             iorapService.onPackageEvent(requestId,
@@ -92,7 +96,6 @@
                             Uri.parse("https://www.google.com"), "com.fake.package"))
         }
         */
-        // FIXME: Broken for some reason. C++ side never sees this call.
     }
 
     @Test
@@ -107,7 +110,7 @@
     @Test
     fun testOnAppLaunchEvent() {
         testAnyMethod { requestId : RequestId ->
-            // iorapService.onAppLaunchEvent(requestId, AppLaunchEvent.IntentStarted())
+            iorapService.onAppLaunchEvent(requestId, AppLaunchEvent.IntentFailed(/*sequenceId*/123))
         }
     }
 
diff --git a/startop/scripts/app_startup/app_startup_runner.py b/startop/scripts/app_startup/app_startup_runner.py
index 9a608af..7cba780 100755
--- a/startop/scripts/app_startup/app_startup_runner.py
+++ b/startop/scripts/app_startup/app_startup_runner.py
@@ -27,28 +27,40 @@
 #
 
 import argparse
-import asyncio
 import csv
 import itertools
 import os
 import sys
 import tempfile
-import time
-from typing import Any, Callable, Dict, Generic, Iterable, List, NamedTuple, TextIO, Tuple, TypeVar, Optional, Union
+from typing import Any, Callable, Iterable, List, NamedTuple, TextIO, Tuple, \
+    TypeVar, Union
+
+# local import
+DIR = os.path.abspath(os.path.dirname(__file__))
+sys.path.append(os.path.dirname(DIR))
+import app_startup.run_app_with_prefetch as run_app_with_prefetch
+import app_startup.lib.args_utils as args_utils
+from app_startup.lib.data_frame import DataFrame
+import lib.cmd_utils as cmd_utils
+import lib.print_utils as print_utils
 
 # The following command line options participate in the combinatorial generation.
 # All other arguments have a global effect.
-_COMBINATORIAL_OPTIONS=['packages', 'readaheads', 'compiler_filters']
-_TRACING_READAHEADS=['mlock', 'fadvise']
-_FORWARD_OPTIONS={'loop_count': '--count'}
-_RUN_SCRIPT=os.path.join(os.path.dirname(os.path.realpath(__file__)), 'run_app_with_prefetch')
+_COMBINATORIAL_OPTIONS = ['package', 'readahead', 'compiler_filter', 'activity']
+_TRACING_READAHEADS = ['mlock', 'fadvise']
+_FORWARD_OPTIONS = {'loop_count': '--count'}
+_RUN_SCRIPT = os.path.join(os.path.dirname(os.path.realpath(__file__)),
+                           'run_app_with_prefetch.py')
 
-RunCommandArgs = NamedTuple('RunCommandArgs', [('package', str), ('readahead', str), ('compiler_filter', Optional[str])])
-CollectorPackageInfo = NamedTuple('CollectorPackageInfo', [('package', str), ('compiler_filter', str)])
-_COLLECTOR_SCRIPT=os.path.join(os.path.dirname(os.path.realpath(__file__)), '../iorap/collector')
-_COLLECTOR_TIMEOUT_MULTIPLIER = 2 # take the regular --timeout and multiply by 2; systrace starts up slowly.
+CollectorPackageInfo = NamedTuple('CollectorPackageInfo',
+                                  [('package', str), ('compiler_filter', str)])
+_COLLECTOR_SCRIPT = os.path.join(os.path.dirname(os.path.realpath(__file__)),
+                                 '../iorap/collector')
+_COLLECTOR_TIMEOUT_MULTIPLIER = 10  # take the regular --timeout and multiply
+# by 2; systrace starts up slowly.
 
-_UNLOCK_SCREEN_SCRIPT=os.path.join(os.path.dirname(os.path.realpath(__file__)), 'unlock_screen')
+_UNLOCK_SCREEN_SCRIPT = os.path.join(
+    os.path.dirname(os.path.realpath(__file__)), 'unlock_screen')
 
 # This must be the only mutable global variable. All other global variables are constants to avoid magic literals.
 _debug = False  # See -d/--debug flag.
@@ -56,105 +68,70 @@
 
 # Type hinting names.
 T = TypeVar('T')
-NamedTupleMeta = Callable[..., T]  # approximation of a (S : NamedTuple<T> where S() == T) metatype.
+NamedTupleMeta = Callable[
+    ..., T]  # approximation of a (S : NamedTuple<T> where S() == T) metatype.
 
 def parse_options(argv: List[str] = None):
   """Parse command line arguments and return an argparse Namespace object."""
-  parser = argparse.ArgumentParser(description="Run one or more Android applications under various settings in order to measure startup time.")
+  parser = argparse.ArgumentParser(description="Run one or more Android "
+                                               "applications under various "
+                                               "settings in order to measure "
+                                               "startup time.")
   # argparse considers args starting with - and -- optional in --help, even though required=True.
   # by using a named argument group --help will clearly say that it's required instead of optional.
   required_named = parser.add_argument_group('required named arguments')
-  required_named.add_argument('-p', '--package', action='append', dest='packages', help='package of the application', required=True)
-  required_named.add_argument('-r', '--readahead', action='append', dest='readaheads', help='which readahead mode to use', choices=('warm', 'cold', 'mlock', 'fadvise'), required=True)
+  required_named.add_argument('-p', '--package', action='append',
+                              dest='packages',
+                              help='package of the application', required=True)
+  required_named.add_argument('-r', '--readahead', action='append',
+                              dest='readaheads',
+                              help='which readahead mode to use',
+                              choices=('warm', 'cold', 'mlock', 'fadvise'),
+                              required=True)
 
   # optional arguments
   # use a group here to get the required arguments to appear 'above' the optional arguments in help.
   optional_named = parser.add_argument_group('optional named arguments')
-  optional_named.add_argument('-c', '--compiler-filter', action='append', dest='compiler_filters', help='which compiler filter to use. if omitted it does not enforce the app\'s compiler filter', choices=('speed', 'speed-profile', 'quicken'))
-  optional_named.add_argument('-s', '--simulate', dest='simulate', action='store_true', help='Print which commands will run, but don\'t run the apps')
-  optional_named.add_argument('-d', '--debug', dest='debug', action='store_true', help='Add extra debugging output')
-  optional_named.add_argument('-o', '--output', dest='output', action='store', help='Write CSV output to file.')
-  optional_named.add_argument('-t', '--timeout', dest='timeout', action='store', type=int, help='Timeout after this many seconds when executing a single run.')
-  optional_named.add_argument('-lc', '--loop-count', dest='loop_count', default=1, type=int, action='store', help='How many times to loop a single run.')
-  optional_named.add_argument('-in', '--inodes', dest='inodes', type=str, action='store', help='Path to inodes file (system/extras/pagecache/pagecache.py -d inodes)')
+  optional_named.add_argument('-c', '--compiler-filter', action='append',
+                              dest='compiler_filters',
+                              help='which compiler filter to use. if omitted it does not enforce the app\'s compiler filter',
+                              choices=('speed', 'speed-profile', 'quicken'))
+  optional_named.add_argument('-s', '--simulate', dest='simulate',
+                              action='store_true',
+                              help='Print which commands will run, but don\'t run the apps')
+  optional_named.add_argument('-d', '--debug', dest='debug',
+                              action='store_true',
+                              help='Add extra debugging output')
+  optional_named.add_argument('-o', '--output', dest='output', action='store',
+                              help='Write CSV output to file.')
+  optional_named.add_argument('-t', '--timeout', dest='timeout', action='store',
+                              type=int, default=10,
+                              help='Timeout after this many seconds when executing a single run.')
+  optional_named.add_argument('-lc', '--loop-count', dest='loop_count',
+                              default=1, type=int, action='store',
+                              help='How many times to loop a single run.')
+  optional_named.add_argument('-in', '--inodes', dest='inodes', type=str,
+                              action='store',
+                              help='Path to inodes file (system/extras/pagecache/pagecache.py -d inodes)')
 
   return parser.parse_args(argv)
 
-# TODO: refactor this with a common library file with analyze_metrics.py
-def _debug_print(*args, **kwargs):
-  """Print the args to sys.stderr if the --debug/-d flag was passed in."""
+def make_script_command_with_temp_output(script: str,
+                                         args: List[str],
+                                         **kwargs) -> Tuple[str, TextIO]:
+  """
+  Create a command to run a script given the args.
+  Appends --count <loop_count> --output <tmp-file-name>.
+  Returns a tuple (cmd, tmp_file)
+  """
+  tmp_output_file = tempfile.NamedTemporaryFile(mode='r')
+  cmd = [script] + args
+  for key, value in kwargs.items():
+    cmd += ['--%s' % (key), "%s" % (value)]
   if _debug:
-    print(*args, **kwargs, file=sys.stderr)
-
-def _expand_gen_repr(args):
-  """Like repr but any generator-like object has its iterator consumed
-  and then called repr on."""
-  new_args_list = []
-  for i in args:
-    # detect iterable objects that do not have their own override of __str__
-    if hasattr(i, '__iter__'):
-      to_str = getattr(i, '__str__')
-      if to_str.__objclass__ == object:
-        # the repr for a generator is just type+address, expand it out instead.
-        new_args_list.append([_expand_gen_repr([j])[0] for j in i])
-        continue
-    # normal case: uses the built-in to-string
-    new_args_list.append(i)
-  return new_args_list
-
-def _debug_print_gen(*args, **kwargs):
-  """Like _debug_print but will turn any iterable args into a list."""
-  if not _debug:
-    return
-
-  new_args_list = _expand_gen_repr(args)
-  _debug_print(*new_args_list, **kwargs)
-
-def _debug_print_nd(*args, **kwargs):
-  """Like _debug_print but will turn any NamedTuple-type args into a string."""
-  if not _debug:
-    return
-
-  new_args_list = []
-  for i in args:
-    if hasattr(i, '_field_types'):
-      new_args_list.append("%s: %s" %(i.__name__, i._field_types))
-    else:
-      new_args_list.append(i)
-
-  _debug_print(*new_args_list, **kwargs)
-
-def dict_lookup_any_key(dictionary: dict, *keys: List[Any]):
-  for k in keys:
-    if k in dictionary:
-      return dictionary[k]
-  raise KeyError("None of the keys %s were in the dictionary" %(keys))
-
-def generate_run_combinations(named_tuple: NamedTupleMeta[T], opts_dict: Dict[str, List[Optional[str]]])\
-    -> Iterable[T]:
-  """
-  Create all possible combinations given the values in opts_dict[named_tuple._fields].
-
-  :type T: type annotation for the named_tuple type.
-  :param named_tuple: named tuple type, whose fields are used to make combinations for
-  :param opts_dict: dictionary of keys to value list. keys correspond to the named_tuple fields.
-  :return: an iterable over named_tuple instances.
-  """
-  combinations_list = []
-  for k in named_tuple._fields:
-    # the key can be either singular or plural , e.g. 'package' or 'packages'
-    val = dict_lookup_any_key(opts_dict, k, k + "s")
-
-    # treat {'x': None} key value pairs as if it was [None]
-    # otherwise itertools.product throws an exception about not being able to iterate None.
-    combinations_list.append(val or [None])
-
-  _debug_print("opts_dict: ", opts_dict)
-  _debug_print_nd("named_tuple: ", named_tuple)
-  _debug_print("combinations_list: ", combinations_list)
-
-  for combo in itertools.product(*combinations_list):
-    yield named_tuple(*combo)
+    cmd += ['--verbose']
+  cmd = cmd + ["--output", tmp_output_file.name]
+  return cmd, tmp_output_file
 
 def key_to_cmdline_flag(key: str) -> str:
   """Convert key into a command line flag, e.g. 'foo-bars' -> '--foo-bar' """
@@ -176,230 +153,26 @@
     args.append(value)
   return args
 
-def generate_group_run_combinations(run_combinations: Iterable[NamedTuple], dst_nt: NamedTupleMeta[T])\
-    -> Iterable[Tuple[T, Iterable[NamedTuple]]]:
+def run_collector_script(collector_info: CollectorPackageInfo,
+                         inodes_path: str,
+                         timeout: int,
+                         simulate: bool) -> Tuple[bool, TextIO]:
+  """Run collector to collect prefetching trace. """
+  # collector_args = ["--package", package_name]
+  collector_args = as_run_command(collector_info)
+  # TODO: forward --wait_time for how long systrace runs?
+  # TODO: forward --trace_buffer_size for size of systrace buffer size?
+  collector_cmd, collector_tmp_output_file = make_script_command_with_temp_output(
+      _COLLECTOR_SCRIPT, collector_args, inodes=inodes_path)
 
-  def group_by_keys(src_nt):
-    src_d = src_nt._asdict()
-    # now remove the keys that aren't legal in dst.
-    for illegal_key in set(src_d.keys()) - set(dst_nt._fields):
-      if illegal_key in src_d:
-        del src_d[illegal_key]
+  collector_timeout = timeout and _COLLECTOR_TIMEOUT_MULTIPLIER * timeout
+  (collector_passed, collector_script_output) = \
+    cmd_utils.execute_arbitrary_command(collector_cmd,
+                                        collector_timeout,
+                                        shell=False,
+                                        simulate=simulate)
 
-    return dst_nt(**src_d)
-
-  for args_list_it in itertools.groupby(run_combinations, group_by_keys):
-    (group_key_value, args_it) = args_list_it
-    yield (group_key_value, args_it)
-
-class DataFrame:
-  """Table-like class for storing a 2D cells table with named columns."""
-  def __init__(self, data: Dict[str, List[object]] = {}):
-    """
-    Create a new DataFrame from a dictionary (keys = headers,
-    values = columns).
-    """
-    self._headers = [i for i in data.keys()]
-    self._rows = []
-
-    row_num = 0
-
-    def get_data_row(idx):
-      r = {}
-      for header, header_data in data.items():
-
-        if not len(header_data) > idx:
-          continue
-
-        r[header] = header_data[idx]
-
-      return r
-
-    while True:
-      row_dict = get_data_row(row_num)
-      if len(row_dict) == 0:
-        break
-
-      self._append_row(row_dict.keys(), row_dict.values())
-      row_num = row_num + 1
-
-  def concat_rows(self, other: 'DataFrame') -> None:
-    """
-    In-place concatenate rows of other into the rows of the
-    current DataFrame.
-
-    None is added in pre-existing cells if new headers
-    are introduced.
-    """
-    other_datas = other._data_only()
-
-    other_headers = other.headers
-
-    for d in other_datas:
-      self._append_row(other_headers, d)
-
-  def _append_row(self, headers: List[str], data: List[object]):
-    new_row = {k:v for k,v in zip(headers, data)}
-    self._rows.append(new_row)
-
-    for header in headers:
-      if not header in self._headers:
-        self._headers.append(header)
-
-  def __repr__(self):
-#     return repr(self._rows)
-    repr = ""
-
-    header_list = self._headers_only()
-
-    row_format = u""
-    for header in header_list:
-      row_format = row_format + u"{:>%d}" %(len(header) + 1)
-
-    repr = row_format.format(*header_list) + "\n"
-
-    for v in self._data_only():
-      repr = repr + row_format.format(*v) + "\n"
-
-    return repr
-
-  def __eq__(self, other):
-    if isinstance(other, self.__class__):
-      return self.headers == other.headers and self.data_table == other.data_table
-    else:
-      print("wrong instance", other.__class__)
-      return False
-
-  @property
-  def headers(self) -> List[str]:
-    return [i for i in self._headers_only()]
-
-  @property
-  def data_table(self) -> List[List[object]]:
-    return list(self._data_only())
-
-  @property
-  def data_table_transposed(self) -> List[List[object]]:
-    return list(self._transposed_data())
-
-  @property
-  def data_row_len(self) -> int:
-    return len(self._rows)
-
-  def data_row_at(self, idx) -> List[object]:
-    """
-    Return a single data row at the specified index (0th based).
-
-    Accepts negative indices, e.g. -1 is last row.
-    """
-    row_dict = self._rows[idx]
-    l = []
-
-    for h in self._headers_only():
-      l.append(row_dict.get(h)) # Adds None in blank spots.
-
-    return l
-
-  def copy(self) -> 'DataFrame':
-    """
-    Shallow copy of this DataFrame.
-    """
-    return self.repeat(count=0)
-
-  def repeat(self, count: int) -> 'DataFrame':
-    """
-    Returns a new DataFrame where each row of this dataframe is repeated count times.
-    A repeat of a row is adjacent to other repeats of that same row.
-    """
-    df = DataFrame()
-    df._headers = self._headers.copy()
-
-    rows = []
-    for row in self._rows:
-      for i in range(count):
-        rows.append(row.copy())
-
-    df._rows = rows
-
-    return df
-
-  def merge_data_columns(self, other: 'DataFrame'):
-    """
-    Merge self and another DataFrame by adding the data from other column-wise.
-    For any headers that are the same, data from 'other' is preferred.
-    """
-    for h in other._headers:
-      if not h in self._headers:
-        self._headers.append(h)
-
-    append_rows = []
-
-    for self_dict, other_dict in itertools.zip_longest(self._rows, other._rows):
-      if not self_dict:
-        d = {}
-        append_rows.append(d)
-      else:
-        d = self_dict
-
-      d_other = other_dict
-      if d_other:
-        for k,v in d_other.items():
-          d[k] = v
-
-    for r in append_rows:
-      self._rows.append(r)
-
-  def data_row_reduce(self, fnc) -> 'DataFrame':
-    """
-    Reduces the data row-wise by applying the fnc to each row (column-wise).
-    Empty cells are skipped.
-
-    fnc(Iterable[object]) -> object
-    fnc is applied over every non-empty cell in that column (descending row-wise).
-
-    Example:
-      DataFrame({'a':[1,2,3]}).data_row_reduce(sum) == DataFrame({'a':[6]})
-
-    Returns a new single-row DataFrame.
-    """
-    df = DataFrame()
-    df._headers = self._headers.copy()
-
-    def yield_by_column(header_key):
-      for row_dict in self._rows:
-        val = row_dict.get(header_key)
-        if val:
-          yield val
-
-    new_row_dict = {}
-    for h in df._headers:
-      cell_value = fnc(yield_by_column(h))
-      new_row_dict[h] = cell_value
-
-    df._rows = [new_row_dict]
-    return df
-
-  def _headers_only(self):
-    return self._headers
-
-  def _data_only(self):
-    row_len = len(self._rows)
-
-    for i in range(row_len):
-      yield self.data_row_at(i)
-
-  def _transposed_data(self):
-    return zip(*self._data_only())
-
-def parse_run_script_csv_file_flat(csv_file: TextIO) -> List[int]:
-  """Parse a CSV file full of integers into a flat int list."""
-  csv_reader = csv.reader(csv_file)
-  arr = []
-  for row in csv_reader:
-    for i in row:
-      if i:
-        arr.append(int(i))
-  return arr
+  return collector_passed, collector_tmp_output_file
 
 def parse_run_script_csv_file(csv_file: TextIO) -> DataFrame:
   """Parse a CSV file full of integers into a DataFrame."""
@@ -433,160 +206,52 @@
 
   return DataFrame(d)
 
-def make_script_command_with_temp_output(script: str, args: List[str], **kwargs)\
-    -> Tuple[str, TextIO]:
-  """
-  Create a command to run a script given the args.
-  Appends --count <loop_count> --output <tmp-file-name>.
-  Returns a tuple (cmd, tmp_file)
-  """
-  tmp_output_file = tempfile.NamedTemporaryFile(mode='r')
-  cmd = [script] + args
-  for key, value in kwargs.items():
-    cmd += ['--%s' %(key), "%s" %(value)]
-  if _debug:
-    cmd += ['--verbose']
-  cmd = cmd + ["--output", tmp_output_file.name]
-  return cmd, tmp_output_file
-
-async def _run_command(*args : List[str], timeout: Optional[int] = None) -> Tuple[int, bytes]:
-  # start child process
-  # NOTE: universal_newlines parameter is not supported
-  process = await asyncio.create_subprocess_exec(*args,
-      stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.STDOUT)
-
-  script_output = b""
-
-  _debug_print("[PID]", process.pid)
-
-#hack
-#  stdout, stderr = await process.communicate()
-#  return (process.returncode, stdout)
-
-  timeout_remaining = timeout
-  time_started = time.time()
-
-  # read line (sequence of bytes ending with b'\n') asynchronously
-  while True:
-    try:
-      line = await asyncio.wait_for(process.stdout.readline(), timeout_remaining)
-      _debug_print("[STDOUT]", line)
-      script_output += line
-
-      if timeout_remaining:
-        time_elapsed = time.time() - time_started
-        timeout_remaining = timeout - time_elapsed
-    except asyncio.TimeoutError:
-      _debug_print("[TIMEDOUT] Process ", process.pid)
-
-#      if process.returncode is not None:
-#        #_debug_print("[WTF] can-write-eof?", process.stdout.can_write_eof())
-#
-#        _debug_print("[TIMEDOUT] Process already terminated")
-#        (remaining_stdout, remaining_stderr) = await process.communicate()
-#        script_output += remaining_stdout
-#
-#        code = await process.wait()
-#        return (code, script_output)
-
-      _debug_print("[TIMEDOUT] Sending SIGTERM.")
-      process.terminate()
-
-      # 1 second timeout for process to handle SIGTERM nicely.
-      try:
-       (remaining_stdout, remaining_stderr) = await asyncio.wait_for(process.communicate(), 5)
-       script_output += remaining_stdout
-      except asyncio.TimeoutError:
-        _debug_print("[TIMEDOUT] Sending SIGKILL.")
-        process.kill()
-
-      # 1 second timeout to finish with SIGKILL.
-      try:
-        (remaining_stdout, remaining_stderr) = await asyncio.wait_for(process.communicate(), 5)
-        script_output += remaining_stdout
-      except asyncio.TimeoutError:
-        # give up, this will leave a zombie process.
-        _debug_print("[TIMEDOUT] SIGKILL failed for process ", process.pid)
-        time.sleep(100)
-        #await process.wait()
-
-      return (-1, script_output)
-    else:
-      if not line: # EOF
-        break
-
-      #if process.returncode is not None:
-      #  _debug_print("[WTF] can-write-eof?", process.stdout.can_write_eof())
-      #  process.stdout.write_eof()
-
-      #if process.stdout.at_eof():
-      #  break
-
-  code = await process.wait() # wait for child process to exit
-  return (code, script_output)
-
-def execute_arbitrary_command(cmd: List[str], simulate: bool, timeout: Optional[int]) -> Tuple[bool, str]:
-  if simulate:
-    print(" ".join(cmd))
-    return (True, "")
-  else:
-    _debug_print("[EXECUTE]", cmd)
-
-    # block until either command finishes or the timeout occurs.
-    loop = asyncio.get_event_loop()
-    (return_code, script_output) = loop.run_until_complete(_run_command(*cmd, timeout=timeout))
-
-    script_output = script_output.decode() # convert bytes to str
-
-    passed = (return_code == 0)
-    _debug_print("[$?]", return_code)
-    if not passed:
-      print("[FAILED, code:%s]" %(return_code), script_output, file=sys.stderr)
-
-    return (passed, script_output)
-
-def execute_run_combos(grouped_run_combos: Iterable[Tuple[CollectorPackageInfo, Iterable[RunCommandArgs]]], simulate: bool, inodes_path: str, timeout: int, loop_count: int, need_trace: bool):
+def execute_run_combos(
+    grouped_run_combos: Iterable[Tuple[CollectorPackageInfo, Iterable[
+      run_app_with_prefetch.RunCommandArgs]]],
+    simulate: bool,
+    inodes_path: str,
+    timeout: int):
   # nothing will work if the screen isn't unlocked first.
-  execute_arbitrary_command([_UNLOCK_SCREEN_SCRIPT], simulate, timeout)
+  cmd_utils.execute_arbitrary_command([_UNLOCK_SCREEN_SCRIPT],
+                                      timeout,
+                                      simulate=simulate,
+                                      shell=False)
 
   for collector_info, run_combos in grouped_run_combos:
-    #collector_args = ["--package", package_name]
-    collector_args = as_run_command(collector_info)
-    # TODO: forward --wait_time for how long systrace runs?
-    # TODO: forward --trace_buffer_size for size of systrace buffer size?
-    collector_cmd, collector_tmp_output_file = make_script_command_with_temp_output(_COLLECTOR_SCRIPT, collector_args, inodes=inodes_path)
+    for combos in run_combos:
+      args = as_run_command(combos)
+      if combos.readahead in _TRACING_READAHEADS:
+        passed, collector_tmp_output_file = run_collector_script(collector_info,
+                                                                 inodes_path,
+                                                                 timeout,
+                                                                 simulate)
+        combos = combos._replace(input=collector_tmp_output_file.name)
 
-    with collector_tmp_output_file:
-      collector_passed = True
-      if need_trace:
-        collector_timeout = timeout and _COLLECTOR_TIMEOUT_MULTIPLIER * timeout
-        (collector_passed, collector_script_output) = execute_arbitrary_command(collector_cmd, simulate, collector_timeout)
-        # TODO: consider to print a ; collector wrote file to <...> into the CSV file so we know it was ran.
+      print_utils.debug_print(combos)
+      output = run_app_with_prefetch.run_test(combos)
 
-      for combos in run_combos:
-        args = as_run_command(combos)
+      yield DataFrame(dict((x, [y]) for x, y in output)) if output else None
 
-        cmd, tmp_output_file = make_script_command_with_temp_output(_RUN_SCRIPT, args, count=loop_count, input=collector_tmp_output_file.name)
-        with tmp_output_file:
-          (passed, script_output) = execute_arbitrary_command(cmd, simulate, timeout)
-          parsed_output = simulate and DataFrame({'fake_ms':[1,2,3]}) or parse_run_script_csv_file(tmp_output_file)
-          yield (passed, script_output, parsed_output)
-
-def gather_results(commands: Iterable[Tuple[bool, str, DataFrame]], key_list: List[str], value_list: List[Tuple[str, ...]]):
-  _debug_print("gather_results: key_list = ", key_list)
-#  yield key_list + ["time(ms)"]
-
+def gather_results(commands: Iterable[Tuple[DataFrame]],
+                   key_list: List[str], value_list: List[Tuple[str, ...]]):
+  print_utils.debug_print("gather_results: key_list = ", key_list)
   stringify_none = lambda s: s is None and "<none>" or s
+  #  yield key_list + ["time(ms)"]
+  for (run_result_list, values) in itertools.zip_longest(commands, value_list):
+    print_utils.debug_print("run_result_list = ", run_result_list)
+    print_utils.debug_print("values = ", values)
 
-  for ((passed, script_output, run_result_list), values) in itertools.zip_longest(commands, value_list):
-    _debug_print("run_result_list = ", run_result_list)
-    _debug_print("values = ", values)
-    if not passed:
+    if not run_result_list:
       continue
 
     # RunCommandArgs(package='com.whatever', readahead='warm', compiler_filter=None)
     # -> {'package':['com.whatever'], 'readahead':['warm'], 'compiler_filter':[None]}
-    values_dict = {k:[v] for k,v in values._asdict().items()}
+    values_dict = {}
+    for k, v in values._asdict().items():
+      if not k in key_list:
+        continue
+      values_dict[k] = [stringify_none(v)]
 
     values_df = DataFrame(values_dict)
     # project 'values_df' to be same number of rows as run_result_list.
@@ -598,7 +263,6 @@
     yield values_df
 
 def eval_and_save_to_csv(output, annotated_result_values):
-
   printed_header = False
 
   csv_writer = csv.writer(output)
@@ -610,9 +274,22 @@
       # TODO: what about when headers change?
 
     for data_row in row.data_table:
+      data_row = [d for d in data_row]
       csv_writer.writerow(data_row)
 
-    output.flush() # see the output live.
+    output.flush()  # see the output live.
+
+def coerce_to_list(opts: dict):
+  """Tranform values of the dictionary to list.
+  For example:
+  1 -> [1], None -> [None], [1,2,3] -> [1,2,3]
+  [[1],[2]] -> [[1],[2]], {1:1, 2:2} -> [{1:1, 2:2}]
+  """
+  result = {}
+  for key in opts:
+    val = opts[key]
+    result[key] = val if issubclass(type(val), list) else [val]
+  return result
 
 def main():
   global _debug
@@ -621,26 +298,34 @@
   _debug = opts.debug
   if _DEBUG_FORCE is not None:
     _debug = _DEBUG_FORCE
-  _debug_print("parsed options: ", opts)
-  need_trace = not not set(opts.readaheads).intersection(set(_TRACING_READAHEADS))
-  if need_trace and not opts.inodes:
-    print("Error: Missing -in/--inodes, required when using a readahead of %s" %(_TRACING_READAHEADS), file=sys.stderr)
-    return 1
+
+  print_utils.DEBUG = _debug
+  cmd_utils.SIMULATE = opts.simulate
+
+  print_utils.debug_print("parsed options: ", opts)
 
   output_file = opts.output and open(opts.output, 'w') or sys.stdout
 
-  combos = lambda: generate_run_combinations(RunCommandArgs, vars(opts))
-  _debug_print_gen("run combinations: ", combos())
+  combos = lambda: args_utils.generate_run_combinations(
+      run_app_with_prefetch.RunCommandArgs,
+      coerce_to_list(vars(opts)),
+      opts.loop_count)
+  print_utils.debug_print_gen("run combinations: ", combos())
 
-  grouped_combos = lambda: generate_group_run_combinations(combos(), CollectorPackageInfo)
-  _debug_print_gen("grouped run combinations: ", grouped_combos())
+  grouped_combos = lambda: args_utils.generate_group_run_combinations(combos(),
+                                                                      CollectorPackageInfo)
 
-  exec = execute_run_combos(grouped_combos(), opts.simulate, opts.inodes, opts.timeout, opts.loop_count, need_trace)
+  print_utils.debug_print_gen("grouped run combinations: ", grouped_combos())
+  exec = execute_run_combos(grouped_combos(),
+                            opts.simulate,
+                            opts.inodes,
+                            opts.timeout)
+
   results = gather_results(exec, _COMBINATORIAL_OPTIONS, combos())
+
   eval_and_save_to_csv(output_file, results)
 
-  return 0
-
+  return 1
 
 if __name__ == '__main__':
   sys.exit(main())
diff --git a/startop/scripts/app_startup/app_startup_runner_test.py b/startop/scripts/app_startup/app_startup_runner_test.py
index fd81667..9aa7014 100755
--- a/startop/scripts/app_startup/app_startup_runner_test.py
+++ b/startop/scripts/app_startup/app_startup_runner_test.py
@@ -31,18 +31,17 @@
 See also https://docs.pytest.org/en/latest/usage.html
 """
 
-# global imports
-from contextlib import contextmanager
 import io
 import shlex
 import sys
 import typing
-
-# pip imports
-import pytest
+# global imports
+from contextlib import contextmanager
 
 # local imports
 import app_startup_runner as asr
+# pip imports
+import pytest
 
 #
 # Argument Parsing Helpers
@@ -91,7 +90,8 @@
   """
   # Combine it with all of the "optional" parameters' default values.
   """
-  d = {'compiler_filters': None, 'simulate': False, 'debug': False, 'output': None, 'timeout': None, 'loop_count': 1, 'inodes': None}
+  d = {'compiler_filters': None, 'simulate': False, 'debug': False,
+       'output': None, 'timeout': 10, 'loop_count': 1, 'inodes': None}
   d.update(kwargs)
   return d
 
@@ -111,7 +111,7 @@
   in default_mock_dict_for_parsed_args.
   """
   req = "--package com.fake.package --readahead warm"
-  return parse_args("%s %s" %(req, str))
+  return parse_args("%s %s" % (req, str))
 
 def test_argparse():
   # missing arguments
@@ -124,15 +124,22 @@
   # required arguments are parsed correctly
   ad = default_dict_for_parsed_args  # assert dict
 
-  assert parse_args("--package xyz --readahead warm") == ad(packages=['xyz'], readaheads=['warm'])
-  assert parse_args("-p xyz -r warm") == ad(packages=['xyz'], readaheads=['warm'])
+  assert parse_args("--package xyz --readahead warm") == ad(packages=['xyz'],
+                                                            readaheads=['warm'])
+  assert parse_args("-p xyz -r warm") == ad(packages=['xyz'],
+                                            readaheads=['warm'])
 
-  assert parse_args("-p xyz -r warm -s") == ad(packages=['xyz'], readaheads=['warm'], simulate=True)
-  assert parse_args("-p xyz -r warm --simulate") == ad(packages=['xyz'], readaheads=['warm'], simulate=True)
+  assert parse_args("-p xyz -r warm -s") == ad(packages=['xyz'],
+                                               readaheads=['warm'],
+                                               simulate=True)
+  assert parse_args("-p xyz -r warm --simulate") == ad(packages=['xyz'],
+                                                       readaheads=['warm'],
+                                                       simulate=True)
 
   # optional arguments are parsed correctly.
   mad = default_mock_dict_for_parsed_args  # mock assert dict
-  assert parse_optional_args("--output filename.csv") == mad(output='filename.csv')
+  assert parse_optional_args("--output filename.csv") == mad(
+    output='filename.csv')
   assert parse_optional_args("-o filename.csv") == mad(output='filename.csv')
 
   assert parse_optional_args("--timeout 123") == mad(timeout=123)
@@ -145,36 +152,6 @@
   assert parse_optional_args("-in baz") == mad(inodes="baz")
 
 
-def generate_run_combinations(*args):
-  # expand out the generator values so that assert x == y works properly.
-  return [i for i in asr.generate_run_combinations(*args)]
-
-def test_generate_run_combinations():
-  blank_nd = typing.NamedTuple('Blank')
-  assert generate_run_combinations(blank_nd, {}) == [()], "empty"
-  assert generate_run_combinations(blank_nd, {'a' : ['a1', 'a2']}) == [()], "empty filter"
-  a_nd = typing.NamedTuple('A', [('a', str)])
-  assert generate_run_combinations(a_nd, {'a': None}) == [(None,)], "None"
-  assert generate_run_combinations(a_nd, {'a': ['a1', 'a2']}) == [('a1',), ('a2',)], "one item"
-  assert generate_run_combinations(a_nd,
-                                   {'a' : ['a1', 'a2'], 'b': ['b1', 'b2']}) == [('a1',), ('a2',)],\
-      "one item filter"
-  ab_nd = typing.NamedTuple('AB', [('a', str), ('b', str)])
-  assert generate_run_combinations(ab_nd,
-                                   {'a': ['a1', 'a2'],
-                                    'b': ['b1', 'b2']}) == [ab_nd('a1', 'b1'),
-                                                            ab_nd('a1', 'b2'),
-                                                            ab_nd('a2', 'b1'),
-                                                            ab_nd('a2', 'b2')],\
-      "two items"
-
-  assert generate_run_combinations(ab_nd,
-                                   {'as': ['a1', 'a2'],
-                                    'bs': ['b1', 'b2']}) == [ab_nd('a1', 'b1'),
-                                                             ab_nd('a1', 'b2'),
-                                                             ab_nd('a2', 'b1'),
-                                                             ab_nd('a2', 'b2')],\
-      "two items plural"
 
 def test_key_to_cmdline_flag():
   assert asr.key_to_cmdline_flag("abc") == "--abc"
@@ -182,138 +159,18 @@
   assert asr.key_to_cmdline_flag("ba_r") == "--ba-r"
   assert asr.key_to_cmdline_flag("ba_zs") == "--ba-z"
 
-
 def test_make_script_command_with_temp_output():
-  cmd_str, tmp_file = asr.make_script_command_with_temp_output("fake_script", args=[], count=1)
+  cmd_str, tmp_file = asr.make_script_command_with_temp_output("fake_script",
+                                                               args=[], count=1)
   with tmp_file:
     assert cmd_str == ["fake_script", "--count", "1", "--output", tmp_file.name]
 
-  cmd_str, tmp_file = asr.make_script_command_with_temp_output("fake_script", args=['a', 'b'], count=2)
+  cmd_str, tmp_file = asr.make_script_command_with_temp_output("fake_script",
+                                                               args=['a', 'b'],
+                                                               count=2)
   with tmp_file:
-    assert cmd_str == ["fake_script", "a", "b", "--count", "2", "--output", tmp_file.name]
-
-def test_parse_run_script_csv_file_flat():
-  # empty file -> empty list
-  f = io.StringIO("")
-  assert asr.parse_run_script_csv_file_flat(f) == []
-
-  # common case
-  f = io.StringIO("1,2,3")
-  assert asr.parse_run_script_csv_file_flat(f) == [1,2,3]
-
-  # ignore trailing comma
-  f = io.StringIO("1,2,3,4,5,")
-  assert asr.parse_run_script_csv_file_flat(f) == [1,2,3,4,5]
-
-def test_data_frame():
-  # trivial empty data frame
-  df = asr.DataFrame()
-  assert df.headers == []
-  assert df.data_table == []
-  assert df.data_table_transposed == []
-
-  # common case, same number of values in each place.
-  df = asr.DataFrame({'TotalTime_ms':[1,2,3], 'Displayed_ms':[4,5,6]})
-  assert df.headers == ['TotalTime_ms', 'Displayed_ms']
-  assert df.data_table == [[1, 4], [2, 5], [3, 6]]
-  assert df.data_table_transposed == [(1, 2, 3), (4, 5, 6)]
-
-  # varying num values.
-  df = asr.DataFrame({'many':[1,2], 'none': []})
-  assert df.headers == ['many', 'none']
-  assert df.data_table == [[1, None], [2, None]]
-  assert df.data_table_transposed == [(1, 2), (None, None)]
-
-  df = asr.DataFrame({'many':[], 'none': [1,2]})
-  assert df.headers == ['many', 'none']
-  assert df.data_table == [[None, 1], [None, 2]]
-  assert df.data_table_transposed == [(None, None), (1, 2)]
-
-  # merge multiple data frames
-  df = asr.DataFrame()
-  df.concat_rows(asr.DataFrame())
-  assert df.headers == []
-  assert df.data_table == []
-  assert df.data_table_transposed == []
-
-  df = asr.DataFrame()
-  df2 = asr.DataFrame({'TotalTime_ms':[1,2,3], 'Displayed_ms':[4,5,6]})
-
-  df.concat_rows(df2)
-  assert df.headers == ['TotalTime_ms', 'Displayed_ms']
-  assert df.data_table == [[1, 4], [2, 5], [3, 6]]
-  assert df.data_table_transposed == [(1, 2, 3), (4, 5, 6)]
-
-  df = asr.DataFrame({'TotalTime_ms':[1,2]})
-  df2 = asr.DataFrame({'Displayed_ms':[4,5]})
-
-  df.concat_rows(df2)
-  assert df.headers == ['TotalTime_ms', 'Displayed_ms']
-  assert df.data_table == [[1, None], [2, None], [None, 4], [None, 5]]
-
-  df = asr.DataFrame({'TotalTime_ms':[1,2]})
-  df2 = asr.DataFrame({'TotalTime_ms': [3, 4], 'Displayed_ms':[5, 6]})
-
-  df.concat_rows(df2)
-  assert df.headers == ['TotalTime_ms', 'Displayed_ms']
-  assert df.data_table == [[1, None], [2, None], [3, 5], [4, 6]]
-
-  # data_row_at
-  df = asr.DataFrame({'TotalTime_ms':[1,2,3], 'Displayed_ms':[4,5,6]})
-  assert df.data_row_at(-1) == [3,6]
-  assert df.data_row_at(2) == [3,6]
-  assert df.data_row_at(1) == [2,5]
-
-  # repeat
-  df = asr.DataFrame({'TotalTime_ms':[1], 'Displayed_ms':[4]})
-  df2 = asr.DataFrame({'TotalTime_ms':[1,1,1], 'Displayed_ms':[4,4,4]})
-  assert df.repeat(3) == df2
-
-  # repeat
-  df = asr.DataFrame({'TotalTime_ms':[1,1,1], 'Displayed_ms':[4,4,4]})
-  assert df.data_row_len == 3
-  df = asr.DataFrame({'TotalTime_ms':[1,1]})
-  assert df.data_row_len == 2
-
-  # repeat
-  df = asr.DataFrame({'TotalTime_ms':[1,1,1], 'Displayed_ms':[4,4,4]})
-  assert df.data_row_len == 3
-  df = asr.DataFrame({'TotalTime_ms':[1,1]})
-  assert df.data_row_len == 2
-
-  # data_row_reduce
-  df = asr.DataFrame({'TotalTime_ms':[1,1,1], 'Displayed_ms':[4,4,4]})
-  df_sum = asr.DataFrame({'TotalTime_ms':[3], 'Displayed_ms':[12]})
-  assert df.data_row_reduce(sum) == df_sum
-
-  # merge_data_columns
-  df = asr.DataFrame({'TotalTime_ms':[1,2,3]})
-  df2 = asr.DataFrame({'Displayed_ms':[3,4,5,6]})
-
-  df.merge_data_columns(df2)
-  assert df == asr.DataFrame({'TotalTime_ms':[1,2,3], 'Displayed_ms':[3,4,5,6]})
-
-  df = asr.DataFrame({'TotalTime_ms':[1,2,3]})
-  df2 = asr.DataFrame({'Displayed_ms':[3,4]})
-
-  df.merge_data_columns(df2)
-  assert df == asr.DataFrame({'TotalTime_ms':[1,2,3], 'Displayed_ms':[3,4]})
-
-  df = asr.DataFrame({'TotalTime_ms':[1,2,3]})
-  df2 = asr.DataFrame({'TotalTime_ms':[10,11]})
-
-  df.merge_data_columns(df2)
-  assert df == asr.DataFrame({'TotalTime_ms':[10,11,3]})
-
-  df = asr.DataFrame({'TotalTime_ms':[]})
-  df2 = asr.DataFrame({'TotalTime_ms':[10,11]})
-
-  df.merge_data_columns(df2)
-  assert df == asr.DataFrame({'TotalTime_ms':[10,11]})
-
-
-
-
+    assert cmd_str == ["fake_script", "a", "b", "--count", "2", "--output",
+                       tmp_file.name]
 
 def test_parse_run_script_csv_file():
   # empty file -> empty list
diff --git a/startop/scripts/app_startup/lib/adb_utils.py b/startop/scripts/app_startup/lib/adb_utils.py
index 00e2e99..0e0065d 100644
--- a/startop/scripts/app_startup/lib/adb_utils.py
+++ b/startop/scripts/app_startup/lib/adb_utils.py
@@ -16,12 +16,18 @@
 
 """Helper util libraries for calling adb command line."""
 
+import datetime
 import os
+import re
 import sys
+import time
+from typing import Optional
 
 sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(
   os.path.abspath(__file__)))))
 import lib.cmd_utils as cmd_utils
+import lib.logcat_utils as logcat_utils
+
 
 def logcat_save_timestamp() -> str:
   """Gets the current logcat timestamp.
@@ -54,10 +60,48 @@
   cmd_utils.run_shell_command('adb wait-for-device')
 
 def pkill(procname: str):
-  """Kills a process in device by its package name."""
+  """Kills a process on device specified by the substring pattern in procname"""
   _, pids = cmd_utils.run_shell_command('adb shell ps | grep "{}" | '
                                         'awk \'{{print $2;}}\''.
                                           format(procname))
 
   for pid in pids.split('\n'):
-    cmd_utils.run_adb_shell_command('kill {}'.format(pid))
+    pid = pid.strip()
+    if pid:
+      passed,_ = cmd_utils.run_adb_shell_command('kill {}'.format(pid))
+      time.sleep(1)
+
+def parse_time_to_milliseconds(time: str) -> int:
+  """Parses the time string to milliseconds."""
+  # Example: +1s56ms, +56ms
+  regex = r'\+((?P<second>\d+?)s)?(?P<millisecond>\d+?)ms'
+  result = re.search(regex, time)
+  second = 0
+  if result.group('second'):
+    second = int(result.group('second'))
+  ms = int(result.group('millisecond'))
+  return second * 1000 + ms
+
+def blocking_wait_for_logcat_displayed_time(timestamp: datetime.datetime,
+                                            package: str,
+                                            timeout: int) -> Optional[int]:
+  """Parses the displayed time in the logcat.
+
+  Returns:
+    the displayed time.
+  """
+  pattern = re.compile('.*ActivityTaskManager: Displayed {}.*'.format(package))
+  # 2019-07-02 22:28:34.469453349 -> 2019-07-02 22:28:34.469453
+  timestamp = datetime.datetime.strptime(timestamp[:-3],
+                                         '%Y-%m-%d %H:%M:%S.%f')
+  timeout_dt = timestamp + datetime.timedelta(0, timeout)
+  # 2019-07-01 14:54:21.946 27365 27392 I ActivityTaskManager:
+  # Displayed com.android.settings/.Settings: +927ms
+  result = logcat_utils.blocking_wait_for_logcat_pattern(timestamp,
+                                                         pattern,
+                                                         timeout_dt)
+  if not result or not '+' in result:
+    return None
+  displayed_time = result[result.rfind('+'):]
+
+  return parse_time_to_milliseconds(displayed_time)
\ No newline at end of file
diff --git a/startop/scripts/app_startup/lib/adb_utils_test.py b/startop/scripts/app_startup/lib/adb_utils_test.py
new file mode 100644
index 0000000..e590fed
--- /dev/null
+++ b/startop/scripts/app_startup/lib/adb_utils_test.py
@@ -0,0 +1,16 @@
+import adb_utils
+
+# pip imports
+import pytest
+
+def test_parse_time_to_milliseconds():
+  # Act
+  result1 = adb_utils.parse_time_to_milliseconds('+1s7ms')
+  result2 = adb_utils.parse_time_to_milliseconds('+523ms')
+
+  # Assert
+  assert result1 == 1007
+  assert result2 == 523
+
+if __name__ == '__main__':
+  pytest.main()
diff --git a/startop/scripts/app_startup/lib/args_utils.py b/startop/scripts/app_startup/lib/args_utils.py
new file mode 100644
index 0000000..080f3b5
--- /dev/null
+++ b/startop/scripts/app_startup/lib/args_utils.py
@@ -0,0 +1,77 @@
+import itertools
+import os
+import sys
+from typing import Any, Callable, Dict, Iterable, List, NamedTuple, Tuple, \
+    TypeVar, Optional
+
+# local import
+sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(
+    os.path.abspath(__file__)))))
+import lib.print_utils as print_utils
+
+T = TypeVar('T')
+NamedTupleMeta = Callable[
+    ..., T]  # approximation of a (S : NamedTuple<T> where S() == T) metatype.
+FilterFuncType = Callable[[NamedTuple], bool]
+
+def dict_lookup_any_key(dictionary: dict, *keys: List[Any]):
+  for k in keys:
+    if k in dictionary:
+      return dictionary[k]
+
+
+  print_utils.debug_print("None of the keys {} were in the dictionary".format(
+      keys))
+  return [None]
+
+def generate_run_combinations(named_tuple: NamedTupleMeta[T],
+                              opts_dict: Dict[str, List[Optional[object]]],
+                              loop_count: int = 1) -> Iterable[T]:
+  """
+  Create all possible combinations given the values in opts_dict[named_tuple._fields].
+
+  :type T: type annotation for the named_tuple type.
+  :param named_tuple: named tuple type, whose fields are used to make combinations for
+  :param opts_dict: dictionary of keys to value list. keys correspond to the named_tuple fields.
+  :param loop_count: number of repetitions.
+  :return: an iterable over named_tuple instances.
+  """
+  combinations_list = []
+  for k in named_tuple._fields:
+    # the key can be either singular or plural , e.g. 'package' or 'packages'
+    val = dict_lookup_any_key(opts_dict, k, k + "s")
+
+    # treat {'x': None} key value pairs as if it was [None]
+    # otherwise itertools.product throws an exception about not being able to iterate None.
+    combinations_list.append(val or [None])
+
+  print_utils.debug_print("opts_dict: ", opts_dict)
+  print_utils.debug_print_nd("named_tuple: ", named_tuple)
+  print_utils.debug_print("combinations_list: ", combinations_list)
+
+  for i in range(loop_count):
+    for combo in itertools.product(*combinations_list):
+      yield named_tuple(*combo)
+
+def filter_run_combinations(named_tuple: NamedTuple,
+                            filters: List[FilterFuncType]) -> bool:
+  for filter in filters:
+    if filter(named_tuple):
+      return False
+  return True
+
+def generate_group_run_combinations(run_combinations: Iterable[NamedTuple],
+                                    dst_nt: NamedTupleMeta[T]) \
+    -> Iterable[Tuple[T, Iterable[NamedTuple]]]:
+  def group_by_keys(src_nt):
+    src_d = src_nt._asdict()
+    # now remove the keys that aren't legal in dst.
+    for illegal_key in set(src_d.keys()) - set(dst_nt._fields):
+      if illegal_key in src_d:
+        del src_d[illegal_key]
+
+    return dst_nt(**src_d)
+
+  for args_list_it in itertools.groupby(run_combinations, group_by_keys):
+    (group_key_value, args_it) = args_list_it
+    yield (group_key_value, args_it)
diff --git a/startop/scripts/app_startup/lib/args_utils_test.py b/startop/scripts/app_startup/lib/args_utils_test.py
new file mode 100644
index 0000000..4b7e0fa
--- /dev/null
+++ b/startop/scripts/app_startup/lib/args_utils_test.py
@@ -0,0 +1,58 @@
+#!/usr/bin/env python3
+#
+# Copyright 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.
+#
+
+"""Unit tests for the args_utils.py script."""
+
+import typing
+
+import args_utils
+
+def generate_run_combinations(*args):
+  # expand out the generator values so that assert x == y works properly.
+  return [i for i in args_utils.generate_run_combinations(*args)]
+
+def test_generate_run_combinations():
+  blank_nd = typing.NamedTuple('Blank')
+  assert generate_run_combinations(blank_nd, {}, 1) == [()], "empty"
+  assert generate_run_combinations(blank_nd, {'a': ['a1', 'a2']}) == [
+    ()], "empty filter"
+  a_nd = typing.NamedTuple('A', [('a', str)])
+  assert generate_run_combinations(a_nd, {'a': None}) == [(None,)], "None"
+  assert generate_run_combinations(a_nd, {'a': ['a1', 'a2']}) == [('a1',), (
+    'a2',)], "one item"
+  assert generate_run_combinations(a_nd,
+                                   {'a': ['a1', 'a2'], 'b': ['b1', 'b2']}) == [
+           ('a1',), ('a2',)], \
+    "one item filter"
+  assert generate_run_combinations(a_nd, {'a': ['a1', 'a2']}, 2) == [('a1',), (
+    'a2',), ('a1',), ('a2',)], "one item"
+  ab_nd = typing.NamedTuple('AB', [('a', str), ('b', str)])
+  assert generate_run_combinations(ab_nd,
+                                   {'a': ['a1', 'a2'],
+                                    'b': ['b1', 'b2']}) == [ab_nd('a1', 'b1'),
+                                                            ab_nd('a1', 'b2'),
+                                                            ab_nd('a2', 'b1'),
+                                                            ab_nd('a2', 'b2')], \
+    "two items"
+
+  assert generate_run_combinations(ab_nd,
+                                   {'as': ['a1', 'a2'],
+                                    'bs': ['b1', 'b2']}) == [ab_nd('a1', 'b1'),
+                                                             ab_nd('a1', 'b2'),
+                                                             ab_nd('a2', 'b1'),
+                                                             ab_nd('a2', 'b2')], \
+    "two items plural"
diff --git a/startop/scripts/app_startup/lib/data_frame.py b/startop/scripts/app_startup/lib/data_frame.py
new file mode 100644
index 0000000..20a2308
--- /dev/null
+++ b/startop/scripts/app_startup/lib/data_frame.py
@@ -0,0 +1,201 @@
+import itertools
+from typing import Dict, List
+
+class DataFrame:
+  """Table-like class for storing a 2D cells table with named columns."""
+  def __init__(self, data: Dict[str, List[object]] = {}):
+    """
+    Create a new DataFrame from a dictionary (keys = headers,
+    values = columns).
+    """
+    self._headers = [i for i in data.keys()]
+    self._rows = []
+
+    row_num = 0
+
+    def get_data_row(idx):
+      r = {}
+      for header, header_data in data.items():
+
+        if not len(header_data) > idx:
+          continue
+
+        r[header] = header_data[idx]
+
+      return r
+
+    while True:
+      row_dict = get_data_row(row_num)
+      if len(row_dict) == 0:
+        break
+
+      self._append_row(row_dict.keys(), row_dict.values())
+      row_num = row_num + 1
+
+  def concat_rows(self, other: 'DataFrame') -> None:
+    """
+    In-place concatenate rows of other into the rows of the
+    current DataFrame.
+
+    None is added in pre-existing cells if new headers
+    are introduced.
+    """
+    other_datas = other._data_only()
+
+    other_headers = other.headers
+
+    for d in other_datas:
+      self._append_row(other_headers, d)
+
+  def _append_row(self, headers: List[str], data: List[object]):
+    new_row = {k:v for k,v in zip(headers, data)}
+    self._rows.append(new_row)
+
+    for header in headers:
+      if not header in self._headers:
+        self._headers.append(header)
+
+  def __repr__(self):
+#     return repr(self._rows)
+    repr = ""
+
+    header_list = self._headers_only()
+
+    row_format = u""
+    for header in header_list:
+      row_format = row_format + u"{:>%d}" %(len(header) + 1)
+
+    repr = row_format.format(*header_list) + "\n"
+
+    for v in self._data_only():
+      repr = repr + row_format.format(*v) + "\n"
+
+    return repr
+
+  def __eq__(self, other):
+    if isinstance(other, self.__class__):
+      return self.headers == other.headers and self.data_table == other.data_table
+    else:
+      print("wrong instance", other.__class__)
+      return False
+
+  @property
+  def headers(self) -> List[str]:
+    return [i for i in self._headers_only()]
+
+  @property
+  def data_table(self) -> List[List[object]]:
+    return list(self._data_only())
+
+  @property
+  def data_table_transposed(self) -> List[List[object]]:
+    return list(self._transposed_data())
+
+  @property
+  def data_row_len(self) -> int:
+    return len(self._rows)
+
+  def data_row_at(self, idx) -> List[object]:
+    """
+    Return a single data row at the specified index (0th based).
+
+    Accepts negative indices, e.g. -1 is last row.
+    """
+    row_dict = self._rows[idx]
+    l = []
+
+    for h in self._headers_only():
+      l.append(row_dict.get(h)) # Adds None in blank spots.
+
+    return l
+
+  def copy(self) -> 'DataFrame':
+    """
+    Shallow copy of this DataFrame.
+    """
+    return self.repeat(count=0)
+
+  def repeat(self, count: int) -> 'DataFrame':
+    """
+    Returns a new DataFrame where each row of this dataframe is repeated count times.
+    A repeat of a row is adjacent to other repeats of that same row.
+    """
+    df = DataFrame()
+    df._headers = self._headers.copy()
+
+    rows = []
+    for row in self._rows:
+      for i in range(count):
+        rows.append(row.copy())
+
+    df._rows = rows
+
+    return df
+
+  def merge_data_columns(self, other: 'DataFrame'):
+    """
+    Merge self and another DataFrame by adding the data from other column-wise.
+    For any headers that are the same, data from 'other' is preferred.
+    """
+    for h in other._headers:
+      if not h in self._headers:
+        self._headers.append(h)
+
+    append_rows = []
+
+    for self_dict, other_dict in itertools.zip_longest(self._rows, other._rows):
+      if not self_dict:
+        d = {}
+        append_rows.append(d)
+      else:
+        d = self_dict
+
+      d_other = other_dict
+      if d_other:
+        for k,v in d_other.items():
+          d[k] = v
+
+    for r in append_rows:
+      self._rows.append(r)
+
+  def data_row_reduce(self, fnc) -> 'DataFrame':
+    """
+    Reduces the data row-wise by applying the fnc to each row (column-wise).
+    Empty cells are skipped.
+
+    fnc(Iterable[object]) -> object
+    fnc is applied over every non-empty cell in that column (descending row-wise).
+
+    Example:
+      DataFrame({'a':[1,2,3]}).data_row_reduce(sum) == DataFrame({'a':[6]})
+
+    Returns a new single-row DataFrame.
+    """
+    df = DataFrame()
+    df._headers = self._headers.copy()
+
+    def yield_by_column(header_key):
+      for row_dict in self._rows:
+        val = row_dict.get(header_key)
+        if val:
+          yield val
+
+    new_row_dict = {}
+    for h in df._headers:
+      cell_value = fnc(yield_by_column(h))
+      new_row_dict[h] = cell_value
+
+    df._rows = [new_row_dict]
+    return df
+
+  def _headers_only(self):
+    return self._headers
+
+  def _data_only(self):
+    row_len = len(self._rows)
+
+    for i in range(row_len):
+      yield self.data_row_at(i)
+
+  def _transposed_data(self):
+    return zip(*self._data_only())
\ No newline at end of file
diff --git a/startop/scripts/app_startup/lib/data_frame_test.py b/startop/scripts/app_startup/lib/data_frame_test.py
new file mode 100644
index 0000000..1cbc1cb
--- /dev/null
+++ b/startop/scripts/app_startup/lib/data_frame_test.py
@@ -0,0 +1,128 @@
+#!/usr/bin/env python3
+#
+# Copyright 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.
+#
+
+"""Unit tests for the data_frame.py script."""
+
+from data_frame import DataFrame
+
+def test_data_frame():
+  # trivial empty data frame
+  df = DataFrame()
+  assert df.headers == []
+  assert df.data_table == []
+  assert df.data_table_transposed == []
+
+  # common case, same number of values in each place.
+  df = DataFrame({'TotalTime_ms': [1, 2, 3], 'Displayed_ms': [4, 5, 6]})
+  assert df.headers == ['TotalTime_ms', 'Displayed_ms']
+  assert df.data_table == [[1, 4], [2, 5], [3, 6]]
+  assert df.data_table_transposed == [(1, 2, 3), (4, 5, 6)]
+
+  # varying num values.
+  df = DataFrame({'many': [1, 2], 'none': []})
+  assert df.headers == ['many', 'none']
+  assert df.data_table == [[1, None], [2, None]]
+  assert df.data_table_transposed == [(1, 2), (None, None)]
+
+  df = DataFrame({'many': [], 'none': [1, 2]})
+  assert df.headers == ['many', 'none']
+  assert df.data_table == [[None, 1], [None, 2]]
+  assert df.data_table_transposed == [(None, None), (1, 2)]
+
+  # merge multiple data frames
+  df = DataFrame()
+  df.concat_rows(DataFrame())
+  assert df.headers == []
+  assert df.data_table == []
+  assert df.data_table_transposed == []
+
+  df = DataFrame()
+  df2 = DataFrame({'TotalTime_ms': [1, 2, 3], 'Displayed_ms': [4, 5, 6]})
+
+  df.concat_rows(df2)
+  assert df.headers == ['TotalTime_ms', 'Displayed_ms']
+  assert df.data_table == [[1, 4], [2, 5], [3, 6]]
+  assert df.data_table_transposed == [(1, 2, 3), (4, 5, 6)]
+
+  df = DataFrame({'TotalTime_ms': [1, 2]})
+  df2 = DataFrame({'Displayed_ms': [4, 5]})
+
+  df.concat_rows(df2)
+  assert df.headers == ['TotalTime_ms', 'Displayed_ms']
+  assert df.data_table == [[1, None], [2, None], [None, 4], [None, 5]]
+
+  df = DataFrame({'TotalTime_ms': [1, 2]})
+  df2 = DataFrame({'TotalTime_ms': [3, 4], 'Displayed_ms': [5, 6]})
+
+  df.concat_rows(df2)
+  assert df.headers == ['TotalTime_ms', 'Displayed_ms']
+  assert df.data_table == [[1, None], [2, None], [3, 5], [4, 6]]
+
+  # data_row_at
+  df = DataFrame({'TotalTime_ms': [1, 2, 3], 'Displayed_ms': [4, 5, 6]})
+  assert df.data_row_at(-1) == [3, 6]
+  assert df.data_row_at(2) == [3, 6]
+  assert df.data_row_at(1) == [2, 5]
+
+  # repeat
+  df = DataFrame({'TotalTime_ms': [1], 'Displayed_ms': [4]})
+  df2 = DataFrame({'TotalTime_ms': [1, 1, 1], 'Displayed_ms': [4, 4, 4]})
+  assert df.repeat(3) == df2
+
+  # repeat
+  df = DataFrame({'TotalTime_ms': [1, 1, 1], 'Displayed_ms': [4, 4, 4]})
+  assert df.data_row_len == 3
+  df = DataFrame({'TotalTime_ms': [1, 1]})
+  assert df.data_row_len == 2
+
+  # repeat
+  df = DataFrame({'TotalTime_ms': [1, 1, 1], 'Displayed_ms': [4, 4, 4]})
+  assert df.data_row_len == 3
+  df = DataFrame({'TotalTime_ms': [1, 1]})
+  assert df.data_row_len == 2
+
+  # data_row_reduce
+  df = DataFrame({'TotalTime_ms': [1, 1, 1], 'Displayed_ms': [4, 4, 4]})
+  df_sum = DataFrame({'TotalTime_ms': [3], 'Displayed_ms': [12]})
+  assert df.data_row_reduce(sum) == df_sum
+
+  # merge_data_columns
+  df = DataFrame({'TotalTime_ms': [1, 2, 3]})
+  df2 = DataFrame({'Displayed_ms': [3, 4, 5, 6]})
+
+  df.merge_data_columns(df2)
+  assert df == DataFrame(
+    {'TotalTime_ms': [1, 2, 3], 'Displayed_ms': [3, 4, 5, 6]})
+
+  df = DataFrame({'TotalTime_ms': [1, 2, 3]})
+  df2 = DataFrame({'Displayed_ms': [3, 4]})
+
+  df.merge_data_columns(df2)
+  assert df == DataFrame(
+    {'TotalTime_ms': [1, 2, 3], 'Displayed_ms': [3, 4]})
+
+  df = DataFrame({'TotalTime_ms': [1, 2, 3]})
+  df2 = DataFrame({'TotalTime_ms': [10, 11]})
+
+  df.merge_data_columns(df2)
+  assert df == DataFrame({'TotalTime_ms': [10, 11, 3]})
+
+  df = DataFrame({'TotalTime_ms': []})
+  df2 = DataFrame({'TotalTime_ms': [10, 11]})
+
+  df.merge_data_columns(df2)
+  assert df == DataFrame({'TotalTime_ms': [10, 11]})
diff --git a/startop/scripts/app_startup/query_compiler_filter.py b/startop/scripts/app_startup/query_compiler_filter.py
index dc97c66..ea14264 100755
--- a/startop/scripts/app_startup/query_compiler_filter.py
+++ b/startop/scripts/app_startup/query_compiler_filter.py
@@ -31,13 +31,15 @@
 #
 
 import argparse
-import sys
+import os
 import re
+import sys
 
 # TODO: refactor this with a common library file with analyze_metrics.py
-import app_startup_runner
-from app_startup_runner import _debug_print
-from app_startup_runner import execute_arbitrary_command
+DIR = os.path.abspath(os.path.dirname(__file__))
+sys.path.append(os.path.dirname(DIR))
+import lib.cmd_utils as cmd_utils
+import lib.print_utils as print_utils
 
 from typing import List, NamedTuple, Iterable
 
@@ -74,7 +76,11 @@
       x86: [status=quicken] [reason=install]
 """ %(package, package, package, package)
 
-  code, res = execute_arbitrary_command(['adb', 'shell', 'dumpsys', 'package', package], simulate=False, timeout=5)
+  code, res = cmd_utils.execute_arbitrary_command(['adb', 'shell', 'dumpsys',
+                                                   'package', package],
+                                                  simulate=False,
+                                                  timeout=5,
+                                                  shell=False)
   if code:
     return res
   else:
@@ -115,7 +121,7 @@
       line = str_lines[line_num]
       current_indent = get_indent_level(line)
 
-      _debug_print("INDENT=%d, LINE=%s" %(current_indent, line))
+      print_utils.debug_print("INDENT=%d, LINE=%s" %(current_indent, line))
 
       current_label = line.lstrip()
 
@@ -135,7 +141,7 @@
       break
 
   new_remainder = str_lines[line_num::]
-  _debug_print("NEW REMAINDER: ", new_remainder)
+  print_utils.debug_print("NEW REMAINDER: ", new_remainder)
 
   parse_tree = ParseTree(label, children)
   return ParseResult(new_remainder, parse_tree)
@@ -159,7 +165,7 @@
 def find_first_compiler_filter(dexopt_state: DexoptState, package: str, instruction_set: str) -> str:
   lst = find_all_compiler_filters(dexopt_state, package)
 
-  _debug_print("all compiler filters: ", lst)
+  print_utils.debug_print("all compiler filters: ", lst)
 
   for compiler_filter_info in lst:
     if not instruction_set:
@@ -180,10 +186,10 @@
   if not package_tree:
     raise AssertionError("Could not find any package subtree for package %s" %(package))
 
-  _debug_print("package tree: ", package_tree)
+  print_utils.debug_print("package tree: ", package_tree)
 
   for path_tree in find_parse_children(package_tree, "path: "):
-    _debug_print("path tree: ", path_tree)
+    print_utils.debug_print("path tree: ", path_tree)
 
     matchre = re.compile("([^:]+):\s+\[status=([^\]]+)\]\s+\[reason=([^\]]+)\]")
 
@@ -198,16 +204,16 @@
 
 def main() -> int:
   opts = parse_options()
-  app_startup_runner._debug = opts.debug
+  cmd_utils._debug = opts.debug
   if _DEBUG_FORCE is not None:
-    app_startup_runner._debug = _DEBUG_FORCE
-  _debug_print("parsed options: ", opts)
+    cmd_utils._debug = _DEBUG_FORCE
+  print_utils.debug_print("parsed options: ", opts)
 
   # Note: This can often 'fail' if the package isn't actually installed.
   package_dumpsys = remote_dumpsys_package(opts.package, opts.simulate)
-  _debug_print("package dumpsys: ", package_dumpsys)
+  print_utils.debug_print("package dumpsys: ", package_dumpsys)
   dumpsys_parse_tree = parse_tab_tree(package_dumpsys, package_dumpsys)
-  _debug_print("parse tree: ", dumpsys_parse_tree)
+  print_utils.debug_print("parse tree: ", dumpsys_parse_tree)
   dexopt_state = parse_dexopt_state(dumpsys_parse_tree)
 
   filter = find_first_compiler_filter(dexopt_state, opts.package, opts.instruction_set)
diff --git a/startop/scripts/app_startup/run_app_with_prefetch.py b/startop/scripts/app_startup/run_app_with_prefetch.py
index c7970f5..8a9135b 100644
--- a/startop/scripts/app_startup/run_app_with_prefetch.py
+++ b/startop/scripts/app_startup/run_app_with_prefetch.py
@@ -30,8 +30,7 @@
 import os
 import sys
 import time
-from typing import List, Tuple
-from pathlib import Path
+from typing import List, Tuple, Optional, NamedTuple
 
 # local imports
 import lib.adb_utils as adb_utils
@@ -40,16 +39,28 @@
 DIR = os.path.abspath(os.path.dirname(__file__))
 IORAP_COMMON_BASH_SCRIPT = os.path.realpath(os.path.join(DIR,
                                                          '../iorap/common'))
+APP_STARTUP_COMMON_BASH_SCRIPT = os.path.realpath(os.path.join(DIR,
+                                                               'lib/common'))
 
 sys.path.append(os.path.dirname(DIR))
 import lib.print_utils as print_utils
 import lib.cmd_utils as cmd_utils
 import iorap.lib.iorapd_utils as iorapd_utils
 
+RunCommandArgs = NamedTuple('RunCommandArgs',
+                            [('package', str),
+                             ('readahead', str),
+                             ('activity', Optional[str]),
+                             ('compiler_filter', Optional[str]),
+                             ('timeout', Optional[int]),
+                             ('debug', bool),
+                             ('simulate', bool),
+                             ('input', Optional[str])])
+
 def parse_options(argv: List[str] = None):
   """Parses command line arguments and return an argparse Namespace object."""
   parser = argparse.ArgumentParser(
-    description='Run an Android application once and measure startup time.'
+      description='Run an Android application once and measure startup time.'
   )
 
   required_named = parser.add_argument_group('required named arguments')
@@ -90,42 +101,44 @@
 
   return parser.parse_args(argv)
 
-def validate_options(opts: argparse.Namespace) -> bool:
+def validate_options(args: argparse.Namespace) -> Tuple[bool, RunCommandArgs]:
   """Validates the activity and trace file if needed.
 
   Returns:
     A bool indicates whether the activity is valid and trace file exists if
     necessary.
   """
-  needs_trace_file = (opts.readahead != 'cold' and opts.readahead != 'warm')
-  if needs_trace_file and (opts.input is None or
-                           not os.path.exists(opts.input)):
+  needs_trace_file = (args.readahead != 'cold' and args.readahead != 'warm')
+  if needs_trace_file and (args.input is None or
+                           not os.path.exists(args.input)):
     print_utils.error_print('--input not specified!')
-    return False
+    return False, args
 
-  # Install necessary trace file.
+  if args.simulate:
+    args = args._replace(activity='act')
+
+  if not args.activity:
+    _, activity = cmd_utils.run_shell_func(IORAP_COMMON_BASH_SCRIPT,
+                                           'get_activity_name',
+                                           [args.package])
+    args = args._replace(activity=activity)
+
+  if not args.activity:
+    print_utils.error_print('Activity name could not be found, '
+                            'invalid package name?!')
+    return False, args
+
+  # Install necessary trace file. This must be after the activity checking.
   if needs_trace_file:
     passed = iorapd_utils.iorapd_compiler_install_trace_file(
-      opts.package, opts.activity, opts.input)
+        args.package, args.activity, args.input)
     if not cmd_utils.SIMULATE and not passed:
       print_utils.error_print('Failed to install compiled TraceFile.pb for '
                               '"{}/{}"'.
-                                format(opts.package, opts.activity))
-      return False
+                                format(args.package, args.activity))
+      return False, args
 
-  if opts.activity is not None:
-    return True
-
-  _, opts.activity = cmd_utils.run_shell_func(IORAP_COMMON_BASH_SCRIPT,
-                                              'get_activity_name',
-                                              [opts.package])
-
-  if not opts.activity:
-    print_utils.error_print('Activity name could not be found, '
-                              'invalid package name?!')
-    return False
-
-  return True
+  return True, args
 
 def set_up_adb_env():
   """Sets up adb environment."""
@@ -147,17 +160,18 @@
 
   passed, current_compiler_filter_info = \
     cmd_utils.run_shell_command(
-      '{} --package {}'.format(os.path.join(DIR, 'query_compiler_filter.py'),
-                               package))
+        '{} --package {}'.format(os.path.join(DIR, 'query_compiler_filter.py'),
+                                 package))
 
   if passed != 0:
     return passed
 
   # TODO: call query_compiler_filter directly as a python function instead of
   #  these shell calls.
-  current_compiler_filter, current_reason, current_isa = current_compiler_filter_info.split(' ')
+  current_compiler_filter, current_reason, current_isa = \
+    current_compiler_filter_info.split(' ')
   print_utils.debug_print('Compiler Filter={} Reason={} Isa={}'.format(
-    current_compiler_filter, current_reason, current_isa))
+      current_compiler_filter, current_reason, current_isa))
 
   # Don't trust reasons that aren't 'unknown' because that means
   #  we didn't manually force the compilation filter.
@@ -184,9 +198,6 @@
   Returns:
     A list of tuples that including metric name, metric value and rest info.
   """
-  if simulate:
-    return [('TotalTime', '123')]
-
   all_metrics = []
   for line in input.split('\n'):
     if not line:
@@ -203,11 +214,38 @@
     print_utils.debug_print('metric: "{metric_name}", '
                             'value: "{metric_value}" '.
                               format(metric_name=metric_name,
-                                     metric_value=metric_value))
+                                   metric_value=metric_value))
 
     all_metrics.append((metric_name, metric_value))
   return all_metrics
 
+def _parse_total_time(am_start_output: str) -> Optional[str]:
+  """Parses the total time from 'adb shell am start pkg' output.
+
+  Returns:
+    the total time of app startup.
+  """
+  for line in am_start_output.split('\n'):
+    if 'TotalTime:' in line:
+      return line[len('TotalTime:'):].strip()
+  return None
+
+def blocking_parse_all_metrics(am_start_output: str, package: str,
+                               pre_launch_timestamp: str,
+                               timeout: int) -> str:
+  """Parses the metric after app startup by reading from logcat in a blocking
+  manner until all metrics have been found".
+
+  Returns:
+    the total time and displayed time of app startup.
+    For example: "TotalTime=123\nDisplayedTime=121
+  """
+  total_time = _parse_total_time(am_start_output)
+  displayed_time = adb_utils.blocking_wait_for_logcat_displayed_time(
+      pre_launch_timestamp, package, timeout)
+
+  return 'TotalTime={}\nDisplayedTime={}'.format(total_time, displayed_time)
+
 def run(readahead: str,
         package: str,
         activity: str,
@@ -223,11 +261,17 @@
   print_utils.debug_print('=====             START              =====')
   print_utils.debug_print('==========================================')
 
+  # Kill any existing process of this app
+  adb_utils.pkill(package)
+
   if readahead != 'warm':
     print_utils.debug_print('Drop caches for non-warm start.')
     # Drop all caches to get cold starts.
     adb_utils.vm_drop_cache()
 
+  if readahead != 'warm' and readahead != 'cold':
+    iorapd_utils.enable_iorapd_readahead()
+
   print_utils.debug_print('Running with timeout {}'.format(timeout))
 
   pre_launch_timestamp = adb_utils.logcat_save_timestamp()
@@ -235,24 +279,25 @@
   passed, output = cmd_utils.run_shell_command('timeout {timeout} '
                                                '"{DIR}/launch_application" '
                                                '"{package}" '
-                                               '"{activity}" | '
-                                               '"{DIR}/parse_metrics" '
-                                               '--package {package} '
-                                               '--activity {activity} '
-                                               '--timestamp "{timestamp}"'
+                                               '"{activity}"'
                                                  .format(timeout=timeout,
-                                                         DIR=DIR,
-                                                         package=package,
-                                                         activity=activity,
-                                                         timestamp=pre_launch_timestamp))
-
-  if not output and not simulate:
+                                                       DIR=DIR,
+                                                       package=package,
+                                                       activity=activity))
+  if not passed and not simulate:
     return None
 
-  results = parse_metrics_output(output, simulate)
+  if simulate:
+    results = [('TotalTime', '123')]
+  else:
+    output = blocking_parse_all_metrics(output,
+                                        package,
+                                        pre_launch_timestamp,
+                                        timeout)
+    results = parse_metrics_output(output, simulate)
 
   passed = perform_post_launch_cleanup(
-    readahead, package, activity, timeout, debug, pre_launch_timestamp)
+      readahead, package, activity, timeout, debug, pre_launch_timestamp)
   if not passed and not simulate:
     print_utils.error_print('Cannot perform post launch cleanup!')
     return None
@@ -272,25 +317,30 @@
     A bool indicates whether the cleanup succeeds or not.
   """
   if readahead != 'warm' and readahead != 'cold':
-    return iorapd_utils.wait_for_iorapd_finish(package,
-                                               activity,
-                                               timeout,
-                                               debug,
-                                               logcat_timestamp)
-    return passed
+    passed = iorapd_utils.wait_for_iorapd_finish(package,
+                                                 activity,
+                                                 timeout,
+                                                 debug,
+                                                 logcat_timestamp)
+
+    if not passed:
+      return passed
+
+    return iorapd_utils.disable_iorapd_readahead()
+
   # Don't need to do anything for warm or cold.
   return True
 
-def run_test(opts: argparse.Namespace) -> List[Tuple[str, str]]:
+def run_test(args: RunCommandArgs) -> List[Tuple[str, str]]:
   """Runs one test using given options.
 
   Returns:
-    A list of tuples that including metric name, metric value and anything left.
+    A list of tuples that including metric name, metric value.
   """
-  print_utils.DEBUG = opts.debug
-  cmd_utils.SIMULATE = opts.simulate
+  print_utils.DEBUG = args.debug
+  cmd_utils.SIMULATE = args.simulate
 
-  passed = validate_options(opts)
+  passed, args = validate_options(args)
   if not passed:
     return None
 
@@ -299,15 +349,22 @@
   # Ensure the APK is currently compiled with whatever we passed in
   # via --compiler-filter.
   # No-op if this option was not passed in.
-  if not configure_compiler_filter(opts.compiler_filter, opts.package,
-                                   opts.activity):
+  if not configure_compiler_filter(args.compiler_filter, args.package,
+                                   args.activity):
     return None
 
-  return run(opts.readahead, opts.package, opts.activity, opts.timeout,
-             opts.simulate, opts.debug)
+  return run(args.readahead, args.package, args.activity, args.timeout,
+             args.simulate, args.debug)
+
+def get_args_from_opts(opts: argparse.Namespace) -> RunCommandArgs:
+  kwargs = {}
+  for field in RunCommandArgs._fields:
+    kwargs[field] = getattr(opts, field)
+  return RunCommandArgs(**kwargs)
 
 def main():
-  args = parse_options()
+  opts = parse_options()
+  args = get_args_from_opts(opts)
   result = run_test(args)
 
   if result is None:
diff --git a/startop/scripts/app_startup/run_app_with_prefetch_test.py b/startop/scripts/app_startup/run_app_with_prefetch_test.py
index 241aea4..a642385 100644
--- a/startop/scripts/app_startup/run_app_with_prefetch_test.py
+++ b/startop/scripts/app_startup/run_app_with_prefetch_test.py
@@ -200,70 +200,82 @@
 
 def _mocked_run_shell_command(*args, **kwargs):
   if args[0] == 'adb shell "date -u +\'%Y-%m-%d %H:%M:%S.%N\'"':
-    return (True, "123:123")
+    return (True, "2019-07-02 23:20:06.972674825")
   elif args[0] == 'adb shell ps | grep "music" | awk \'{print $2;}\'':
     return (True, '9999')
   else:
     return (True, 'a1=b1\nc1=d1=d2\ne1=f1')
 
-def test_run_no_vm_cache_drop():
-  with patch('lib.cmd_utils.run_shell_command',
-             new_callable=Mock) as mock_run_shell_command:
-    mock_run_shell_command.side_effect = _mocked_run_shell_command
-    run.run('warm',
-            'music',
-            'MainActivity',
-            timeout=10,
-            simulate=False,
-            debug=False)
+@patch('lib.adb_utils.blocking_wait_for_logcat_displayed_time')
+@patch('lib.cmd_utils.run_shell_command')
+def test_run_no_vm_cache_drop(mock_run_shell_command,
+                              mock_blocking_wait_for_logcat_displayed_time):
+  mock_run_shell_command.side_effect = _mocked_run_shell_command
+  mock_blocking_wait_for_logcat_displayed_time.return_value = 123
 
-    calls = [call('adb shell "date -u +\'%Y-%m-%d %H:%M:%S.%N\'"'),
-             call(
-               'timeout {timeout} "{DIR}/launch_application" "{package}" "{activity}" | '
-               '"{DIR}/parse_metrics" --package {package} --activity {activity} '
-               '--timestamp "{timestamp}"'
-                 .format(timeout=10,
-                         DIR=run.DIR,
-                         package='music',
-                         activity='MainActivity',
-                         timestamp='123:123')),
-             call('adb shell ps | grep "music" | awk \'{print $2;}\''),
-             call('adb shell "kill 9999"')]
-    mock_run_shell_command.assert_has_calls(calls)
+  run.run('warm',
+          'music',
+          'MainActivity',
+          timeout=10,
+          simulate=False,
+          debug=False)
 
-def test_run_with_vm_cache_drop_and_post_launch_cleanup():
-  with patch('lib.cmd_utils.run_shell_command',
-             new_callable=Mock) as mock_run_shell_command:
-    mock_run_shell_command.side_effect = _mocked_run_shell_command
-    run.run('fadvise',
-            'music',
-            'MainActivity',
-            timeout=10,
-            simulate=False,
-            debug=False)
+  calls = [call('adb shell ps | grep "music" | awk \'{print $2;}\''),
+           call('adb shell "kill 9999"'),
+           call('adb shell "date -u +\'%Y-%m-%d %H:%M:%S.%N\'"'),
+           call(
+             'timeout {timeout} "{DIR}/launch_application" "{package}" "{activity}"'
+               .format(timeout=10,
+                       DIR=run.DIR,
+                       package='music',
+                       activity='MainActivity',
+                       timestamp='2019-07-02 23:20:06.972674825')),
+           call('adb shell ps | grep "music" | awk \'{print $2;}\''),
+           call('adb shell "kill 9999"')]
+  mock_run_shell_command.assert_has_calls(calls)
 
-    calls = [call('adb shell "echo 3 > /proc/sys/vm/drop_caches"'),
-             call('adb shell "date -u +\'%Y-%m-%d %H:%M:%S.%N\'"'),
-             call(
-               'timeout {timeout} "{DIR}/launch_application" "{package}" "{activity}" | '
-               '"{DIR}/parse_metrics" --package {package} --activity {activity} '
-               '--timestamp "{timestamp}"'
-                 .format(timeout=10,
-                         DIR=run.DIR,
-                         package='music',
-                         activity='MainActivity',
-                         timestamp='123:123')),
-             call(
-               'bash -c "source {script_path}; '
-               'iorapd_readahead_wait_until_finished '
-               '\'{package}\' \'{activity}\' \'{timestamp}\' \'{timeout}\'"'.
-                 format(timeout=10,
-                        package='music',
-                        activity='MainActivity',
-                        timestamp='123:123',
-                        script_path=run.IORAP_COMMON_BASH_SCRIPT)),
-             call('adb shell ps | grep "music" | awk \'{print $2;}\''),
-             call('adb shell "kill 9999"')]
+@patch('lib.adb_utils.blocking_wait_for_logcat_displayed_time')
+@patch('lib.cmd_utils.run_shell_command')
+def test_run_with_vm_cache_drop_and_post_launch_cleanup(
+    mock_run_shell_command,
+    mock_blocking_wait_for_logcat_displayed_time):
+  mock_run_shell_command.side_effect = _mocked_run_shell_command
+  mock_blocking_wait_for_logcat_displayed_time.return_value = 123
+
+  run.run('fadvise',
+          'music',
+          'MainActivity',
+          timeout=10,
+          simulate=False,
+          debug=False)
+
+  calls = [call('adb shell ps | grep "music" | awk \'{print $2;}\''),
+           call('adb shell "kill 9999"'),
+           call('adb shell "echo 3 > /proc/sys/vm/drop_caches"'),
+           call('bash -c "source {}; iorapd_readahead_enable"'.
+                format(run.IORAP_COMMON_BASH_SCRIPT)),
+           call('adb shell "date -u +\'%Y-%m-%d %H:%M:%S.%N\'"'),
+           call(
+             'timeout {timeout} "{DIR}/launch_application" '
+             '"{package}" "{activity}"'
+               .format(timeout=10,
+                       DIR=run.DIR,
+                       package='music',
+                       activity='MainActivity',
+                       timestamp='2019-07-02 23:20:06.972674825')),
+           call(
+             'bash -c "source {script_path}; '
+             'iorapd_readahead_wait_until_finished '
+             '\'{package}\' \'{activity}\' \'{timestamp}\' \'{timeout}\'"'.
+               format(timeout=10,
+                      package='music',
+                      activity='MainActivity',
+                      timestamp='2019-07-02 23:20:06.972674825',
+                      script_path=run.IORAP_COMMON_BASH_SCRIPT)),
+           call('bash -c "source {}; iorapd_readahead_disable"'.
+                format(run.IORAP_COMMON_BASH_SCRIPT)),
+           call('adb shell ps | grep "music" | awk \'{print $2;}\''),
+           call('adb shell "kill 9999"')]
   mock_run_shell_command.assert_has_calls(calls)
 
 if __name__ == '__main__':
diff --git a/startop/scripts/iorap/lib/iorapd_utils.py b/startop/scripts/iorap/lib/iorapd_utils.py
index f907305..c03e9b0 100644
--- a/startop/scripts/iorap/lib/iorapd_utils.py
+++ b/startop/scripts/iorap/lib/iorapd_utils.py
@@ -86,3 +86,28 @@
                                        [package, activity, logcat_timestamp,
                                         str(timeout)])
   return passed
+
+
+def enable_iorapd_readahead() -> bool:
+  """
+  Disable readahead. Subsequent launches of an application will be sped up
+  by iorapd readahead prefetching.
+
+  Returns:
+    A bool indicates whether the enabling is done successfully or not.
+  """
+  passed, _ = cmd_utils.run_shell_func(IORAP_COMMON_BASH_SCRIPT,
+                                       'iorapd_readahead_enable', [])
+  return passed
+
+def disable_iorapd_readahead() -> bool:
+  """
+  Disable readahead. Subsequent launches of an application will be not be sped
+  up by iorapd readahead prefetching.
+
+  Returns:
+    A bool indicates whether the disabling is done successfully or not.
+  """
+  passed, _ = cmd_utils.run_shell_func(IORAP_COMMON_BASH_SCRIPT,
+                                       'iorapd_readahead_disable', [])
+  return passed
diff --git a/startop/scripts/lib/cmd_utils.py b/startop/scripts/lib/cmd_utils.py
index c3d9605..bc5ca31 100644
--- a/startop/scripts/lib/cmd_utils.py
+++ b/startop/scripts/lib/cmd_utils.py
@@ -44,10 +44,16 @@
     A tuple of running status (True=succeeded, False=failed or timed out) and
     std output (string contents of stdout with trailing whitespace removed) .
   """
-  cmd = 'bash -c "source {script_path}; {func} {args}"'.format(
-    script_path=script_path,
-    func=func,
-    args=' '.join("'{}'".format(arg) for arg in args))
+  if args:
+    cmd = 'bash -c "source {script_path}; {func} {args}"'.format(
+      script_path=script_path,
+      func=func,
+      args=' '.join("'{}'".format(arg) for arg in args))
+  else:
+    cmd = 'bash -c "source {script_path}; {func}"'.format(
+      script_path=script_path,
+      func=func)
+
   print_utils.debug_print(cmd)
   return run_shell_command(cmd)
 
diff --git a/startop/scripts/lib/logcat_utils.py b/startop/scripts/lib/logcat_utils.py
new file mode 100644
index 0000000..8a3d00b
--- /dev/null
+++ b/startop/scripts/lib/logcat_utils.py
@@ -0,0 +1,104 @@
+#!/usr/bin/env python3
+#
+# 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.
+
+"""Helper util libraries for parsing logcat logs."""
+
+import asyncio
+import re
+from datetime import datetime
+from typing import Optional, Pattern
+
+# local import
+import lib.print_utils as print_utils
+
+def parse_logcat_datetime(timestamp: str) -> Optional[datetime]:
+  """Parses the timestamp of logcat.
+
+  Params:
+    timestamp: for example "2019-07-01 16:13:55.221".
+
+  Returns:
+    a datetime of timestamp with the year now.
+  """
+  try:
+    # Match the format of logcat. For example: "2019-07-01 16:13:55.221",
+    # because it doesn't have year, set current year to it.
+    timestamp = datetime.strptime(timestamp,
+                                  '%Y-%m-%d %H:%M:%S.%f')
+    return timestamp
+  except ValueError as ve:
+    print_utils.debug_print('Invalid line: ' + timestamp)
+    return None
+
+def _is_time_out(timeout: datetime, line: str) -> bool:
+  """Checks if the timestamp of this line exceeds the timeout.
+
+  Returns:
+    true if the timestamp exceeds the timeout.
+  """
+  # Get the timestampe string.
+  cur_timestamp_str = ' '.join(re.split(r'\s+', line)[0:2])
+  timestamp = parse_logcat_datetime(cur_timestamp_str)
+  if not timestamp:
+    return False
+
+  return timestamp > timeout
+
+async def _blocking_wait_for_logcat_pattern(timestamp: datetime,
+                                            pattern: Pattern,
+                                            timeout: datetime) -> Optional[str]:
+  # Show the year in the timestampe.
+  logcat_cmd = 'adb logcat -v UTC -v year -v threadtime -T'.split()
+  logcat_cmd.append(str(timestamp))
+  print_utils.debug_print('[LOGCAT]:' + ' '.join(logcat_cmd))
+
+  # Create subprocess
+  process = await asyncio.create_subprocess_exec(
+      *logcat_cmd,
+      # stdout must a pipe to be accessible as process.stdout
+      stdout=asyncio.subprocess.PIPE)
+
+  while (True):
+    # Read one line of output.
+    data = await process.stdout.readline()
+    line = data.decode('utf-8').rstrip()
+
+    # 2019-07-01 14:54:21.946 27365 27392 I ActivityTaskManager: Displayed
+    # com.android.settings/.Settings: +927ms
+    # TODO: Detect timeouts even when there is no logcat output.
+    if _is_time_out(timeout, line):
+      print_utils.debug_print('DID TIMEOUT BEFORE SEEING ANYTHING ('
+                              'timeout={timeout} seconds << {pattern} '
+                              '>>'.format(timeout=timeout, pattern=pattern))
+      return None
+
+    if pattern.match(line):
+      print_utils.debug_print(
+          'WE DID SEE PATTERN << "{}" >>.'.format(pattern))
+      return line
+
+def blocking_wait_for_logcat_pattern(timestamp: datetime,
+                                     pattern: Pattern,
+                                     timeout: datetime) -> Optional[str]:
+  """Selects the line that matches the pattern and within the timeout.
+
+  Returns:
+    the line that matches the pattern and within the timeout.
+  """
+  loop = asyncio.get_event_loop()
+  result = loop.run_until_complete(
+      _blocking_wait_for_logcat_pattern(timestamp, pattern, timeout))
+  return result
diff --git a/startop/scripts/lib/logcat_utils_test.py b/startop/scripts/lib/logcat_utils_test.py
new file mode 100644
index 0000000..ab82515
--- /dev/null
+++ b/startop/scripts/lib/logcat_utils_test.py
@@ -0,0 +1,88 @@
+#!/usr/bin/env python3
+#
+# 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.
+#
+"""Unit tests for the logcat_utils.py script."""
+
+import asyncio
+import datetime
+import re
+
+import logcat_utils
+from mock import MagicMock, patch
+
+def test_parse_logcat_datatime():
+  # Act
+  result = logcat_utils.parse_logcat_datetime('2019-07-01 16:13:55.221')
+
+  # Assert
+  assert result == datetime.datetime(2019, 7, 1, 16, 13, 55, 221000)
+
+class AsyncMock(MagicMock):
+  async def __call__(self, *args, **kwargs):
+    return super(AsyncMock, self).__call__(*args, **kwargs)
+
+def _async_return():
+  f = asyncio.Future()
+  f.set_result(
+      b'2019-07-01 15:51:53.290 27365 27392 I ActivityTaskManager: '
+      b'Displayed com.google.android.music/com.android.music.activitymanagement.'
+      b'TopLevelActivity: +1s7ms')
+  return f
+
+def test_parse_displayed_time_succeed():
+  # Act
+  with patch('asyncio.create_subprocess_exec',
+             new_callable=AsyncMock) as asyncio_mock:
+    asyncio_mock.return_value.stdout.readline = _async_return
+    timestamp = datetime.datetime(datetime.datetime.now().year, 7, 1, 16, 13,
+                                  55, 221000)
+    timeout_dt = timestamp + datetime.timedelta(0, 10)
+    pattern = re.compile('.*ActivityTaskManager: Displayed '
+                         'com.google.android.music/com.android.music.*')
+    result = logcat_utils.blocking_wait_for_logcat_pattern(timestamp,
+                                                           pattern,
+                                                           timeout_dt)
+
+    # Assert
+    assert result == '2019-07-01 15:51:53.290 27365 27392 I ' \
+                     'ActivityTaskManager: ' \
+                     'Displayed com.google.android.music/com.android.music.' \
+                     'activitymanagement.TopLevelActivity: +1s7ms'
+
+def _async_timeout_return():
+  f = asyncio.Future()
+  f.set_result(
+      b'2019-07-01 17:51:53.290 27365 27392 I ActivityTaskManager: '
+      b'Displayed com.google.android.music/com.android.music.activitymanagement.'
+      b'TopLevelActivity: +1s7ms')
+  return f
+
+def test_parse_displayed_time_timeout():
+  # Act
+  with patch('asyncio.create_subprocess_exec',
+             new_callable=AsyncMock) as asyncio_mock:
+    asyncio_mock.return_value.stdout.readline = _async_timeout_return
+    timestamp = datetime.datetime(datetime.datetime.now().year,
+                                  7, 1, 16, 13, 55, 221000)
+    timeout_dt = timestamp + datetime.timedelta(0, 10)
+    pattern = re.compile('.*ActivityTaskManager: Displayed '
+                         'com.google.android.music/com.android.music.*')
+    result = logcat_utils.blocking_wait_for_logcat_pattern(timestamp,
+                                                           pattern,
+                                                           timeout_dt)
+
+    # Assert
+    assert result == None
diff --git a/startop/scripts/lib/print_utils.py b/startop/scripts/lib/print_utils.py
index c33e0f9..8c5999d 100644
--- a/startop/scripts/lib/print_utils.py
+++ b/startop/scripts/lib/print_utils.py
@@ -27,3 +27,41 @@
 
 def error_print(*args, **kwargs):
   print('[ERROR]:', *args, file=sys.stderr, **kwargs)
+
+def _expand_gen_repr(args):
+  """Like repr but any generator-like object has its iterator consumed
+  and then called repr on."""
+  new_args_list = []
+  for i in args:
+    # detect iterable objects that do not have their own override of __str__
+    if hasattr(i, '__iter__'):
+      to_str = getattr(i, '__str__')
+      if to_str.__objclass__ == object:
+        # the repr for a generator is just type+address, expand it out instead.
+        new_args_list.append([_expand_gen_repr([j])[0] for j in i])
+        continue
+    # normal case: uses the built-in to-string
+    new_args_list.append(i)
+  return new_args_list
+
+def debug_print_gen(*args, **kwargs):
+  """Like _debug_print but will turn any iterable args into a list."""
+  if not DEBUG:
+    return
+
+  new_args_list = _expand_gen_repr(args)
+  debug_print(*new_args_list, **kwargs)
+
+def debug_print_nd(*args, **kwargs):
+  """Like _debug_print but will turn any NamedTuple-type args into a string."""
+  if not DEBUG:
+    return
+
+  new_args_list = []
+  for i in args:
+    if hasattr(i, '_field_types'):
+      new_args_list.append("%s: %s" % (i.__name__, i._field_types))
+    else:
+      new_args_list.append(i)
+
+  debug_print(*new_args_list, **kwargs)
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 484fd3b..2822fcc 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -2116,29 +2116,36 @@
     }
 
     /**
+     * TODO(b/137102918) Make this static, tests use this as an instance method currently.
+     *
      * @return the list of subId's that are active,
      *         is never null but the length maybe 0.
      * @hide
      */
     @UnsupportedAppUsage
     public @NonNull int[] getActiveSubscriptionIdList() {
-        int[] subId = null;
+        return getActiveSubscriptionIdList(/* visibleOnly */ true);
+    }
 
+    /**
+     * TODO(b/137102918) Make this static, tests use this as an instance method currently.
+     *
+     * @return a non-null list of subId's that are active.
+     *
+     * @hide
+     */
+    public @NonNull int[] getActiveSubscriptionIdList(boolean visibleOnly) {
         try {
             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
             if (iSub != null) {
-                subId = iSub.getActiveSubIdList(/*visibleOnly*/true);
+                int[] subId = iSub.getActiveSubIdList(visibleOnly);
+                if (subId != null) return subId;
             }
         } catch (RemoteException ex) {
             // ignore it
         }
 
-        if (subId == null) {
-            subId = new int[0];
-        }
-
-        return subId;
-
+        return new int[0];
     }
 
     /**
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 22a8232..fd47561 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -3983,9 +3983,14 @@
      * The returned set of subscriber IDs will include the subscriber ID corresponding to this
      * TelephonyManager's subId.
      *
+     * This is deprecated and {@link #getMergedSubscriberIdsFromGroup()} should be used for data
+     * usage merging purpose.
+     * TODO: remove this API.
+     *
      * @hide
      */
     @UnsupportedAppUsage
+    @Deprecated
     public @Nullable String[] getMergedSubscriberIds() {
         try {
             ITelephony telephony = getITelephony();
@@ -3998,6 +4003,28 @@
     }
 
     /**
+     * Return the set of subscriber IDs that should be considered "merged together" for data usage
+     * purposes. Unlike {@link #getMergedSubscriberIds()} this API merge subscriberIds based on
+     * subscription grouping: subscriberId of those in the same group will all be returned.
+     *
+     * <p>Requires the calling app to have READ_PRIVILEGED_PHONE_STATE permission.
+     *
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    public @Nullable String[] getMergedSubscriberIdsFromGroup() {
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                return telephony.getMergedSubscriberIdsFromGroup(getSubId(), getOpPackageName());
+            }
+        } catch (RemoteException ex) {
+        } catch (NullPointerException ex) {
+        }
+        return null;
+    }
+
+    /**
      * Returns the MSISDN string.
      * for a GSM phone. Return null if it is unavailable.
      *
@@ -4901,7 +4928,8 @@
             ITelephony telephony = getITelephony();
             if (telephony == null)
                 return DATA_ACTIVITY_NONE;
-            return telephony.getDataActivity();
+            return telephony.getDataActivityForSubId(
+                    getSubId(SubscriptionManager.getActiveDataSubscriptionId()));
         } catch (RemoteException ex) {
             // the phone process is restarting.
             return DATA_ACTIVITY_NONE;
@@ -4949,7 +4977,8 @@
             ITelephony telephony = getITelephony();
             if (telephony == null)
                 return DATA_DISCONNECTED;
-            return telephony.getDataState();
+            return telephony.getDataStateForSubId(
+                    getSubId(SubscriptionManager.getActiveDataSubscriptionId()));
         } catch (RemoteException ex) {
             // the phone process is restarting.
             return DATA_DISCONNECTED;
@@ -10834,7 +10863,6 @@
      * @param callback Callback will be triggered once it succeeds or failed.
      *                 See {@link TelephonyManager.SetOpportunisticSubscriptionResult}
      *                 for more details. Pass null if don't care about the result.
-     *
      */
     public void setPreferredOpportunisticDataSubscription(int subId, boolean needValidation,
             @Nullable @CallbackExecutor Executor executor, @Nullable Consumer<Integer> callback) {
@@ -10842,6 +10870,12 @@
         try {
             IOns iOpportunisticNetworkService = getIOns();
             if (iOpportunisticNetworkService == null) {
+                if (executor == null || callback == null) {
+                    return;
+                }
+                Binder.withCleanCallingIdentity(() -> executor.execute(() -> {
+                    callback.accept(SET_OPPORTUNISTIC_SUB_INACTIVE_SUBSCRIPTION);
+                }));
                 return;
             }
             ISetOpportunisticDataCallback callbackStub = new ISetOpportunisticDataCallback.Stub() {
@@ -10923,9 +10957,16 @@
                 if (executor == null || callback == null) {
                     return;
                 }
-                Binder.withCleanCallingIdentity(() -> executor.execute(() -> {
-                    callback.accept(UPDATE_AVAILABLE_NETWORKS_INVALID_ARGUMENTS);
-                }));
+                if (iOpportunisticNetworkService == null) {
+                    /* Todo<b/130595455> passing unknown due to lack of good error codes */
+                    Binder.withCleanCallingIdentity(() -> executor.execute(() -> {
+                        callback.accept(UPDATE_AVAILABLE_NETWORKS_UNKNOWN_FAILURE);
+                    }));
+                } else {
+                    Binder.withCleanCallingIdentity(() -> executor.execute(() -> {
+                        callback.accept(UPDATE_AVAILABLE_NETWORKS_INVALID_ARGUMENTS);
+                    }));
+                }
                 return;
             }
             IUpdateAvailableNetworksCallback callbackStub =
diff --git a/telephony/java/android/telephony/ims/RcsControllerCall.java b/telephony/java/android/telephony/ims/RcsControllerCall.java
index a2d68ad..ce03c3c 100644
--- a/telephony/java/android/telephony/ims/RcsControllerCall.java
+++ b/telephony/java/android/telephony/ims/RcsControllerCall.java
@@ -19,10 +19,11 @@
 import android.content.Context;
 import android.os.RemoteException;
 import android.os.ServiceManager;
-import android.telephony.ims.aidl.IRcs;
+import android.telephony.ims.aidl.IRcsMessage;
 
 /**
- * A wrapper class around RPC calls that {@link RcsMessageStore} APIs to minimize boilerplate code.
+ * A wrapper class around RPC calls that {@link RcsMessageManager} APIs to minimize boilerplate
+ * code.
  *
  * @hide - not meant for public use
  */
@@ -34,13 +35,14 @@
     }
 
     <R> R call(RcsServiceCall<R> serviceCall) throws RcsMessageStoreException {
-        IRcs iRcs = IRcs.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_RCS_SERVICE));
-        if (iRcs == null) {
+        IRcsMessage iRcsMessage = IRcsMessage.Stub.asInterface(ServiceManager.getService(
+                Context.TELEPHONY_RCS_MESSAGE_SERVICE));
+        if (iRcsMessage == null) {
             throw new RcsMessageStoreException("Could not connect to RCS storage service");
         }
 
         try {
-            return serviceCall.methodOnIRcs(iRcs, mContext.getOpPackageName());
+            return serviceCall.methodOnIRcs(iRcsMessage, mContext.getOpPackageName());
         } catch (RemoteException exception) {
             throw new RcsMessageStoreException(exception.getMessage());
         }
@@ -48,17 +50,17 @@
 
     void callWithNoReturn(RcsServiceCallWithNoReturn serviceCall)
             throws RcsMessageStoreException {
-        call((iRcs, callingPackage) -> {
-            serviceCall.methodOnIRcs(iRcs, callingPackage);
+        call((iRcsMessage, callingPackage) -> {
+            serviceCall.methodOnIRcs(iRcsMessage, callingPackage);
             return null;
         });
     }
 
     interface RcsServiceCall<R> {
-        R methodOnIRcs(IRcs iRcs, String callingPackage) throws RemoteException;
+        R methodOnIRcs(IRcsMessage iRcs, String callingPackage) throws RemoteException;
     }
 
     interface RcsServiceCallWithNoReturn {
-        void methodOnIRcs(IRcs iRcs, String callingPackage) throws RemoteException;
+        void methodOnIRcs(IRcsMessage iRcs, String callingPackage) throws RemoteException;
     }
 }
diff --git a/telephony/java/android/telephony/ims/RcsManager.java b/telephony/java/android/telephony/ims/RcsManager.java
deleted file mode 100644
index 0d6ca3c..0000000
--- a/telephony/java/android/telephony/ims/RcsManager.java
+++ /dev/null
@@ -1,43 +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 android.telephony.ims;
-
-import android.annotation.SystemService;
-import android.content.Context;
-
-/**
- * The manager class for RCS related utilities.
- *
- * @hide
- */
-@SystemService(Context.TELEPHONY_RCS_SERVICE)
-public class RcsManager {
-    private final RcsMessageStore mRcsMessageStore;
-
-    /**
-     * @hide
-     */
-    public RcsManager(Context context) {
-        mRcsMessageStore = new RcsMessageStore(context);
-    }
-
-    /**
-     * Returns an instance of {@link RcsMessageStore}
-     */
-    public RcsMessageStore getRcsMessageStore() {
-        return mRcsMessageStore;
-    }
-}
diff --git a/telephony/java/android/telephony/ims/RcsMessageStore.java b/telephony/java/android/telephony/ims/RcsMessageManager.java
similarity index 96%
rename from telephony/java/android/telephony/ims/RcsMessageStore.java
rename to telephony/java/android/telephony/ims/RcsMessageManager.java
index d112798..a1c7c0f 100644
--- a/telephony/java/android/telephony/ims/RcsMessageStore.java
+++ b/telephony/java/android/telephony/ims/RcsMessageManager.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.SystemService;
 import android.annotation.WorkerThread;
 import android.content.Context;
 import android.net.Uri;
@@ -25,15 +26,20 @@
 import java.util.List;
 
 /**
- * RcsMessageStore is the application interface to RcsProvider and provides access methods to
+ * RcsMessageManager is the application interface to RcsProvider and provides access methods to
  * RCS related database tables.
  *
  * @hide
  */
-public class RcsMessageStore {
+@SystemService(Context.TELEPHONY_RCS_MESSAGE_SERVICE)
+public class RcsMessageManager {
     RcsControllerCall mRcsControllerCall;
 
-    RcsMessageStore(Context context) {
+    /**
+     * Use {@link Context#getSystemService(String)} to get an instance of this service.
+     * @hide
+     */
+    public RcsMessageManager(Context context) {
         mRcsControllerCall = new RcsControllerCall(context);
     }
 
diff --git a/telephony/java/android/telephony/ims/aidl/IRcs.aidl b/telephony/java/android/telephony/ims/aidl/IRcsMessage.aidl
similarity index 99%
rename from telephony/java/android/telephony/ims/aidl/IRcs.aidl
rename to telephony/java/android/telephony/ims/aidl/IRcsMessage.aidl
index 9ee15da..0ae6303 100644
--- a/telephony/java/android/telephony/ims/aidl/IRcs.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IRcsMessage.aidl
@@ -35,7 +35,7 @@
  * RPC definition between RCS storage APIs and phone process.
  * {@hide}
  */
-interface IRcs {
+interface IRcsMessage {
     /////////////////////////
     // RcsMessageStore APIs
     /////////////////////////
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 5a27a0f..dcfd193 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -308,18 +308,46 @@
      */
     List<NeighboringCellInfo> getNeighboringCellInfo(String callingPkg);
 
-     @UnsupportedAppUsage
-     int getCallState();
+    @UnsupportedAppUsage
+    int getCallState();
 
     /**
      * Returns the call state for a slot.
      */
-     int getCallStateForSlot(int slotIndex);
+    int getCallStateForSlot(int slotIndex);
 
-     @UnsupportedAppUsage
-     int getDataActivity();
-     @UnsupportedAppUsage
-     int getDataState();
+    /**
+     * Replaced by getDataActivityForSubId.
+     */
+    int getDataActivity();
+
+    /**
+     * Returns a constant indicating the type of activity on a data connection
+     * (cellular).
+     *
+     * @see #DATA_ACTIVITY_NONE
+     * @see #DATA_ACTIVITY_IN
+     * @see #DATA_ACTIVITY_OUT
+     * @see #DATA_ACTIVITY_INOUT
+     * @see #DATA_ACTIVITY_DORMANT
+     */
+    int getDataActivityForSubId(int subId);
+
+    /**
+     * Replaced by getDataStateForSubId.
+     */
+    int getDataState();
+
+    /**
+     * Returns a constant indicating the current data connection state
+     * (cellular).
+     *
+     * @see #DATA_DISCONNECTED
+     * @see #DATA_CONNECTING
+     * @see #DATA_CONNECTED
+     * @see #DATA_SUSPENDED
+     */
+    int getDataStateForSubId(int subId);
 
     /**
      * Returns the current active phone type as integer.
@@ -1059,6 +1087,11 @@
     String[] getMergedSubscriberIds(int subId, String callingPackage);
 
     /**
+     * @hide
+     */
+    String[] getMergedSubscriberIdsFromGroup(int subId, String callingPackage);
+
+    /**
      * Override the operator branding for the current ICCID.
      *
      * Once set, whenever the SIM is present in the device, the service
diff --git a/telephony/java/com/android/internal/telephony/TelephonyPermissions.java b/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
index 7a0ab9c..51c5d12 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
@@ -600,26 +600,21 @@
         }
     }
 
-    /**
-     * Returns whether the provided uid has carrier privileges for any active subscription ID.
-     */
-    private static boolean checkCarrierPrivilegeForAnySubId(Context context,
-            Supplier<ITelephony> telephonySupplier, int uid) {
+    /** Returns whether the provided uid has carrier privileges for any active subscription ID. */
+    private static boolean checkCarrierPrivilegeForAnySubId(
+            Context context, Supplier<ITelephony> telephonySupplier, int uid) {
         SubscriptionManager sm = (SubscriptionManager) context.getSystemService(
                 Context.TELEPHONY_SUBSCRIPTION_SERVICE);
-        int[] activeSubIds = sm.getActiveSubscriptionIdList();
-        if (activeSubIds != null) {
-            for (int activeSubId : activeSubIds) {
-                if (getCarrierPrivilegeStatus(telephonySupplier, activeSubId, uid)
-                        == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
-                    return true;
-                }
+        int[] activeSubIds = sm.getActiveSubscriptionIdList(/* visibleOnly */ false);
+        for (int activeSubId : activeSubIds) {
+            if (getCarrierPrivilegeStatus(telephonySupplier, activeSubId, uid)
+                    == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
+                return true;
             }
         }
         return false;
     }
 
-
     private static int getCarrierPrivilegeStatus(
             Supplier<ITelephony> telephonySupplier, int subId, int uid) {
         ITelephony telephony = telephonySupplier.get();
diff --git a/test-mock/api/test-current.txt b/test-mock/api/test-current.txt
index a87e2f5..cc260ac 100644
--- a/test-mock/api/test-current.txt
+++ b/test-mock/api/test-current.txt
@@ -7,6 +7,7 @@
   }
 
   @Deprecated public class MockPackageManager extends android.content.pm.PackageManager {
+    method public void addOnPermissionsChangeListener(android.content.pm.PackageManager.OnPermissionsChangedListener);
     method public boolean arePermissionsIndividuallyControlled();
     method public String getDefaultBrowserPackageNameAsUser(int);
     method public int getInstallReason(String, android.os.UserHandle);
@@ -18,6 +19,7 @@
     method @NonNull public String getServicesSystemSharedLibraryPackageName();
     method @NonNull public String getSharedSystemSharedLibraryPackageName();
     method public void grantRuntimePermission(String, String, android.os.UserHandle);
+    method public void removeOnPermissionsChangeListener(android.content.pm.PackageManager.OnPermissionsChangedListener);
     method public void revokeRuntimePermission(String, String, android.os.UserHandle);
     method public void updatePermissionFlags(String, String, int, int, android.os.UserHandle);
   }
diff --git a/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamBoolTest.java b/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamBoolTest.java
index c21c403..3415d2e 100644
--- a/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamBoolTest.java
+++ b/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamBoolTest.java
@@ -384,55 +384,55 @@
         };
 
         ProtoInputStream pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readFloat(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readDouble(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readInt(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readLong(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readBytes(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readString(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
diff --git a/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamBytesTest.java b/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamBytesTest.java
index 09fe40e..8796807 100644
--- a/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamBytesTest.java
+++ b/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamBytesTest.java
@@ -306,55 +306,55 @@
         };
 
         ProtoInputStream pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readFloat(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readDouble(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readInt(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readLong(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readBoolean(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readString(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
diff --git a/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamDoubleTest.java b/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamDoubleTest.java
index 118fe34..2b54e96 100644
--- a/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamDoubleTest.java
+++ b/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamDoubleTest.java
@@ -611,55 +611,55 @@
         };
 
         ProtoInputStream pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readFloat(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readBoolean(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readInt(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readLong(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readBytes(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readString(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
diff --git a/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamEnumTest.java b/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamEnumTest.java
index f55d951..19bad70 100644
--- a/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamEnumTest.java
+++ b/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamEnumTest.java
@@ -454,55 +454,55 @@
         };
 
         ProtoInputStream pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readFloat(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readDouble(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readBoolean(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readLong(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readBytes(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readString(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
diff --git a/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamFixed32Test.java b/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamFixed32Test.java
index df68476..2bc61a0 100644
--- a/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamFixed32Test.java
+++ b/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamFixed32Test.java
@@ -431,55 +431,55 @@
         };
 
         ProtoInputStream pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readFloat(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readDouble(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readBoolean(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readLong(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readBytes(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readString(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
diff --git a/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamFixed64Test.java b/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamFixed64Test.java
index af4130b..a54ecf9 100644
--- a/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamFixed64Test.java
+++ b/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamFixed64Test.java
@@ -532,55 +532,55 @@
         };
 
         ProtoInputStream pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readFloat(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readDouble(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readInt(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readBoolean(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readBytes(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readString(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
diff --git a/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamFloatTest.java b/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamFloatTest.java
index 9bc07dc..0477e9e 100644
--- a/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamFloatTest.java
+++ b/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamFloatTest.java
@@ -563,55 +563,55 @@
         };
 
         ProtoInputStream pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readBoolean(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readDouble(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readInt(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readLong(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readBytes(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readString(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
diff --git a/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamInt32Test.java b/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamInt32Test.java
index 0065870..a7f3f65 100644
--- a/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamInt32Test.java
+++ b/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamInt32Test.java
@@ -449,55 +449,55 @@
         };
 
         ProtoInputStream pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readFloat(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readDouble(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readBoolean(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readLong(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readBytes(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readString(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
diff --git a/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamInt64Test.java b/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamInt64Test.java
index 4d6d105..dc42468 100644
--- a/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamInt64Test.java
+++ b/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamInt64Test.java
@@ -529,55 +529,55 @@
         };
 
         ProtoInputStream pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readFloat(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readDouble(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readInt(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readBoolean(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readBytes(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readString(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
diff --git a/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamObjectTest.java b/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamObjectTest.java
index 5e49eea..1c0832e 100644
--- a/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamObjectTest.java
+++ b/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamObjectTest.java
@@ -391,55 +391,55 @@
         };
 
         ProtoInputStream pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readFloat(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readDouble(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readInt(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readLong(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readBoolean(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readString(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
diff --git a/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamSFixed32Test.java b/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamSFixed32Test.java
index 75c88a4..d349ea2 100644
--- a/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamSFixed32Test.java
+++ b/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamSFixed32Test.java
@@ -431,55 +431,55 @@
         };
 
         ProtoInputStream pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readFloat(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readDouble(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readBoolean(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readLong(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readBytes(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readString(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
diff --git a/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamSFixed64Test.java b/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamSFixed64Test.java
index 4c65cf4..81a9c59 100644
--- a/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamSFixed64Test.java
+++ b/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamSFixed64Test.java
@@ -531,55 +531,55 @@
         };
 
         ProtoInputStream pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readFloat(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readDouble(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readInt(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readBoolean(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readBytes(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readString(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
diff --git a/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamSInt32Test.java b/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamSInt32Test.java
index 6854cd8..9719444 100644
--- a/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamSInt32Test.java
+++ b/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamSInt32Test.java
@@ -431,55 +431,55 @@
         };
 
         ProtoInputStream pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readFloat(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readDouble(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readBoolean(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readLong(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readBytes(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readString(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
diff --git a/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamSInt64Test.java b/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamSInt64Test.java
index c53e9d7..118476c 100644
--- a/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamSInt64Test.java
+++ b/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamSInt64Test.java
@@ -506,55 +506,55 @@
         };
 
         ProtoInputStream pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readFloat(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readDouble(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readInt(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readBoolean(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readBytes(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readString(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
diff --git a/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamStringTest.java b/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamStringTest.java
index 816d5f9..51ee78f 100644
--- a/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamStringTest.java
+++ b/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamStringTest.java
@@ -287,55 +287,55 @@
         };
 
         ProtoInputStream pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readFloat(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readDouble(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readInt(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readLong(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readBytes(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readBoolean(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
diff --git a/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamUInt32Test.java b/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamUInt32Test.java
index 50fc537..42f3e99 100644
--- a/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamUInt32Test.java
+++ b/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamUInt32Test.java
@@ -448,55 +448,55 @@
         };
 
         ProtoInputStream pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readFloat(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readDouble(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readBoolean(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readLong(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readBytes(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readString(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
diff --git a/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamUInt64Test.java b/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamUInt64Test.java
index 20969e9..8ba2c0c 100644
--- a/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamUInt64Test.java
+++ b/tests/ProtoInputStreamTests/src/com/android/test/protoinputstream/ProtoInputStreamUInt64Test.java
@@ -525,55 +525,55 @@
         };
 
         ProtoInputStream pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readFloat(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readDouble(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readInt(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readBoolean(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readBytes(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
 
         pi = new ProtoInputStream(protobuf);
-        pi.isNextField(fieldId1);
+        pi.nextField();
         try {
             pi.readString(fieldId1);
-            fail("Should have throw IllegalArgumentException");
+            fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException iae) {
             // good
         }
diff --git a/tools/aapt2/cmd/Optimize.h b/tools/aapt2/cmd/Optimize.h
index 7f4a3ed..0be7dad 100644
--- a/tools/aapt2/cmd/Optimize.h
+++ b/tools/aapt2/cmd/Optimize.h
@@ -57,7 +57,7 @@
   std::unordered_set<std::string> kept_artifacts;
 
   // Whether or not to shorten resource paths in the APK.
-  bool shorten_resource_paths;
+  bool shorten_resource_paths = false;
 
   // Path to the output map of original resource paths to shortened paths.
   Maybe<std::string> shortened_paths_map_path;
diff --git a/tools/preload2/Android.bp b/tools/preload2/Android.bp
new file mode 100644
index 0000000..5809421
--- /dev/null
+++ b/tools/preload2/Android.bp
@@ -0,0 +1,50 @@
+// 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.
+
+java_library_host {
+    name: "preload2",
+
+    srcs: ["src/**/*.java"],
+
+    // To connect to devices (and take hprof dumps).
+    static_libs: [
+        "ddmlib-prebuilt",
+        "tools-common-prebuilt",
+
+        // To process hprof dumps.
+        "perflib-prebuilt",
+
+        "trove-prebuilt",
+        "guavalib",
+
+        // For JDWP access we use the framework in the JDWP tests from Apache Harmony, for
+        // convenience (and to not depend on internal JDK APIs).
+        "apache-harmony-jdwp-tests",
+        "junit",
+    ],
+
+    // Copy to build artifacts
+    dist: {
+        targets: [
+            "dist_files",
+        ],
+    },
+}
+
+// Copy the preload-tool shell script to the host's bin directory.
+sh_binary_host {
+    name: "preload-tool",
+    src: "preload-tool",
+    required: ["preload2"],
+}
diff --git a/tools/preload2/Android.mk b/tools/preload2/Android.mk
deleted file mode 100644
index d3ee1d3..0000000
--- a/tools/preload2/Android.mk
+++ /dev/null
@@ -1,30 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under,src)
-
-# To connect to devices (and take hprof dumps).
-LOCAL_STATIC_JAVA_LIBRARIES := ddmlib-prebuilt tools-common-prebuilt
-
-# To process hprof dumps.
-LOCAL_STATIC_JAVA_LIBRARIES += perflib-prebuilt trove-prebuilt guavalib
-
-# For JDWP access we use the framework in the JDWP tests from Apache Harmony, for
-# convenience (and to not depend on internal JDK APIs).
-LOCAL_STATIC_JAVA_LIBRARIES += apache-harmony-jdwp-tests-host junit-host
-
-LOCAL_MODULE:= preload2
-
-include $(BUILD_HOST_JAVA_LIBRARY)
-# Copy to build artifacts
-$(call dist-for-goals,dist_files,$(LOCAL_BUILT_MODULE):$(LOCAL_MODULE).jar)
-
-# Copy the preload-tool shell script to the host's bin directory.
-include $(CLEAR_VARS)
-LOCAL_IS_HOST_MODULE := true
-LOCAL_MODULE_CLASS := EXECUTABLES
-LOCAL_MODULE := preload-tool
-LOCAL_SRC_FILES := preload-tool
-LOCAL_REQUIRED_MODULES := preload2
-include $(BUILD_PREBUILT)
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 9010f3c9..1829baa 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -29,7 +29,6 @@
 import android.net.wifi.ISoftApCallback;
 import android.net.wifi.ITrafficStateCallback;
 import android.net.wifi.IOnWifiUsabilityStatsListener;
-import android.net.wifi.PasspointManagementObjectDefinition;
 import android.net.wifi.ScanResult;
 import android.net.wifi.WifiActivityEnergyInfo;
 import android.net.wifi.WifiConfiguration;
diff --git a/wifi/java/android/net/wifi/PasspointManagementObjectDefinition.aidl b/wifi/java/android/net/wifi/PasspointManagementObjectDefinition.aidl
deleted file mode 100644
index eb7cc39..0000000
--- a/wifi/java/android/net/wifi/PasspointManagementObjectDefinition.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/**
- * 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.
- */
-
-package android.net.wifi;
-
-parcelable PasspointManagementObjectDefinition;
diff --git a/wifi/java/android/net/wifi/PasspointManagementObjectDefinition.java b/wifi/java/android/net/wifi/PasspointManagementObjectDefinition.java
deleted file mode 100644
index 70577b9..0000000
--- a/wifi/java/android/net/wifi/PasspointManagementObjectDefinition.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * 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.
- */
-
-package android.net.wifi;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * This object describes a partial tree structure in the Hotspot 2.0 release 2 management object.
- * The object is used during subscription remediation to modify parts of an existing PPS MO
- * tree (Hotspot 2.0 specification section 9.1).
- * @hide
- */
-public class PasspointManagementObjectDefinition implements Parcelable {
-    private final String mBaseUri;
-    private final String mUrn;
-    private final String mMoTree;
-
-    public PasspointManagementObjectDefinition(String baseUri, String urn, String moTree) {
-        mBaseUri = baseUri;
-        mUrn = urn;
-        mMoTree = moTree;
-    }
-
-    public String getBaseUri() {
-        return mBaseUri;
-    }
-
-    public String getUrn() {
-        return mUrn;
-    }
-
-    public String getMoTree() {
-        return mMoTree;
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeString(mBaseUri);
-        dest.writeString(mUrn);
-        dest.writeString(mMoTree);
-    }
-
-    /**
-     * Implement the Parcelable interface {@hide}
-     */
-    public static final @android.annotation.NonNull Creator<PasspointManagementObjectDefinition> CREATOR =
-            new Creator<PasspointManagementObjectDefinition>() {
-                public PasspointManagementObjectDefinition createFromParcel(Parcel in) {
-                    return new PasspointManagementObjectDefinition(
-                            in.readString(),    /* base URI */
-                            in.readString(),    /* URN */
-                            in.readString()     /* Tree XML */
-                    );
-                }
-
-                public PasspointManagementObjectDefinition[] newArray(int size) {
-                    return new PasspointManagementObjectDefinition[size];
-                }
-            };
-}
-
diff --git a/wifi/java/android/net/wifi/WpsResult.aidl b/wifi/java/android/net/wifi/WpsResult.aidl
deleted file mode 100644
index eb4c4f5..0000000
--- a/wifi/java/android/net/wifi/WpsResult.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/**
- * 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.
- */
-
-package android.net.wifi;
-
-parcelable WpsResult;
diff --git a/wifi/java/android/net/wifi/WpsResult.java b/wifi/java/android/net/wifi/WpsResult.java
deleted file mode 100644
index f2ffb6f..0000000
--- a/wifi/java/android/net/wifi/WpsResult.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * 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.
- */
-
-package android.net.wifi;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * A class representing the result of a WPS request
- * @hide
- */
-public class WpsResult implements Parcelable {
-
-    public enum Status {
-        SUCCESS,
-        FAILURE,
-        IN_PROGRESS,
-    }
-
-    public Status status;
-
-    public String pin;
-
-    public WpsResult() {
-        status = Status.FAILURE;
-        pin = null;
-    }
-
-    public WpsResult(Status s) {
-        status = s;
-        pin = null;
-    }
-
-    public String toString() {
-        StringBuffer sbuf = new StringBuffer();
-        sbuf.append(" status: ").append(status.toString());
-        sbuf.append('\n');
-        sbuf.append(" pin: ").append(pin);
-        sbuf.append("\n");
-        return sbuf.toString();
-    }
-
-    /** Implement the Parcelable interface {@hide} */
-    public int describeContents() {
-        return 0;
-    }
-
-    /** copy constructor {@hide} */
-    public WpsResult(WpsResult source) {
-        if (source != null) {
-            status = source.status;
-            pin = source.pin;
-        }
-    }
-
-    /** Implement the Parcelable interface {@hide} */
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeString(status.name());
-        dest.writeString(pin);
-    }
-
-    /** Implement the Parcelable interface {@hide} */
-    public static final @android.annotation.NonNull Creator<WpsResult> CREATOR =
-        new Creator<WpsResult>() {
-            public WpsResult createFromParcel(Parcel in) {
-                WpsResult result = new WpsResult();
-                result.status = Status.valueOf(in.readString());
-                result.pin = in.readString();
-                return result;
-            }
-
-            public WpsResult[] newArray(int size) {
-                return new WpsResult[size];
-            }
-        };
-}
diff --git a/wifi/java/android/net/wifi/hotspot2/pps/Policy.aidl b/wifi/java/android/net/wifi/hotspot2/pps/Policy.aidl
deleted file mode 100644
index e923f1f..0000000
--- a/wifi/java/android/net/wifi/hotspot2/pps/Policy.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.wifi.hotspot2.pps;
-
-parcelable Policy;
diff --git a/wifi/java/android/net/wifi/hotspot2/pps/UpdateParameter.aidl b/wifi/java/android/net/wifi/hotspot2/pps/UpdateParameter.aidl
deleted file mode 100644
index 701db47..0000000
--- a/wifi/java/android/net/wifi/hotspot2/pps/UpdateParameter.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net.wifi.hotspot2.pps;
-
-parcelable UpdateParameter;
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pGroupList.aidl b/wifi/java/android/net/wifi/p2p/WifiP2pGroupList.aidl
deleted file mode 100644
index 3d8a476..0000000
--- a/wifi/java/android/net/wifi/p2p/WifiP2pGroupList.aidl
+++ /dev/null
@@ -1,19 +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.net.wifi.p2p;
-
-parcelable WifiP2pGroupList;
\ No newline at end of file
diff --git a/wifi/java/android/net/wifi/p2p/nsd/WifiP2pServiceResponse.aidl b/wifi/java/android/net/wifi/p2p/nsd/WifiP2pServiceResponse.aidl
deleted file mode 100644
index c81d1f9..0000000
--- a/wifi/java/android/net/wifi/p2p/nsd/WifiP2pServiceResponse.aidl
+++ /dev/null
@@ -1,19 +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.net.wifi.p2p.servicediscovery;
-
-parcelable WifiP2pServiceResponse;