Merge changes I3e6b6b44,I467e4264

* changes:
  Run system_server benchmarks for 5 seconds
  Add additional system_server benchmarks
diff --git a/Android.bp b/Android.bp
index 121decb..ee3cb8f 100644
--- a/Android.bp
+++ b/Android.bp
@@ -234,6 +234,11 @@
             "wifi/java",
         ],
     },
+
+    required: [
+        // TODO: remove gps_debug when the build system propagates "required" properly.
+        "gps_debug.conf",
+    ],
 }
 
 // Collection of classes that are generated from non-Java files that are not listed in
@@ -307,11 +312,6 @@
 
     static_libs: ["framework-internal-utils"],
 
-    required: [
-        // TODO: remove gps_debug when the build system propagates "required" properly.
-        "gps_debug.conf",
-    ],
-
     dxflags: [
         "--core-library",
         "--multi-dex",
diff --git a/api/current.txt b/api/current.txt
index 26c90df..e3fde23 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -16906,9 +16906,10 @@
     method @NonNull public abstract android.hardware.camera2.CaptureRequest.Builder createReprocessCaptureRequest(@NonNull android.hardware.camera2.TotalCaptureResult) throws android.hardware.camera2.CameraAccessException;
     method public abstract void createReprocessableCaptureSession(@NonNull android.hardware.camera2.params.InputConfiguration, @NonNull java.util.List<android.view.Surface>, @NonNull android.hardware.camera2.CameraCaptureSession.StateCallback, @Nullable android.os.Handler) throws android.hardware.camera2.CameraAccessException;
     method public abstract void createReprocessableCaptureSessionByConfigurations(@NonNull android.hardware.camera2.params.InputConfiguration, @NonNull java.util.List<android.hardware.camera2.params.OutputConfiguration>, @NonNull android.hardware.camera2.CameraCaptureSession.StateCallback, @Nullable android.os.Handler) throws android.hardware.camera2.CameraAccessException;
+    method public int getCameraAudioRestriction() throws android.hardware.camera2.CameraAccessException;
     method @NonNull public abstract String getId();
     method public boolean isSessionConfigurationSupported(@NonNull android.hardware.camera2.params.SessionConfiguration) throws android.hardware.camera2.CameraAccessException;
-    method public int setCameraAudioRestriction(int) throws android.hardware.camera2.CameraAccessException;
+    method public void setCameraAudioRestriction(int) throws android.hardware.camera2.CameraAccessException;
     field public static final int AUDIO_RESTRICTION_NONE = 0; // 0x0
     field public static final int AUDIO_RESTRICTION_VIBRATION = 1; // 0x1
     field public static final int AUDIO_RESTRICTION_VIBRATION_SOUND = 3; // 0x3
diff --git a/cmds/app_process/Android.bp b/cmds/app_process/Android.bp
index f925023..8be95e4 100644
--- a/cmds/app_process/Android.bp
+++ b/cmds/app_process/Android.bp
@@ -22,7 +22,6 @@
         "libcutils",
         "libdl",
         "libhidlbase",
-        "libhwbinder",
         "liblog",
         "libnativeloader",
         "libutils",
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 15c6425..287a289 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -146,6 +146,7 @@
 import java.io.PrintWriter;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -3646,6 +3647,22 @@
         return false;
     }
 
+    private static final class RequestFinishCallback extends IRequestFinishCallback.Stub {
+        private final WeakReference<Activity> mActivityRef;
+
+        RequestFinishCallback(WeakReference<Activity> activityRef) {
+            mActivityRef = activityRef;
+        }
+
+        @Override
+        public void requestFinish() {
+            Activity activity = mActivityRef.get();
+            if (activity != null) {
+                activity.mHandler.post(activity::finishAfterTransition);
+            }
+        }
+    }
+
     /**
      * Called when the activity has detected the user's press of the back
      * key.  The default implementation simply finishes the current activity,
@@ -3671,11 +3688,7 @@
             // while at the root of the task. This call allows ActivityTaskManager
             // to intercept or defer finishing.
             ActivityTaskManager.getService().onBackPressedOnTaskRoot(mToken,
-                    new IRequestFinishCallback.Stub() {
-                        public void requestFinish() {
-                            mHandler.post(() -> finishAfterTransition());
-                        }
-                    });
+                    new RequestFinishCallback(new WeakReference<>(this)));
         } catch (RemoteException e) {
             finishAfterTransition();
         }
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 1f283ea..bb87d96 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -5845,39 +5845,42 @@
                     ActivityThread.currentOpPackageName())) {
                 // This app is noting an app-op for itself. Deliver immediately.
                 sNotedAppOpsCollector.onSelfNoted(new SyncNotedAppOp(code));
-            } else if (binderUid != null && binderUid == uid) {
-                // We are inside of a two-way binder call. Delivered to caller via
-                // {@link #prefixParcelWithAppOpsIfNeeded}
-                long[] appOpsNotedInThisBinderTransaction;
 
-                appOpsNotedInThisBinderTransaction = sAppOpsNotedInThisBinderTransaction.get();
-                if (appOpsNotedInThisBinderTransaction == null) {
-                    appOpsNotedInThisBinderTransaction = new long[2];
-                    sAppOpsNotedInThisBinderTransaction.set(appOpsNotedInThisBinderTransaction);
-                }
+                return;
+            }
+        }
 
-                if (code < 64) {
-                    appOpsNotedInThisBinderTransaction[0] |= 1L << code;
-                } else {
-                    appOpsNotedInThisBinderTransaction[1] |= 1L << (code - 64);
-                }
+        if (binderUid != null && binderUid == uid) {
+            // If this is inside of a two-way binder call: Delivered to caller via
+            // {@link #prefixParcelWithAppOpsIfNeeded}
+            long[] appOpsNotedInThisBinderTransaction;
+
+            appOpsNotedInThisBinderTransaction = sAppOpsNotedInThisBinderTransaction.get();
+            if (appOpsNotedInThisBinderTransaction == null) {
+                appOpsNotedInThisBinderTransaction = new long[2];
+                sAppOpsNotedInThisBinderTransaction.set(appOpsNotedInThisBinderTransaction);
+            }
+
+            if (code < 64) {
+                appOpsNotedInThisBinderTransaction[0] |= 1L << code;
             } else {
-                // We cannot deliver the note synchronous. Hence send it to the system server to
-                // notify the noted process.
-                if (message == null) {
-                    // Default message is a stack trace
-                    message = getFormattedStackTrace();
-                }
+                appOpsNotedInThisBinderTransaction[1] |= 1L << (code - 64);
+            }
+        } else {
+            // Cannot deliver the note synchronous: Hence send it to the system server to
+            // notify the noted process.
+            if (message == null) {
+                // Default message is a stack trace
+                message = getFormattedStackTrace();
+            }
 
-                long token = Binder.clearCallingIdentity();
-                try {
-                    mService.noteAsyncOp(mContext.getOpPackageName(), uid, packageName, code,
-                            message);
-                } catch (RemoteException e) {
-                    e.rethrowFromSystemServer();
-                } finally {
-                    Binder.restoreCallingIdentity(token);
-                }
+            long token = Binder.clearCallingIdentity();
+            try {
+                mService.noteAsyncOp(mContext.getOpPackageName(), uid, packageName, code, message);
+            } catch (RemoteException e) {
+                e.rethrowFromSystemServer();
+            } finally {
+                Binder.restoreCallingIdentity(token);
             }
         }
     }
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index 9cf54f4..ac1cbd4 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -23,6 +23,7 @@
 import static android.content.ConfigurationProto.KEYBOARD;
 import static android.content.ConfigurationProto.KEYBOARD_HIDDEN;
 import static android.content.ConfigurationProto.LOCALES;
+import static android.content.ConfigurationProto.LOCALE_LIST;
 import static android.content.ConfigurationProto.MCC;
 import static android.content.ConfigurationProto.MNC;
 import static android.content.ConfigurationProto.NAVIGATION;
@@ -1111,7 +1112,7 @@
             protoOutputStream.write(MCC, mcc);
             protoOutputStream.write(MNC, mnc);
             if (mLocaleList != null) {
-                mLocaleList.writeToProto(protoOutputStream, LOCALES);
+                protoOutputStream.write(LOCALE_LIST, mLocaleList.toLanguageTags());
             }
             protoOutputStream.write(SCREEN_LAYOUT, screenLayout);
             protoOutputStream.write(COLOR_MODE, colorMode);
@@ -1283,6 +1284,14 @@
                     case (int) WINDOW_CONFIGURATION:
                         windowConfiguration.readFromProto(protoInputStream, WINDOW_CONFIGURATION);
                         break;
+                    case (int) LOCALE_LIST:
+                        try {
+                            setLocales(LocaleList.forLanguageTags(protoInputStream.readString(
+                                    LOCALE_LIST)));
+                        } catch (Exception e) {
+                            Slog.e(TAG, "error parsing locale list in configuration.", e);
+                        }
+                        break;
                 }
             }
         } finally {
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index b8ab114..8e8a81d 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -2169,11 +2169,18 @@
     }
 
     /**
-     * Setting camera audio restriction mode.
+     * Set camera audio restriction mode.
      *
      * @hide
      */
-    public native final int setAudioRestriction(int mode);
+    public native final void setAudioRestriction(int mode);
+
+    /**
+     * Get currently applied camera audio restriction mode.
+     *
+     * @hide
+     */
+    public native final int getAudioRestriction();
 
     /**
      * Image size (width and height dimensions).
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index ed2d0c9..0714884 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -1251,25 +1251,43 @@
      * are setting different modes, the system will pick a the mode that's union of
      * all modes set by CameraDevice.</p>
      *
-     * <p>The mute settings will be automatically removed when the CameraDevice is closed or
-     * the application is disconnected from the camera.</p>
+     * <p>The mute settings from this CameraDevice will be automatically removed when the
+     * CameraDevice is closed or the application is disconnected from the camera.</p>
      *
      * @param mode An enumeration selecting the audio restriction mode for this camera device.
      *
-     * @return The system-wide mute mode setting resulting from this call
-     *
      * @throws IllegalArgumentException if the mode is not supported
      *
      * @throws CameraAccessException if the camera device is no longer connected or has
      *                               encountered a fatal error
      * @throws IllegalStateException if the camera device has been closed
+     *
+     * @see #getCameraAudioRestriction
      */
-    public @CAMERA_AUDIO_RESTRICTION int setCameraAudioRestriction(
+    public void setCameraAudioRestriction(
             @CAMERA_AUDIO_RESTRICTION int mode) throws CameraAccessException {
         throw new UnsupportedOperationException("Subclasses must override this method");
     }
 
     /**
+     * Get currently applied global camera audio restriction mode.
+     *
+     * <p>Application can use this method to retrieve the system-wide camera audio restriction
+     * settings described in {@link #setCameraAudioRestriction}.</p>
+     *
+     * @return The system-wide mute mode setting resulting from this call
+     *
+     * @throws CameraAccessException if the camera device is no longer connected or has
+     *                               encountered a fatal error
+     * @throws IllegalStateException if the camera device has been closed
+     *
+     * @see #setCameraAudioRestriction
+     */
+    public @CAMERA_AUDIO_RESTRICTION int getCameraAudioRestriction() throws CameraAccessException {
+        throw new UnsupportedOperationException("Subclasses must override this method");
+    }
+
+    /**
      * To be inherited by android.hardware.camera2.* code only.
      * @hide
      */
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
index 1f385dd..4494d27 100644
--- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
@@ -2570,11 +2570,19 @@
     }
 
     @Override
-    public @CAMERA_AUDIO_RESTRICTION int setCameraAudioRestriction(
+    public void setCameraAudioRestriction(
             @CAMERA_AUDIO_RESTRICTION int mode) throws CameraAccessException {
         synchronized(mInterfaceLock) {
             checkIfCameraClosedOrInError();
-            return mRemoteDevice.setCameraAudioRestriction(mode);
+            mRemoteDevice.setCameraAudioRestriction(mode);
+        }
+    }
+
+    @Override
+    public @CAMERA_AUDIO_RESTRICTION int getCameraAudioRestriction() throws CameraAccessException {
+        synchronized(mInterfaceLock) {
+            checkIfCameraClosedOrInError();
+            return mRemoteDevice.getGlobalAudioRestriction();
         }
     }
 }
diff --git a/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java b/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java
index ff2819b..3660f29 100644
--- a/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java
+++ b/core/java/android/hardware/camera2/impl/ICameraDeviceUserWrapper.java
@@ -258,9 +258,18 @@
         }
     }
 
-    public int setCameraAudioRestriction(int mode) throws CameraAccessException {
+    public void setCameraAudioRestriction(int mode) throws CameraAccessException {
         try {
-            return mRemoteDevice.setCameraAudioRestriction(mode);
+            mRemoteDevice.setCameraAudioRestriction(mode);
+        } catch (Throwable t) {
+            CameraManager.throwAsPublicException(t);
+            throw new UnsupportedOperationException("Unexpected exception", t);
+        }
+    }
+
+    public int getGlobalAudioRestriction() throws CameraAccessException {
+        try {
+            return mRemoteDevice.getGlobalAudioRestriction();
         } catch (Throwable t) {
             CameraManager.throwAsPublicException(t);
             throw new UnsupportedOperationException("Unexpected exception", t);
diff --git a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
index 0fa17c1..5d1435a 100644
--- a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
+++ b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
@@ -767,14 +767,25 @@
     }
 
     @Override
-    public int setCameraAudioRestriction(int mode) {
+    public void setCameraAudioRestriction(int mode) {
         if (mLegacyDevice.isClosed()) {
             String err = "Cannot set camera audio restriction, device has been closed.";
             Log.e(TAG, err);
             throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
         }
 
-        return mLegacyDevice.setAudioRestriction(mode);
+        mLegacyDevice.setAudioRestriction(mode);
+    }
+
+    @Override
+    public int getGlobalAudioRestriction() {
+        if (mLegacyDevice.isClosed()) {
+            String err = "Cannot set camera audio restriction, device has been closed.";
+            Log.e(TAG, err);
+            throw new ServiceSpecificException(ICameraService.ERROR_DISCONNECTED, err);
+        }
+
+        return mLegacyDevice.getAudioRestriction();
     }
 
     @Override
diff --git a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
index c0d8baa..fbc9ac32 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
@@ -550,8 +550,12 @@
         return lastFrame;
     }
 
-    public int setAudioRestriction(int mode) {
-        return mRequestThreadManager.setAudioRestriction(mode);
+    public void setAudioRestriction(int mode) {
+        mRequestThreadManager.setAudioRestriction(mode);
+    }
+
+    public int getAudioRestriction() {
+        return mRequestThreadManager.getAudioRestriction();
     }
 
     /**
diff --git a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
index a514ee1..32411fb 100644
--- a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
+++ b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
@@ -1105,9 +1105,16 @@
         condition.block();
     }
 
-    public int setAudioRestriction(int mode) {
+    public void setAudioRestriction(int mode) {
         if (mCamera != null) {
-            return mCamera.setAudioRestriction(mode);
+            mCamera.setAudioRestriction(mode);
+        }
+        throw new IllegalStateException("Camera has been released!");
+    }
+
+    public int getAudioRestriction() {
+        if (mCamera != null) {
+            return mCamera.getAudioRestriction();
         }
         throw new IllegalStateException("Camera has been released!");
     }
diff --git a/core/java/android/os/LocaleList.java b/core/java/android/os/LocaleList.java
index 7782753..0de09ef 100644
--- a/core/java/android/os/LocaleList.java
+++ b/core/java/android/os/LocaleList.java
@@ -21,9 +21,7 @@
 import android.annotation.Nullable;
 import android.annotation.Size;
 import android.annotation.UnsupportedAppUsage;
-import android.content.LocaleProto;
 import android.icu.util.ULocale;
-import android.util.proto.ProtoOutputStream;
 
 import com.android.internal.annotations.GuardedBy;
 
@@ -143,26 +141,6 @@
     }
 
     /**
-     * Helper to write LocaleList to a protocol buffer output stream.  Assumes the parent
-     * protobuf has declared the locale as repeated.
-     *
-     * @param protoOutputStream Stream to write the locale to.
-     * @param fieldId Field Id of the Locale as defined in the parent message.
-     * @hide
-     */
-    public void writeToProto(ProtoOutputStream protoOutputStream, long fieldId) {
-        for (int i = 0; i < mList.length; i++) {
-            final Locale locale = mList[i];
-            final long token = protoOutputStream.start(fieldId);
-            protoOutputStream.write(LocaleProto.LANGUAGE, locale.getLanguage());
-            protoOutputStream.write(LocaleProto.COUNTRY, locale.getCountry());
-            protoOutputStream.write(LocaleProto.VARIANT, locale.getVariant());
-            protoOutputStream.write(LocaleProto.SCRIPT, locale.getScript());
-            protoOutputStream.end(token);
-        }
-    }
-
-    /**
      * Retrieves a String representation of the language tags in this list.
      */
     @NonNull
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index b5d4945..31995f7 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -460,7 +460,7 @@
         ZygoteHooks.gcAndFinalize();
     }
 
-    private static boolean profileSystemServer() {
+    private static boolean shouldProfileSystemServer() {
         boolean defaultValue = SystemProperties.getBoolean("dalvik.vm.profilesystemserver",
                 /*default=*/ false);
         // Can't use DeviceConfig since it's not initialized at this point.
@@ -492,7 +492,7 @@
             }
             // Capturing profiles is only supported for debug or eng builds since selinux normally
             // prevents it.
-            if (profileSystemServer() && (Build.IS_USERDEBUG || Build.IS_ENG)) {
+            if (shouldProfileSystemServer() && (Build.IS_USERDEBUG || Build.IS_ENG)) {
                 try {
                     Log.d(TAG, "Preparing system server profile");
                     prepareSystemServerProfile(systemServerClasspath);
@@ -765,8 +765,7 @@
             Zygote.applyDebuggerSystemProperty(parsedArgs);
             Zygote.applyInvokeWithSystemProperty(parsedArgs);
 
-            if (profileSystemServer()) {
-
+            if (shouldProfileSystemServer()) {
                 parsedArgs.mRuntimeFlags |= Zygote.PROFILE_SYSTEM_SERVER;
             }
 
diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp
index f87163b..bc69735 100644
--- a/core/jni/android_hardware_Camera.cpp
+++ b/core/jni/android_hardware_Camera.cpp
@@ -1023,22 +1023,38 @@
     }
 }
 
-static int32_t android_hardware_Camera_setAudioRestriction(
+static void android_hardware_Camera_setAudioRestriction(
         JNIEnv *env, jobject thiz, jint mode)
 {
     ALOGV("setAudioRestriction");
     sp<Camera> camera = get_native_camera(env, thiz, NULL);
     if (camera == 0) {
         jniThrowRuntimeException(env, "camera has been disconnected");
-        return -1;
+        return;
     }
 
     int32_t ret = camera->setAudioRestriction(mode);
     if (ret < 0) {
         jniThrowRuntimeException(env, "Illegal argument or low-level eror");
+        return;
+    }
+}
+
+static int32_t android_hardware_Camera_getAudioRestriction(
+        JNIEnv *env, jobject thiz)
+{
+    ALOGV("getAudioRestriction");
+    sp<Camera> camera = get_native_camera(env, thiz, NULL);
+    if (camera == 0) {
+        jniThrowRuntimeException(env, "camera has been disconnected");
         return -1;
     }
 
+    int32_t ret = camera->getGlobalAudioRestriction();
+    if (ret < 0) {
+        jniThrowRuntimeException(env, "Illegal argument or low-level eror");
+        return -1;
+    }
     return ret;
 }
 
@@ -1127,8 +1143,11 @@
     "(I)V",
     (void *)android_hardware_Camera_enableFocusMoveCallback},
   { "setAudioRestriction",
-    "(I)I",
+    "(I)V",
     (void *)android_hardware_Camera_setAudioRestriction},
+  { "getAudioRestriction",
+    "()I",
+    (void *)android_hardware_Camera_getAudioRestriction},
 };
 
 struct field {
diff --git a/core/proto/android/content/configuration.proto b/core/proto/android/content/configuration.proto
index 57ced09..7fa0ff6 100644
--- a/core/proto/android/content/configuration.proto
+++ b/core/proto/android/content/configuration.proto
@@ -32,7 +32,7 @@
     optional float font_scale = 1;
     optional uint32 mcc = 2;
     optional uint32 mnc = 3 [ (.android.privacy).dest = DEST_EXPLICIT ];
-    repeated LocaleProto locales = 4;
+    repeated LocaleProto locales = 4 [deprecated = true];
     optional uint32 screen_layout = 5;
     optional uint32 color_mode = 6;
     optional uint32 touchscreen = 7;
@@ -48,6 +48,7 @@
     optional uint32 smallest_screen_width_dp = 17;
     optional uint32 density_dpi = 18;
     optional .android.app.WindowConfigurationProto window_configuration = 19;
+    optional string locale_list = 20;
 }
 
 /**
diff --git a/core/proto/android/content/locale.proto b/core/proto/android/content/locale.proto
index bae6ec1..a8f2a13 100644
--- a/core/proto/android/content/locale.proto
+++ b/core/proto/android/content/locale.proto
@@ -22,6 +22,7 @@
 package android.content;
 
 message LocaleProto {
+    option deprecated = true;
     option (.android.msg_privacy).dest = DEST_AUTOMATIC;
 
     optional string language = 1;
diff --git a/core/proto/android/stats/docsui/docsui_enums.proto b/core/proto/android/stats/docsui/docsui_enums.proto
index 655b5e3..f648912 100644
--- a/core/proto/android/stats/docsui/docsui_enums.proto
+++ b/core/proto/android/stats/docsui/docsui_enums.proto
@@ -184,6 +184,8 @@
     TYPE_CHIP_DOCS = 4;
     TYPE_SEARCH_HISTORY = 5;
     TYPE_SEARCH_STRING = 6;
+    TYPE_CHIP_LARGE_FILES = 7;
+    TYPE_CHIP_FROM_THIS_WEEK = 8;
 }
 
 enum SearchMode {
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index 797d75f..839aaac 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -95,6 +95,7 @@
     <string name="notification_channel_voice_mail" msgid="3954099424160511919">"Voicemail messages"</string>
     <string name="notification_channel_wfc" msgid="2130802501654254801">"Wi-Fi Calling"</string>
     <string name="notification_channel_sim" msgid="4052095493875188564">"SIM status"</string>
+    <string name="notification_channel_sim_high_prio" msgid="1787666807724243207">"High priority SIM status"</string>
     <string name="peerTtyModeFull" msgid="6165351790010341421">"Peer requested TTY Mode FULL"</string>
     <string name="peerTtyModeHco" msgid="5728602160669216784">"Peer requested TTY Mode HCO"</string>
     <string name="peerTtyModeVco" msgid="1742404978686538049">"Peer requested TTY Mode VCO"</string>
@@ -1256,10 +1257,10 @@
     <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"Tap to see all networks"</string>
     <string name="wifi_available_action_connect" msgid="2635699628459488788">"Connect"</string>
     <string name="wifi_available_action_all_networks" msgid="4368435796357931006">"All networks"</string>
-    <string name="wifi_suggestion_title" msgid="9099832833531486167">"Connect to Wi‑Fi networks?"</string>
-    <string name="wifi_suggestion_content" msgid="5883181205841582873">"Suggested by <xliff:g id="NAME">%s</xliff:g>"</string>
-    <string name="wifi_suggestion_action_allow_app" msgid="3689946344485394085">"Yes"</string>
-    <string name="wifi_suggestion_action_disallow_app" msgid="7977918905605931385">"No"</string>
+    <string name="wifi_suggestion_title" msgid="6396033039578436801">"Allow suggested Wi‑Fi networks?"</string>
+    <string name="wifi_suggestion_content" msgid="5603992011371520746">"<xliff:g id="NAME">%s</xliff:g> suggested networks. Device may connect automatically."</string>
+    <string name="wifi_suggestion_action_allow_app" msgid="7978995387498669901">"Allow"</string>
+    <string name="wifi_suggestion_action_disallow_app" msgid="6434097275967940372">"No, thanks"</string>
     <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"Wi‑Fi will turn on automatically"</string>
     <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"When you\'re near a high‑quality saved network"</string>
     <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"Don\'t turn back on"</string>
diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml
index 7ea7650..7961a86 100644
--- a/core/res/res/values-en-rXC/strings.xml
+++ b/core/res/res/values-en-rXC/strings.xml
@@ -95,6 +95,7 @@
     <string name="notification_channel_voice_mail" msgid="3954099424160511919">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‎‏‏‎‏‏‏‏‏‏‏‎‎‏‎‎‎‎‏‏‏‏‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‏‏‏‏‏‎‏‏‏‏‎‏‎‏‏‏‏‎Voicemail messages‎‏‎‎‏‎"</string>
     <string name="notification_channel_wfc" msgid="2130802501654254801">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‏‏‎‎‏‎‎‏‎‎‎‏‎‎‎‎‏‏‎‎‏‎‏‎‏‏‏‏‏‎‏‎‏‏‎‎‏‏‏‎‏‏‎‎‏‎‏‎‎‏‏‎‏‎‎‎‏‎Wi-Fi calling‎‏‎‎‏‎"</string>
     <string name="notification_channel_sim" msgid="4052095493875188564">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‎‎‎‏‏‏‎‏‏‏‏‏‎‏‏‏‏‎‏‏‎‎‎‎‏‏‏‏‏‏‏‎‎‎‏‏‎‎‏‎‎‎‏‎‎‎‎‏‏‎‏‎‏‎‏‎‎‎SIM status‎‏‎‎‏‎"</string>
+    <string name="notification_channel_sim_high_prio" msgid="1787666807724243207">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‎‏‏‎‎‏‏‏‏‎‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‏‏‏‏‎‏‏‎‎‏‎‏‎‎‎‏‏‏‏‏‎‎‏‎‎‎‎‎‏‏‏‎High priority SIM status‎‏‎‎‏‎"</string>
     <string name="peerTtyModeFull" msgid="6165351790010341421">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‏‎‎‎‏‏‏‏‏‎‏‏‏‎‏‎‏‏‎‎‏‎‎‏‏‎‎‏‏‏‏‎‏‏‏‎‎‎‏‎‏‎‎‏‏‎‎‎‎‎‏‎‏‏‎‏‎Peer requested TTY Mode FULL‎‏‎‎‏‎"</string>
     <string name="peerTtyModeHco" msgid="5728602160669216784">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‏‏‎‎‎‎‎‎‎‎‎‎‏‎‏‎‏‎‏‎‏‎‎‎‎‎‏‎‎‏‏‏‎‎‎‏‏‏‎‎‏‎‏‎‏‎‎‎‎‎‎‎‏‎‎‎‎‎Peer requested TTY Mode HCO‎‏‎‎‏‎"</string>
     <string name="peerTtyModeVco" msgid="1742404978686538049">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‎‎‎‏‎‏‏‏‎‎‏‎‎‎‏‎‎‎‎‎‏‏‎‎‎‏‎‏‏‎‎‎‏‎‏‏‏‏‎‏‏‏‎‏‏‎‎‎‏‎‏‎‎‎‎‎‏‎Peer requested TTY Mode VCO‎‏‎‎‏‎"</string>
@@ -1256,10 +1257,10 @@
     <string name="wifi_available_content_failed_to_connect" msgid="3377406637062802645">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‏‎‏‏‎‏‏‏‏‎‏‏‏‏‎‏‎‏‎‏‏‏‎‎‎‏‎‎‏‏‎‎‎‎‎‎‏‎‏‏‎‎‏‏‎‎‏‏‎‎‏‏‎‏‎‏‎‏‎Tap to see all networks‎‏‎‎‏‎"</string>
     <string name="wifi_available_action_connect" msgid="2635699628459488788">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‎‏‎‎‏‎‎‏‏‏‏‏‎‎‎‏‎‏‏‎‏‏‎‎‎‏‏‏‏‏‎‎‎‏‏‏‏‎‏‎‎‏‏‏‏‎‏‏‎‎‎‎‏‎‏‎‎‎Connect‎‏‎‎‏‎"</string>
     <string name="wifi_available_action_all_networks" msgid="4368435796357931006">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‎‏‎‎‏‏‏‏‏‏‏‎‎‏‏‎‏‎‎‏‏‎‏‏‎‎‎‏‏‏‎‏‎‎‎‎‎‎‎‏‏‏‏‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎All networks‎‏‎‎‏‎"</string>
-    <string name="wifi_suggestion_title" msgid="9099832833531486167">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‎‎‏‎‎‏‎‎‎‏‏‎‎‏‏‎‏‏‏‏‏‏‏‏‎‎‎‏‏‎‎‎‎‏‎‏‎‎‏‎‎‏‏‏‏‏‏‏‎‏‎‏‏‏‎Connect to Wi‑Fi networks?‎‏‎‎‏‎"</string>
-    <string name="wifi_suggestion_content" msgid="5883181205841582873">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‏‏‎‏‎‎‏‎‏‎‏‎‎‎‎‏‎‎‎‏‎‎‎‏‎‏‏‏‎‎‎‏‏‎‏‏‏‎‎‎‏‎‎‎‏‏‎‏‏‎‎‎‏‏‎‎‏‎Suggested by ‎‏‎‎‏‏‎<xliff:g id="NAME">%s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
-    <string name="wifi_suggestion_action_allow_app" msgid="3689946344485394085">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‏‎‎‏‏‎‏‎‏‎‏‎‏‎‎‏‎‏‎‏‎‎‏‏‎‎‏‏‎‏‏‏‏‎‏‎‎‏‏‎‏‏‎‎‏‎‏‏‎‏‎‏‎‎‏‎‏‎Yes‎‏‎‎‏‎"</string>
-    <string name="wifi_suggestion_action_disallow_app" msgid="7977918905605931385">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‎‏‎‏‏‎‏‏‏‎‏‎‎‎‎‏‎‏‏‏‏‏‎‎‏‏‏‎‎‏‏‏‏‏‎‎‎‎‎‏‏‏‏‎‎‎‎‎‏‎‏‏‏‏‎‎‏‎No‎‏‎‎‏‎"</string>
+    <string name="wifi_suggestion_title" msgid="6396033039578436801">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‎‏‏‎‎‎‎‏‏‎‏‎‎‎‏‏‎‎‎‏‎‏‎‎‏‎‏‏‎‏‏‏‏‏‎‏‏‏‏‎‎‎‎‎‏‎‏‎‎‏‏‎‎‎‎‎‏‎Allow suggested Wi‑Fi networks?‎‏‎‎‏‎"</string>
+    <string name="wifi_suggestion_content" msgid="5603992011371520746">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‏‏‏‎‎‎‏‎‏‎‏‏‎‎‎‎‏‎‎‎‎‏‎‏‏‎‎‎‎‏‎‎‏‏‏‏‎‏‏‎‏‎‎‏‎‎‎‏‎‏‏‏‎‏‎‏‎‎‎‏‎‎‏‏‎<xliff:g id="NAME">%s</xliff:g>‎‏‎‎‏‏‏‎ suggested networks. Device may connect automatically.‎‏‎‎‏‎"</string>
+    <string name="wifi_suggestion_action_allow_app" msgid="7978995387498669901">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‎‏‎‏‏‏‎‏‏‎‎‎‏‎‏‏‎‎‎‎‎‎‏‏‏‏‏‎‎‏‎‎‎‎‏‎‏‎‏‏‎‏‎‏‎‎‏‏‏‎‏‎‎‏‏‎‏‎Allow‎‏‎‎‏‎"</string>
+    <string name="wifi_suggestion_action_disallow_app" msgid="6434097275967940372">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‏‎‏‎‎‏‎‏‎‏‎‎‎‎‎‎‏‎‏‏‎‎‎‏‎‎‎‎‏‏‎‎‎‎‏‏‎‎‎‎‎‏‎‏‎‎‏‏‏‎‎‎‏‎‏‎‎‎No thanks‎‏‎‎‏‎"</string>
     <string name="wifi_wakeup_onboarding_title" msgid="228772560195634292">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‎‏‏‎‎‏‎‏‏‎‎‏‏‎‎‎‎‏‏‎‏‏‎‏‏‏‎‎‏‏‏‎‎‎‎‏‏‎‏‎‎‎‏‎‏‎‎‎‏‎‎‎‏‏‏‎‏‎‎‎Wi‑Fi will turn on automatically‎‏‎‎‏‎"</string>
     <string name="wifi_wakeup_onboarding_subtext" msgid="3989697580301186973">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‏‎‏‎‏‏‏‏‎‎‏‎‎‎‎‎‎‏‏‎‎‏‏‏‏‏‎‎‏‏‎‏‏‎‎‎‏‎‏‏‎‎‏‏‏‎‏‏‏‏‎‎‏‏‏‎‏‎When you\'re near a high quality saved network‎‏‎‎‏‎"</string>
     <string name="wifi_wakeup_onboarding_action_disable" msgid="838648204200836028">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‏‏‎‏‎‎‎‏‏‎‏‏‏‏‎‏‎‎‎‎‏‏‎‎‏‎‎‏‎‏‏‏‎‏‏‏‎‏‎‎‎‏‏‏‏‏‎‏‏‏‎‏‏‏‏‎‎‎Don\'t turn back on‎‏‎‎‏‎"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 1346b86..0229cf5 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -30,7 +30,7 @@
     <string name="untitled" msgid="4638956954852782576">"&lt;Sin título&gt;"</string>
     <string name="emptyPhoneNumber" msgid="7694063042079676517">"(No hay número de teléfono)"</string>
     <string name="unknownName" msgid="6867811765370350269">"Desconocido"</string>
-    <string name="defaultVoiceMailAlphaTag" msgid="2660020990097733077">"Correo de voz"</string>
+    <string name="defaultVoiceMailAlphaTag" msgid="2660020990097733077">"Buzón de voz"</string>
     <string name="defaultMsisdnAlphaTag" msgid="2850889754919584674">"MSISDN1"</string>
     <string name="mmiError" msgid="5154499457739052907">"Problema de conexión o código incorrecto de MMI."</string>
     <string name="mmiFdnError" msgid="5224398216385316471">"La operación está limitada a números de marcación fija."</string>
@@ -944,7 +944,7 @@
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Permite que la aplicación modifique el historial o los favoritos del navegador almacenados en el dispositivo. La aplicación puede utilizar este permiso para borrar o modificar los datos del navegador. Nota: Este permiso no puede ser utilizado por navegadores externos ni otras aplicaciones que tengan funciones de navegación por Internet."</string>
     <string name="permlab_setAlarm" msgid="1379294556362091814">"programar una alarma"</string>
     <string name="permdesc_setAlarm" msgid="316392039157473848">"Permite que la aplicación establezca una alarma en una aplicación de alarma instalada. Es posible que algunas aplicaciones de alarma no incluyan esta función."</string>
-    <string name="permlab_addVoicemail" msgid="5525660026090959044">"agregar correo de voz"</string>
+    <string name="permlab_addVoicemail" msgid="5525660026090959044">"agregar buzón de voz"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Permite que la aplicación agregue mensajes a la bandeja de entrada de tu buzón de voz."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"Modificar los permisos de ubicación geográfica del navegador"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Permite que la aplicación modifique los permisos de ubicación geográfica del navegador. Las aplicaciones maliciosas pueden utilizar esto para permitir el envío de información de ubicación a sitios web arbitrarios."</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 7c6c159..b75644b 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -2053,7 +2053,7 @@
     <string name="shortcut_restore_signature_mismatch" msgid="2406209324521327518">"Bližnjice ni bilo mogoče obnoviti zaradi neujemanja podpisa aplikacije"</string>
     <string name="shortcut_restore_unknown_issue" msgid="8703738064603262597">"Bližnjice ni bilo mogoče obnoviti"</string>
     <string name="shortcut_disabled_reason_unknown" msgid="5276016910284687075">"Bližnjica je onemogočena"</string>
-    <string name="harmful_app_warning_uninstall" msgid="4837672735619532931">"ODSTRANI"</string>
+    <string name="harmful_app_warning_uninstall" msgid="4837672735619532931">"ODMESTI"</string>
     <string name="harmful_app_warning_open_anyway" msgid="596432803680914321">"VSEENO ODPRI"</string>
     <string name="harmful_app_warning_title" msgid="8982527462829423432">"Zaznana je bila škodljiva aplikacija"</string>
     <string name="slices_permission_request" msgid="8484943441501672932">"Aplikacija <xliff:g id="APP_0">%1$s</xliff:g> želi prikazati izreze aplikacije <xliff:g id="APP_2">%2$s</xliff:g>"</string>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index 726e223..7028672 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -365,9 +365,9 @@
     <string name="permlab_enableCarMode" msgid="5684504058192921098">"கார் பயன்முறையை இயக்குதல்"</string>
     <string name="permdesc_enableCarMode" msgid="4853187425751419467">"கார் முறையை இயக்க, ஆப்ஸை அனுமதிக்கிறது."</string>
     <string name="permlab_killBackgroundProcesses" msgid="3914026687420177202">"பிற பயன்பாடுகளை மூடுதல்"</string>
-    <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"பிற பயன்பாடுகளின் பின்புலச் செயல்முறைகளை நிறுத்த ஆப்ஸை அனுமதிக்கிறது. இதனால் பிற பயன்பாடுகள் இயங்குவதை நிறுத்தலாம்."</string>
-    <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"இந்த ஆப்ஸ் பிற பயன்பாடுகளின் மேலே தோன்றலாம்"</string>
-    <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"இந்த ஆப்ஸ் பிற பயன்பாடுகளின் மேலே அல்லது திரையின் பிற பகுதிகளில் தோன்றலாம். இது வழக்கமான ஆப்ஸ் உபயோகத்தில் குறுக்கிட்டு, பிற பயன்பாடுகள் தோன்றும் விதத்தை மாற்றக்கூடும்."</string>
+    <string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"பிற ஆப்ஸின் பின்புலச் செயல்முறைகளை நிறுத்த ஆப்ஸை அனுமதிக்கிறது. இதனால் பிற பயன்பாடுகள் இயங்குவதை நிறுத்தலாம்."</string>
+    <string name="permlab_systemAlertWindow" msgid="7238805243128138690">"இந்த ஆப்ஸ் பிற ஆப்ஸின் மேலே தோன்றலாம்"</string>
+    <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"இந்த ஆப்ஸ் பிற ஆப்ஸின் மேலே அல்லது திரையின் பிற பகுதிகளில் தோன்றலாம். இது வழக்கமான ஆப்ஸ் உபயோகத்தில் குறுக்கிட்டு, பிற பயன்பாடுகள் தோன்றும் விதத்தை மாற்றக்கூடும்."</string>
     <string name="permlab_runInBackground" msgid="7365290743781858803">"பின்னணியில் இயக்கு"</string>
     <string name="permdesc_runInBackground" msgid="7370142232209999824">"இந்த ஆப்ஸ், பின்னணியில் இயங்கலாம். இதனால் பேட்டரி விரைவாகத் தீர்ந்துவிடக்கூடும்."</string>
     <string name="permlab_useDataInBackground" msgid="8694951340794341809">"பின்னணியில் தரவைப் பயன்படுத்து"</string>
@@ -1380,7 +1380,7 @@
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="alert_windows_notification_channel_group_name" msgid="1463953341148606396">"பிற ஆப்ஸின் மேலே காட்டு"</string>
-    <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> பிற பயன்பாடுகளின் மீது தோன்றுகிறது"</string>
+    <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> பிற ஆப்ஸின் மீது தோன்றுகிறது"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> பிற ஆப்ஸின் மீது தோன்றுகிறது"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"<xliff:g id="NAME">%s</xliff:g> இந்த அம்சத்தைப் பயன்படுத்த வேண்டாம் என நினைத்தால், அமைப்புகளைத் திறந்து அதை முடக்க, தட்டவும்."</string>
     <string name="alert_windows_notification_turn_off_action" msgid="2902891971380544651">"ஆஃப் செய்"</string>
@@ -2004,7 +2004,7 @@
     <string name="standby_warning_message" product="default" msgid="5222741828239073484">"இந்தச் சாதனம் விரைவில் ஆஃப் ஆகலாம். இதைத் தொடர்ந்து ஆனில் வைக்கத் தட்டவும்."</string>
     <string name="notification_appops_camera_active" msgid="5050283058419699771">"கேமரா"</string>
     <string name="notification_appops_microphone_active" msgid="4335305527588191730">"மைக்ரோஃபோன்"</string>
-    <string name="notification_appops_overlay_active" msgid="633813008357934729">"உங்கள் திரையில் உள்ள பிற பயன்பாடுகளின் மேல் காட்டுகிறது"</string>
+    <string name="notification_appops_overlay_active" msgid="633813008357934729">"உங்கள் திரையில் உள்ள பிற ஆப்ஸின் மேல் காட்டுகிறது"</string>
     <string name="dynamic_mode_notification_channel_name" msgid="2348803891571320452">"வழக்கமான பேட்டரி சேமிப்பானுக்கான விவர அறிவிப்பு"</string>
     <string name="dynamic_mode_notification_title" msgid="508815255807182035">"வழக்கமாகச் சார்ஜ் செய்வதற்கு முன்பே பேட்டரி தீர்ந்துபோகக்கூடும்"</string>
     <string name="dynamic_mode_notification_summary" msgid="2541166298550402690">"பேட்டரி நிலையை நீட்டிக்க பேட்டரி சேமிப்பான் இயக்கப்பட்டுள்ளது"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index d170932..3472cb2 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -299,7 +299,7 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"ไมโครโฟน"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"บันทึกเสียง"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"อนุญาตให้ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; บันทึกเสียงไหม"</string>
-    <string name="permgrouplab_activityRecognition" msgid="1565108047054378642">"กิจกรรมการเคลื่อนไหวร่างกาย"</string>
+    <string name="permgrouplab_activityRecognition" msgid="1565108047054378642">"การเคลื่อนไหวร่างกาย"</string>
     <string name="permgroupdesc_activityRecognition" msgid="6949472038320473478">"เข้าถึงกิจกรรมการเคลื่อนไหวร่างกายของคุณ"</string>
     <string name="permgrouprequest_activityRecognition" msgid="7626438016904799383">"อนุญาตให้ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; เข้าถึงกิจกรรมการเคลื่อนไหวร่างกายของคุณไหม"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"กล้องถ่ายรูป"</string>
diff --git a/core/tests/coretests/src/android/content/res/ConfigurationTest.java b/core/tests/coretests/src/android/content/res/ConfigurationTest.java
index 2fc3e36..4a93f42 100644
--- a/core/tests/coretests/src/android/content/res/ConfigurationTest.java
+++ b/core/tests/coretests/src/android/content/res/ConfigurationTest.java
@@ -16,16 +16,29 @@
 
 package android.content.res;
 
+import android.content.Context;
+import android.os.LocaleList;
 import android.platform.test.annotations.Presubmit;
+import android.util.AtomicFile;
+import android.util.proto.ProtoInputStream;
+import android.util.proto.ProtoOutputStream;
 
+import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
 
+import com.android.server.usage.IntervalStatsProto;
+
 import junit.framework.TestCase;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
 
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.util.Locale;
+
 /**
  * Build/install/run: bit FrameworksCoreTests:android.content.res.ConfigurationTest
  */
@@ -54,4 +67,70 @@
         config2.updateFrom(config);
         assertEquals(config2.screenLayout, Configuration.SCREENLAYOUT_COMPAT_NEEDED);
     }
+
+    @Test
+    public void testReadWriteProto() throws Exception {
+        final Context context = InstrumentationRegistry.getTargetContext();
+        final File testDir = new File(context.getFilesDir(), "ConfigurationTest");
+        testDir.mkdirs();
+        final File proto = new File(testDir, "configs");
+        if (proto.exists()) {
+            proto.delete();
+        }
+
+        final Locale arabic = new Locale.Builder().setLocale(new Locale("ar", "AE")).build();
+        final Locale urdu = new Locale.Builder().setLocale(new Locale("ur", "IN")).build();
+        final Locale urduExtension = new Locale.Builder().setLocale(new Locale("ur", "IN"))
+                .setExtension('u', "nu-latn").build();
+        Configuration write = new Configuration();
+        write.setLocales(new LocaleList(arabic, urdu, urduExtension));
+        writeToProto(proto, write);
+        assertTrue("Failed to write configs to proto.", proto.exists());
+
+        final Configuration read = new Configuration();
+        try {
+            readFromProto(proto, read);
+        } finally {
+            proto.delete();
+        }
+
+        assertEquals("Missing locales in proto file written to disk.",
+                read.getLocales().size(), write.getLocales().size());
+        assertTrue("Arabic locale not found in Configuration locale list.",
+                read.getLocales().indexOf(arabic) != -1);
+        assertTrue("Urdu locale not found in Configuration locale list.",
+                read.getLocales().indexOf(urdu) != -1);
+        assertTrue("Urdu locale with extensions not found in Configuration locale list.",
+                read.getLocales().indexOf(urduExtension) != -1);
+    }
+
+    private void writeToProto(File f, Configuration config) throws Exception {
+        final AtomicFile af = new AtomicFile(f);
+        FileOutputStream fos = af.startWrite();
+        try {
+            final ProtoOutputStream protoOut = new ProtoOutputStream(fos);
+            final long token = protoOut.start(IntervalStatsProto.CONFIGURATIONS);
+            config.writeToProto(protoOut, IntervalStatsProto.Configuration.CONFIG, false, false);
+            protoOut.end(token);
+            protoOut.flush();
+            af.finishWrite(fos);
+            fos = null;
+        } finally {
+            af.failWrite(fos);
+        }
+    }
+
+    private void readFromProto(File f, Configuration config) throws Exception {
+        final AtomicFile afRead = new AtomicFile(f);
+        try (FileInputStream in = afRead.openRead()) {
+            final ProtoInputStream protoIn = new ProtoInputStream(in);
+            if (protoIn.nextField(IntervalStatsProto.CONFIGURATIONS)) {
+                final long token = protoIn.start(IntervalStatsProto.CONFIGURATIONS);
+                if (protoIn.nextField(IntervalStatsProto.Configuration.CONFIG)) {
+                    config.readFromProto(protoIn, IntervalStatsProto.Configuration.CONFIG);
+                    protoIn.end(token);
+                }
+            }
+        }
+    }
 }
diff --git a/media/jni/Android.bp b/media/jni/Android.bp
index c49b1e4..84fe27d 100644
--- a/media/jni/Android.bp
+++ b/media/jni/Android.bp
@@ -52,7 +52,6 @@
         "libandroidfw",
         "libhidlallocatorutils",
         "libhidlbase",
-        "libhidltransport",
         "android.hardware.cas@1.0",
         "android.hardware.cas.native@1.0",
         "android.hidl.memory@1.0",
@@ -147,7 +146,6 @@
         "android.hidl.memory@1.0",
         "libhidlbase",
         "libhidlmemory",
-        "libhidltransport",
         "libbinderthreadstate",
 
         // MediaPlayer2 implementation
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
index 55ff591..a2fa461 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
@@ -135,6 +135,7 @@
 
         mEnableOk = true;
         mOk.setEnabled(true);
+        mOk.setFilterTouchesWhenObscured(true);
     }
 
     /**
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index 84f5a04..98db7c8 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -27,6 +27,7 @@
 import android.os.ParcelUuid;
 import android.os.SystemClock;
 import android.text.TextUtils;
+import android.util.EventLog;
 import android.util.Log;
 
 import androidx.annotation.VisibleForTesting;
@@ -799,10 +800,9 @@
                         == BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE ||
                     mDevice.getBluetoothClass().getDeviceClass()
                         == BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET) {
-                    mDevice.setPhonebookAccessPermission(BluetoothDevice.ACCESS_ALLOWED);
-                } else {
-                    mDevice.setPhonebookAccessPermission(BluetoothDevice.ACCESS_REJECTED);
+                    EventLog.writeEvent(0x534e4554, "138529441", -1, "");
                 }
+                mDevice.setPhonebookAccessPermission(BluetoothDevice.ACCESS_REJECTED);
             }
         }
     }
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
index 9be636d..4a0ed6f 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
@@ -148,5 +148,6 @@
         VALIDATORS.put(Global.POWER_BUTTON_LONG_PRESS, new InclusiveIntegerRangeValidator(0, 5));
         VALIDATORS.put(
                 Global.POWER_BUTTON_VERY_LONG_PRESS, new InclusiveIntegerRangeValidator(0, 1));
+        VALIDATORS.put(Global.NOTIFICATION_BUBBLES, BOOLEAN_VALIDATOR);
     }
 }
diff --git a/packages/Shell/res/values-zh-rTW/strings.xml b/packages/Shell/res/values-zh-rTW/strings.xml
index fc6397d..96671c8 100644
--- a/packages/Shell/res/values-zh-rTW/strings.xml
+++ b/packages/Shell/res/values-zh-rTW/strings.xml
@@ -25,9 +25,9 @@
     <string name="bugreport_finished_text" product="watch" msgid="1223616207145252689">"系統即將在手機上顯示錯誤報告"</string>
     <string name="bugreport_finished_text" product="tv" msgid="5758325479058638893">"選取即可分享錯誤報告"</string>
     <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"輕觸即可分享錯誤報告"</string>
-    <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"選取即可分享不包含螢幕擷取畫面的錯誤報告;你也可以等候螢幕畫面擷取完畢"</string>
-    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"輕觸即可分享無螢幕擷圖的錯誤報告;你也可以等候螢幕畫面擷取完畢"</string>
-    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"輕觸即可分享無螢幕擷圖的錯誤報告;你也可以等候螢幕畫面擷取完畢"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"選取即可分享不包含螢幕截圖的錯誤報告;你也可以等候螢幕畫面擷取完畢"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"輕觸即可分享無螢幕截圖的錯誤報告;你也可以等候螢幕畫面擷取完畢"</string>
+    <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"輕觸即可分享無螢幕截圖的錯誤報告;你也可以等候螢幕畫面擷取完畢"</string>
     <string name="bugreport_confirm" msgid="5917407234515812495">"錯誤報告的資料來自系統的各種記錄檔,當中可能包含敏感資料 (例如應用程式使用情形和位置資料)。請務必只與你信任的使用者和應用程式分享錯誤報告。"</string>
     <string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"不要再顯示"</string>
     <string name="bugreport_storage_title" msgid="5332488144740527109">"錯誤報告"</string>
@@ -35,9 +35,9 @@
     <string name="bugreport_add_details_to_zip_failed" msgid="1302931926486712371">"無法在 ZIP 檔案中加入錯誤報告"</string>
     <string name="bugreport_unnamed" msgid="2800582406842092709">"未命名"</string>
     <string name="bugreport_info_action" msgid="2158204228510576227">"詳細資料"</string>
-    <string name="bugreport_screenshot_action" msgid="8677781721940614995">"螢幕擷取畫面"</string>
-    <string name="bugreport_screenshot_taken" msgid="5684211273096253120">"已成功拍攝螢幕擷取畫面。"</string>
-    <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"無法拍攝螢幕擷取畫面。"</string>
+    <string name="bugreport_screenshot_action" msgid="8677781721940614995">"螢幕截圖"</string>
+    <string name="bugreport_screenshot_taken" msgid="5684211273096253120">"已成功拍攝螢幕截圖。"</string>
+    <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"無法拍攝螢幕截圖。"</string>
     <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"錯誤報告 <xliff:g id="ID">#%d</xliff:g> 的詳細資料"</string>
     <string name="bugreport_info_name" msgid="4414036021935139527">"檔案名稱"</string>
     <string name="bugreport_info_title" msgid="2306030793918239804">"錯誤標題"</string>
diff --git a/packages/SystemUI/res-keyguard/values-cs/strings.xml b/packages/SystemUI/res-keyguard/values-cs/strings.xml
index 0d88a20..3adc279 100644
--- a/packages/SystemUI/res-keyguard/values-cs/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-cs/strings.xml
@@ -41,7 +41,7 @@
     <string name="keyguard_low_battery" msgid="9218432555787624490">"Připojte dobíjecí zařízení."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8566679946700751371">"Klávesy odemknete stisknutím tlačítka nabídky."</string>
     <string name="keyguard_network_locked_message" msgid="6743537524631420759">"Síť je blokována"</string>
-    <string name="keyguard_missing_sim_message_short" msgid="6327533369959764518">"Není vložena SIM karta"</string>
+    <string name="keyguard_missing_sim_message_short" msgid="6327533369959764518">"Chybí SIM karta"</string>
     <string name="keyguard_missing_sim_message" product="tablet" msgid="4550152848200783542">"V tabletu není SIM karta."</string>
     <string name="keyguard_missing_sim_message" product="default" msgid="6585414237800161146">"V telefonu není SIM karta."</string>
     <string name="keyguard_missing_sim_instructions" msgid="7350295932015220392">"Vložte SIM kartu."</string>
diff --git a/packages/SystemUI/res-keyguard/values-fa/strings.xml b/packages/SystemUI/res-keyguard/values-fa/strings.xml
index 22c4c48..9c9de22 100644
--- a/packages/SystemUI/res-keyguard/values-fa/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-fa/strings.xml
@@ -37,7 +37,7 @@
     <string name="keyguard_plugged_in_wireless" msgid="8404159927155454732">"<xliff:g id="PERCENTAGE">%s</xliff:g> • درحال شارژ بی‌سیم"</string>
     <string name="keyguard_plugged_in" msgid="3161102098900158923">"<xliff:g id="PERCENTAGE">%s</xliff:g> • درحال شارژ شدن"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="3684592786276709342">"<xliff:g id="PERCENTAGE">%s</xliff:g> • درحال شارژ سریع"</string>
-    <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • درحال شارژ آهسته"</string>
+    <string name="keyguard_plugged_in_charging_slowly" msgid="509533586841478405">"<xliff:g id="PERCENTAGE">%s</xliff:g> • آهسته‌آهسته شارژ می‌شود"</string>
     <string name="keyguard_low_battery" msgid="9218432555787624490">"شارژر را وصل کنید."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8566679946700751371">"برای باز کردن قفل روی «منو» فشار دهید."</string>
     <string name="keyguard_network_locked_message" msgid="6743537524631420759">"شبکه قفل شد"</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index dcd31bd..3674564 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -329,7 +329,7 @@
     <string name="quick_settings_location_off_label" msgid="7464544086507331459">"Вызначэнне месцазнаходжання адключана"</string>
     <string name="quick_settings_media_device_label" msgid="1302906836372603762">"Мультымедыйная прылада"</string>
     <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
-    <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Толькі экстраныя выклікі"</string>
+    <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Толькі экстранныя выклікі"</string>
     <string name="quick_settings_settings_label" msgid="5326556592578065401">"Налады"</string>
     <string name="quick_settings_time_label" msgid="4635969182239736408">"Час"</string>
     <string name="quick_settings_user_label" msgid="5238995632130897840">"Я"</string>
@@ -423,7 +423,7 @@
     <string name="keyguard_indication_charging_time_wireless" msgid="6959284458466962592">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ідзе бесправадная зарадка (да поўнага зараду засталося <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
     <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"Ідзе зарадка (<xliff:g id="PERCENTAGE">%2$s</xliff:g>, яшчэ <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
     <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"Ідзе хуткая зарадка (<xliff:g id="PERCENTAGE">%2$s</xliff:g>, яшчэ <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"Ідзе павольная зарадка (<xliff:g id="PERCENTAGE">%2$s</xliff:g>, яшчэ <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"Ідзе павольная зарадка (<xliff:g id="PERCENTAGE">%2$s</xliff:g>, <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> да канца)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Перайсці да іншага карыстальніка"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Перайсці да іншага карыстальніка, бягучы карыстальнік <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Бягучы карыстальнік <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 5141b57..6b7561b 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -232,9 +232,9 @@
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"বিমান মোড চালু হয়েছে।"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="2960643943620637020">"সম্পূর্ণ নীরব"</string>
     <string name="accessibility_quick_settings_dnd_alarms_on" msgid="3357131899365865386">"শুধুমাত্র অ্যালার্ম"</string>
-    <string name="accessibility_quick_settings_dnd" msgid="5555155552520665891">"বিরক্ত করবেন না।"</string>
-    <string name="accessibility_quick_settings_dnd_changed_off" msgid="2757071272328547807">"\'বিরক্ত করবেন না\' বন্ধ আছে।"</string>
-    <string name="accessibility_quick_settings_dnd_changed_on" msgid="6808220653747701059">"\'বিরক্ত করবেন না\' চালু করা হয়েছে।"</string>
+    <string name="accessibility_quick_settings_dnd" msgid="5555155552520665891">"বিরক্ত করবে না।"</string>
+    <string name="accessibility_quick_settings_dnd_changed_off" msgid="2757071272328547807">"\'বিরক্ত করবে না\' বন্ধ আছে।"</string>
+    <string name="accessibility_quick_settings_dnd_changed_on" msgid="6808220653747701059">"\'বিরক্ত করবে না\' চালু করা হয়েছে।"</string>
     <string name="accessibility_quick_settings_bluetooth" msgid="6341675755803320038">"ব্লুটুথ"</string>
     <string name="accessibility_quick_settings_bluetooth_off" msgid="2133631372372064339">"ব্লুটুথ বন্ধ আছে।"</string>
     <string name="accessibility_quick_settings_bluetooth_on" msgid="7681999166216621838">"ব্লুটুথ চালু আছে।"</string>
@@ -299,7 +299,7 @@
     <string name="start_dreams" msgid="5640361424498338327">"স্ক্রিন সেভার"</string>
     <string name="ethernet_label" msgid="7967563676324087464">"ইথারনেট"</string>
     <string name="quick_settings_header_onboarding_text" msgid="8030309023792936283">"আরও বিকল্পের জন্য আইকনগুলি টাচ করে ধরে থাকুন"</string>
-    <string name="quick_settings_dnd_label" msgid="7112342227663678739">"বিরক্ত করবেন না"</string>
+    <string name="quick_settings_dnd_label" msgid="7112342227663678739">"বিরক্ত করবে না"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"শুধুমাত্র অগ্রাধিকার"</string>
     <string name="quick_settings_dnd_alarms_label" msgid="2559229444312445858">"শুধুমাত্র অ্যালার্মগুলি"</string>
     <string name="quick_settings_dnd_none_label" msgid="5025477807123029478">"একদম নিরব"</string>
@@ -461,7 +461,7 @@
     <string name="manage_notifications_text" msgid="2386728145475108753">"পরিচালনা করুন"</string>
     <string name="notification_section_header_gentle" msgid="4372438504154095677">"নীরব বিজ্ঞপ্তি"</string>
     <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4286716295850400959">"সব নীরব বিজ্ঞপ্তি মুছুন"</string>
-    <string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"\'বিরক্ত করবেন না\' দিয়ে বিজ্ঞপ্তি পজ করা হয়েছে"</string>
+    <string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"\'বিরক্ত করবে না\' দিয়ে বিজ্ঞপ্তি পজ করা হয়েছে"</string>
     <string name="media_projection_action_text" msgid="8470872969457985954">"এখন শুরু করুন"</string>
     <string name="empty_shade_text" msgid="708135716272867002">"কোনো বিজ্ঞপ্তি নেই"</string>
     <string name="profile_owned_footer" msgid="8021888108553696069">"প্রোফাইল পর্যবেক্ষণ করা হতে পারে"</string>
@@ -737,9 +737,9 @@
     <string name="keyboard_shortcut_group_applications_youtube" msgid="6555453761294723317">"YouTube"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="9043614299194991263">"ক্যালেন্ডার"</string>
     <string name="tuner_full_zen_title" msgid="4540823317772234308">"ভলিউম নিয়ন্ত্রণ সহ দেখান"</string>
-    <string name="volume_and_do_not_disturb" msgid="1750270820297253561">"বিরক্ত করবেন না"</string>
+    <string name="volume_and_do_not_disturb" msgid="1750270820297253561">"বিরক্ত করবে না"</string>
     <string name="volume_dnd_silent" msgid="4363882330723050727">"ভলিউম বোতামের শর্টকাট"</string>
-    <string name="volume_up_silent" msgid="7545869833038212815">"ভলিউম বাড়িয়ে \'বিরক্ত করবেন না\' মোড থেকে বেরিয়ে আসুন"</string>
+    <string name="volume_up_silent" msgid="7545869833038212815">"ভলিউম বাড়িয়ে \'বিরক্ত করবে না\' মোড থেকে বেরিয়ে আসুন"</string>
     <string name="battery" msgid="7498329822413202973">"ব্যাটারি"</string>
     <string name="clock" msgid="7416090374234785905">"ঘড়ি"</string>
     <string name="headset" msgid="4534219457597457353">"হেডসেট"</string>
@@ -883,10 +883,10 @@
     <string name="mobile_carrier_text_format" msgid="3241721038678469804">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="MOBILE_DATA_TYPE">%2$s</xliff:g>"</string>
     <string name="wifi_is_off" msgid="1838559392210456893">"ওয়াই ফাই বন্ধ আছে"</string>
     <string name="bt_is_off" msgid="2640685272289706392">"ব্লুটুথ বন্ধ আছে"</string>
-    <string name="dnd_is_off" msgid="6167780215212497572">"বিরক্ত করবেন না বিকল্পটি বন্ধ আছে"</string>
-    <string name="qs_dnd_prompt_auto_rule" msgid="862559028345233052">"বিরক্ত করবেন না বিকল্পটি একটি স্বয়ংক্রিয় নিয়ম <xliff:g id="ID_1">%s</xliff:g> এর দ্বারা চালু করা হয়েছে।"</string>
-    <string name="qs_dnd_prompt_app" msgid="7978037419334156034">"বিরক্ত করবেন না বিকল্পটি একটি অ্যাপ <xliff:g id="ID_1">%s</xliff:g> এর দ্বারা চালু করা হয়েছে।"</string>
-    <string name="qs_dnd_prompt_auto_rule_app" msgid="2599343675391111951">"বিরক্ত করবেন না বিকল্পটি একটি স্বয়ংক্রিয় নিয়ম বা অ্যাপের দ্বারা চালু করা হয়েছে।"</string>
+    <string name="dnd_is_off" msgid="6167780215212497572">"বিরক্ত করবে না বিকল্পটি বন্ধ আছে"</string>
+    <string name="qs_dnd_prompt_auto_rule" msgid="862559028345233052">"বিরক্ত করবে না বিকল্পটি একটি স্বয়ংক্রিয় নিয়ম <xliff:g id="ID_1">%s</xliff:g> এর দ্বারা চালু করা হয়েছে।"</string>
+    <string name="qs_dnd_prompt_app" msgid="7978037419334156034">"বিরক্ত করবে না বিকল্পটি একটি অ্যাপ <xliff:g id="ID_1">%s</xliff:g> এর দ্বারা চালু করা হয়েছে।"</string>
+    <string name="qs_dnd_prompt_auto_rule_app" msgid="2599343675391111951">"বিরক্ত করবে না বিকল্পটি একটি স্বয়ংক্রিয় নিয়ম বা অ্যাপের দ্বারা চালু করা হয়েছে।"</string>
     <string name="qs_dnd_until" msgid="3469471136280079874">"<xliff:g id="ID_1">%s</xliff:g> পর্যন্ত"</string>
     <string name="qs_dnd_keep" msgid="1825009164681928736">"রাখুন"</string>
     <string name="qs_dnd_replace" msgid="8019520786644276623">"বদলে দিন"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index abea52a..87aaa94 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -194,7 +194,7 @@
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Sdílené připojení přes Bluetooth."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Režim Letadlo."</string>
     <string name="accessibility_vpn_on" msgid="5993385083262856059">"VPN je zapnuto."</string>
-    <string name="accessibility_no_sims" msgid="3957997018324995781">"Není vložena SIM karta"</string>
+    <string name="accessibility_no_sims" msgid="3957997018324995781">"Chybí SIM karta"</string>
     <string name="carrier_network_change_mode" msgid="8149202439957837762">"Probíhá změna sítě operátora"</string>
     <string name="accessibility_battery_details" msgid="7645516654955025422">"Otevřít podrobnosti o baterii"</string>
     <string name="accessibility_battery_level" msgid="7451474187113371965">"Stav baterie: <xliff:g id="NUMBER">%d</xliff:g> procent."</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 6a97ee6..57c934e 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -215,7 +215,7 @@
     <skip />
     <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notifikationen er annulleret."</string>
     <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Notifikationspanel."</string>
-    <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Hurtige indstillinger."</string>
+    <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Kvikmenu."</string>
     <string name="accessibility_desc_lock_screen" msgid="5625143713611759164">"Låseskærm."</string>
     <string name="accessibility_desc_settings" msgid="3417884241751434521">"Indstillinger"</string>
     <string name="accessibility_desc_recent_apps" msgid="4876900986661819788">"Oversigt."</string>
@@ -588,7 +588,7 @@
     <string name="system_ui_tuner" msgid="708224127392452018">"System UI Tuner"</string>
     <string name="show_battery_percentage" msgid="5444136600512968798">"Vis procent for det indbyggede batteri"</string>
     <string name="show_battery_percentage_summary" msgid="3215025775576786037">"Vis procenttallet for batteriniveauet i ikonet for statusbjælken, når der ikke oplades"</string>
-    <string name="quick_settings" msgid="10042998191725428">"Hurtige indstillinger"</string>
+    <string name="quick_settings" msgid="10042998191725428">"Kvikmenu"</string>
     <string name="status_bar" msgid="4877645476959324760">"Statusbjælke"</string>
     <string name="overview" msgid="4018602013895926956">"Oversigt"</string>
     <string name="demo_mode" msgid="2532177350215638026">"Demotilstand for systemets brugerflade"</string>
@@ -604,7 +604,7 @@
     <string name="zen_alarm_warning" msgid="444533119582244293">"Du vil ikke kunne høre din næste alarm <xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="alarm_template" msgid="3980063409350522735">"kl. <xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="alarm_template_far" msgid="4242179982586714810">"på <xliff:g id="WHEN">%1$s</xliff:g>"</string>
-    <string name="accessibility_quick_settings_detail" msgid="2579369091672902101">"Hurtige indstillinger <xliff:g id="TITLE">%s</xliff:g>."</string>
+    <string name="accessibility_quick_settings_detail" msgid="2579369091672902101">"Kvikmenu <xliff:g id="TITLE">%s</xliff:g>."</string>
     <string name="accessibility_status_bar_hotspot" msgid="4099381329956402865">"Hotspot"</string>
     <string name="accessibility_managed_profile" msgid="6613641363112584120">"Arbejdsprofil"</string>
     <string name="tuner_warning_title" msgid="7094689930793031682">"Sjovt for nogle, men ikke for alle"</string>
@@ -617,8 +617,8 @@
     <string name="activity_not_found" msgid="348423244327799974">"Applikationen er ikke installeret på din enhed."</string>
     <string name="clock_seconds" msgid="7689554147579179507">"Vis sekunder"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"Vis sekunder i statuslinjen. Dette kan påvirke batteriets levetid."</string>
-    <string name="qs_rearrange" msgid="8060918697551068765">"Omarranger Hurtige indstillinger"</string>
-    <string name="show_brightness" msgid="6613930842805942519">"Vis lysstyrke i Hurtige indstillinger"</string>
+    <string name="qs_rearrange" msgid="8060918697551068765">"Omarranger Kvikmenu"</string>
+    <string name="show_brightness" msgid="6613930842805942519">"Vis lysstyrke i Kvikmenu"</string>
     <string name="experimental" msgid="6198182315536726162">"Eksperimentel"</string>
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"Vil du slå Bluetooth til?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"Bluetooth skal være slået til, før du kan knytte dit tastatur til din tablet."</string>
@@ -813,15 +813,15 @@
     <string name="accessibility_qs_edit_remove_tile" msgid="7484493384665907197">"Fjern <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_add" msgid="3520406665865985109">"Føj <xliff:g id="TILE_NAME">%1$s</xliff:g> til position <xliff:g id="POSITION">%2$d</xliff:g>"</string>
     <string name="accessibility_qs_edit_tile_move" msgid="3108103090006972938">"Flyt <xliff:g id="TILE_NAME">%1$s</xliff:g> til position <xliff:g id="POSITION">%2$d</xliff:g>"</string>
-    <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Redigeringsværktøj for Hurtige indstillinger."</string>
+    <string name="accessibility_desc_quick_settings_edit" msgid="8073587401747016103">"Redigeringsværktøj til Kvikmenu."</string>
     <string name="accessibility_desc_notification_icon" msgid="8352414185263916335">"<xliff:g id="ID_1">%1$s</xliff:g>-notifikation: <xliff:g id="ID_2">%2$s</xliff:g>"</string>
     <string name="dock_forced_resizable" msgid="5914261505436217520">"Appen fungerer muligvis ikke i opdelt skærm."</string>
     <string name="dock_non_resizeble_failed_to_dock_text" msgid="3871617304250207291">"Appen understøtter ikke opdelt skærm."</string>
     <string name="forced_resizable_secondary_display" msgid="4230857851756391925">"Appen fungerer muligvis ikke på sekundære skærme."</string>
     <string name="activity_launch_on_secondary_display_failed_text" msgid="7793821742158306742">"Appen kan ikke åbnes på sekundære skærme."</string>
     <string name="accessibility_quick_settings_settings" msgid="6132460890024942157">"Åbn Indstillinger."</string>
-    <string name="accessibility_quick_settings_expand" msgid="2375165227880477530">"Åbn Hurtige indstillinger."</string>
-    <string name="accessibility_quick_settings_collapse" msgid="1792625797142648105">"Luk Hurtige indstillinger."</string>
+    <string name="accessibility_quick_settings_expand" msgid="2375165227880477530">"Åbn Kvikmenu."</string>
+    <string name="accessibility_quick_settings_collapse" msgid="1792625797142648105">"Luk Kvikmenu."</string>
     <string name="accessibility_quick_settings_alarm_set" msgid="1863000242431528676">"Alarmen er indstillet."</string>
     <string name="accessibility_quick_settings_user" msgid="1567445362870421770">"Logget ind som <xliff:g id="ID_1">%s</xliff:g>"</string>
     <string name="data_connection_no_internet" msgid="4503302451650972989">"Intet internet"</string>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index 9903cc0..938cb0d 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -401,6 +401,7 @@
     <string name="speed_bump_explanation" msgid="1288875699658819755">"Less urgent notifications below"</string>
     <string name="notification_tap_again" msgid="7590196980943943842">"Tap again to open"</string>
     <string name="keyguard_unlock" msgid="6035822649218712063">"Swipe up to open"</string>
+    <string name="keyguard_retry" msgid="5221600879614948709">"Swipe up to try again"</string>
     <string name="do_disclosure_generic" msgid="5615898451805157556">"This device is managed by your organisation"</string>
     <string name="do_disclosure_with_name" msgid="5640615509915445501">"This device is managed by <xliff:g id="ORGANIZATION_NAME">%s</xliff:g>"</string>
     <string name="phone_hint" msgid="4872890986869209950">"Swipe from icon for phone"</string>
@@ -544,6 +545,7 @@
     <string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"This keeps it in view until you unpin. Touch &amp; hold Home to unpin."</string>
     <string name="screen_pinning_toast" msgid="2266705122951934150">"To unpin this screen, touch &amp; hold Back and Overview buttons"</string>
     <string name="screen_pinning_toast_recents_invisible" msgid="8252402309499161281">"To unpin this screen, touch &amp; hold Back and Home buttons"</string>
+    <string name="screen_pinning_toast_gesture_nav" msgid="5070548776081664958">"To unpin this screen, swipe up &amp; hold"</string>
     <string name="screen_pinning_positive" msgid="3783985798366751226">"Got it"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"No, thanks"</string>
     <string name="screen_pinning_start" msgid="1022122128489278317">"Screen pinned"</string>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index d8c862a..139215aa 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -401,6 +401,7 @@
     <string name="speed_bump_explanation" msgid="1288875699658819755">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‏‏‏‏‎‎‎‏‏‎‎‎‎‎‎‎‏‏‎‎‏‏‏‏‎‏‎‏‏‏‏‎‏‏‏‎‎‏‏‎‎‎‎‎‎‏‎‎‎‏‎‏‎‏‎‏‏‎Less urgent notifications below‎‏‎‎‏‎"</string>
     <string name="notification_tap_again" msgid="7590196980943943842">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‏‎‏‎‏‎‏‎‏‏‏‎‎‏‎‏‏‏‏‏‏‎‎‎‎‏‎‎‎‏‎‎‎‎‏‏‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‎‎‏‎‎Tap again to open‎‏‎‎‏‎"</string>
     <string name="keyguard_unlock" msgid="6035822649218712063">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‏‏‏‎‎‎‎‏‏‏‎‎‎‏‏‎‎‏‎‏‏‏‎‎‎‎‏‏‎‎‏‎‏‏‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‏‎Swipe up to open‎‏‎‎‏‎"</string>
+    <string name="keyguard_retry" msgid="5221600879614948709">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‎‎‏‏‏‎‏‏‎‏‏‎‏‏‎‏‎‎‏‎‏‎‏‎‏‏‎‏‏‎‏‎‎‎‏‎‏‎‎‎‎‏‏‏‏‎‏‎‏‎‏‏‎‎‏‎‏‎Swipe up to try again‎‏‎‎‏‎"</string>
     <string name="do_disclosure_generic" msgid="5615898451805157556">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‏‏‏‏‎‏‏‏‏‏‎‏‎‏‏‎‏‏‏‏‎‎‎‏‏‎‎‏‏‏‎‏‎‏‎‎‎‎‎‏‏‎‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‎This device is managed by your organization‎‏‎‎‏‎"</string>
     <string name="do_disclosure_with_name" msgid="5640615509915445501">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‏‎‎‎‏‏‏‎‏‏‏‏‏‎‏‏‏‏‎‏‎‏‏‏‏‎‎‎‏‏‏‎‎‎‏‎‎‎‏‏‎‏‎‏‎‎‎‏‏‏‏‏‏‎‏‎This device is managed by ‎‏‎‎‏‏‎<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="phone_hint" msgid="4872890986869209950">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‏‏‎‎‏‏‏‏‏‏‏‏‏‏‏‎‎‏‎‎‎‏‎‎‎‏‏‏‎‏‏‎‏‏‎‎‎‏‎‏‎‏‎‏‏‏‎‏‏‎‏‎‏‏‏‏‎‎Swipe from icon for phone‎‏‎‎‏‎"</string>
@@ -544,6 +545,7 @@
     <string name="screen_pinning_description_recents_invisible_accessible" msgid="6134833683151189507">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‎‏‎‎‎‏‏‎‏‎‎‏‏‏‎‏‎‏‏‏‎‏‏‎‎‏‎‏‎‎‎‎‏‎‏‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎‎‎‎‏‏‎This keeps it in view until you unpin. Touch &amp; hold Home to unpin.‎‏‎‎‏‎"</string>
     <string name="screen_pinning_toast" msgid="2266705122951934150">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‎‏‏‏‎‏‎‎‏‏‏‏‎‏‎‎‎‏‎‎‏‏‎‎‏‏‎‎‎‎‎‎‎‎‎‏‏‎‏‏‏‎‏‏‎‎‎‎‏‏‎‎‎‏‏‎‎To unpin this screen, touch &amp; hold Back and Overview buttons‎‏‎‎‏‎"</string>
     <string name="screen_pinning_toast_recents_invisible" msgid="8252402309499161281">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‎‏‎‎‎‎‏‏‎‎‏‏‎‏‏‎‎‎‎‏‎‏‏‎‏‎‏‏‎‏‎‎‏‎‏‎‎‏‏‏‏‏‎‎‎‏‎‏‎‏‏‎‎‎‎‎‏‎To unpin this screen, touch &amp; hold Back and Home buttons‎‏‎‎‏‎"</string>
+    <string name="screen_pinning_toast_gesture_nav" msgid="5070548776081664958">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‎‎‏‎‏‏‏‏‎‎‎‏‏‎‏‎‏‎‎‏‏‏‏‏‏‎‎‏‏‎‏‏‎‏‎‏‎‎‎‏‏‏‎‏‎‏‎‏‏‏‎‏‏‏‏‏‎‎To unpin this screen, swipe up &amp; hold‎‏‎‎‏‎"</string>
     <string name="screen_pinning_positive" msgid="3783985798366751226">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‎‏‎‎‎‎‎‏‏‎‏‏‎‏‎‏‏‎‎‎‎‏‎‎‏‎‎‎‎‎‎‏‎‏‏‎‎‎‏‎‏‏‏‏‎‏‎‎‏‏‏‏‏‏‎‏‎‎Got it‎‏‎‎‏‎"</string>
     <string name="screen_pinning_negative" msgid="3741602308343880268">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‏‏‏‏‎‏‏‎‎‏‏‎‏‎‏‏‏‎‏‏‏‏‎‎‏‏‎‏‏‏‏‏‏‏‎‎‏‏‏‏‎‎‏‎‏‏‎‏‎‎‏‎‎‏‏‎‎‎No thanks‎‏‎‎‏‎"</string>
     <string name="screen_pinning_start" msgid="1022122128489278317">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‎‎‏‎‏‏‏‏‎‏‎‎‏‏‏‎‏‎‏‎‏‎‎‏‎‎‎‏‎‎‎‏‏‎‏‎‏‎‏‏‎‏‏‎‏‎‏‏‎‏‏‎‏‏‎‏‎Screen pinned‎‏‎‎‏‎"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 137b780..e8e4232 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -417,7 +417,7 @@
     <string name="keyguard_indication_charging_time_wireless" msgid="6959284458466962592">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • En recharge sans fil (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> jusqu\'à la recharge complète)"</string>
     <string name="keyguard_indication_charging_time" msgid="2056340799276374421">"En recharge : <xliff:g id="PERCENTAGE">%2$s</xliff:g> (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> jusqu\'à charge complète)"</string>
     <string name="keyguard_indication_charging_time_fast" msgid="7767562163577492332">"En recharge rapide : <xliff:g id="PERCENTAGE">%2$s</xliff:g> (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> jusqu\'à ch. comp.)"</string>
-    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"En recharge lente : <xliff:g id="PERCENTAGE">%2$s</xliff:g> (<xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g> jusqu\'à ch. comp.)"</string>
+    <string name="keyguard_indication_charging_time_slowly" msgid="3769655133567307069">"Recharge lente : <xliff:g id="PERCENTAGE">%2$s</xliff:g> (à 100 %% dans <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>)"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="7305948938141024937">"Changer d\'utilisateur"</string>
     <string name="accessibility_multi_user_switch_switcher_with_current" msgid="8434880595284601601">"Changer d\'utilisateur (utilisateur actuel <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>)"</string>
     <string name="accessibility_multi_user_switch_inactive" msgid="1424081831468083402">"Utilisateur actuel : <xliff:g id="CURRENT_USER_NAME">%s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 15d9c2b..5480eab 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -599,7 +599,7 @@
     <string name="status_bar_work" msgid="6022553324802866373">"Perfil de traballo"</string>
     <string name="status_bar_airplane" msgid="7057575501472249002">"Modo avión"</string>
     <string name="add_tile" msgid="2995389510240786221">"Engade un atallo"</string>
-    <string name="broadcast_tile" msgid="3894036511763289383">"Atallo de emisión"</string>
+    <string name="broadcast_tile" msgid="3894036511763289383">"Atallo de difusión"</string>
     <string name="zen_alarm_warning_indef" msgid="3482966345578319605">"Non escoitarás a alarma seguinte <xliff:g id="WHEN">%1$s</xliff:g> a menos que desactives esta opción antes desa hora"</string>
     <string name="zen_alarm_warning" msgid="444533119582244293">"Non escoitarás a alarma seguinte <xliff:g id="WHEN">%1$s</xliff:g>"</string>
     <string name="alarm_template" msgid="3980063409350522735">"ás <xliff:g id="WHEN">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index f90f494..1a15cf7 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -314,7 +314,7 @@
     <string name="quick_settings_bluetooth_secondary_label_hearing_aids" msgid="4930931771490695395">"શ્રવણ યંત્રો"</string>
     <string name="quick_settings_bluetooth_secondary_label_transient" msgid="4551281899312150640">"ચાલુ કરી રહ્યાં છીએ…"</string>
     <string name="quick_settings_brightness_label" msgid="6968372297018755815">"તેજ"</string>
-    <string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"આપમેળે ફેરવો"</string>
+    <string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"ઑટો રોટેટ"</string>
     <string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"સ્ક્રીનને આપમેળે ફેરવો"</string>
     <string name="accessibility_quick_settings_rotation_value" msgid="8187398200140760213">"<xliff:g id="ID_1">%s</xliff:g> મોડ"</string>
     <string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"પરિભ્રમણ લૉક થયું"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 5f47e20..3e3696b 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -647,7 +647,7 @@
     <string name="inline_minimize_button" msgid="966233327974702195">"Kis méret"</string>
     <string name="inline_silent_button_silent" msgid="5315879183296940969">"Néma"</string>
     <string name="inline_silent_button_stay_silent" msgid="6308371431217601009">"Néma megjelenítés"</string>
-    <string name="inline_silent_button_alert" msgid="6008435419895088034">"Értesítések"</string>
+    <string name="inline_silent_button_alert" msgid="6008435419895088034">"Figyelemfelkeltő"</string>
     <string name="inline_silent_button_keep_alerting" msgid="327696842264359693">"Értesítések folytatása"</string>
     <string name="inline_turn_off_notifications" msgid="8635596135532202355">"Az értesítések kikapcsolása"</string>
     <string name="inline_keep_showing_app" msgid="1723113469580031041">"Továbbra is megjelenjenek az alkalmazás értesítései?"</string>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index 3760007..e9b150c 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -250,9 +250,9 @@
     <string name="accessibility_quick_settings_close" msgid="3115847794692516306">"ପ୍ୟାନେଲ୍ ବନ୍ଦ କରନ୍ତୁ।"</string>
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"ଅଧିକ ସମୟ।"</string>
     <string name="accessibility_quick_settings_less_time" msgid="2404728746293515623">"କମ୍ ସମୟ।"</string>
-    <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"ଫ୍ଲାଶ୍‌ଲାଇଟ୍ ଅଫ୍ ଅଛି।"</string>
+    <string name="accessibility_quick_settings_flashlight_off" msgid="4936432000069786988">"ଫ୍ଲାସ୍‍ଲାଇଟ୍ ବନ୍ଦ ଅଛି।"</string>
     <string name="accessibility_quick_settings_flashlight_unavailable" msgid="8012811023312280810">"ଟର୍ଚ୍ଚ ଲାଇଟ୍‍ ଅନୁପଲବ୍ଧ।"</string>
-    <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"ଫ୍ଲାଶ୍‌ଲାଇଟ୍ ଅନ୍ ଅଛି।"</string>
+    <string name="accessibility_quick_settings_flashlight_on" msgid="2003479320007841077">"ଫ୍ଲାସ୍‍ଲାଇଟ୍ ଚାଲୁଅଛି।"</string>
     <string name="accessibility_quick_settings_flashlight_changed_off" msgid="3303701786768224304">"ଟର୍ଚ୍ଚ ଲାଇଟ୍ ବନ୍ଦ ଅଛି।"</string>
     <string name="accessibility_quick_settings_flashlight_changed_on" msgid="6531793301533894686">"ଟର୍ଚ୍ଚ ଲାଇଟ୍ ଅନ୍ ଅଛି।"</string>
     <string name="accessibility_quick_settings_color_inversion_changed_off" msgid="4406577213290173911">"ରଙ୍ଗ ବିପରୀତିକରଣକୁ ବନ୍ଦ କରିଦିଆଗଲା।"</string>
@@ -362,7 +362,7 @@
       <item quantity="one">%d ଡିଭାଇସ୍</item>
     </plurals>
     <string name="quick_settings_notifications_label" msgid="4818156442169154523">"ବିଜ୍ଞପ୍ତି"</string>
-    <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"ଫ୍ଲାଶ୍‍ଲାଇଟ"</string>
+    <string name="quick_settings_flashlight_label" msgid="2133093497691661546">"ଫ୍ଲାସ୍‍ଲାଇଟ୍"</string>
     <string name="quick_settings_cellular_detail_title" msgid="3661194685666477347">"ମୋବାଇଲ୍‌ ଡାଟା"</string>
     <string name="quick_settings_cellular_detail_data_usage" msgid="1964260360259312002">"ଡାଟାର ବ୍ୟବହାର"</string>
     <string name="quick_settings_cellular_detail_remaining_data" msgid="722715415543541249">"ଅବଶିଷ୍ଟ ଡାଟା"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 93a2c12..4be1a0f 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -465,10 +465,10 @@
     <string name="media_projection_dialog_service_text" msgid="3075544489835858258">"Podczas nagrywania lub przesyłania usługa udostępniająca tę funkcję może rejestrować wszelkie informacje poufne wyświetlane na ekranie lub odtwarzane na urządzeniu takie jak dźwięki czy podawane hasła, informacje o płatnościach, zdjęcia i wiadomości."</string>
     <string name="media_projection_dialog_title" msgid="8124184308671641248">"Ujawnianie poufnych informacji podczas przesyłania/nagrywania"</string>
     <string name="media_projection_remember_text" msgid="3103510882172746752">"Nie pokazuj ponownie"</string>
-    <string name="clear_all_notifications_text" msgid="814192889771462828">"Ukryj wszystkie"</string>
+    <string name="clear_all_notifications_text" msgid="814192889771462828">"Usuń wszystkie"</string>
     <string name="manage_notifications_text" msgid="2386728145475108753">"Zarządzaj"</string>
-    <string name="notification_section_header_gentle" msgid="4372438504154095677">"Powiadomienia ciche"</string>
-    <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4286716295850400959">"Wyczyść wszystkie ciche powiadomienia"</string>
+    <string name="notification_section_header_gentle" msgid="4372438504154095677">"Ciche powiadomienia"</string>
+    <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4286716295850400959">"Usuń wszystkie ciche powiadomienia"</string>
     <string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"Powiadomienia wstrzymane przez tryb Nie przeszkadzać"</string>
     <string name="media_projection_action_text" msgid="8470872969457985954">"Rozpocznij teraz"</string>
     <string name="empty_shade_text" msgid="708135716272867002">"Brak powiadomień"</string>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index d56ccef..2b12149 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -845,7 +845,7 @@
     <string name="pip_skip_to_prev" msgid="1955311326688637914">"முந்தையதற்குச் செல்"</string>
     <string name="thermal_shutdown_title" msgid="4458304833443861111">"வெப்பத்தினால் ஃபோன் ஆஃப் செய்யப்பட்டது"</string>
     <string name="thermal_shutdown_message" msgid="9006456746902370523">"இப்போது உங்கள் ஃபோன் இயல்புநிலையில் இயங்குகிறது"</string>
-    <string name="thermal_shutdown_dialog_message" msgid="566347880005304139">"உங்கள் ஃபோன் அதிகமாகச் சூடானதால், அதன் சூட்டைக் குறைக்க, ஆஃப் செய்யப்பட்டது. இப்போது உங்கள் ஃபோன் இயல்புநிலையில் இயங்குகிறது.\n\nபின்வருவனவற்றைச் செய்தால், ஃபோன் சூடாகலாம்:\n	• அதிகளவு தரவைப் பயன்படுத்தும் பயன்பாடுகளை (எ.கா: கேமிங், வீடியோ (அ) வழிகாட்டுதல் பயன்பாடுகள்) பயன்படுத்துவது\n	• பெரிய கோப்புகளைப் பதிவிறக்குவது/பதிவேற்றுவது\n	• அதிக வெப்பநிலையில் ஃபோனைப் பயன்படுத்துவது"</string>
+    <string name="thermal_shutdown_dialog_message" msgid="566347880005304139">"உங்கள் ஃபோன் அதிகமாகச் சூடானதால், அதன் சூட்டைக் குறைக்க, ஆஃப் செய்யப்பட்டது. இப்போது உங்கள் ஃபோன் இயல்புநிலையில் இயங்குகிறது.\n\nபின்வருவனவற்றைச் செய்தால், ஃபோன் சூடாகலாம்:\n	• அதிகளவு தரவைப் பயன்படுத்தும் ஆப்ஸை (எ.கா: கேமிங், வீடியோ (அ) வழிகாட்டுதல் பயன்பாடுகள்) பயன்படுத்துவது\n	• பெரிய கோப்புகளைப் பதிவிறக்குவது/பதிவேற்றுவது\n	• அதிக வெப்பநிலையில் ஃபோனைப் பயன்படுத்துவது"</string>
     <string name="high_temp_title" msgid="4589508026407318374">"மொபைல் சூடாகிறது"</string>
     <string name="high_temp_notif_message" msgid="5642466103153429279">"மொபைலின் வெப்ப அளவு குறையும் போது, சில அம்சங்களைப் பயன்படுத்த முடியாது"</string>
     <string name="high_temp_dialog_message" msgid="6840700639374113553">"உங்கள் மொபைலின் வெப்ப அளவு தானாகவே குறையும். தொடர்ந்து நீங்கள் மொபைலைப் பயன்படுத்தலாம், ஆனால் அதன் வேகம் குறைவாக இருக்கக்கூடும்.\n\nமொபைலின் வெப்ப அளவு குறைந்தவுடன், அது இயல்பு நிலையில் இயங்கும்."</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 6f38b18..d3caa2b 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -55,11 +55,11 @@
     <string name="label_view" msgid="6304565553218192990">"Xem"</string>
     <string name="always_use_device" msgid="4015357883336738417">"Luôn mở <xliff:g id="APPLICATION">%1$s</xliff:g> khi kết nối <xliff:g id="USB_DEVICE">%2$s</xliff:g>"</string>
     <string name="always_use_accessory" msgid="3257892669444535154">"Luôn mở <xliff:g id="APPLICATION">%1$s</xliff:g> khi kết nối <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>"</string>
-    <string name="usb_debugging_title" msgid="4513918393387141949">"Cho phép gỡ lỗi USB?"</string>
+    <string name="usb_debugging_title" msgid="4513918393387141949">"Cho phép gỡ lỗi qua USB?"</string>
     <string name="usb_debugging_message" msgid="2220143855912376496">"Tệp tham chiếu khóa RSA của máy tính là:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
     <string name="usb_debugging_always" msgid="303335496705863070">"Luôn cho phép từ máy tính này"</string>
     <string name="usb_debugging_allow" msgid="2272145052073254852">"Cho phép"</string>
-    <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"Tính năng gỡ lỗi USB không được phép"</string>
+    <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"Không cho phép chế độ gỡ lỗi qua USB"</string>
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Người dùng hiện đã đăng nhập vào thiết bị này không thể bật tính năng gỡ lỗi USB. Để sử dụng tính năng này, hãy chuyển sang người dùng chính."</string>
     <string name="usb_contaminant_title" msgid="206854874263058490">"Đã tắt cổng USB"</string>
     <string name="usb_contaminant_message" msgid="7379089091591609111">"Để bảo vệ thiết bị của bạn khỏi chất lỏng hay mảnh vỡ, cổng USB sẽ tắt và không phát hiện được bất kỳ phụ kiện nào.\n\nBạn sẽ nhận được thông báo khi có thể sử dụng lại cổng USB."</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 03e31cd..457206d 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -264,8 +264,8 @@
     <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"工作模式已開啟。"</string>
     <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"工作模式已關閉。"</string>
     <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"工作模式已開啟。"</string>
-    <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"Data Saver 已關閉。"</string>
-    <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"Data Saver 已開啟。"</string>
+    <string name="accessibility_quick_settings_data_saver_changed_off" msgid="650231949881093289">"數據節省模式已關閉。"</string>
+    <string name="accessibility_quick_settings_data_saver_changed_on" msgid="4218725402373934151">"數據節省模式已開啟。"</string>
     <string name="accessibility_quick_settings_sensor_privacy_changed_off" msgid="5152819588955163090">"已關閉感應器隱私設定。"</string>
     <string name="accessibility_quick_settings_sensor_privacy_changed_on" msgid="529705259565826355">"已開啟感應器隱私設定。"</string>
     <string name="accessibility_brightness" msgid="8003681285547803095">"螢幕亮度"</string>
@@ -459,8 +459,8 @@
     <string name="media_projection_remember_text" msgid="3103510882172746752">"不要再顯示"</string>
     <string name="clear_all_notifications_text" msgid="814192889771462828">"全部清除"</string>
     <string name="manage_notifications_text" msgid="2386728145475108753">"管理"</string>
-    <string name="notification_section_header_gentle" msgid="4372438504154095677">"無聲通知"</string>
-    <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4286716295850400959">"清除所有無聲通知"</string>
+    <string name="notification_section_header_gentle" msgid="4372438504154095677">"靜音通知"</string>
+    <string name="accessibility_notification_section_header_gentle_clear_all" msgid="4286716295850400959">"清除所有靜音通知"</string>
     <string name="dnd_suppressing_shade_text" msgid="1904574852846769301">"「零打擾」模式已將通知設為暫停"</string>
     <string name="media_projection_action_text" msgid="8470872969457985954">"立即開始"</string>
     <string name="empty_shade_text" msgid="708135716272867002">"沒有通知"</string>
@@ -645,7 +645,7 @@
     <string name="inline_block_button" msgid="8735843688021655065">"封鎖"</string>
     <string name="inline_keep_button" msgid="6665940297019018232">"繼續顯示"</string>
     <string name="inline_minimize_button" msgid="966233327974702195">"最小化"</string>
-    <string name="inline_silent_button_silent" msgid="5315879183296940969">"無聲"</string>
+    <string name="inline_silent_button_silent" msgid="5315879183296940969">"靜音"</string>
     <string name="inline_silent_button_stay_silent" msgid="6308371431217601009">"繼續顯示通知但不發出音效"</string>
     <string name="inline_silent_button_alert" msgid="6008435419895088034">"快訊"</string>
     <string name="inline_silent_button_keep_alerting" msgid="327696842264359693">"繼續顯示通知"</string>
@@ -747,8 +747,8 @@
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"已與耳機連線"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"已與耳機連線"</string>
     <string name="data_saver" msgid="5037565123367048522">"數據節省模式"</string>
-    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"Data Saver 已開啟"</string>
-    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"Data Saver 已關閉"</string>
+    <string name="accessibility_data_saver_on" msgid="8454111686783887148">"數據節省模式已開啟"</string>
+    <string name="accessibility_data_saver_off" msgid="8841582529453005337">"數據節省模式已關閉"</string>
     <string name="switch_bar_on" msgid="1142437840752794229">"開啟"</string>
     <string name="switch_bar_off" msgid="8803270596930432874">"關閉"</string>
     <string name="nav_bar" msgid="1993221402773877607">"導覽列"</string>
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index b964edf..720074b 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -217,8 +217,6 @@
         }
     }
 
-    private static KeyguardUpdateMonitor sInstance;
-
     private final Context mContext;
     private final boolean mIsPrimaryUser;
     HashMap<Integer, SimData> mSimDatas = new HashMap<Integer, SimData>();
@@ -1389,15 +1387,6 @@
         Trace.endSection();
     }
 
-
-    /** Provides access to the static instance. */
-    public static KeyguardUpdateMonitor getInstance(Context context) {
-        if (sInstance == null) {
-            sInstance = new KeyguardUpdateMonitor(context, Looper.getMainLooper());
-        }
-        return sInstance;
-    }
-
     protected void handleStartedGoingToSleep(int arg1) {
         checkIsHandlerThread();
         mLockIconPressed = false;
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactory.java
index 0f99674..e8b5285 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactory.java
@@ -21,6 +21,8 @@
 import android.content.ContentProvider;
 import android.content.Context;
 import android.content.Intent;
+import android.os.Process;
+import android.util.Log;
 
 import androidx.annotation.NonNull;
 import androidx.core.app.AppComponentFactory;
@@ -38,6 +40,7 @@
  */
 public class SystemUIAppComponentFactory extends AppComponentFactory {
 
+    private static final String TAG = "AppComponentFactory";
     @Inject
     public ContextComponentHelper mComponentHelper;
 
@@ -57,6 +60,9 @@
                         SystemUIFactory.createFromConfig(context);
                         SystemUIFactory.getInstance().getRootComponent().inject(
                                 SystemUIAppComponentFactory.this);
+                        Log.d(TAG, "Initialized during Application creation in Process "
+                                + Process.myPid() + ", Thread " + Process.myTid());
+                        Log.d(TAG, "mComponentHelper: " + mComponentHelper);
                     }
             );
         }
@@ -77,6 +83,8 @@
                         SystemUIFactory.createFromConfig(context);
                         SystemUIFactory.getInstance().getRootComponent().inject(
                                 contentProvider);
+                        Log.d(TAG, "Initialized during ContentProvider creation in Process "
+                                + Process.myPid() + ", Thread " + Process.myTid());
                     }
             );
         }
@@ -89,6 +97,12 @@
     public Service instantiateServiceCompat(
             @NonNull ClassLoader cl, @NonNull String className, Intent intent)
             throws InstantiationException, IllegalAccessException, ClassNotFoundException {
+        if (mComponentHelper == null) {
+            // Everything is about to crash if this is true, but that is inevitable. We either crash
+            // here or crash lower in the stack. Better to crash early!
+            Log.wtf(TAG, "Uninitialized mComponentHelper in Process" + Process.myPid() + ", Thread "
+                    + Process.myTid());
+        }
         Service service = mComponentHelper.resolveService(className);
         if (service != null) {
             return service;
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
index 00bfb3f..bab64db 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
@@ -417,6 +417,9 @@
         mDozeSensors.dump(pw);
     }
 
+    /**
+     * @see DozeSensors.ProxSensor
+     */
     private abstract class ProximityCheck implements SensorEventListener, Runnable {
         private static final int TIMEOUT_DELAY_MS = 500;
 
@@ -428,6 +431,7 @@
         private boolean mRegistered;
         private boolean mFinished;
         private float mMaxRange;
+        private boolean mUsingBrightnessSensor;
 
         protected abstract void onProximityResult(int result);
 
@@ -435,6 +439,7 @@
             Preconditions.checkState(!mFinished && !mRegistered);
             Sensor sensor = DozeSensors.findSensorWithType(mSensorManager,
                     mContext.getString(R.string.doze_brightness_sensor_type));
+            mUsingBrightnessSensor = sensor != null;
             if (sensor == null) {
                 sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
             }
@@ -453,6 +458,9 @@
             mRegistered = true;
         }
 
+        /**
+         * @see DozeSensors.ProxSensor#onSensorChanged(SensorEvent)
+         */
         @Override
         public void onSensorChanged(SensorEvent event) {
             if (event.values.length == 0) {
@@ -462,7 +470,14 @@
                 if (DozeMachine.DEBUG) {
                     Log.d(TAG, "ProxCheck: Event: value=" + event.values[0] + " max=" + mMaxRange);
                 }
-                final boolean isNear = event.values[0] < mMaxRange;
+                final boolean isNear;
+                if (mUsingBrightnessSensor) {
+                    // The custom brightness sensor is gated by the proximity sensor and will
+                    // return 0 whenever prox is covered.
+                    isNear = event.values[0] == 0;
+                } else {
+                    isNear = event.values[0] < mMaxRange;
+                }
                 finishWithResult(isNear ? RESULT_NEAR : RESULT_FAR);
             }
         }
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ru/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ru/strings.xml
index dc77981..0ff85fe 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ru/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-ru/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"Сделать вырез в углу"</string>
+    <string name="display_cutout_emulation_overlay" msgid="1677693377327336341">"В правом углу"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ru/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ru/strings.xml
index a02eaf7..2493da3 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ru/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-ru/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Увеличить вырез вдвое"</string>
+    <string name="display_cutout_emulation_overlay" msgid="5323179900047630217">"Сверху и снизу"</string>
 </resources>
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ru/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ru/strings.xml
index 1d1656d..89ac1c3 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ru/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-ru/strings.xml
@@ -17,5 +17,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Сделать вырез выше"</string>
+    <string name="display_cutout_emulation_overlay" msgid="6424539415439220018">"Сверху"</string>
 </resources>
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index e53cbc1..7f69a68 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -65,7 +65,6 @@
 import android.content.pm.UserInfo;
 import android.database.ContentObserver;
 import android.hardware.camera2.CameraDevice.CAMERA_AUDIO_RESTRICTION;
-import android.media.AudioAttributes;
 import android.net.Uri;
 import android.os.AsyncTask;
 import android.os.Binder;
@@ -361,7 +360,7 @@
 
         public int startNesting;
         public ArrayMap<String, Ops> pkgOps;
-        public SparseIntArray opModes;
+        private SparseIntArray opModes;
 
         // true indicates there is an interested observer, false there isn't but it has such an op
         public SparseBooleanArray foregroundOps;
@@ -383,6 +382,64 @@
                     && (pendingState == UID_STATE_CACHED));
         }
 
+        public int getOpModeCount() {
+            return opModes != null ? opModes.size() : 0;
+        }
+
+        public int getOpCodeAt(int index) {
+            return opModes.keyAt(index);
+        }
+
+        public boolean hasOpMode(int code) {
+            return opModes != null && opModes.indexOfKey(code) >= 0;
+        }
+
+        public int getOpMode(int code) {
+            return opModes.get(code);
+        }
+
+        public boolean putOpMode(int code, int mode) {
+            if (mode == AppOpsManager.opToDefaultMode(code)) {
+                return removeOpMode(code);
+            }
+            if (opModes == null) {
+                opModes = new SparseIntArray();
+            }
+            int index = opModes.indexOfKey(code);
+            if (index < 0) {
+                opModes.put(code, mode);
+                return true;
+            }
+            if (opModes.valueAt(index) == mode) {
+                return false;
+            }
+            opModes.setValueAt(index, mode);
+            return true;
+        }
+
+        public boolean removeOpMode(int code) {
+            if (opModes == null) {
+                return false;
+            }
+            int index = opModes.indexOfKey(code);
+            if (index < 0) {
+                return false;
+            }
+            opModes.removeAt(index);
+            if (opModes.size() == 0) {
+                opModes = null;
+            }
+            return true;
+        }
+
+        @Nullable
+        public SparseIntArray cloneOpModes() {
+            if (opModes == null) {
+                return null;
+            }
+            return opModes.clone();
+        }
+
         int evalMode(int op, int mode) {
             if (mode == AppOpsManager.MODE_FOREGROUND) {
                 return state <= AppOpsManager.resolveFirstUnrestrictedUidState(op)
@@ -410,14 +467,13 @@
         public void evalForegroundOps(SparseArray<ArraySet<ModeCallback>> watchers) {
             SparseBooleanArray which = null;
             hasForegroundWatchers = false;
-            if (opModes != null) {
-                for (int i = opModes.size() - 1; i >= 0; i--) {
-                    if (opModes.valueAt(i) == AppOpsManager.MODE_FOREGROUND) {
-                        if (which == null) {
-                            which = new SparseBooleanArray();
-                        }
-                        evalForegroundWatchers(opModes.keyAt(i), watchers, which);
+            for (int i = getOpModeCount() - 1; i >= 0; i--) {
+                int code = getOpCodeAt(i);
+                if (getOpMode(code) == AppOpsManager.MODE_FOREGROUND) {
+                    if (which == null) {
+                        which = new SparseBooleanArray();
                     }
+                    evalForegroundWatchers(code, watchers, which);
                 }
             }
             if (pkgOps != null) {
@@ -1056,24 +1112,28 @@
         return resOps;
     }
 
-    private ArrayList<AppOpsManager.OpEntry> collectOps(SparseIntArray uidOps, int[] ops) {
-        if (uidOps == null) {
+    @Nullable
+    private ArrayList<AppOpsManager.OpEntry> collectOps(@NonNull UidState uidState,
+            @Nullable int[] ops) {
+        int opModeCount = uidState.getOpModeCount();
+        if (opModeCount == 0) {
             return null;
         }
         ArrayList<AppOpsManager.OpEntry> resOps = null;
         if (ops == null) {
             resOps = new ArrayList<>();
-            for (int j=0; j<uidOps.size(); j++) {
-                resOps.add(new OpEntry(uidOps.keyAt(j), uidOps.valueAt(j)));
+            for (int i = 0; i < opModeCount; i++) {
+                int code = uidState.getOpCodeAt(i);
+                resOps.add(new OpEntry(code, uidState.getOpMode(code)));
             }
         } else {
-            for (int j=0; j<ops.length; j++) {
-                int index = uidOps.indexOfKey(ops[j]);
-                if (index >= 0) {
+            for (int i = 0; i < ops.length; i++) {
+                int code = ops[i];
+                if (uidState.hasOpMode(code)) {
                     if (resOps == null) {
                         resOps = new ArrayList<>();
                     }
-                    resOps.add(new OpEntry(uidOps.keyAt(j), uidOps.valueAt(j)));
+                    resOps.add(new OpEntry(code, uidState.getOpMode(code)));
                 }
             }
         }
@@ -1219,11 +1279,11 @@
             if (uidState == null) {
                 return null;
             }
-            ArrayList<AppOpsManager.OpEntry> resOps = collectOps(uidState.opModes, ops);
+            ArrayList<AppOpsManager.OpEntry> resOps = collectOps(uidState, ops);
             if (resOps == null) {
                 return null;
             }
-            ArrayList<AppOpsManager.PackageOps> res = new ArrayList<AppOpsManager.PackageOps>();
+            ArrayList<AppOpsManager.PackageOps> res = new ArrayList<>();
             AppOpsManager.PackageOps resPackage = new AppOpsManager.PackageOps(
                     null, uidState.uid, resOps);
             res.add(resPackage);
@@ -1291,29 +1351,14 @@
                     return;
                 }
                 uidState = new UidState(uid);
-                uidState.opModes = new SparseIntArray();
-                uidState.opModes.put(code, mode);
+                uidState.putOpMode(code, mode);
                 mUidStates.put(uid, uidState);
                 scheduleWriteLocked();
-            } else if (uidState.opModes == null) {
-                if (mode != defaultMode) {
-                    uidState.opModes = new SparseIntArray();
-                    uidState.opModes.put(code, mode);
+            } else {
+                boolean changed = uidState.putOpMode(code, mode);
+                if (changed) {
                     scheduleWriteLocked();
                 }
-            } else {
-                if (uidState.opModes.indexOfKey(code) >= 0 && uidState.opModes.get(code) == mode) {
-                    return;
-                }
-                if (mode == defaultMode) {
-                    uidState.opModes.delete(code);
-                    if (uidState.opModes.size() <= 0) {
-                        uidState.opModes = null;
-                    }
-                } else {
-                    uidState.opModes.put(code, mode);
-                }
-                scheduleWriteLocked();
             }
             uidState.evalForegroundOps(mOpModeWatchers);
         }
@@ -1552,16 +1597,13 @@
             for (int i = mUidStates.size() - 1; i >= 0; i--) {
                 UidState uidState = mUidStates.valueAt(i);
 
-                SparseIntArray opModes = uidState.opModes;
-                if (opModes != null && (uidState.uid == reqUid || reqUid == -1)) {
-                    final int uidOpCount = opModes.size();
-                    for (int j = uidOpCount - 1; j >= 0; j--) {
-                        final int code = opModes.keyAt(j);
+                if (uidState.uid == reqUid || reqUid == -1) {
+                    for (int opModeIndex = uidState.getOpModeCount() - 1; opModeIndex >= 0;
+                            opModeIndex--) {
+                        final int code = uidState.getOpCodeAt(opModeIndex);
+
                         if (AppOpsManager.opAllowsReset(code)) {
-                            opModes.removeAt(j);
-                            if (opModes.size() <= 0) {
-                                uidState.opModes = null;
-                            }
+                            uidState.removeOpMode(code);
                             for (String packageName : getPackagesForUid(uidState.uid)) {
                                 callbacks = addCallbacks(callbacks, code, uidState.uid, packageName,
                                         mOpModeWatchers.get(code));
@@ -1811,9 +1853,8 @@
             }
             code = AppOpsManager.opToSwitch(code);
             UidState uidState = getUidStateLocked(uid, false);
-            if (uidState != null && uidState.opModes != null
-                    && uidState.opModes.indexOfKey(code) >= 0) {
-                final int rawMode = uidState.opModes.get(code);
+            if (uidState != null && uidState.hasOpMode(code)) {
+                final int rawMode = uidState.getOpMode(code);
                 return raw ? rawMode : uidState.evalMode(code, rawMode);
             }
             Op op = getOpLocked(code, uid, packageName, false, false);
@@ -1982,8 +2023,8 @@
             final int switchCode = AppOpsManager.opToSwitch(code);
             // If there is a non-default per UID policy (we set UID op mode only if
             // non-default) it takes over, otherwise use the per package policy.
-            if (uidState.opModes != null && uidState.opModes.indexOfKey(switchCode) >= 0) {
-                final int uidMode = uidState.evalMode(code, uidState.opModes.get(switchCode));
+            if (uidState.hasOpMode(switchCode)) {
+                final int uidMode = uidState.evalMode(code, uidState.getOpMode(switchCode));
                 if (uidMode != AppOpsManager.MODE_ALLOWED) {
                     if (DEBUG) Slog.d(TAG, "noteOperation: uid reject #" + uidMode + " for code "
                             + switchCode + " (" + code + ") uid " + uid + " package "
@@ -2284,8 +2325,8 @@
             // If there is a non-default per UID policy (we set UID op mode only if
             // non-default) it takes over, otherwise use the per package policy.
             final int opCode = op.op;
-            if (uidState.opModes != null && uidState.opModes.indexOfKey(switchCode) >= 0) {
-                final int uidMode = uidState.evalMode(code, uidState.opModes.get(switchCode));
+            if (uidState.hasOpMode(switchCode)) {
+                final int uidMode = uidState.evalMode(code, uidState.getOpMode(switchCode));
                 if (uidMode != AppOpsManager.MODE_ALLOWED
                         && (!startIfModeDefault || uidMode != AppOpsManager.MODE_DEFAULT)) {
                     if (DEBUG) Slog.d(TAG, "noteOperation: uid reject #" + uidMode + " for code "
@@ -2604,9 +2645,8 @@
                                 || !callback.isWatchingUid(uidState.uid)) {
                             continue;
                         }
-                        boolean doAllPackages = uidState.opModes != null
-                                && uidState.opModes.indexOfKey(code) >= 0
-                                && uidState.opModes.get(code) == AppOpsManager.MODE_FOREGROUND;
+                        boolean doAllPackages = uidState.hasOpMode(code)
+                                && uidState.getOpMode(code) == AppOpsManager.MODE_FOREGROUND;
                         if (uidState.pkgOps != null) {
                             for (int pkgi = uidState.pkgOps.size() - 1; pkgi >= 0; pkgi--) {
                                 final Op op = uidState.pkgOps.valueAt(pkgi).get(code);
@@ -2927,12 +2967,9 @@
             if (uidState == null) {
                 continue;
             }
-            if (uidState.opModes != null) {
-                final int idx = uidState.opModes.indexOfKey(AppOpsManager.OP_RUN_IN_BACKGROUND);
-                if (idx >= 0) {
-                    uidState.opModes.put(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND,
-                        uidState.opModes.valueAt(idx));
-                }
+            if (uidState.hasOpMode(AppOpsManager.OP_RUN_IN_BACKGROUND)) {
+                uidState.putOpMode(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, uidState.getOpMode(
+                        AppOpsManager.OP_RUN_IN_BACKGROUND));
             }
             if (uidState.pkgOps == null) {
                 continue;
@@ -2988,10 +3025,7 @@
                 final int code = Integer.parseInt(parser.getAttributeValue(null, "n"));
                 final int mode = Integer.parseInt(parser.getAttributeValue(null, "m"));
                 UidState uidState = getUidStateLocked(uid, true);
-                if (uidState.opModes == null) {
-                    uidState.opModes = new SparseIntArray();
-                }
-                uidState.opModes.put(code, mode);
+                uidState.putOpMode(code, mode);
             } else {
                 Slog.w(TAG, "Unknown element under <uid-ops>: "
                         + parser.getName());
@@ -3143,47 +3177,38 @@
                 out.startTag(null, "app-ops");
                 out.attribute(null, "v", String.valueOf(CURRENT_VERSION));
 
-                SparseArray<SparseIntArray> uidStatesClone;
+                final SparseArray<SparseIntArray> uidOpModes = new SparseArray<>();
                 synchronized (this) {
-                    uidStatesClone = new SparseArray<>(mUidStates.size());
-
-                    final int uidStateCount = mUidStates.size();
-                    for (int uidStateNum = 0; uidStateNum < uidStateCount; uidStateNum++) {
-                        UidState uidState = mUidStates.valueAt(uidStateNum);
-                        int uid = mUidStates.keyAt(uidStateNum);
-
-                        SparseIntArray opModes = uidState.opModes;
-                        if (opModes != null && opModes.size() > 0) {
-                            uidStatesClone.put(uid, new SparseIntArray(opModes.size()));
-
-                            final int opCount = opModes.size();
-                            for (int opCountNum = 0; opCountNum < opCount; opCountNum++) {
-                                uidStatesClone.get(uid).put(
-                                        opModes.keyAt(opCountNum),
-                                        opModes.valueAt(opCountNum));
-                            }
+                    final int uidStatesSize = mUidStates.size();
+                    for (int i = 0; i < uidStatesSize; i++) {
+                        final SparseIntArray opModes = mUidStates.valueAt(i).cloneOpModes();
+                        if (opModes != null) {
+                            final int uid = mUidStates.keyAt(i);
+                            uidOpModes.put(uid, opModes);
                         }
                     }
                 }
 
-                final int uidStateCount = uidStatesClone.size();
-                for (int uidStateNum = 0; uidStateNum < uidStateCount; uidStateNum++) {
-                    SparseIntArray opModes = uidStatesClone.valueAt(uidStateNum);
-                    if (opModes != null && opModes.size() > 0) {
-                        out.startTag(null, "uid");
-                        out.attribute(null, "n",
-                                Integer.toString(uidStatesClone.keyAt(uidStateNum)));
-                        final int opCount = opModes.size();
-                        for (int opCountNum = 0; opCountNum < opCount; opCountNum++) {
-                            final int op = opModes.keyAt(opCountNum);
-                            final int mode = opModes.valueAt(opCountNum);
-                            out.startTag(null, "op");
-                            out.attribute(null, "n", Integer.toString(op));
-                            out.attribute(null, "m", Integer.toString(mode));
-                            out.endTag(null, "op");
-                        }
-                        out.endTag(null, "uid");
+                final int uidOpModesSize = uidOpModes.size();
+                for (int uidOpModesIndex = 0; uidOpModesIndex < uidOpModesSize; uidOpModesIndex++) {
+                    final int uid = uidOpModes.keyAt(uidOpModesIndex);
+                    final SparseIntArray opModes = uidOpModes.valueAt(uidOpModesIndex);
+
+                    out.startTag(null, "uid");
+                    out.attribute(null, "n", Integer.toString(uid));
+
+                    final int opModesSize = opModes.size();
+                    for (int opModesIndex = 0; opModesIndex < opModesSize; opModesIndex++) {
+                        final int code = opModes.keyAt(opModesIndex);
+                        final int mode = opModes.valueAt(opModesIndex);
+
+                        out.startTag(null, "op");
+                        out.attribute(null, "n", Integer.toString(code));
+                        out.attribute(null, "m", Integer.toString(mode));
+                        out.endTag(null, "op");
                     }
+
+                    out.endTag(null, "uid");
                 }
 
                 if (allOps != null) {
@@ -4128,21 +4153,22 @@
             }
             for (int i=0; i<mUidStates.size(); i++) {
                 UidState uidState = mUidStates.valueAt(i);
-                final SparseIntArray opModes = uidState.opModes;
                 final ArrayMap<String, Ops> pkgOps = uidState.pkgOps;
 
                 if (dumpWatchers || dumpHistory) {
                     continue;
                 }
                 if (dumpOp >= 0 || dumpPackage != null || dumpMode >= 0) {
-                    boolean hasOp = dumpOp < 0 || (uidState.opModes != null
-                            && uidState.opModes.indexOfKey(dumpOp) >= 0);
+                    boolean hasOp = dumpOp < 0 || uidState.hasOpMode(dumpOp);
                     boolean hasPackage = dumpPackage == null;
                     boolean hasMode = dumpMode < 0;
-                    if (!hasMode && opModes != null) {
-                        for (int opi = 0; !hasMode && opi < opModes.size(); opi++) {
-                            if (opModes.valueAt(opi) == dumpMode) {
+                    if (!hasMode) {
+                        int opModeCount = uidState.getOpModeCount();
+                        for (int opModeIndex = 0; opModeIndex < opModeCount; opModeIndex++) {
+                            int code = uidState.getOpCodeAt(opModeIndex);
+                            if (uidState.getOpMode(code) == dumpMode) {
                                 hasMode = true;
+                                break;
                             }
                         }
                     }
@@ -4209,20 +4235,18 @@
                 }
                 needSep = true;
 
-                if (opModes != null) {
-                    final int opModeCount = opModes.size();
-                    for (int j = 0; j < opModeCount; j++) {
-                        final int code = opModes.keyAt(j);
-                        final int mode = opModes.valueAt(j);
-                        if (dumpOp >= 0 && dumpOp != code) {
-                            continue;
-                        }
-                        if (dumpMode >= 0 && dumpMode != mode) {
-                            continue;
-                        }
-                        pw.print("      "); pw.print(AppOpsManager.opToName(code));
-                        pw.print(": mode="); pw.println(AppOpsManager.modeToName(mode));
+                final int opModeCount = uidState.getOpModeCount();
+                for (int opModeIndex = 0; opModeIndex < opModeCount; opModeIndex++) {
+                    final int code = uidState.getOpCodeAt(opModeIndex);
+                    final int mode = uidState.getOpMode(code);
+                    if (dumpOp >= 0 && dumpOp != code) {
+                        continue;
                     }
+                    if (dumpMode >= 0 && dumpMode != mode) {
+                        continue;
+                    }
+                    pw.print("      "); pw.print(AppOpsManager.opToName(code));
+                    pw.print(": mode="); pw.println(AppOpsManager.modeToName(mode));
                 }
 
                 if (pkgOps == null) {
diff --git a/services/core/java/com/android/server/pm/dex/ArtManagerService.java b/services/core/java/com/android/server/pm/dex/ArtManagerService.java
index 9948a3a..b3f1867 100644
--- a/services/core/java/com/android/server/pm/dex/ArtManagerService.java
+++ b/services/core/java/com/android/server/pm/dex/ArtManagerService.java
@@ -277,9 +277,6 @@
         try {
             fd = ParcelFileDescriptor.open(snapshotProfile, ParcelFileDescriptor.MODE_READ_ONLY);
             if (fd == null || !fd.getFileDescriptor().valid()) {
-                Slog.wtf(TAG,
-                        "ParcelFileDescriptor.open returned an invalid descriptor for "
-                                + packageName + ":" + snapshotProfile + ". isNull=" + (fd == null));
                 postError(callback, packageName, ArtManager.SNAPSHOT_FAILED_INTERNAL_ERROR);
             } else {
                 postSuccess(packageName, fd, callback);
diff --git a/services/core/java/com/android/server/rollback/Rollback.java b/services/core/java/com/android/server/rollback/Rollback.java
index 0d5746b..6769fe0 100644
--- a/services/core/java/com/android/server/rollback/Rollback.java
+++ b/services/core/java/com/android/server/rollback/Rollback.java
@@ -65,7 +65,7 @@
     /**
      * The directory where the rollback data is stored.
      */
-    public final File backupDir;
+    private final File mBackupDir;
 
     /**
      * The time when the upgrade occurred, for purposes of expiring
@@ -74,24 +74,24 @@
      * The timestamp is not applicable for all rollback states, but we make
      * sure to keep it non-null to avoid potential errors there.
      */
-    public @NonNull Instant timestamp;
+    private @NonNull Instant mTimestamp;
 
     /**
      * The session ID for the staged session if this rollback data represents a staged session,
      * {@code -1} otherwise.
      */
-    public final int stagedSessionId;
+    private final int mStagedSessionId;
 
     /**
      * The current state of the rollback.
      * ENABLING, AVAILABLE, or COMMITTED.
      */
-    public @RollbackState int state;
+    private @RollbackState int mState;
 
     /**
      * The id of the post-reboot apk session for a staged install, if any.
      */
-    public int apkSessionId = -1;
+    private int mApkSessionId = -1;
 
     /**
      * True if we are expecting the package manager to call restoreUserData
@@ -99,7 +99,7 @@
      * has not yet been fully applied.
      */
     // NOTE: All accesses to this field are from the RollbackManager handler thread.
-    public boolean restoreUserDataInProgress = false;
+    private boolean mRestoreUserDataInProgress = false;
 
     /**
      * Constructs a new, empty Rollback instance.
@@ -114,10 +114,10 @@
                 /* isStaged */ stagedSessionId != -1,
                 /* causePackages */ new ArrayList<>(),
                 /* committedSessionId */ -1);
-        this.backupDir = backupDir;
-        this.stagedSessionId = stagedSessionId;
-        this.state = ROLLBACK_STATE_ENABLING;
-        this.timestamp = Instant.now();
+        mBackupDir = backupDir;
+        mStagedSessionId = stagedSessionId;
+        mState = ROLLBACK_STATE_ENABLING;
+        mTimestamp = Instant.now();
     }
 
     /**
@@ -126,21 +126,115 @@
     Rollback(RollbackInfo info, File backupDir, Instant timestamp, int stagedSessionId,
             @RollbackState int state, int apkSessionId, boolean restoreUserDataInProgress) {
         this.info = info;
-        this.backupDir = backupDir;
-        this.timestamp = timestamp;
-        this.stagedSessionId = stagedSessionId;
-        this.state = state;
-        this.apkSessionId = apkSessionId;
-        this.restoreUserDataInProgress = restoreUserDataInProgress;
+        mBackupDir = backupDir;
+        mTimestamp = timestamp;
+        mStagedSessionId = stagedSessionId;
+        mState = state;
+        mApkSessionId = apkSessionId;
+        mRestoreUserDataInProgress = restoreUserDataInProgress;
     }
 
     /**
      * Whether the rollback is for rollback of a staged install.
      */
-    public boolean isStaged() {
+    boolean isStaged() {
         return info.isStaged();
     }
 
+    /**
+     * Returns the directory in which rollback data should be stored.
+     */
+    File getBackupDir() {
+        return mBackupDir;
+    }
+
+    /**
+     * Returns the time when the upgrade occurred, for purposes of expiring rollback data.
+     */
+    Instant getTimestamp() {
+        return mTimestamp;
+    }
+
+    /**
+     * Sets the time at which upgrade occurred.
+     */
+    void setTimestamp(Instant timestamp) {
+        mTimestamp = timestamp;
+    }
+
+    /**
+     * Returns the session ID for the staged session if this rollback data represents a staged
+     * session, or {@code -1} otherwise.
+     */
+    int getStagedSessionId() {
+        return mStagedSessionId;
+    }
+
+    /**
+     * Returns true if the rollback is in the ENABLING state.
+     */
+    boolean isEnabling() {
+        return mState == ROLLBACK_STATE_ENABLING;
+    }
+
+    /**
+     * Returns true if the rollback is in the AVAILABLE state.
+     */
+    boolean isAvailable() {
+        return mState == ROLLBACK_STATE_AVAILABLE;
+    }
+
+    /**
+     * Returns true if the rollback is in the COMMITTED state.
+     */
+    boolean isCommitted() {
+        return mState == ROLLBACK_STATE_COMMITTED;
+    }
+
+    /**
+     * Sets the state of the rollback to AVAILABLE.
+     */
+    void setAvailable() {
+        mState = ROLLBACK_STATE_AVAILABLE;
+    }
+
+    /**
+     * Sets the state of the rollback to COMMITTED.
+     */
+    void setCommitted() {
+        mState = ROLLBACK_STATE_COMMITTED;
+    }
+
+    /**
+     * Returns the id of the post-reboot apk session for a staged install, if any.
+     */
+    int getApkSessionId() {
+        return mApkSessionId;
+    }
+
+    /**
+     * Sets the id of the post-reboot apk session for a staged install.
+     */
+    void setApkSessionId(int apkSessionId) {
+        mApkSessionId = apkSessionId;
+    }
+
+    /**
+     * Returns true if we are expecting the package manager to call restoreUserData for this
+     * rollback because it has just been committed but the rollback has not yet been fully applied.
+     */
+    boolean isRestoreUserDataInProgress() {
+        return mRestoreUserDataInProgress;
+    }
+
+    /**
+     * Sets whether we are expecting the package manager to call restoreUserData for this
+     * rollback because it has just been committed but the rollback has not yet been fully applied.
+     */
+    void setRestoreUserDataInProgress(boolean restoreUserDataInProgress) {
+        mRestoreUserDataInProgress = restoreUserDataInProgress;
+    }
+
     static String rollbackStateToString(@RollbackState int state) {
         switch (state) {
             case Rollback.ROLLBACK_STATE_ENABLING: return "enabling";
@@ -160,7 +254,7 @@
         throw new ParseException("Invalid rollback state: " + state, 0);
     }
 
-    public String getStateAsString() {
-        return rollbackStateToString(state);
+    String getStateAsString() {
+        return rollbackStateToString(mState);
     }
 }
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index 3147bc6..96d284b 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -282,7 +282,7 @@
             List<RollbackInfo> rollbacks = new ArrayList<>();
             for (int i = 0; i < mRollbacks.size(); ++i) {
                 Rollback rollback = mRollbacks.get(i);
-                if (rollback.state == Rollback.ROLLBACK_STATE_AVAILABLE) {
+                if (rollback.isAvailable()) {
                     rollbacks.add(rollback.info);
                 }
             }
@@ -298,7 +298,7 @@
             List<RollbackInfo> rollbacks = new ArrayList<>();
             for (int i = 0; i < mRollbacks.size(); ++i) {
                 Rollback rollback = mRollbacks.get(i);
-                if (rollback.state == Rollback.ROLLBACK_STATE_COMMITTED) {
+                if (rollback.isCommitted()) {
                     rollbacks.add(rollback.info);
                 }
             }
@@ -332,7 +332,7 @@
                     Iterator<Rollback> iter = mRollbacks.iterator();
                     while (iter.hasNext()) {
                         Rollback rollback = iter.next();
-                        rollback.timestamp = rollback.timestamp.plusMillis(timeDifference);
+                        rollback.setTimestamp(rollback.getTimestamp().plusMillis(timeDifference));
                         saveRollback(rollback);
                     }
                 }
@@ -358,7 +358,7 @@
         Slog.i(TAG, "Initiating rollback");
 
         Rollback rollback = getRollbackForId(rollbackId);
-        if (rollback == null || rollback.state != Rollback.ROLLBACK_STATE_AVAILABLE) {
+        if (rollback == null || !rollback.isAvailable()) {
             sendFailure(statusReceiver, RollbackManager.STATUS_FAILURE_ROLLBACK_UNAVAILABLE,
                     "Rollback unavailable");
             return;
@@ -454,8 +454,8 @@
                                     // TODO: Could this cause a rollback to be
                                     // resurrected if it should otherwise have
                                     // expired by now?
-                                    rollback.state = Rollback.ROLLBACK_STATE_AVAILABLE;
-                                    rollback.restoreUserDataInProgress = false;
+                                    rollback.setAvailable();
+                                    rollback.setRestoreUserDataInProgress(false);
                                 }
                                 sendFailure(statusReceiver, RollbackManager.STATUS_FAILURE_INSTALL,
                                         "Rollback downgrade install failed: "
@@ -468,7 +468,7 @@
                                 if (!rollback.isStaged()) {
                                     // All calls to restoreUserData should have
                                     // completed by now for a non-staged install.
-                                    rollback.restoreUserDataInProgress = false;
+                                    rollback.setRestoreUserDataInProgress(false);
                                 }
 
                                 rollback.info.setCommittedSessionId(parentSessionId);
@@ -490,8 +490,8 @@
             );
 
             synchronized (mLock) {
-                rollback.state = Rollback.ROLLBACK_STATE_COMMITTED;
-                rollback.restoreUserDataInProgress = true;
+                rollback.setCommitted();
+                rollback.setRestoreUserDataInProgress(true);
             }
             parentSession.commit(receiver.getIntentSender());
         } catch (IOException e) {
@@ -618,9 +618,9 @@
             synchronized (mLock) {
                 for (Rollback rollback : mRollbacks) {
                     if (rollback.isStaged()) {
-                        if (rollback.state == Rollback.ROLLBACK_STATE_ENABLING) {
+                        if (rollback.isEnabling()) {
                             enabling.add(rollback);
-                        } else if (rollback.restoreUserDataInProgress) {
+                        } else if (rollback.isRestoreUserDataInProgress()) {
                             restoreInProgress.add(rollback);
                         }
 
@@ -635,8 +635,8 @@
 
             for (Rollback rollback : enabling) {
                 PackageInstaller installer = mContext.getPackageManager().getPackageInstaller();
-                PackageInstaller.SessionInfo session = installer.getSessionInfo(
-                        rollback.stagedSessionId);
+                PackageInstaller.SessionInfo session =
+                        installer.getSessionInfo(rollback.getStagedSessionId());
                 if (session == null || session.isStagedSessionFailed()) {
                     // TODO: Do we need to remove this from
                     // mRollbacks, or is it okay to leave as
@@ -650,13 +650,13 @@
 
             for (Rollback rollback : restoreInProgress) {
                 PackageInstaller installer = mContext.getPackageManager().getPackageInstaller();
-                PackageInstaller.SessionInfo session = installer.getSessionInfo(
-                        rollback.stagedSessionId);
+                PackageInstaller.SessionInfo session =
+                        installer.getSessionInfo(rollback.getStagedSessionId());
                 // TODO: What if session is null?
                 if (session != null) {
                     if (session.isStagedSessionApplied() || session.isStagedSessionFailed()) {
                         synchronized (mLock) {
-                            rollback.restoreUserDataInProgress = false;
+                            rollback.setRestoreUserDataInProgress(false);
                         }
                         saveRollback(rollback);
                     }
@@ -694,8 +694,7 @@
             while (iter.hasNext()) {
                 Rollback rollback = iter.next();
                 // TODO: Should we remove rollbacks in the ENABLING state here?
-                if (rollback.state == Rollback.ROLLBACK_STATE_AVAILABLE
-                        || rollback.state == Rollback.ROLLBACK_STATE_ENABLING) {
+                if (rollback.isEnabling() || rollback.isAvailable()) {
                     for (PackageRollbackInfo info : rollback.info.getPackages()) {
                         if (info.getPackageName().equals(packageName)
                                 && !packageVersionsEqual(
@@ -761,15 +760,16 @@
             Iterator<Rollback> iter = mRollbacks.iterator();
             while (iter.hasNext()) {
                 Rollback rollback = iter.next();
-                if (rollback.state != Rollback.ROLLBACK_STATE_AVAILABLE) {
+                if (!rollback.isAvailable()) {
                     continue;
                 }
                 if (!now.isBefore(
-                            rollback.timestamp.plusMillis(mRollbackLifetimeDurationInMillis))) {
+                            rollback.getTimestamp()
+                                    .plusMillis(mRollbackLifetimeDurationInMillis))) {
                     iter.remove();
                     deleteRollback(rollback);
-                } else if (oldest == null || oldest.isAfter(rollback.timestamp)) {
-                    oldest = rollback.timestamp;
+                } else if (oldest == null || oldest.isAfter(rollback.getTimestamp())) {
+                    oldest = rollback.getTimestamp();
                 }
             }
         }
@@ -877,7 +877,7 @@
         synchronized (mLock) {
             for (int i = 0; i < mRollbacks.size(); ++i) {
                 Rollback rollback = mRollbacks.get(i);
-                if (rollback.apkSessionId == parentSession.getSessionId()) {
+                if (rollback.getApkSessionId() == parentSession.getSessionId()) {
                     // This is the apk session for a staged session with rollback enabled. We do not
                     // need to create a new rollback for this session.
                     return true;
@@ -1020,7 +1020,7 @@
             // staged installs
             for (int i = 0; i < mRollbacks.size(); i++) {
                 Rollback rollback = mRollbacks.get(i);
-                if (rollback.state != Rollback.ROLLBACK_STATE_ENABLING) {
+                if (!rollback.isEnabling()) {
                     continue;
                 }
 
@@ -1053,7 +1053,7 @@
         synchronized (mLock) {
             for (int i = 0; i < mRollbacks.size(); ++i) {
                 Rollback candidate = mRollbacks.get(i);
-                if (candidate.restoreUserDataInProgress) {
+                if (candidate.isRestoreUserDataInProgress()) {
                     info = getPackageRollbackInfo(candidate, packageName);
                     if (info != null) {
                         rollback = candidate;
@@ -1146,8 +1146,8 @@
             synchronized (mLock) {
                 for (int i = 0; i < mRollbacks.size(); ++i) {
                     Rollback candidate = mRollbacks.get(i);
-                    if (candidate.stagedSessionId == originalSessionId) {
-                        candidate.apkSessionId = apkSessionId;
+                    if (candidate.getStagedSessionId() == originalSessionId) {
+                        candidate.setApkSessionId(apkSessionId);
                         rollback = candidate;
                         break;
                     }
@@ -1333,8 +1333,8 @@
         // to a new package being installed. Won't this revive an expired
         // rollback? Consider adding a ROLLBACK_STATE_EXPIRED to address this.
         synchronized (mLock) {
-            rollback.state = Rollback.ROLLBACK_STATE_AVAILABLE;
-            rollback.timestamp = Instant.now();
+            rollback.setAvailable();
+            rollback.setTimestamp(Instant.now());
         }
         saveRollback(rollback);
 
@@ -1434,9 +1434,9 @@
                 ipw.println(info.getRollbackId() + ":");
                 ipw.increaseIndent();
                 ipw.println("-state: " + rollback.getStateAsString());
-                ipw.println("-timestamp: " + rollback.timestamp);
-                if (rollback.stagedSessionId != -1) {
-                    ipw.println("-stagedSessionId: " + rollback.stagedSessionId);
+                ipw.println("-timestamp: " + rollback.getTimestamp());
+                if (rollback.getStagedSessionId() != -1) {
+                    ipw.println("-stagedSessionId: " + rollback.getStagedSessionId());
                 }
                 ipw.println("-packages:");
                 ipw.increaseIndent();
@@ -1446,7 +1446,7 @@
                             + " -> " + pkg.getVersionRolledBackTo().getLongVersionCode());
                 }
                 ipw.decreaseIndent();
-                if (rollback.state == Rollback.ROLLBACK_STATE_COMMITTED) {
+                if (rollback.isCommitted()) {
                     ipw.println("-causePackages:");
                     ipw.increaseIndent();
                     for (VersionedPackage cPkg : info.getCausePackages()) {
diff --git a/services/core/java/com/android/server/rollback/RollbackStore.java b/services/core/java/com/android/server/rollback/RollbackStore.java
index b2448f6..772c53f 100644
--- a/services/core/java/com/android/server/rollback/RollbackStore.java
+++ b/services/core/java/com/android/server/rollback/RollbackStore.java
@@ -17,7 +17,6 @@
 package com.android.server.rollback;
 
 import static com.android.server.rollback.Rollback.rollbackStateFromString;
-import static com.android.server.rollback.Rollback.rollbackStateToString;
 
 import android.annotation.NonNull;
 import android.content.pm.VersionedPackage;
@@ -216,7 +215,7 @@
     static void backupPackageCodePath(Rollback rollback, String packageName, String codePath)
             throws IOException {
         File sourceFile = new File(codePath);
-        File targetDir = new File(rollback.backupDir, packageName);
+        File targetDir = new File(rollback.getBackupDir(), packageName);
         targetDir.mkdirs();
         File targetFile = new File(targetDir, sourceFile.getName());
 
@@ -229,7 +228,7 @@
      * Includes the base apk and any splits. Returns null if none found.
      */
     static File[] getPackageCodePaths(Rollback rollback, String packageName) {
-        File targetDir = new File(rollback.backupDir, packageName);
+        File targetDir = new File(rollback.getBackupDir(), packageName);
         File[] files = targetDir.listFiles();
         if (files == null || files.length == 0) {
             return null;
@@ -243,7 +242,7 @@
      */
     static void deletePackageCodePaths(Rollback rollback) {
         for (PackageRollbackInfo info : rollback.info.getPackages()) {
-            File targetDir = new File(rollback.backupDir, info.getPackageName());
+            File targetDir = new File(rollback.getBackupDir(), info.getPackageName());
             removeFile(targetDir);
         }
     }
@@ -255,13 +254,13 @@
         try {
             JSONObject dataJson = new JSONObject();
             dataJson.put("info", rollbackInfoToJson(rollback.info));
-            dataJson.put("timestamp", rollback.timestamp.toString());
-            dataJson.put("stagedSessionId", rollback.stagedSessionId);
-            dataJson.put("state", rollbackStateToString(rollback.state));
-            dataJson.put("apkSessionId", rollback.apkSessionId);
-            dataJson.put("restoreUserDataInProgress", rollback.restoreUserDataInProgress);
+            dataJson.put("timestamp", rollback.getTimestamp().toString());
+            dataJson.put("stagedSessionId", rollback.getStagedSessionId());
+            dataJson.put("state", rollback.getStateAsString());
+            dataJson.put("apkSessionId", rollback.getApkSessionId());
+            dataJson.put("restoreUserDataInProgress", rollback.isRestoreUserDataInProgress());
 
-            PrintWriter pw = new PrintWriter(new File(rollback.backupDir, "rollback.json"));
+            PrintWriter pw = new PrintWriter(new File(rollback.getBackupDir(), "rollback.json"));
             pw.println(dataJson.toString());
             pw.close();
         } catch (JSONException e) {
@@ -273,7 +272,7 @@
      * Removes all persistent storage associated with the given rollback.
      */
     void deleteRollback(Rollback rollback) {
-        removeFile(rollback.backupDir);
+        removeFile(rollback.getBackupDir());
     }
 
     /**
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index 7274d17..97b2047 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -109,8 +109,6 @@
         "libGLESv2",
         "libnetutils",
         "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
         "libutils",
         "libhwui",
         "libbpf_android",
diff --git a/services/tests/servicestests/src/com/android/server/appop/AppOpsUpgradeTest.java b/services/tests/servicestests/src/com/android/server/appop/AppOpsUpgradeTest.java
index 66d2bab..70650de 100644
--- a/services/tests/servicestests/src/com/android/server/appop/AppOpsUpgradeTest.java
+++ b/services/tests/servicestests/src/com/android/server/appop/AppOpsUpgradeTest.java
@@ -89,13 +89,11 @@
         final int defaultModeOp2 = AppOpsManager.opToDefaultMode(op2);
         for(int i = 0; i < uidStates.size(); i++) {
             final AppOpsService.UidState uidState = uidStates.valueAt(i);
-            if (uidState.opModes != null) {
-                final int uidMode1 = uidState.opModes.get(op1, defaultModeOp1);
-                final int uidMode2 = uidState.opModes.get(op2, defaultModeOp2);
-                assertEquals(uidMode1, uidMode2);
-                if (uidMode1 != defaultModeOp1) {
-                    numberOfNonDefaultOps++;
-                }
+            final int uidMode1 = uidState.hasOpMode(op1) ? uidState.getOpMode(op1) : defaultModeOp1;
+            final int uidMode2 = uidState.hasOpMode(op2) ? uidState.getOpMode(op2) : defaultModeOp2;
+            assertEquals(uidMode1, uidMode2);
+            if (uidMode1 != defaultModeOp1) {
+                numberOfNonDefaultOps++;
             }
             if (uidState.pkgOps == null) {
                 continue;
diff --git a/services/tests/servicestests/src/com/android/server/rollback/RollbackUnitTest.java b/services/tests/servicestests/src/com/android/server/rollback/RollbackUnitTest.java
new file mode 100644
index 0000000..d27f1c7
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/rollback/RollbackUnitTest.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.rollback;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.io.File;
+
+@RunWith(JUnit4.class)
+public class RollbackUnitTest {
+
+    @Test
+    public void newEmptyStagedRollbackDefaults() {
+        int rollbackId = 123;
+        int sessionId = 567;
+        File file = new File("/test/testing");
+
+        Rollback rollback = new Rollback(rollbackId, file, sessionId);
+
+        assertThat(rollback.isEnabling()).isTrue();
+        assertThat(rollback.getBackupDir().getAbsolutePath()).isEqualTo("/test/testing");
+        assertThat(rollback.isStaged()).isTrue();
+        assertThat(rollback.getStagedSessionId()).isEqualTo(567);
+    }
+
+    @Test
+    public void newEmptyNonStagedRollbackDefaults() {
+        int rollbackId = 123;
+        File file = new File("/test/testing");
+
+        Rollback rollback = new Rollback(rollbackId, file, -1);
+
+        assertThat(rollback.isEnabling()).isTrue();
+        assertThat(rollback.getBackupDir().getAbsolutePath()).isEqualTo("/test/testing");
+        assertThat(rollback.isStaged()).isFalse();
+    }
+
+    @Test
+    public void rollbackStateChanges() {
+        Rollback rollback = new Rollback(123, new File("/test/testing"), -1);
+
+        assertThat(rollback.isEnabling()).isTrue();
+        assertThat(rollback.isAvailable()).isFalse();
+        assertThat(rollback.isCommitted()).isFalse();
+
+        rollback.setAvailable();
+
+        assertThat(rollback.isEnabling()).isFalse();
+        assertThat(rollback.isAvailable()).isTrue();
+        assertThat(rollback.isCommitted()).isFalse();
+
+        rollback.setCommitted();
+
+        assertThat(rollback.isEnabling()).isFalse();
+        assertThat(rollback.isAvailable()).isFalse();
+        assertThat(rollback.isCommitted()).isTrue();
+    }
+
+}
diff --git a/startop/scripts/app_startup/app_startup_runner.py b/startop/scripts/app_startup/app_startup_runner.py
index eb582f9..fa1c4e6 100755
--- a/startop/scripts/app_startup/app_startup_runner.py
+++ b/startop/scripts/app_startup/app_startup_runner.py
@@ -41,11 +41,12 @@
 sys.path.append(os.path.dirname(DIR))
 import lib.cmd_utils as cmd_utils
 import lib.print_utils as print_utils
-import iorap.compiler as compiler
 from app_startup.run_app_with_prefetch import PrefetchAppRunner
 import app_startup.lib.args_utils as args_utils
 from app_startup.lib.data_frame import DataFrame
 from app_startup.lib.perfetto_trace_collector import PerfettoTraceCollector
+from iorap.compiler import CompilerType
+import iorap.compiler as compiler
 
 # The following command line options participate in the combinatorial generation.
 # All other arguments have a global effect.
@@ -58,8 +59,6 @@
 
 CollectorPackageInfo = NamedTuple('CollectorPackageInfo',
                                   [('package', str), ('compiler_filter', str)])
-_COMPILER_SCRIPT = os.path.join(os.path.dirname(os.path.dirname(
-    os.path.realpath(__file__))), 'iorap/compiler.py')
 # by 2; systrace starts up slowly.
 
 _UNLOCK_SCREEN_SCRIPT = os.path.join(
@@ -135,6 +134,10 @@
                               action='append',
                               help='The trace duration (milliseconds) in '
                                    'compilation')
+  optional_named.add_argument('--compiler-type', dest='compiler_type',
+                              type=CompilerType, choices=list(CompilerType),
+                              default=CompilerType.DEVICE,
+                              help='The type of compiler.')
 
   return parser.parse_args(argv)
 
@@ -211,26 +214,26 @@
 
   return DataFrame(d)
 
-def compile_perfetto_trace(inodes_path: str,
+def build_ri_compiler_argv(inodes_path: str,
                            perfetto_trace_file: str,
-                           trace_duration: Optional[timedelta]) -> TextIO:
-  compiler_trace_file = tempfile.NamedTemporaryFile()
-  argv = [_COMPILER_SCRIPT, '-i', inodes_path, '--perfetto-trace',
-          perfetto_trace_file, '-o', compiler_trace_file.name]
+                           trace_duration: Optional[timedelta]
+                           ) -> str:
+  argv = ['-i', inodes_path, '--perfetto-trace',
+          perfetto_trace_file]
 
   if trace_duration is not None:
     argv += ['--duration', str(int(trace_duration.total_seconds()
-                               * PerfettoTraceCollector.MS_PER_SEC))]
+                                   * PerfettoTraceCollector.MS_PER_SEC))]
 
   print_utils.debug_print(argv)
-  compiler.main(argv)
-  return compiler_trace_file
+  return argv
 
 def execute_run_using_perfetto_trace(collector_info,
                                      run_combos: Iterable[RunCommandArgs],
                                      simulate: bool,
                                      inodes_path: str,
-                                     timeout: int) -> DataFrame:
+                                     timeout: int,
+                                     compiler_type: CompilerType) -> DataFrame:
   """ Executes run based on perfetto trace. """
   passed, perfetto_trace_file = run_perfetto_collector(collector_info,
                                                        timeout,
@@ -244,9 +247,15 @@
         if simulate:
           compiler_trace_file = tempfile.NamedTemporaryFile()
         else:
-          compiler_trace_file = compile_perfetto_trace(inodes_path,
-                                                       perfetto_trace_file.name,
-                                                       combos.trace_duration)
+          ri_compiler_argv = build_ri_compiler_argv(inodes_path,
+                                                    perfetto_trace_file.name,
+                                                    combos.trace_duration)
+          compiler_trace_file = compiler.compile(compiler_type,
+                                                 inodes_path,
+                                                 ri_compiler_argv,
+                                                 combos.package,
+                                                 combos.activity)
+
         with compiler_trace_file:
           combos = combos._replace(input=compiler_trace_file.name)
           print_utils.debug_print(combos)
@@ -261,7 +270,8 @@
     grouped_run_combos: Iterable[Tuple[CollectorPackageInfo, Iterable[RunCommandArgs]]],
     simulate: bool,
     inodes_path: str,
-    timeout: int):
+    timeout: int,
+    compiler_type: CompilerType):
   # nothing will work if the screen isn't unlocked first.
   cmd_utils.execute_arbitrary_command([_UNLOCK_SCREEN_SCRIPT],
                                       timeout,
@@ -273,7 +283,8 @@
                                                 run_combos,
                                                 simulate,
                                                 inodes_path,
-                                                timeout)
+                                                timeout,
+                                                compiler_type)
 
 def gather_results(commands: Iterable[Tuple[DataFrame]],
                    key_list: List[str], value_list: List[Tuple[str, ...]]):
@@ -361,7 +372,8 @@
   exec = execute_run_combos(grouped_combos(),
                             opts.simulate,
                             opts.inodes,
-                            opts.timeout)
+                            opts.timeout,
+                            opts.compiler_type)
 
   results = gather_results(exec, _COMBINATORIAL_OPTIONS, combos())
 
diff --git a/startop/scripts/app_startup/app_startup_runner_test.py b/startop/scripts/app_startup/app_startup_runner_test.py
index 42ea5f0..382f6f3 100755
--- a/startop/scripts/app_startup/app_startup_runner_test.py
+++ b/startop/scripts/app_startup/app_startup_runner_test.py
@@ -92,7 +92,7 @@
   """
   d = {'compiler_filters': None, 'simulate': False, 'debug': False,
        'output': None, 'timeout': 10, 'loop_count': 1, 'inodes': None,
-       'trace_duration': None}
+       'trace_duration': None, 'compiler_type': asr.CompilerType.HOST}
   d.update(kwargs)
   return d
 
diff --git a/startop/scripts/iorap/compiler.py b/startop/scripts/iorap/compiler.py
old mode 100755
new mode 100644
index 17b58c1..1426d34
--- a/startop/scripts/iorap/compiler.py
+++ b/startop/scripts/iorap/compiler.py
@@ -1,323 +1,73 @@
 #!/usr/bin/env python3
-
 #
-# Copyright (C) 2019 The Android Open Source Project
+# 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
+#     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.
-#
 
-#
-# Dependencies:
-#
-# $> sudo apt-get install python3-pip
-# $> pip3 install --user protobuf sqlalchemy sqlite3
-#
-
-import optparse
+import importlib
 import os
-import re
 import sys
 import tempfile
-from pathlib import Path
-from datetime import timedelta
-from typing import Iterable, Optional, List
+from enum import Enum
+from typing import TextIO, List
 
+# local import
 DIR = os.path.abspath(os.path.dirname(__file__))
 sys.path.append(os.path.dirname(DIR))
-from iorap.generated.TraceFile_pb2 import *
-from iorap.lib.inode2filename import Inode2Filename
+import lib.print_utils as print_utils
 
-parent_dir_name = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
-sys.path.append(parent_dir_name)
-from trace_analyzer.lib.trace2db import Trace2Db, MmFilemapAddToPageCache, \
-    RawFtraceEntry
-import lib.cmd_utils as cmd_utils
+# Type of compiler.
+class CompilerType(Enum):
+  HOST = 1  # iorap.cmd.compiler on host
+  DEVICE = 2  # adb shell iorap.cmd.compiler
+  RI = 3  # compiler.py
 
-_PAGE_SIZE = 4096 # adb shell getconf PAGESIZE ## size of a memory page in bytes.
-ANDROID_BUILD_TOP = Path(parent_dir_name).parents[3]
-TRACECONV_BIN = ANDROID_BUILD_TOP.joinpath(
-    'external/perfetto/tools/traceconv')
+def compile_perfetto_trace_ri(
+    argv: List[str],
+    compiler) -> TextIO:
+  print_utils.debug_print('Compile using RI compiler.')
+  compiler_trace_file = tempfile.NamedTemporaryFile()
+  argv.extend(['-o', compiler_trace_file.name])
+  print_utils.debug_print(argv)
+  compiler.main([''] + argv)
+  return compiler_trace_file
 
-class PageRun:
-  """
-  Intermediate representation for a run of one or more pages.
-  """
-  def __init__(self, device_number: int, inode: int, offset: int, length: int):
-    self.device_number = device_number
-    self.inode = inode
-    self.offset = offset
-    self.length = length
+def compile_perfetto_trace_device(inodes_path: str,
+                                  package: str,
+                                  activity: str,
+                                  compiler) -> TextIO:
+  print_utils.debug_print('Compile using on-device compiler.')
+  compiler_trace_file = tempfile.NamedTemporaryFile()
+  compiler.main(inodes_path, package, activity, compiler_trace_file.name)
+  return compiler_trace_file
 
-  def __str__(self):
-    return "PageRun(device_number=%d, inode=%d, offset=%d, length=%d)" \
-        %(self.device_number, self.inode, self.offset, self.length)
+def compile(compiler_type: CompilerType,
+            inodes_path: str,
+            ri_compiler_argv,
+            package: str,
+            activity: str) -> TextIO:
+  if compiler_type == CompilerType.RI:
+    compiler = importlib.import_module('iorap.compiler_ri')
+    compiler_trace_file = compile_perfetto_trace_ri(ri_compiler_argv,
+                                                    compiler)
+    return compiler_trace_file
+  if compiler_type == CompilerType.DEVICE:
+    compiler = importlib.import_module('iorap.compiler_device')
+    compiler_trace_file = compile_perfetto_trace_device(inodes_path,
+                                                        package,
+                                                        activity,
+                                                        compiler)
+    return compiler_trace_file
 
-def debug_print(msg):
-  #print(msg)
-  pass
-
-UNDER_LAUNCH = False
-
-def page_cache_entries_to_runs(page_cache_entries: Iterable[MmFilemapAddToPageCache]):
-  global _PAGE_SIZE
-
-  runs = [
-      PageRun(device_number=pg_entry.dev, inode=pg_entry.ino, offset=pg_entry.ofs,
-              length=_PAGE_SIZE)
-        for pg_entry in page_cache_entries
-  ]
-
-  for r in runs:
-    debug_print(r)
-
-  print("Stats: Page runs totaling byte length: %d" %(len(runs) * _PAGE_SIZE))
-
-  return runs
-
-def optimize_page_runs(page_runs):
-  new_entries = []
-  last_entry = None
-  for pg_entry in page_runs:
-    if last_entry:
-      if pg_entry.device_number == last_entry.device_number and pg_entry.inode == last_entry.inode:
-        # we are dealing with a run for the same exact file as a previous run.
-        if pg_entry.offset == last_entry.offset + last_entry.length:
-          # trivially contiguous entries. merge them together.
-          last_entry.length += pg_entry.length
-          continue
-    # Default: Add the run without merging it to a previous run.
-    last_entry = pg_entry
-    new_entries.append(pg_entry)
-  return new_entries
-
-def is_filename_matching_filter(file_name, filters=[]):
-  """
-  Blacklist-style regular expression filters.
-
-  :return: True iff file_name has an RE match in one of the filters.
-  """
-  for filt in filters:
-    res = re.search(filt, file_name)
-    if res:
-      return True
-
-  return False
-
-def build_protobuf(page_runs, inode2filename, filters=[]):
-  trace_file = TraceFile()
-  trace_file_index = trace_file.index
-
-  file_id_counter = 0
-  file_id_map = {} # filename -> id
-
-  stats_length_total = 0
-  filename_stats = {} # filename -> total size
-
-  skipped_inode_map = {}
-  filtered_entry_map = {} # filename -> count
-
-  for pg_entry in page_runs:
-    fn = inode2filename.resolve(pg_entry.device_number, pg_entry.inode)
-    if not fn:
-      skipped_inode_map[pg_entry.inode] = skipped_inode_map.get(pg_entry.inode, 0) + 1
-      continue
-
-    filename = fn
-
-    if filters and not is_filename_matching_filter(filename, filters):
-      filtered_entry_map[filename] = filtered_entry_map.get(filename, 0) + 1
-      continue
-
-    file_id = file_id_map.get(filename)
-    if not file_id:
-      file_id = file_id_counter
-      file_id_map[filename] = file_id_counter
-      file_id_counter = file_id_counter + 1
-
-      file_index_entry = trace_file_index.entries.add()
-      file_index_entry.id = file_id
-      file_index_entry.file_name = filename
-
-    # already in the file index, add the file entry.
-    file_entry = trace_file.list.entries.add()
-    file_entry.index_id = file_id
-    file_entry.file_length = pg_entry.length
-    stats_length_total += file_entry.file_length
-    file_entry.file_offset = pg_entry.offset
-
-    filename_stats[filename] = filename_stats.get(filename, 0) + file_entry.file_length
-
-  for inode, count in skipped_inode_map.items():
-    print("WARNING: Skip inode %s because it's not in inode map (%d entries)" %(inode, count))
-
-  print("Stats: Sum of lengths %d" %(stats_length_total))
-
-  if filters:
-    print("Filter: %d total files removed." %(len(filtered_entry_map)))
-
-    for fn, count in filtered_entry_map.items():
-      print("Filter: File '%s' removed '%d' entries." %(fn, count))
-
-  for filename, file_size in filename_stats.items():
-    print("%s,%s" %(filename, file_size))
-
-  return trace_file
-
-def calc_trace_end_time(trace2db: Trace2Db,
-                        trace_duration: Optional[timedelta]) -> float:
-  """
-  Calculates the end time based on the trace duration.
-  The start time is the first receiving mm file map event.
-  The end time is the start time plus the trace duration.
-  All of them are in milliseconds.
-  """
-  # If the duration is not set, assume all time is acceptable.
-  if trace_duration is None:
-    # float('inf')
-    return RawFtraceEntry.__table__.c.timestamp.type.python_type('inf')
-
-  first_event = trace2db.session.query(MmFilemapAddToPageCache).join(
-      MmFilemapAddToPageCache.raw_ftrace_entry).order_by(
-      RawFtraceEntry.timestamp).first()
-
-  # total_seconds() will return a float number.
-  return first_event.raw_ftrace_entry.timestamp + trace_duration.total_seconds()
-
-def query_add_to_page_cache(trace2db: Trace2Db, trace_duration: Optional[timedelta]):
-  end_time = calc_trace_end_time(trace2db, trace_duration)
-  # SELECT * FROM tbl ORDER BY id;
-  return trace2db.session.query(MmFilemapAddToPageCache).join(
-      MmFilemapAddToPageCache.raw_ftrace_entry).filter(
-      RawFtraceEntry.timestamp <= end_time).order_by(
-      MmFilemapAddToPageCache.id).all()
-
-def transform_perfetto_trace_to_systrace(path_to_perfetto_trace: str,
-                                         path_to_tmp_systrace: str) -> None:
-  """ Transforms the systrace file from perfetto trace. """
-  cmd_utils.run_command_nofail([str(TRACECONV_BIN),
-                                'systrace',
-                                path_to_perfetto_trace,
-                                path_to_tmp_systrace])
-
-
-def run(sql_db_path:str,
-        trace_file:str,
-        trace_duration:Optional[timedelta],
-        output_file:str,
-        inode_table:str,
-        filter:List[str]) -> int:
-  trace2db = Trace2Db(sql_db_path)
-  # Speed optimization: Skip any entries that aren't mm_filemap_add_to_pagecache.
-  trace2db.set_raw_ftrace_entry_filter(\
-      lambda entry: entry['function'] == 'mm_filemap_add_to_page_cache')
-  # TODO: parse multiple trace files here.
-  parse_count = trace2db.parse_file_into_db(trace_file)
-
-  mm_filemap_add_to_page_cache_rows = query_add_to_page_cache(trace2db,
-                                                              trace_duration)
-  print("DONE. Parsed %d entries into sql db." %(len(mm_filemap_add_to_page_cache_rows)))
-
-  page_runs = page_cache_entries_to_runs(mm_filemap_add_to_page_cache_rows)
-  print("DONE. Converted %d entries" %(len(page_runs)))
-
-  # TODO: flags to select optimizations.
-  optimized_page_runs = optimize_page_runs(page_runs)
-  print("DONE. Optimized down to %d entries" %(len(optimized_page_runs)))
-
-  print("Build protobuf...")
-  trace_file = build_protobuf(optimized_page_runs, inode_table, filter)
-
-  print("Write protobuf to file...")
-  output_file = open(output_file, 'wb')
-  output_file.write(trace_file.SerializeToString())
-  output_file.close()
-
-  print("DONE")
-
-  # TODO: Silent running mode [no output except on error] for build runs.
-
-  return 0
-
-def main(argv):
-  parser = optparse.OptionParser(usage="Usage: %prog [options]", description="Compile systrace file into TraceFile.pb")
-  parser.add_option('-i', dest='inode_data_file', metavar='FILE',
-                    help='Read cached inode data from a file saved earlier with pagecache.py -d')
-  parser.add_option('-t', dest='trace_file', metavar='FILE',
-                    help='Path to systrace file (trace.html) that will be parsed')
-  parser.add_option('--perfetto-trace', dest='perfetto_trace_file',
-                    metavar='FILE',
-                    help='Path to perfetto trace that will be parsed')
-
-  parser.add_option('--db', dest='sql_db', metavar='FILE',
-                    help='Path to intermediate sqlite3 database [default: in-memory].')
-
-  parser.add_option('-f', dest='filter', action="append", default=[],
-                    help="Add file filter. All file entries not matching one of the filters are discarded.")
-
-  parser.add_option('-l', dest='launch_lock', action="store_true", default=False,
-                    help="Exclude all events not inside launch_lock")
-
-  parser.add_option('-o', dest='output_file', metavar='FILE',
-                    help='Output protobuf file')
-
-  parser.add_option('--duration', dest='trace_duration', action="store",
-                    type=int, help='The duration of trace in milliseconds.')
-
-  options, categories = parser.parse_args(argv[1:])
-
-  # TODO: OptionParser should have some flags to make these mandatory.
-  if not options.inode_data_file:
-    parser.error("-i is required")
-  if not options.trace_file and not options.perfetto_trace_file:
-    parser.error("one of -t or --perfetto-trace is required")
-  if options.trace_file and options.perfetto_trace_file:
-    parser.error("please enter either -t or --perfetto-trace, not both")
-  if not options.output_file:
-    parser.error("-o is required")
-
-  if options.launch_lock:
-    print("INFO: Launch lock flag (-l) enabled; filtering all events not inside launch_lock.")
-
-  inode_table = Inode2Filename.new_from_filename(options.inode_data_file)
-
-  sql_db_path = ":memory:"
-  if options.sql_db:
-    sql_db_path = options.sql_db
-
-  trace_duration = timedelta(milliseconds=options.trace_duration) if \
-    options.trace_duration is not None else None
-
-  # if the input is systrace
-  if options.trace_file:
-    return run(sql_db_path,
-               options.trace_file,
-               trace_duration,
-               options.output_file,
-               inode_table,
-               options.filter)
-
-  # if the input is perfetto trace
-  # TODO python 3.7 switch to using nullcontext
-  with tempfile.NamedTemporaryFile() as trace_file:
-    transform_perfetto_trace_to_systrace(options.perfetto_trace_file,
-                                         trace_file.name)
-    return run(sql_db_path,
-               trace_file.name,
-               trace_duration,
-               options.output_file,
-               inode_table,
-               options.filter)
-
-if __name__ == '__main__':
-  print(sys.argv)
-  sys.exit(main(sys.argv))
+  # Should not arrive here.
+  raise ValueError('Unknown compiler type')
diff --git a/startop/scripts/iorap/compiler_device.py b/startop/scripts/iorap/compiler_device.py
new file mode 100644
index 0000000..d941cd9
--- /dev/null
+++ b/startop/scripts/iorap/compiler_device.py
@@ -0,0 +1,68 @@
+#!/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.
+
+import argparse
+import os
+import sys
+from typing import List
+
+DIR = os.path.abspath(os.path.dirname(__file__))
+sys.path.append(os.path.dirname(DIR))  # framework/base/startop/script
+import lib.print_utils as print_utils
+import iorap.lib.iorapd_utils as iorapd_utils
+from app_startup.lib.app_runner import AppRunner
+
+IORAP_COMMON_BASH_SCRIPT = os.path.join(DIR, 'common')
+
+def parse_options(argv: List[str] = None):
+  """Parses command line arguments and returns an argparse Namespace object."""
+  parser = argparse.ArgumentParser(description="Compile perfetto trace file")
+  required_named = parser.add_argument_group('required named arguments')
+
+  required_named.add_argument('-i', dest='inodes', metavar='FILE',
+                              help='Read cached inode data from a file saved '
+                                   'earlier with pagecache.py -d')
+  required_named.add_argument('-p', dest='package',
+                              help='Package of the app to be compiled')
+
+  optional_named = parser.add_argument_group('optional named arguments')
+  optional_named.add_argument('-o', dest='output',
+                              help='The compiled trace is stored into the output file')
+  optional_named.add_argument('-a', dest='activity',
+                              help='Activity of the app to be compiled')
+  optional_named.add_argument('-d', dest='debug', action='store_true'
+                              , help='Activity of the app to be compiled')
+
+  return parser.parse_args(argv)
+
+def main(inodes, package, activity, output, **kwargs) -> int:
+  """Entries of the program."""
+  if not activity:
+    activity = AppRunner.get_activity(package)
+
+  passed = iorapd_utils.compile_perfetto_trace_on_device(package, activity,
+                                                         inodes)
+  if passed and output:
+    iorapd_utils.get_iorapd_compiler_trace(package, activity, output)
+
+  return 0
+
+if __name__ == '__main__':
+  opts = parse_options()
+  if opts.debug:
+    print_utils.DEBUG = opts.debug
+  print_utils.debug_print(opts)
+  sys.exit(main(**(vars(opts))))
diff --git a/startop/scripts/iorap/compiler_ri.py b/startop/scripts/iorap/compiler_ri.py
new file mode 100755
index 0000000..17b58c1
--- /dev/null
+++ b/startop/scripts/iorap/compiler_ri.py
@@ -0,0 +1,323 @@
+#!/usr/bin/env python3
+
+#
+# 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.
+#
+
+#
+# Dependencies:
+#
+# $> sudo apt-get install python3-pip
+# $> pip3 install --user protobuf sqlalchemy sqlite3
+#
+
+import optparse
+import os
+import re
+import sys
+import tempfile
+from pathlib import Path
+from datetime import timedelta
+from typing import Iterable, Optional, List
+
+DIR = os.path.abspath(os.path.dirname(__file__))
+sys.path.append(os.path.dirname(DIR))
+from iorap.generated.TraceFile_pb2 import *
+from iorap.lib.inode2filename import Inode2Filename
+
+parent_dir_name = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
+sys.path.append(parent_dir_name)
+from trace_analyzer.lib.trace2db import Trace2Db, MmFilemapAddToPageCache, \
+    RawFtraceEntry
+import lib.cmd_utils as cmd_utils
+
+_PAGE_SIZE = 4096 # adb shell getconf PAGESIZE ## size of a memory page in bytes.
+ANDROID_BUILD_TOP = Path(parent_dir_name).parents[3]
+TRACECONV_BIN = ANDROID_BUILD_TOP.joinpath(
+    'external/perfetto/tools/traceconv')
+
+class PageRun:
+  """
+  Intermediate representation for a run of one or more pages.
+  """
+  def __init__(self, device_number: int, inode: int, offset: int, length: int):
+    self.device_number = device_number
+    self.inode = inode
+    self.offset = offset
+    self.length = length
+
+  def __str__(self):
+    return "PageRun(device_number=%d, inode=%d, offset=%d, length=%d)" \
+        %(self.device_number, self.inode, self.offset, self.length)
+
+def debug_print(msg):
+  #print(msg)
+  pass
+
+UNDER_LAUNCH = False
+
+def page_cache_entries_to_runs(page_cache_entries: Iterable[MmFilemapAddToPageCache]):
+  global _PAGE_SIZE
+
+  runs = [
+      PageRun(device_number=pg_entry.dev, inode=pg_entry.ino, offset=pg_entry.ofs,
+              length=_PAGE_SIZE)
+        for pg_entry in page_cache_entries
+  ]
+
+  for r in runs:
+    debug_print(r)
+
+  print("Stats: Page runs totaling byte length: %d" %(len(runs) * _PAGE_SIZE))
+
+  return runs
+
+def optimize_page_runs(page_runs):
+  new_entries = []
+  last_entry = None
+  for pg_entry in page_runs:
+    if last_entry:
+      if pg_entry.device_number == last_entry.device_number and pg_entry.inode == last_entry.inode:
+        # we are dealing with a run for the same exact file as a previous run.
+        if pg_entry.offset == last_entry.offset + last_entry.length:
+          # trivially contiguous entries. merge them together.
+          last_entry.length += pg_entry.length
+          continue
+    # Default: Add the run without merging it to a previous run.
+    last_entry = pg_entry
+    new_entries.append(pg_entry)
+  return new_entries
+
+def is_filename_matching_filter(file_name, filters=[]):
+  """
+  Blacklist-style regular expression filters.
+
+  :return: True iff file_name has an RE match in one of the filters.
+  """
+  for filt in filters:
+    res = re.search(filt, file_name)
+    if res:
+      return True
+
+  return False
+
+def build_protobuf(page_runs, inode2filename, filters=[]):
+  trace_file = TraceFile()
+  trace_file_index = trace_file.index
+
+  file_id_counter = 0
+  file_id_map = {} # filename -> id
+
+  stats_length_total = 0
+  filename_stats = {} # filename -> total size
+
+  skipped_inode_map = {}
+  filtered_entry_map = {} # filename -> count
+
+  for pg_entry in page_runs:
+    fn = inode2filename.resolve(pg_entry.device_number, pg_entry.inode)
+    if not fn:
+      skipped_inode_map[pg_entry.inode] = skipped_inode_map.get(pg_entry.inode, 0) + 1
+      continue
+
+    filename = fn
+
+    if filters and not is_filename_matching_filter(filename, filters):
+      filtered_entry_map[filename] = filtered_entry_map.get(filename, 0) + 1
+      continue
+
+    file_id = file_id_map.get(filename)
+    if not file_id:
+      file_id = file_id_counter
+      file_id_map[filename] = file_id_counter
+      file_id_counter = file_id_counter + 1
+
+      file_index_entry = trace_file_index.entries.add()
+      file_index_entry.id = file_id
+      file_index_entry.file_name = filename
+
+    # already in the file index, add the file entry.
+    file_entry = trace_file.list.entries.add()
+    file_entry.index_id = file_id
+    file_entry.file_length = pg_entry.length
+    stats_length_total += file_entry.file_length
+    file_entry.file_offset = pg_entry.offset
+
+    filename_stats[filename] = filename_stats.get(filename, 0) + file_entry.file_length
+
+  for inode, count in skipped_inode_map.items():
+    print("WARNING: Skip inode %s because it's not in inode map (%d entries)" %(inode, count))
+
+  print("Stats: Sum of lengths %d" %(stats_length_total))
+
+  if filters:
+    print("Filter: %d total files removed." %(len(filtered_entry_map)))
+
+    for fn, count in filtered_entry_map.items():
+      print("Filter: File '%s' removed '%d' entries." %(fn, count))
+
+  for filename, file_size in filename_stats.items():
+    print("%s,%s" %(filename, file_size))
+
+  return trace_file
+
+def calc_trace_end_time(trace2db: Trace2Db,
+                        trace_duration: Optional[timedelta]) -> float:
+  """
+  Calculates the end time based on the trace duration.
+  The start time is the first receiving mm file map event.
+  The end time is the start time plus the trace duration.
+  All of them are in milliseconds.
+  """
+  # If the duration is not set, assume all time is acceptable.
+  if trace_duration is None:
+    # float('inf')
+    return RawFtraceEntry.__table__.c.timestamp.type.python_type('inf')
+
+  first_event = trace2db.session.query(MmFilemapAddToPageCache).join(
+      MmFilemapAddToPageCache.raw_ftrace_entry).order_by(
+      RawFtraceEntry.timestamp).first()
+
+  # total_seconds() will return a float number.
+  return first_event.raw_ftrace_entry.timestamp + trace_duration.total_seconds()
+
+def query_add_to_page_cache(trace2db: Trace2Db, trace_duration: Optional[timedelta]):
+  end_time = calc_trace_end_time(trace2db, trace_duration)
+  # SELECT * FROM tbl ORDER BY id;
+  return trace2db.session.query(MmFilemapAddToPageCache).join(
+      MmFilemapAddToPageCache.raw_ftrace_entry).filter(
+      RawFtraceEntry.timestamp <= end_time).order_by(
+      MmFilemapAddToPageCache.id).all()
+
+def transform_perfetto_trace_to_systrace(path_to_perfetto_trace: str,
+                                         path_to_tmp_systrace: str) -> None:
+  """ Transforms the systrace file from perfetto trace. """
+  cmd_utils.run_command_nofail([str(TRACECONV_BIN),
+                                'systrace',
+                                path_to_perfetto_trace,
+                                path_to_tmp_systrace])
+
+
+def run(sql_db_path:str,
+        trace_file:str,
+        trace_duration:Optional[timedelta],
+        output_file:str,
+        inode_table:str,
+        filter:List[str]) -> int:
+  trace2db = Trace2Db(sql_db_path)
+  # Speed optimization: Skip any entries that aren't mm_filemap_add_to_pagecache.
+  trace2db.set_raw_ftrace_entry_filter(\
+      lambda entry: entry['function'] == 'mm_filemap_add_to_page_cache')
+  # TODO: parse multiple trace files here.
+  parse_count = trace2db.parse_file_into_db(trace_file)
+
+  mm_filemap_add_to_page_cache_rows = query_add_to_page_cache(trace2db,
+                                                              trace_duration)
+  print("DONE. Parsed %d entries into sql db." %(len(mm_filemap_add_to_page_cache_rows)))
+
+  page_runs = page_cache_entries_to_runs(mm_filemap_add_to_page_cache_rows)
+  print("DONE. Converted %d entries" %(len(page_runs)))
+
+  # TODO: flags to select optimizations.
+  optimized_page_runs = optimize_page_runs(page_runs)
+  print("DONE. Optimized down to %d entries" %(len(optimized_page_runs)))
+
+  print("Build protobuf...")
+  trace_file = build_protobuf(optimized_page_runs, inode_table, filter)
+
+  print("Write protobuf to file...")
+  output_file = open(output_file, 'wb')
+  output_file.write(trace_file.SerializeToString())
+  output_file.close()
+
+  print("DONE")
+
+  # TODO: Silent running mode [no output except on error] for build runs.
+
+  return 0
+
+def main(argv):
+  parser = optparse.OptionParser(usage="Usage: %prog [options]", description="Compile systrace file into TraceFile.pb")
+  parser.add_option('-i', dest='inode_data_file', metavar='FILE',
+                    help='Read cached inode data from a file saved earlier with pagecache.py -d')
+  parser.add_option('-t', dest='trace_file', metavar='FILE',
+                    help='Path to systrace file (trace.html) that will be parsed')
+  parser.add_option('--perfetto-trace', dest='perfetto_trace_file',
+                    metavar='FILE',
+                    help='Path to perfetto trace that will be parsed')
+
+  parser.add_option('--db', dest='sql_db', metavar='FILE',
+                    help='Path to intermediate sqlite3 database [default: in-memory].')
+
+  parser.add_option('-f', dest='filter', action="append", default=[],
+                    help="Add file filter. All file entries not matching one of the filters are discarded.")
+
+  parser.add_option('-l', dest='launch_lock', action="store_true", default=False,
+                    help="Exclude all events not inside launch_lock")
+
+  parser.add_option('-o', dest='output_file', metavar='FILE',
+                    help='Output protobuf file')
+
+  parser.add_option('--duration', dest='trace_duration', action="store",
+                    type=int, help='The duration of trace in milliseconds.')
+
+  options, categories = parser.parse_args(argv[1:])
+
+  # TODO: OptionParser should have some flags to make these mandatory.
+  if not options.inode_data_file:
+    parser.error("-i is required")
+  if not options.trace_file and not options.perfetto_trace_file:
+    parser.error("one of -t or --perfetto-trace is required")
+  if options.trace_file and options.perfetto_trace_file:
+    parser.error("please enter either -t or --perfetto-trace, not both")
+  if not options.output_file:
+    parser.error("-o is required")
+
+  if options.launch_lock:
+    print("INFO: Launch lock flag (-l) enabled; filtering all events not inside launch_lock.")
+
+  inode_table = Inode2Filename.new_from_filename(options.inode_data_file)
+
+  sql_db_path = ":memory:"
+  if options.sql_db:
+    sql_db_path = options.sql_db
+
+  trace_duration = timedelta(milliseconds=options.trace_duration) if \
+    options.trace_duration is not None else None
+
+  # if the input is systrace
+  if options.trace_file:
+    return run(sql_db_path,
+               options.trace_file,
+               trace_duration,
+               options.output_file,
+               inode_table,
+               options.filter)
+
+  # if the input is perfetto trace
+  # TODO python 3.7 switch to using nullcontext
+  with tempfile.NamedTemporaryFile() as trace_file:
+    transform_perfetto_trace_to_systrace(options.perfetto_trace_file,
+                                         trace_file.name)
+    return run(sql_db_path,
+               trace_file.name,
+               trace_duration,
+               options.output_file,
+               inode_table,
+               options.filter)
+
+if __name__ == '__main__':
+  print(sys.argv)
+  sys.exit(main(sys.argv))
diff --git a/startop/scripts/iorap/compiler_test.py b/startop/scripts/iorap/compiler_test.py
index 1a9f059..d1f11c5 100644
--- a/startop/scripts/iorap/compiler_test.py
+++ b/startop/scripts/iorap/compiler_test.py
@@ -30,7 +30,7 @@
 """
 import os
 
-import compiler
+import compiler_host as compiler
 
 DIR = os.path.abspath(os.path.dirname(__file__))
 TEXTCACHE = os.path.join(DIR, 'test_fixtures/compiler/common_textcache')
diff --git a/startop/scripts/iorap/lib/iorapd_utils.py b/startop/scripts/iorap/lib/iorapd_utils.py
index 0d62180..f6f21fd 100644
--- a/startop/scripts/iorap/lib/iorapd_utils.py
+++ b/startop/scripts/iorap/lib/iorapd_utils.py
@@ -18,10 +18,9 @@
 
 import os
 import sys
-from pathlib import Path
 
-# up to two level, like '../../'
-sys.path.append(Path(os.path.abspath(__file__)).parents[2])
+# up to two level
+sys.path.append(os.path.join(os.path.abspath(__file__),'../..'))
 import lib.cmd_utils as cmd_utils
 
 IORAPID_LIB_DIR = os.path.abspath(os.path.dirname(__file__))
@@ -39,6 +38,22 @@
   # Match logic of 'AppComponentName' in iorap::compiler C++ code.
   return '{}/{}%2F{}.{}'.format(IORAPD_DATA_PATH, package, activity, suffix)
 
+def compile_perfetto_trace_on_device(package: str, activity: str,
+                                     inodes: str) -> bool:
+  """Compiles the perfetto trace using on-device compiler."""
+  passed, _ = cmd_utils.run_shell_func(IORAP_COMMON_BASH_SCRIPT,
+                                       'iorapd_compiler_for_app_trace',
+                                       [package, activity, inodes])
+  return passed
+
+def get_iorapd_compiler_trace(package: str, activity: str, dest: str) -> str:
+  """Gets compiler trace to dest file."""
+  src = _iorapd_path_to_data_file(package, activity, 'compiled_trace.pb')
+  passed, _ = cmd_utils.run_shell_command('adb pull "{}" "{}"'.format(src, dest))
+  if not passed:
+    return False
+  return True
+
 def iorapd_compiler_install_trace_file(package: str, activity: str,
                                        input_file: str) -> bool:
   """Installs a compiled trace file.
diff --git a/tests/BootImageProfileTest/Android.bp b/tests/BootImageProfileTest/Android.bp
new file mode 100644
index 0000000..1b097a8
--- /dev/null
+++ b/tests/BootImageProfileTest/Android.bp
@@ -0,0 +1,20 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+java_test_host {
+    name: "BootImageProfileTest",
+    srcs: ["src/**/*.java"],
+    libs: ["tradefed"],
+    test_suites: ["general-tests"],
+}
diff --git a/tests/BootImageProfileTest/AndroidTest.xml b/tests/BootImageProfileTest/AndroidTest.xml
new file mode 100644
index 0000000..c132007
--- /dev/null
+++ b/tests/BootImageProfileTest/AndroidTest.xml
@@ -0,0 +1,39 @@
+<?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="Config for BootImageProfileTest">
+     <!-- 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" />
+
+        <option name="run-command" value="setprop dalvik.vm.profilesystemserver true" />
+        <option name="run-command" value="setprop dalvik.vm.profilebootclasspath true" />
+
+        <!-- Profiling does not pick up the above changes we restart the shell -->
+        <option name="run-command" value="stop" />
+        <option name="run-command" value="start" />
+
+        <!-- give it some time to restart the shell; otherwise the first unit test might fail -->
+        <option name="run-command" value="sleep 2" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.HostTest" >
+        <option name="class" value="com.android.bootimageprofile.BootImageProfileTest" />
+    </test>
+</configuration>
diff --git a/tests/BootImageProfileTest/TEST_MAPPING b/tests/BootImageProfileTest/TEST_MAPPING
new file mode 100644
index 0000000..1b569f9
--- /dev/null
+++ b/tests/BootImageProfileTest/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit": [
+    {
+      "name": "BootImageProfileTest"
+    }
+  ]
+}
diff --git a/tests/BootImageProfileTest/src/com/android/bootimageprofile/BootImageProfileTest.java b/tests/BootImageProfileTest/src/com/android/bootimageprofile/BootImageProfileTest.java
new file mode 100644
index 0000000..17986a3
--- /dev/null
+++ b/tests/BootImageProfileTest/src/com/android/bootimageprofile/BootImageProfileTest.java
@@ -0,0 +1,88 @@
+/*
+ * 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.bootimageprofile;
+
+import static org.junit.Assert.assertTrue;
+
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.IDeviceTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class BootImageProfileTest implements IDeviceTest {
+    private ITestDevice mTestDevice;
+    private static final String SYSTEM_SERVER_PROFILE =
+            "/data/misc/profiles/cur/0/android/primary.prof";
+
+    @Override
+    public void setDevice(ITestDevice testDevice) {
+        mTestDevice = testDevice;
+    }
+
+    @Override
+    public ITestDevice getDevice() {
+        return mTestDevice;
+    }
+
+    /**
+     * Test that the boot image profile properties are set.
+     */
+    @Test
+    public void testProperties() throws Exception {
+        String res = mTestDevice.getProperty("dalvik.vm.profilebootclasspath");
+        assertTrue("profile boot class path not enabled", res != null && res.equals("true"));
+        res = mTestDevice.getProperty("dalvik.vm.profilesystemserver");
+        assertTrue("profile system server not enabled", res != null && res.equals("true"));
+    }
+
+    private void forceSaveProfile(String pkg) throws Exception {
+        String pid = mTestDevice.executeShellCommand("pidof " + pkg).trim();
+        assertTrue("Invalid pid " + pid, pid.length() > 0);
+        String res = mTestDevice.executeShellCommand("kill -s SIGUSR1 " + pid).trim();
+        assertTrue("kill SIGUSR1: " + res, res.length() == 0);
+    }
+
+    @Test
+    public void testSystemServerProfile() throws Exception {
+        // Trunacte the profile before force it to be saved to prevent previous profiles
+        // causing the test to pass.
+        String res;
+        res = mTestDevice.executeShellCommand("truncate -s 0 " + SYSTEM_SERVER_PROFILE).trim();
+        assertTrue(res, res.length() == 0);
+        // Force save profiles in case the system just started.
+        Thread.sleep(1000);
+        forceSaveProfile("system_server");
+        Thread.sleep(2000);
+        // Validate that the profile is non empty.
+        res = mTestDevice.executeShellCommand("profman --dump-only --profile-file="
+                + SYSTEM_SERVER_PROFILE);
+        boolean sawFramework = false;
+        boolean sawServices = false;
+        for (String line : res.split("\n")) {
+            if (line.contains("framework.jar")) {
+                sawFramework = true;
+            } else if (line.contains("services.jar")) {
+                sawServices = true;
+            }
+        }
+        assertTrue("Did not see framework.jar in " + res, sawFramework);
+        assertTrue("Did not see services.jar in " + res, sawServices);
+    }
+}
diff --git a/tests/PackageWatchdog/Android.bp b/tests/PackageWatchdog/Android.bp
index 88d92c4..0b75039 100644
--- a/tests/PackageWatchdog/Android.bp
+++ b/tests/PackageWatchdog/Android.bp
@@ -23,6 +23,7 @@
         "androidx.test.rules",
         "services.core",
         "services.net",
+        "truth-prebuilt",
     ],
     libs: ["android.test.runner"],
     jni_libs: [
diff --git a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
index 6c05bb8..9a60330 100644
--- a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
+++ b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
@@ -18,9 +18,8 @@
 
 import static android.service.watchdog.ExplicitHealthCheckService.PackageConfig;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+import static com.google.common.truth.Truth.assertThat;
+
 import static org.junit.Assert.fail;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyString;
@@ -65,7 +64,6 @@
 import java.util.concurrent.TimeUnit;
 import java.util.function.Consumer;
 
-// TODO: Use Truth in tests.
 /**
  * Test PackageWatchdog.
  */
@@ -119,13 +117,12 @@
         TestObserver observer = new TestObserver(OBSERVER_NAME_1);
 
         watchdog.startObservingHealth(observer, Arrays.asList(APP_A), SHORT_DURATION);
-        raiseFatalFailure(watchdog, Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
-        mTestLooper.dispatchAll();
+        raiseFatalFailureAndDispatch(watchdog,
+                Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
 
         // The failed packages should be the same as the registered ones to ensure registration is
         // done successfully
-        assertEquals(1, observer.mHealthCheckFailedPackages.size());
-        assertTrue(observer.mHealthCheckFailedPackages.contains(APP_A));
+        assertThat(observer.mHealthCheckFailedPackages).containsExactly(APP_A);
     }
 
     @Test
@@ -136,17 +133,14 @@
 
         watchdog.startObservingHealth(observer1, Arrays.asList(APP_A), SHORT_DURATION);
         watchdog.startObservingHealth(observer2, Arrays.asList(APP_A, APP_B), SHORT_DURATION);
-        raiseFatalFailure(watchdog, Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE),
-                new VersionedPackage(APP_B, VERSION_CODE)));
-        mTestLooper.dispatchAll();
+        raiseFatalFailureAndDispatch(watchdog,
+                Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE),
+                        new VersionedPackage(APP_B, VERSION_CODE)));
 
         // The failed packages should be the same as the registered ones to ensure registration is
         // done successfully
-        assertEquals(1, observer1.mHealthCheckFailedPackages.size());
-        assertEquals(2, observer2.mHealthCheckFailedPackages.size());
-        assertTrue(observer1.mHealthCheckFailedPackages.contains(APP_A));
-        assertTrue(observer2.mHealthCheckFailedPackages.contains(APP_A));
-        assertTrue(observer2.mHealthCheckFailedPackages.contains(APP_B));
+        assertThat(observer1.mHealthCheckFailedPackages).containsExactly(APP_A);
+        assertThat(observer2.mHealthCheckFailedPackages).containsExactly(APP_A, APP_B);
     }
 
     @Test
@@ -156,11 +150,11 @@
 
         watchdog.startObservingHealth(observer, Arrays.asList(APP_A), SHORT_DURATION);
         watchdog.unregisterHealthObserver(observer);
-        raiseFatalFailure(watchdog, Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
-        mTestLooper.dispatchAll();
+        raiseFatalFailureAndDispatch(watchdog,
+                Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
 
         // We should have no failed packages to ensure unregistration is done successfully
-        assertEquals(0, observer.mHealthCheckFailedPackages.size());
+        assertThat(observer.mHealthCheckFailedPackages).isEmpty();
     }
 
     @Test
@@ -172,13 +166,13 @@
         watchdog.startObservingHealth(observer1, Arrays.asList(APP_A), SHORT_DURATION);
         watchdog.startObservingHealth(observer2, Arrays.asList(APP_A), SHORT_DURATION);
         watchdog.unregisterHealthObserver(observer2);
-        raiseFatalFailure(watchdog, Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
-        mTestLooper.dispatchAll();
+        raiseFatalFailureAndDispatch(watchdog,
+                Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
 
         // observer1 should receive failed packages as intended.
-        assertEquals(1, observer1.mHealthCheckFailedPackages.size());
+        assertThat(observer1.mHealthCheckFailedPackages).containsExactly(APP_A);
         // observer2 should have no failed packages to ensure unregistration is done successfully
-        assertEquals(0, observer2.mHealthCheckFailedPackages.size());
+        assertThat(observer2.mHealthCheckFailedPackages).isEmpty();
     }
 
     @Test
@@ -188,11 +182,11 @@
 
         watchdog.startObservingHealth(observer, Arrays.asList(APP_A), SHORT_DURATION);
         moveTimeForwardAndDispatch(SHORT_DURATION);
-        raiseFatalFailure(watchdog, Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
-        mTestLooper.dispatchAll();
+        raiseFatalFailureAndDispatch(watchdog,
+                Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
 
         // We should have no failed packages for the fatal failure is raised after expiration
-        assertEquals(0, observer.mHealthCheckFailedPackages.size());
+        assertThat(observer.mHealthCheckFailedPackages).isEmpty();
     }
 
     @Test
@@ -204,13 +198,13 @@
         watchdog.startObservingHealth(observer1, Arrays.asList(APP_A), SHORT_DURATION);
         watchdog.startObservingHealth(observer2, Arrays.asList(APP_A), LONG_DURATION);
         moveTimeForwardAndDispatch(SHORT_DURATION);
-        raiseFatalFailure(watchdog, Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
-        mTestLooper.dispatchAll();
+        raiseFatalFailureAndDispatch(watchdog,
+                Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
 
         // We should have no failed packages for the fatal failure is raised after expiration
-        assertEquals(0, observer1.mHealthCheckFailedPackages.size());
+        assertThat(observer1.mHealthCheckFailedPackages).isEmpty();
         // We should have failed packages since observer2 hasn't expired
-        assertEquals(1, observer2.mHealthCheckFailedPackages.size());
+        assertThat(observer2.mHealthCheckFailedPackages).containsExactly(APP_A);
     }
 
     /** Observing already observed package extends the observation time. */
@@ -231,12 +225,11 @@
         // Then advance time such that it should have expired were it not for the second observation
         moveTimeForwardAndDispatch((SHORT_DURATION / 2) + 1);
 
-        raiseFatalFailure(watchdog, Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
-        mTestLooper.dispatchAll();
+        raiseFatalFailureAndDispatch(watchdog,
+                Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
 
         // Verify that we receive failed packages as expected for APP_A not expired
-        assertEquals(1, observer.mHealthCheckFailedPackages.size());
-        assertTrue(observer.mHealthCheckFailedPackages.contains(APP_A));
+        assertThat(observer.mHealthCheckFailedPackages).containsExactly(APP_A);
     }
 
     /**
@@ -257,17 +250,14 @@
         // Then resume observer1 and observer2
         watchdog2.registerHealthObserver(observer1);
         watchdog2.registerHealthObserver(observer2);
-        raiseFatalFailure(watchdog2, Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE),
-                new VersionedPackage(APP_B, VERSION_CODE)));
-        mTestLooper.dispatchAll();
+        raiseFatalFailureAndDispatch(watchdog2,
+                Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE),
+                        new VersionedPackage(APP_B, VERSION_CODE)));
 
         // We should receive failed packages as expected to ensure observers are persisted and
         // resumed correctly
-        assertEquals(1, observer1.mHealthCheckFailedPackages.size());
-        assertEquals(2, observer2.mHealthCheckFailedPackages.size());
-        assertTrue(observer1.mHealthCheckFailedPackages.contains(APP_A));
-        assertTrue(observer1.mHealthCheckFailedPackages.contains(APP_A));
-        assertTrue(observer2.mHealthCheckFailedPackages.contains(APP_B));
+        assertThat(observer1.mHealthCheckFailedPackages).containsExactly(APP_A);
+        assertThat(observer2.mHealthCheckFailedPackages).containsExactly(APP_A, APP_B);
     }
 
     /**
@@ -291,8 +281,8 @@
         mTestLooper.dispatchAll();
 
         // Verify that observers are not notified
-        assertEquals(0, observer1.mMitigatedPackages.size());
-        assertEquals(0, observer2.mMitigatedPackages.size());
+        assertThat(observer1.mHealthCheckFailedPackages).isEmpty();
+        assertThat(observer2.mHealthCheckFailedPackages).isEmpty();
     }
 
     /**
@@ -310,14 +300,12 @@
         watchdog.startObservingHealth(observer1, Arrays.asList(APP_B), SHORT_DURATION);
 
         // Then fail APP_C (not observed) above the threshold
-        raiseFatalFailure(watchdog, Arrays.asList(new VersionedPackage(APP_C, VERSION_CODE)));
-
-        // Run handler so package failures are dispatched to observers
-        mTestLooper.dispatchAll();
+        raiseFatalFailureAndDispatch(watchdog,
+                Arrays.asList(new VersionedPackage(APP_C, VERSION_CODE)));
 
         // Verify that observers are not notified
-        assertEquals(0, observer1.mMitigatedPackages.size());
-        assertEquals(0, observer2.mMitigatedPackages.size());
+        assertThat(observer1.mHealthCheckFailedPackages).isEmpty();
+        assertThat(observer2.mHealthCheckFailedPackages).isEmpty();
     }
 
     /**
@@ -342,14 +330,11 @@
         watchdog.startObservingHealth(observer, Arrays.asList(APP_A), SHORT_DURATION);
 
         // Then fail APP_A (different version) above the threshold
-        raiseFatalFailure(watchdog,
+        raiseFatalFailureAndDispatch(watchdog,
                 Arrays.asList(new VersionedPackage(APP_A, differentVersionCode)));
 
-        // Run handler so package failures are dispatched to observers
-        mTestLooper.dispatchAll();
-
         // Verify that observers are not notified
-        assertEquals(0, observer.mMitigatedPackages.size());
+        assertThat(observer.mHealthCheckFailedPackages).isEmpty();
     }
 
 
@@ -379,13 +364,11 @@
                 SHORT_DURATION);
 
         // Then fail all apps above the threshold
-        raiseFatalFailure(watchdog, Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE),
-                new VersionedPackage(APP_B, VERSION_CODE),
-                new VersionedPackage(APP_C, VERSION_CODE),
-                new VersionedPackage(APP_D, VERSION_CODE)));
-
-        // Run handler so package failures are dispatched to observers
-        mTestLooper.dispatchAll();
+        raiseFatalFailureAndDispatch(watchdog,
+                Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE),
+                        new VersionedPackage(APP_B, VERSION_CODE),
+                        new VersionedPackage(APP_C, VERSION_CODE),
+                        new VersionedPackage(APP_D, VERSION_CODE)));
 
         // Verify least impact observers are notifed of package failures
         List<String> observerNonePackages = observerNone.mMitigatedPackages;
@@ -394,16 +377,13 @@
         List<String> observerLowPackages = observerLow.mMitigatedPackages;
 
         // APP_D failure observed by only observerNone is not caught cos its impact is none
-        assertEquals(0, observerNonePackages.size());
+        assertThat(observerNonePackages).isEmpty();
         // APP_C failure is caught by observerHigh cos it's the lowest impact observer
-        assertEquals(1, observerHighPackages.size());
-        assertEquals(APP_C, observerHighPackages.get(0));
+        assertThat(observerHighPackages).containsExactly(APP_C);
         // APP_B failure is caught by observerMid cos it's the lowest impact observer
-        assertEquals(1, observerMidPackages.size());
-        assertEquals(APP_B, observerMidPackages.get(0));
+        assertThat(observerMidPackages).containsExactly(APP_B);
         // APP_A failure is caught by observerLow cos it's the lowest impact observer
-        assertEquals(1, observerLowPackages.size());
-        assertEquals(APP_A, observerLowPackages.get(0));
+        assertThat(observerLowPackages).containsExactly(APP_A);
     }
 
     /**
@@ -430,14 +410,12 @@
         watchdog.startObservingHealth(observerSecond, Arrays.asList(APP_A), LONG_DURATION);
 
         // Then fail APP_A above the threshold
-        raiseFatalFailure(watchdog, Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
-        // Run handler so package failures are dispatched to observers
-        mTestLooper.dispatchAll();
+        raiseFatalFailureAndDispatch(watchdog,
+                Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
 
         // Verify only observerFirst is notifed
-        assertEquals(1, observerFirst.mMitigatedPackages.size());
-        assertEquals(APP_A, observerFirst.mMitigatedPackages.get(0));
-        assertEquals(0, observerSecond.mMitigatedPackages.size());
+        assertThat(observerFirst.mMitigatedPackages).containsExactly(APP_A);
+        assertThat(observerSecond.mMitigatedPackages).isEmpty();
 
         // After observerFirst handles failure, next action it has is high impact
         observerFirst.mImpact = PackageHealthObserverImpact.USER_IMPACT_HIGH;
@@ -445,14 +423,12 @@
         observerSecond.mMitigatedPackages.clear();
 
         // Then fail APP_A again above the threshold
-        raiseFatalFailure(watchdog, Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
-        // Run handler so package failures are dispatched to observers
-        mTestLooper.dispatchAll();
+        raiseFatalFailureAndDispatch(watchdog,
+                Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
 
         // Verify only observerSecond is notifed cos it has least impact
-        assertEquals(1, observerSecond.mMitigatedPackages.size());
-        assertEquals(APP_A, observerSecond.mMitigatedPackages.get(0));
-        assertEquals(0, observerFirst.mMitigatedPackages.size());
+        assertThat(observerSecond.mMitigatedPackages).containsExactly(APP_A);
+        assertThat(observerFirst.mMitigatedPackages).isEmpty();
 
         // After observerSecond handles failure, it has no further actions
         observerSecond.mImpact = PackageHealthObserverImpact.USER_IMPACT_NONE;
@@ -460,14 +436,12 @@
         observerSecond.mMitigatedPackages.clear();
 
         // Then fail APP_A again above the threshold
-        raiseFatalFailure(watchdog, Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
-        // Run handler so package failures are dispatched to observers
-        mTestLooper.dispatchAll();
+        raiseFatalFailureAndDispatch(watchdog,
+                Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
 
         // Verify only observerFirst is notifed cos it has the only action
-        assertEquals(1, observerFirst.mMitigatedPackages.size());
-        assertEquals(APP_A, observerFirst.mMitigatedPackages.get(0));
-        assertEquals(0, observerSecond.mMitigatedPackages.size());
+        assertThat(observerFirst.mMitigatedPackages).containsExactly(APP_A);
+        assertThat(observerSecond.mMitigatedPackages).isEmpty();
 
         // After observerFirst handles failure, it too has no further actions
         observerFirst.mImpact = PackageHealthObserverImpact.USER_IMPACT_NONE;
@@ -475,13 +449,12 @@
         observerSecond.mMitigatedPackages.clear();
 
         // Then fail APP_A again above the threshold
-        raiseFatalFailure(watchdog, Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
-        // Run handler so package failures are dispatched to observers
-        mTestLooper.dispatchAll();
+        raiseFatalFailureAndDispatch(watchdog,
+                Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
 
         // Verify no observer is notified cos no actions left
-        assertEquals(0, observerFirst.mMitigatedPackages.size());
-        assertEquals(0, observerSecond.mMitigatedPackages.size());
+        assertThat(observerFirst.mMitigatedPackages).isEmpty();
+        assertThat(observerSecond.mMitigatedPackages).isEmpty();
     }
 
     /**
@@ -500,15 +473,12 @@
         watchdog.startObservingHealth(observer1, Arrays.asList(APP_A), SHORT_DURATION);
 
         // Then fail APP_A above the threshold
-        raiseFatalFailure(watchdog, Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
-
-        // Run handler so package failures are dispatched to observers
-        mTestLooper.dispatchAll();
+        raiseFatalFailureAndDispatch(watchdog,
+                Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
 
         // Verify only one observer is notifed
-        assertEquals(1, observer1.mMitigatedPackages.size());
-        assertEquals(APP_A, observer1.mMitigatedPackages.get(0));
-        assertEquals(0, observer2.mMitigatedPackages.size());
+        assertThat(observer1.mMitigatedPackages).containsExactly(APP_A);
+        assertThat(observer2.mMitigatedPackages).isEmpty();
     }
 
     /**
@@ -537,9 +507,7 @@
 
         // Verify we requested health checks for APP_A and APP_B
         List<String> requestedPackages = controller.getRequestedPackages();
-        assertEquals(2, requestedPackages.size());
-        assertEquals(APP_A, requestedPackages.get(0));
-        assertEquals(APP_B, requestedPackages.get(1));
+        assertThat(requestedPackages).containsExactly(APP_A, APP_B);
 
         // Then health check passed for APP_A (observer1 is aware)
         controller.setPackagePassed(APP_A);
@@ -554,18 +522,16 @@
         moveTimeForwardAndDispatch(SHORT_DURATION);
 
         // Verify we cancelled all requests on expiry
-        assertEquals(0, controller.getRequestedPackages().size());
+        assertThat(controller.getRequestedPackages()).isEmpty();
 
         // Verify observer1 is not notified
-        assertEquals(0, observer1.mMitigatedPackages.size());
+        assertThat(observer1.mMitigatedPackages).isEmpty();
 
         // Verify observer2 is notifed because health checks for APP_B never passed
-        assertEquals(1, observer2.mMitigatedPackages.size());
-        assertEquals(APP_B, observer2.mMitigatedPackages.get(0));
+        assertThat(observer2.mMitigatedPackages).containsExactly(APP_B);
 
         // Verify observer3 is notifed because health checks for APP_A did not pass before expiry
-        assertEquals(1, observer3.mMitigatedPackages.size());
-        assertEquals(APP_A, observer3.mMitigatedPackages.get(0));
+        assertThat(observer3.mMitigatedPackages).containsExactly(APP_A);
     }
 
     /**
@@ -592,9 +558,7 @@
 
         // Verify we requested health checks for APP_A and APP_B
         List<String> requestedPackages = controller.getRequestedPackages();
-        assertEquals(2, requestedPackages.size());
-        assertEquals(APP_A, requestedPackages.get(0));
-        assertEquals(APP_B, requestedPackages.get(1));
+        assertThat(requestedPackages).containsExactly(APP_A, APP_B);
 
         // Disable explicit health checks (marks APP_A and APP_B as passed)
         setExplicitHealthCheckEnabled(false);
@@ -603,13 +567,13 @@
         mTestLooper.dispatchAll();
 
         // Verify all checks are cancelled
-        assertEquals(0, controller.getRequestedPackages().size());
+        assertThat(controller.getRequestedPackages()).isEmpty();
 
         // Then expire APP_A
         moveTimeForwardAndDispatch(SHORT_DURATION);
 
         // Verify APP_A is not failed (APP_B) is not expired yet
-        assertEquals(0, observer.mMitigatedPackages.size());
+        assertThat(observer.mMitigatedPackages).isEmpty();
 
         // Re-enable explicit health checks
         setExplicitHealthCheckEnabled(true);
@@ -618,7 +582,7 @@
         mTestLooper.dispatchAll();
 
         // Verify no requests are made cos APP_A is expired and APP_B was marked as passed
-        assertEquals(0, controller.getRequestedPackages().size());
+        assertThat(controller.getRequestedPackages()).isEmpty();
 
         // Then set new supported packages
         controller.setSupportedPackages(Arrays.asList(APP_C));
@@ -630,15 +594,13 @@
 
         // Verify requests are only made for APP_C
         requestedPackages = controller.getRequestedPackages();
-        assertEquals(1, requestedPackages.size());
-        assertEquals(APP_C, requestedPackages.get(0));
+        assertThat(requestedPackages).containsExactly(APP_C);
 
         // Then expire APP_A and APP_C
         moveTimeForwardAndDispatch(SHORT_DURATION);
 
         // Verify only APP_C is failed because explicit health checks was not supported for APP_A
-        assertEquals(1, observer.mMitigatedPackages.size());
-        assertEquals(APP_C, observer.mMitigatedPackages.get(0));
+        assertThat(observer.mMitigatedPackages).containsExactly(APP_C);
     }
 
     /**
@@ -662,8 +624,7 @@
         moveTimeForwardAndDispatch(SHORT_DURATION);
 
         // Verify that health check is failed
-        assertEquals(1, observer.mMitigatedPackages.size());
-        assertEquals(APP_A, observer.mMitigatedPackages.get(0));
+        assertThat(observer.mMitigatedPackages).containsExactly(APP_A);
 
         // Then clear failed packages and start observing a random package so requests are synced
         // and PackageWatchdog#onSupportedPackages is called and APP_A has a chance to fail again
@@ -672,7 +633,7 @@
         watchdog.startObservingHealth(observer, Arrays.asList(APP_B), LONG_DURATION);
 
         // Verify that health check failure is not notified again
-        assertTrue(observer.mMitigatedPackages.isEmpty());
+        assertThat(observer.mMitigatedPackages).isEmpty();
     }
 
     /** Tests {@link MonitoredPackage} health check state transitions. */
@@ -688,36 +649,38 @@
 
         // Verify transition: inactive -> active -> passed
         // Verify initially inactive
-        assertEquals(HealthCheckState.INACTIVE, m1.getHealthCheckStateLocked());
+        assertThat(m1.getHealthCheckStateLocked()).isEqualTo(HealthCheckState.INACTIVE);
         // Verify still inactive, until we #setHealthCheckActiveLocked
-        assertEquals(HealthCheckState.INACTIVE, m1.handleElapsedTimeLocked(SHORT_DURATION));
+        assertThat(m1.handleElapsedTimeLocked(SHORT_DURATION)).isEqualTo(HealthCheckState.INACTIVE);
         // Verify now active
-        assertEquals(HealthCheckState.ACTIVE, m1.setHealthCheckActiveLocked(SHORT_DURATION));
+        assertThat(m1.setHealthCheckActiveLocked(SHORT_DURATION)).isEqualTo(
+                HealthCheckState.ACTIVE);
         // Verify now passed
-        assertEquals(HealthCheckState.PASSED, m1.tryPassHealthCheckLocked());
+        assertThat(m1.tryPassHealthCheckLocked()).isEqualTo(HealthCheckState.PASSED);
 
         // Verify transition: inactive -> active -> failed
         // Verify initially inactive
-        assertEquals(HealthCheckState.INACTIVE, m2.getHealthCheckStateLocked());
+        assertThat(m2.getHealthCheckStateLocked()).isEqualTo(HealthCheckState.INACTIVE);
         // Verify now active
-        assertEquals(HealthCheckState.ACTIVE, m2.setHealthCheckActiveLocked(SHORT_DURATION));
+        assertThat(m2.setHealthCheckActiveLocked(SHORT_DURATION)).isEqualTo(
+                HealthCheckState.ACTIVE);
         // Verify now failed
-        assertEquals(HealthCheckState.FAILED, m2.handleElapsedTimeLocked(SHORT_DURATION));
+        assertThat(m2.handleElapsedTimeLocked(SHORT_DURATION)).isEqualTo(HealthCheckState.FAILED);
 
         // Verify transition: inactive -> failed
         // Verify initially inactive
-        assertEquals(HealthCheckState.INACTIVE, m3.getHealthCheckStateLocked());
+        assertThat(m3.getHealthCheckStateLocked()).isEqualTo(HealthCheckState.INACTIVE);
         // Verify now failed because package expired
-        assertEquals(HealthCheckState.FAILED, m3.handleElapsedTimeLocked(LONG_DURATION));
+        assertThat(m3.handleElapsedTimeLocked(LONG_DURATION)).isEqualTo(HealthCheckState.FAILED);
         // Verify remains failed even when asked to pass
-        assertEquals(HealthCheckState.FAILED, m3.tryPassHealthCheckLocked());
+        assertThat(m3.tryPassHealthCheckLocked()).isEqualTo(HealthCheckState.FAILED);
 
         // Verify transition: passed
-        assertEquals(HealthCheckState.PASSED, m4.getHealthCheckStateLocked());
+        assertThat(m4.getHealthCheckStateLocked()).isEqualTo(HealthCheckState.PASSED);
         // Verify remains passed even if health check fails
-        assertEquals(HealthCheckState.PASSED, m4.handleElapsedTimeLocked(SHORT_DURATION));
+        assertThat(m4.handleElapsedTimeLocked(SHORT_DURATION)).isEqualTo(HealthCheckState.PASSED);
         // Verify remains passed even if package expires
-        assertEquals(HealthCheckState.PASSED, m4.handleElapsedTimeLocked(LONG_DURATION));
+        assertThat(m4.handleElapsedTimeLocked(LONG_DURATION)).isEqualTo(HealthCheckState.PASSED);
     }
 
     @Test
@@ -736,8 +699,7 @@
         mTestLooper.dispatchAll();
 
         // Verify the NetworkStack observer is notified
-        assertEquals(1, observer.mMitigatedPackages.size());
-        assertEquals(APP_A, observer.mMitigatedPackages.get(0));
+        assertThat(observer.mMitigatedPackages).containsExactly(APP_A);
     }
 
     private void adoptShellPermissions(String... permissions) {
@@ -773,10 +735,12 @@
     }
 
     /** Trigger package failures above the threshold. */
-    private void raiseFatalFailure(PackageWatchdog watchdog, List<VersionedPackage> packages) {
+    private void raiseFatalFailureAndDispatch(PackageWatchdog watchdog,
+            List<VersionedPackage> packages) {
         for (int i = 0; i < watchdog.getTriggerFailureCount(); i++) {
             watchdog.onPackageFailure(packages);
         }
+        mTestLooper.dispatchAll();
     }
 
     private PackageWatchdog createWatchdog() {
@@ -791,13 +755,13 @@
                 new PackageWatchdog(mSpyContext, policyFile, handler, handler, controller,
                         mConnectivityModuleConnector, mTestClock);
         // Verify controller is not automatically started
-        assertFalse(controller.mIsEnabled);
+        assertThat(controller.mIsEnabled).isFalse();
         if (withPackagesReady) {
             // Only capture the NetworkStack callback for the latest registered watchdog
             reset(mConnectivityModuleConnector);
             watchdog.onPackagesReady();
             // Verify controller by default is started when packages are ready
-            assertTrue(controller.mIsEnabled);
+            assertThat(controller.mIsEnabled).isTrue();
 
             verify(mConnectivityModuleConnector).registerHealthListener(
                     mConnectivityModuleCallbackCaptor.capture());
diff --git a/tests/net/Android.bp b/tests/net/Android.bp
index 502aa97..e91abb6 100644
--- a/tests/net/Android.bp
+++ b/tests/net/Android.bp
@@ -20,8 +20,6 @@
         "libdl_android",
         "libhidl-gen-utils",
         "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
         "libjsoncpp",
         "liblog",
         "liblzma",