Merge "MediaRouter: Address API review issues"
diff --git a/Android.bp b/Android.bp
index 5292b2d..df276a0 100644
--- a/Android.bp
+++ b/Android.bp
@@ -273,7 +273,8 @@
 
         // etc.
         ":framework-javastream-protos",
-        ":framework-statslog-gen",
+        ":framework-statslog-gen", // StatsLogInternal.java
+        ":statslog-framework-java-gen", // FrameworkStatsLog.java
 
         // telephony annotations
         ":framework-telephony-annotations",
@@ -541,7 +542,7 @@
     srcs: [":framework-all-sources"],
     installable: false,
     static_libs: [
-        "exoplayer2-core",
+        "exoplayer2-extractor",
         "android.hardware.wifi-V1.0-java-constants",
     ],
     libs: ["icing-java-proto-lite"],
@@ -561,7 +562,7 @@
         "compat-changeid-annotation-processor",
     ],
     static_libs: [
-        "exoplayer2-core",
+        "exoplayer2-extractor",
         "android.hardware.wifi-V1.0-java-constants",
     ]
 }
@@ -612,6 +613,14 @@
     out: ["android/util/StatsLogInternal.java"],
 }
 
+genrule {
+    name: "statslog-framework-java-gen",
+    tools: ["stats-log-api-gen"],
+    cmd: "$(location stats-log-api-gen) --java $(out) --module framework" +
+         " --javaPackage com.android.internal.util --javaClass FrameworkStatsLog --worksource",
+    out: ["com/android/internal/util/FrameworkStatsLog.java"],
+}
+
 gensrcs {
     name: "framework-javastream-protos",
     depfile: true,
@@ -930,6 +939,8 @@
     srcs: [
         "core/java/android/os/incremental/IIncrementalManager.aidl",
         "core/java/android/os/incremental/IIncrementalManagerNative.aidl",
+        "core/java/android/os/incremental/IncrementalNewFileParams.aidl",
+        "core/java/android/os/incremental/IncrementalSignature.aidl",
     ],
     path: "core/java",
 }
diff --git a/apct-tests/perftests/core/src/android/wm/RelayoutPerfTest.java b/apct-tests/perftests/core/src/android/wm/RelayoutPerfTest.java
index c62aad6..b6e39e1 100644
--- a/apct-tests/perftests/core/src/android/wm/RelayoutPerfTest.java
+++ b/apct-tests/perftests/core/src/android/wm/RelayoutPerfTest.java
@@ -150,7 +150,7 @@
                         mViewVisibility.getAsInt(), mFlags, mFrameNumber, mOutFrame,
                         mOutContentInsets, mOutVisibleInsets, mOutStableInsets,
                         mOutBackDropFrame, mOutDisplayCutout, mOutMergedConfiguration,
-                        mOutSurfaceControl, mOutInsetsState, new Point());
+                        mOutSurfaceControl, mOutInsetsState, new Point(), new SurfaceControl());
             }
         }
     }
diff --git a/apex/media/framework/Android.bp b/apex/media/framework/Android.bp
index 18382a4..2266d04 100644
--- a/apex/media/framework/Android.bp
+++ b/apex/media/framework/Android.bp
@@ -50,7 +50,7 @@
     ],
 
     static_libs: [
-        "exoplayer2-core"
+        "exoplayer2-extractor"
     ],
     jarjar_rules: "jarjar_rules.txt",
 
diff --git a/apex/sdkextensions/OWNERS b/apex/sdkextensions/OWNERS
index feb2742..a6e5522 100644
--- a/apex/sdkextensions/OWNERS
+++ b/apex/sdkextensions/OWNERS
@@ -1 +1,2 @@
+dariofreni@google.com
 hansson@google.com
diff --git a/apex/statsd/framework/java/android/app/StatsManager.java b/apex/statsd/framework/java/android/app/StatsManager.java
index ad1ac95..a1de330 100644
--- a/apex/statsd/framework/java/android/app/StatsManager.java
+++ b/apex/statsd/framework/java/android/app/StatsManager.java
@@ -474,17 +474,6 @@
     }
 
     /**
-     * Temp registration for while the migration is in progress.
-     *
-     * @hide
-     */
-    public void registerPullAtomCallback(int atomTag, @Nullable PullAtomMetadata metadata,
-            @NonNull StatsPullAtomCallback callback,
-            @NonNull @CallbackExecutor Executor executor) {
-        registerPullAtomCallback(atomTag, metadata, executor, callback);
-    }
-
-    /**
      * Registers a callback for an atom when that atom is to be pulled. The stats service will
      * invoke pullData in the callback when the stats service determines that this atom needs to be
      * pulled.
@@ -591,15 +580,6 @@
         }
 
         /**
-         * Temp for while migrations are in progress.
-         *
-         * @hide
-         */
-        public static PullAtomMetadata.Builder newBuilder() {
-            return new PullAtomMetadata.Builder();
-        }
-
-        /**
          *  Builder for PullAtomMetadata.
          */
         public static class Builder {
diff --git a/apex/statsd/tests/libstatspull/Android.bp b/apex/statsd/tests/libstatspull/Android.bp
new file mode 100644
index 0000000..e813964
--- /dev/null
+++ b/apex/statsd/tests/libstatspull/Android.bp
@@ -0,0 +1,56 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+android_test {
+    name: "LibStatsPullTests",
+    static_libs: [
+        "androidx.test.rules",
+        "platformprotoslite",
+        "statsdprotolite",
+        "truth-prebuilt",
+    ],
+    libs: [
+        "android.test.runner.stubs",
+        "android.test.base.stubs",
+    ],
+    jni_libs: [
+        "libstatspull_testhelper",
+    ],
+    srcs: [
+        "src/**/*.java",
+        "protos/**/*.proto",
+        ],
+    test_suites: [
+        "general-tests",
+    ],
+    platform_apis: true,
+    privileged: true,
+    certificate: "platform",
+    compile_multilib: "both",
+}
+
+cc_library_shared {
+    name: "libstatspull_testhelper",
+    srcs: ["jni/stats_pull_helper.cpp"],
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+    shared_libs: [
+        "libbinder",
+        "libutils",
+        "libstatspull",
+        "libstatssocket",
+    ],
+}
\ No newline at end of file
diff --git a/apex/statsd/tests/libstatspull/AndroidManifest.xml b/apex/statsd/tests/libstatspull/AndroidManifest.xml
new file mode 100644
index 0000000..bffd400
--- /dev/null
+++ b/apex/statsd/tests/libstatspull/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.internal.os.statsd.libstats" >
+
+
+    <uses-permission android:name="android.permission.DUMP" />
+    <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
+
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="com.android.internal.os.statsd.libstats"
+                     android:label="Tests for libstatspull">
+    </instrumentation>
+</manifest>
+
diff --git a/apex/statsd/tests/libstatspull/TEST_MAPPING b/apex/statsd/tests/libstatspull/TEST_MAPPING
new file mode 100644
index 0000000..5e1178cf
--- /dev/null
+++ b/apex/statsd/tests/libstatspull/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit" : [
+    {
+      "name" : "LibStatsPullTests"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/apex/statsd/tests/libstatspull/jni/stats_pull_helper.cpp b/apex/statsd/tests/libstatspull/jni/stats_pull_helper.cpp
new file mode 100644
index 0000000..e4ab823
--- /dev/null
+++ b/apex/statsd/tests/libstatspull/jni/stats_pull_helper.cpp
@@ -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.
+ */
+
+#include <binder/ProcessState.h>
+#include <jni.h>
+#include <log/log.h>
+#include <stats_event.h>
+#include <stats_pull_atom_callback.h>
+
+#include <chrono>
+#include <thread>
+
+using std::this_thread::sleep_for;
+using namespace android;
+
+namespace {
+static int32_t sAtomTag;
+static int32_t sPullReturnVal;
+static int64_t sLatencyMillis;
+static int32_t sAtomsPerPull;
+static int32_t sNumPulls = 0;
+
+static bool initialized = false;
+
+static void init() {
+    if (!initialized) {
+        initialized = true;
+        // Set up the binder
+        sp<ProcessState> ps(ProcessState::self());
+        ps->setThreadPoolMaxThreadCount(9);
+        ps->startThreadPool();
+        ps->giveThreadPoolName();
+    }
+}
+
+static status_pull_atom_return_t pullAtomCallback(int32_t atomTag, pulled_stats_event_list* data,
+                                                  void* /*cookie*/) {
+    sNumPulls++;
+    sleep_for(std::chrono::milliseconds(sLatencyMillis));
+    for (int i = 0; i < sAtomsPerPull; i++) {
+        stats_event* event = add_stats_event_to_pull_data(data);
+        stats_event_set_atom_id(event, atomTag);
+        stats_event_write_int64(event, (int64_t) sNumPulls);
+        stats_event_build(event);
+    }
+    return sPullReturnVal;
+}
+
+extern "C"
+JNIEXPORT void JNICALL
+Java_com_android_internal_os_statsd_libstats_LibStatsPullTests_registerStatsPuller(
+        JNIEnv* /*env*/, jobject /* this */, jint atomTag, jlong timeoutNs, jlong coolDownNs,
+        jint pullRetVal, jlong latencyMillis, int atomsPerPull)
+{
+    init();
+    sAtomTag = atomTag;
+    sPullReturnVal = pullRetVal;
+    sLatencyMillis = latencyMillis;
+    sAtomsPerPull = atomsPerPull;
+    sNumPulls = 0;
+    pull_atom_metadata metadata = {.cool_down_ns = coolDownNs,
+                                   .timeout_ns = timeoutNs,
+                                   .additive_fields = nullptr,
+                                   .additive_fields_size = 0};
+    register_stats_pull_atom_callback(sAtomTag, &pullAtomCallback, &metadata, nullptr);
+}
+
+extern "C"
+JNIEXPORT void JNICALL
+Java_com_android_internal_os_statsd_libstats_LibStatsPullTests_unregisterStatsPuller(
+        JNIEnv* /*env*/, jobject /* this */, jint /*atomTag*/)
+{
+    unregister_stats_pull_atom_callback(sAtomTag);
+}
+} // namespace
\ No newline at end of file
diff --git a/apex/statsd/tests/libstatspull/protos/test_atoms.proto b/apex/statsd/tests/libstatspull/protos/test_atoms.proto
new file mode 100644
index 0000000..56c1b53
--- /dev/null
+++ b/apex/statsd/tests/libstatspull/protos/test_atoms.proto
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+syntax = "proto2";
+
+package com.android.internal.os.statsd.protos;
+
+option java_package = "com.android.internal.os.statsd.protos";
+option java_outer_classname = "TestAtoms";
+
+message PullCallbackAtomWrapper {
+  optional PullCallbackAtom pull_callback_atom = 150030;
+}
+
+message PullCallbackAtom {
+  optional int64 long_val = 1;
+}
+
+
+
diff --git a/apex/statsd/tests/libstatspull/src/com/android/internal/os/statsd/StatsConfigUtils.java b/apex/statsd/tests/libstatspull/src/com/android/internal/os/statsd/StatsConfigUtils.java
new file mode 100644
index 0000000..d0d1400
--- /dev/null
+++ b/apex/statsd/tests/libstatspull/src/com/android/internal/os/statsd/StatsConfigUtils.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.os.statsd;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.StatsManager;
+import android.util.Log;
+
+import com.android.internal.os.StatsdConfigProto.AtomMatcher;
+import com.android.internal.os.StatsdConfigProto.FieldValueMatcher;
+import com.android.internal.os.StatsdConfigProto.SimpleAtomMatcher;
+import com.android.internal.os.StatsdConfigProto.StatsdConfig;
+import com.android.os.AtomsProto.AppBreadcrumbReported;
+import com.android.os.AtomsProto.Atom;
+import com.android.os.StatsLog.ConfigMetricsReport;
+import com.android.os.StatsLog.ConfigMetricsReportList;
+import com.android.os.StatsLog.GaugeBucketInfo;
+import com.android.os.StatsLog.GaugeMetricData;
+import com.android.os.StatsLog.StatsLogReport;
+import com.android.os.StatsLog.StatsdStatsReport;
+import com.android.os.StatsLog.StatsdStatsReport.ConfigStats;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Util class for constructing statsd configs.
+ */
+public class StatsConfigUtils {
+    public static final String TAG = "statsd.StatsConfigUtils";
+    public static final int SHORT_WAIT = 2_000; // 2 seconds.
+
+    /**
+     * @return An empty StatsdConfig in serialized proto format.
+     */
+    public static StatsdConfig.Builder getSimpleTestConfig(long configId) {
+        return StatsdConfig.newBuilder().setId(configId)
+                .addAllowedLogSource(StatsConfigUtils.class.getPackage().getName());
+    }
+
+
+    public static boolean verifyValidConfigExists(StatsManager statsManager, long configId) {
+        StatsdStatsReport report = null;
+        try {
+            report = StatsdStatsReport.parser().parseFrom(statsManager.getStatsMetadata());
+        } catch (Exception e) {
+            Log.e(TAG, "getMetadata failed", e);
+        }
+        assertThat(report).isNotNull();
+        boolean foundConfig = false;
+        for (ConfigStats configStats : report.getConfigStatsList()) {
+            if (configStats.getId() == configId && configStats.getIsValid()
+                    && configStats.getDeletionTimeSec() == 0) {
+                foundConfig = true;
+            }
+        }
+        return foundConfig;
+    }
+
+    public static AtomMatcher getAppBreadcrumbMatcher(long id, int label) {
+        return AtomMatcher.newBuilder()
+                .setId(id)
+                .setSimpleAtomMatcher(
+                        SimpleAtomMatcher.newBuilder()
+                                .setAtomId(Atom.APP_BREADCRUMB_REPORTED_FIELD_NUMBER)
+                                .addFieldValueMatcher(FieldValueMatcher.newBuilder()
+                                        .setField(AppBreadcrumbReported.LABEL_FIELD_NUMBER)
+                                        .setEqInt(label)
+                                )
+                )
+                .build();
+    }
+
+    public static ConfigMetricsReport getConfigMetricsReport(StatsManager statsManager,
+            long configId) {
+        ConfigMetricsReportList reportList = null;
+        try {
+            reportList = ConfigMetricsReportList.parser()
+                    .parseFrom(statsManager.getReports(configId));
+        } catch (Exception e) {
+            Log.e(TAG, "getData failed", e);
+        }
+        assertThat(reportList).isNotNull();
+        assertThat(reportList.getReportsCount()).isEqualTo(1);
+        ConfigMetricsReport report = reportList.getReports(0);
+        assertThat(report.getDumpReportReason())
+                .isEqualTo(ConfigMetricsReport.DumpReportReason.GET_DATA_CALLED);
+        return report;
+
+    }
+    public static List<Atom> getGaugeMetricDataList(ConfigMetricsReport report) {
+        List<Atom> data = new ArrayList<>();
+        for (StatsLogReport metric : report.getMetricsList()) {
+            for (GaugeMetricData gaugeMetricData : metric.getGaugeMetrics().getDataList()) {
+                for (GaugeBucketInfo bucketInfo : gaugeMetricData.getBucketInfoList()) {
+                    for (Atom atom : bucketInfo.getAtomList()) {
+                        data.add(atom);
+                    }
+                }
+            }
+        }
+        return data;
+    }
+
+    public static List<Atom> getGaugeMetricDataList(StatsManager statsManager, long configId) {
+        ConfigMetricsReport report = getConfigMetricsReport(statsManager, configId);
+        return getGaugeMetricDataList(report);
+    }
+}
+
diff --git a/apex/statsd/tests/libstatspull/src/com/android/internal/os/statsd/libstats/LibStatsPullTests.java b/apex/statsd/tests/libstatspull/src/com/android/internal/os/statsd/libstats/LibStatsPullTests.java
new file mode 100644
index 0000000..dbd636d
--- /dev/null
+++ b/apex/statsd/tests/libstatspull/src/com/android/internal/os/statsd/libstats/LibStatsPullTests.java
@@ -0,0 +1,285 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.os.statsd.libstats;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.StatsManager;
+import android.content.Context;
+import android.util.Log;
+import android.util.StatsLog;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.MediumTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.os.StatsdConfigProto.AtomMatcher;
+import com.android.internal.os.StatsdConfigProto.FieldFilter;
+import com.android.internal.os.StatsdConfigProto.GaugeMetric;
+import com.android.internal.os.StatsdConfigProto.SimpleAtomMatcher;
+import com.android.internal.os.StatsdConfigProto.StatsdConfig;
+import com.android.internal.os.StatsdConfigProto.TimeUnit;
+import com.android.internal.os.statsd.StatsConfigUtils;
+import com.android.internal.os.statsd.protos.TestAtoms;
+import com.android.os.AtomsProto.Atom;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.List;
+
+/**
+ * Test puller registration.
+ */
+@MediumTest
+@RunWith(AndroidJUnit4.class)
+public class LibStatsPullTests {
+    private static final String LOG_TAG = LibStatsPullTests.class.getSimpleName();
+    private static final int SHORT_SLEEP_MILLIS = 250;
+    private static final int LONG_SLEEP_MILLIS = 1_000;
+    private Context mContext;
+    private static final int PULL_ATOM_TAG = 150030;
+    private static final int APP_BREADCRUMB_LABEL = 3;
+    private static int sPullReturnValue;
+    private static long sConfigId;
+    private static long sPullLatencyMillis;
+    private static long sPullTimeoutNs;
+    private static long sCoolDownNs;
+    private static int sAtomsPerPull;
+
+    static {
+        System.loadLibrary("statspull_testhelper");
+    }
+
+    /**
+     * Setup the tests. Initialize shared data.
+     */
+    @Before
+    public void setup() {
+//        Debug.waitForDebugger();
+        mContext = InstrumentationRegistry.getTargetContext();
+        assertThat(InstrumentationRegistry.getInstrumentation()).isNotNull();
+        sPullReturnValue = StatsManager.PULL_SUCCESS;
+        sPullLatencyMillis = 0;
+        sPullTimeoutNs = 10_000_000_000L;
+        sCoolDownNs = 1_000_000_000L;
+        sAtomsPerPull = 1;
+    }
+
+    /**
+     * Teardown the tests.
+     */
+    @After
+    public void tearDown() throws Exception {
+        unregisterStatsPuller(PULL_ATOM_TAG);
+        StatsManager statsManager = (StatsManager) mContext.getSystemService(
+                Context.STATS_MANAGER);
+        statsManager.removeConfig(sConfigId);
+    }
+
+    /**
+     * Tests adding a puller callback and that pulls complete successfully.
+     */
+    @Test
+    public void testPullAtomCallbackRegistration() throws Exception {
+        StatsManager statsManager = (StatsManager) mContext.getSystemService(
+                Context.STATS_MANAGER);
+        // Upload a config that captures that pulled atom.
+        createAndAddConfigToStatsd(statsManager);
+
+        // Add the puller.
+        registerStatsPuller(PULL_ATOM_TAG, sPullTimeoutNs, sCoolDownNs, sPullReturnValue,
+                sPullLatencyMillis, sAtomsPerPull);
+        Thread.sleep(SHORT_SLEEP_MILLIS);
+        StatsLog.logStart(APP_BREADCRUMB_LABEL);
+        // Let the current bucket finish.
+        Thread.sleep(LONG_SLEEP_MILLIS);
+        List<Atom> data = StatsConfigUtils.getGaugeMetricDataList(statsManager, sConfigId);
+        unregisterStatsPuller(PULL_ATOM_TAG);
+        assertThat(data.size()).isEqualTo(1);
+        TestAtoms.PullCallbackAtomWrapper atomWrapper = null;
+        try {
+            atomWrapper = TestAtoms.PullCallbackAtomWrapper.parser()
+                    .parseFrom(data.get(0).toByteArray());
+        } catch (Exception e) {
+            Log.e(LOG_TAG, "Failed to parse primitive atoms");
+        }
+        assertThat(atomWrapper).isNotNull();
+        assertThat(atomWrapper.hasPullCallbackAtom()).isTrue();
+        TestAtoms.PullCallbackAtom atom =
+                atomWrapper.getPullCallbackAtom();
+        assertThat(atom.getLongVal()).isEqualTo(1);
+    }
+
+    /**
+     * Tests that a failed pull is skipped.
+     */
+    @Test
+    public void testPullAtomCallbackFailure() throws Exception {
+        StatsManager statsManager = (StatsManager) mContext.getSystemService(
+                Context.STATS_MANAGER);
+        createAndAddConfigToStatsd(statsManager);
+        sPullReturnValue = StatsManager.PULL_SKIP;
+        // Add the puller.
+        registerStatsPuller(PULL_ATOM_TAG, sPullTimeoutNs, sCoolDownNs, sPullReturnValue,
+                sPullLatencyMillis, sAtomsPerPull);
+        Thread.sleep(SHORT_SLEEP_MILLIS);
+        StatsLog.logStart(APP_BREADCRUMB_LABEL);
+        // Let the current bucket finish.
+        Thread.sleep(LONG_SLEEP_MILLIS);
+        List<Atom> data = StatsConfigUtils.getGaugeMetricDataList(statsManager, sConfigId);
+        unregisterStatsPuller(PULL_ATOM_TAG);
+        assertThat(data.size()).isEqualTo(0);
+    }
+
+    /**
+     * Tests that a pull that times out is skipped.
+     */
+    @Test
+    public void testPullAtomCallbackTimeout() throws Exception {
+        StatsManager statsManager = (StatsManager) mContext.getSystemService(
+                Context.STATS_MANAGER);
+        createAndAddConfigToStatsd(statsManager);
+        // The puller will sleep for 1.5 sec.
+        sPullLatencyMillis = 1_500;
+        // 1 second timeout
+        sPullTimeoutNs = 1_000_000_000;
+
+        // Add the puller.
+        registerStatsPuller(PULL_ATOM_TAG, sPullTimeoutNs, sCoolDownNs, sPullReturnValue,
+                sPullLatencyMillis, sAtomsPerPull);
+        Thread.sleep(SHORT_SLEEP_MILLIS);
+        StatsLog.logStart(APP_BREADCRUMB_LABEL);
+        // Let the current bucket finish and the pull timeout.
+        Thread.sleep(sPullLatencyMillis * 2);
+        List<Atom> data = StatsConfigUtils.getGaugeMetricDataList(statsManager, sConfigId);
+        unregisterStatsPuller(PULL_ATOM_TAG);
+        assertThat(data.size()).isEqualTo(0);
+    }
+
+    /**
+     * Tests that 2 pulls in quick succession use the cache instead of pulling again.
+     */
+    @Test
+    public void testPullAtomCallbackCache() throws Exception {
+        StatsManager statsManager = (StatsManager) mContext.getSystemService(
+                Context.STATS_MANAGER);
+        createAndAddConfigToStatsd(statsManager);
+
+        // Set the cooldown to 10 seconds
+        sCoolDownNs = 10_000_000_000L;
+        // Add the puller.
+        registerStatsPuller(PULL_ATOM_TAG, sPullTimeoutNs, sCoolDownNs, sPullReturnValue,
+                sPullLatencyMillis, sAtomsPerPull);
+
+        Thread.sleep(SHORT_SLEEP_MILLIS);
+        StatsLog.logStart(APP_BREADCRUMB_LABEL);
+        // Pull from cache.
+        StatsLog.logStart(APP_BREADCRUMB_LABEL);
+        Thread.sleep(LONG_SLEEP_MILLIS);
+        List<Atom> data = StatsConfigUtils.getGaugeMetricDataList(statsManager, sConfigId);
+        unregisterStatsPuller(PULL_ATOM_TAG);
+        assertThat(data.size()).isEqualTo(2);
+        for (int i = 0; i < data.size(); i++) {
+            TestAtoms.PullCallbackAtomWrapper atomWrapper = null;
+            try {
+                atomWrapper = TestAtoms.PullCallbackAtomWrapper.parser()
+                        .parseFrom(data.get(i).toByteArray());
+            } catch (Exception e) {
+                Log.e(LOG_TAG, "Failed to parse primitive atoms");
+            }
+            assertThat(atomWrapper).isNotNull();
+            assertThat(atomWrapper.hasPullCallbackAtom()).isTrue();
+            TestAtoms.PullCallbackAtom atom =
+                    atomWrapper.getPullCallbackAtom();
+            assertThat(atom.getLongVal()).isEqualTo(1);
+        }
+    }
+
+    /**
+     * Tests that a pull that returns 1000 stats events works properly.
+     */
+    @Test
+    public void testPullAtomCallbackStress() throws Exception {
+        StatsManager statsManager = (StatsManager) mContext.getSystemService(
+                Context.STATS_MANAGER);
+        // Upload a config that captures that pulled atom.
+        createAndAddConfigToStatsd(statsManager);
+        sAtomsPerPull = 1000;
+        // Add the puller.
+        registerStatsPuller(PULL_ATOM_TAG, sPullTimeoutNs, sCoolDownNs, sPullReturnValue,
+                sPullLatencyMillis, sAtomsPerPull);
+
+        Thread.sleep(SHORT_SLEEP_MILLIS);
+        StatsLog.logStart(APP_BREADCRUMB_LABEL);
+        // Let the current bucket finish.
+        Thread.sleep(LONG_SLEEP_MILLIS);
+        List<Atom> data = StatsConfigUtils.getGaugeMetricDataList(statsManager, sConfigId);
+        statsManager.unregisterPullAtomCallback(PULL_ATOM_TAG);
+        assertThat(data.size()).isEqualTo(sAtomsPerPull);
+
+        for (int i = 0; i < data.size(); i++) {
+            TestAtoms.PullCallbackAtomWrapper atomWrapper = null;
+            try {
+                atomWrapper = TestAtoms.PullCallbackAtomWrapper.parser()
+                        .parseFrom(data.get(i).toByteArray());
+            } catch (Exception e) {
+                Log.e(LOG_TAG, "Failed to parse primitive atoms");
+            }
+            assertThat(atomWrapper).isNotNull();
+            assertThat(atomWrapper.hasPullCallbackAtom()).isTrue();
+            TestAtoms.PullCallbackAtom atom =
+                    atomWrapper.getPullCallbackAtom();
+            assertThat(atom.getLongVal()).isEqualTo(1);
+        }
+    }
+
+    private void createAndAddConfigToStatsd(StatsManager statsManager) throws Exception {
+        sConfigId = System.currentTimeMillis();
+        long triggerMatcherId = sConfigId + 10;
+        long pullerMatcherId = sConfigId + 11;
+        long metricId = sConfigId + 100;
+        StatsdConfig config = StatsConfigUtils.getSimpleTestConfig(sConfigId)
+                .addAtomMatcher(
+                        StatsConfigUtils.getAppBreadcrumbMatcher(triggerMatcherId,
+                                APP_BREADCRUMB_LABEL))
+                .addAtomMatcher(AtomMatcher.newBuilder()
+                        .setId(pullerMatcherId)
+                        .setSimpleAtomMatcher(SimpleAtomMatcher.newBuilder()
+                                .setAtomId(PULL_ATOM_TAG))
+                )
+                .addGaugeMetric(GaugeMetric.newBuilder()
+                        .setId(metricId)
+                        .setWhat(pullerMatcherId)
+                        .setTriggerEvent(triggerMatcherId)
+                        .setGaugeFieldsFilter(FieldFilter.newBuilder().setIncludeAll(true))
+                        .setBucket(TimeUnit.CTS)
+                        .setSamplingType(GaugeMetric.SamplingType.FIRST_N_SAMPLES)
+                        .setMaxNumGaugeAtomsPerBucket(1000)
+                )
+                .build();
+        statsManager.addConfig(sConfigId, config.toByteArray());
+        assertThat(StatsConfigUtils.verifyValidConfigExists(statsManager, sConfigId)).isTrue();
+    }
+
+    private native void registerStatsPuller(int atomTag, long timeoutNs, long coolDownNs,
+            int pullReturnVal, long latencyMillis, int atomPerPull);
+
+    private native void unregisterStatsPuller(int atomTag);
+}
+
diff --git a/api/current.txt b/api/current.txt
index 5467248..12d8b70 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -14249,9 +14249,12 @@
     method public int getWidth();
     method public boolean isHardwareAccelerated();
     method public boolean isOpaque();
-    method public boolean quickReject(@NonNull android.graphics.RectF, @NonNull android.graphics.Canvas.EdgeType);
-    method public boolean quickReject(@NonNull android.graphics.Path, @NonNull android.graphics.Canvas.EdgeType);
-    method public boolean quickReject(float, float, float, float, @NonNull android.graphics.Canvas.EdgeType);
+    method @Deprecated public boolean quickReject(@NonNull android.graphics.RectF, @NonNull android.graphics.Canvas.EdgeType);
+    method public boolean quickReject(@NonNull android.graphics.RectF);
+    method @Deprecated public boolean quickReject(@NonNull android.graphics.Path, @NonNull android.graphics.Canvas.EdgeType);
+    method public boolean quickReject(@NonNull android.graphics.Path);
+    method @Deprecated public boolean quickReject(float, float, float, float, @NonNull android.graphics.Canvas.EdgeType);
+    method public boolean quickReject(float, float, float, float);
     method public void restore();
     method public void restoreToCount(int);
     method public void rotate(float);
@@ -14276,9 +14279,9 @@
     field public static final int ALL_SAVE_FLAG = 31; // 0x1f
   }
 
-  public enum Canvas.EdgeType {
-    enum_constant public static final android.graphics.Canvas.EdgeType AA;
-    enum_constant public static final android.graphics.Canvas.EdgeType BW;
+  @Deprecated public enum Canvas.EdgeType {
+    enum_constant @Deprecated public static final android.graphics.Canvas.EdgeType AA;
+    enum_constant @Deprecated public static final android.graphics.Canvas.EdgeType BW;
   }
 
   public enum Canvas.VertexMode {
@@ -29199,6 +29202,7 @@
     method public void onAppPrivateCommand(@NonNull String, android.os.Bundle);
     method public abstract void onRelease();
     method public abstract void onStartRecording(@Nullable android.net.Uri);
+    method public void onStartRecording(@Nullable android.net.Uri, @NonNull android.os.Bundle);
     method public abstract void onStopRecording();
     method public abstract void onTune(android.net.Uri);
     method public void onTune(android.net.Uri, android.os.Bundle);
@@ -29249,6 +29253,7 @@
     method public void release();
     method public void sendAppPrivateCommand(@NonNull String, android.os.Bundle);
     method public void startRecording(@Nullable android.net.Uri);
+    method public void startRecording(@Nullable android.net.Uri, @NonNull android.os.Bundle);
     method public void stopRecording();
     method public void tune(String, android.net.Uri);
     method public void tune(String, android.net.Uri, android.os.Bundle);
@@ -36482,7 +36487,7 @@
     method public boolean isSustainedPerformanceModeSupported();
     method public boolean isWakeLockLevelSupported(int);
     method public android.os.PowerManager.WakeLock newWakeLock(int, String);
-    method public void reboot(@Nullable String);
+    method @RequiresPermission(android.Manifest.permission.REBOOT) public void reboot(@Nullable String);
     method public void removeThermalStatusListener(@NonNull android.os.PowerManager.OnThermalStatusChangedListener);
     field public static final int ACQUIRE_CAUSES_WAKEUP = 268435456; // 0x10000000
     field public static final String ACTION_DEVICE_IDLE_MODE_CHANGED = "android.os.action.DEVICE_IDLE_MODE_CHANGED";
@@ -36924,6 +36929,7 @@
     method public static android.os.VibrationEffect createWaveform(long[], int);
     method public static android.os.VibrationEffect createWaveform(long[], int[], int);
     method public int describeContents();
+    method @NonNull public static android.os.VibrationEffect.Composition startComposition();
     field @NonNull public static final android.os.Parcelable.Creator<android.os.VibrationEffect> CREATOR;
     field public static final int DEFAULT_AMPLITUDE = -1; // 0xffffffff
     field public static final int EFFECT_CLICK = 0; // 0x0
@@ -36932,7 +36938,26 @@
     field public static final int EFFECT_TICK = 2; // 0x2
   }
 
+  public static class VibrationEffect.Composition {
+    ctor public VibrationEffect.Composition();
+    method @Nullable public android.os.VibrationEffect.Composition addPrimitive(int);
+    method @Nullable public android.os.VibrationEffect.Composition addPrimitive(int, @FloatRange(from=0.0f, to=1.0f) float);
+    method @Nullable public android.os.VibrationEffect.Composition addPrimitive(int, @FloatRange(from=0.0f, to=1.0f) float, @IntRange(from=0) int);
+    method @NonNull public android.os.VibrationEffect compose();
+    field public static final int PRIMITIVE_CLICK = 1; // 0x1
+    field public static final int PRIMITIVE_LIGHT_TICK = 7; // 0x7
+    field public static final int PRIMITIVE_QUICK_FALL = 6; // 0x6
+    field public static final int PRIMITIVE_QUICK_RISE = 4; // 0x4
+    field public static final int PRIMITIVE_SLOW_RISE = 5; // 0x5
+    field public static final int PRIMITIVE_SPIN = 3; // 0x3
+    field public static final int PRIMITIVE_THUD = 2; // 0x2
+  }
+
   public abstract class Vibrator {
+    method @Nullable public Boolean areAllEffectsSupported(@NonNull int...);
+    method public boolean areAllPrimitivesSupported(@NonNull int...);
+    method @Nullable public boolean[] areEffectsSupported(@NonNull int...);
+    method @NonNull public boolean[] arePrimitivesSupported(@NonNull int...);
     method @RequiresPermission(android.Manifest.permission.VIBRATE) public abstract void cancel();
     method public abstract boolean hasAmplitudeControl();
     method public abstract boolean hasVibrator();
@@ -43867,11 +43892,13 @@
     method public android.graphics.drawable.Icon getIcon();
     method public CharSequence getLabel();
     method public int getState();
+    method @Nullable public CharSequence getStateDescription();
     method @Nullable public CharSequence getSubtitle();
     method public void setContentDescription(CharSequence);
     method public void setIcon(android.graphics.drawable.Icon);
     method public void setLabel(CharSequence);
     method public void setState(int);
+    method public void setStateDescription(@Nullable CharSequence);
     method public void setSubtitle(@Nullable CharSequence);
     method public void updateTile();
     method public void writeToParcel(android.os.Parcel, int);
diff --git a/api/system-current.txt b/api/system-current.txt
index 1a039dc..23beedb 100755
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -8367,7 +8367,7 @@
     method @NonNull public android.os.BatterySaverPolicyConfig.Builder setLocationMode(int);
   }
 
-  public class BatteryStatsManager {
+  public final class BatteryStatsManager {
     method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public android.os.connectivity.CellularBatteryStats getCellularBatteryStats();
     method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public android.os.connectivity.WifiBatteryStats getWifiBatteryStats();
     method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportFullWifiLockAcquiredFromSource(@NonNull android.os.WorkSource);
@@ -9703,6 +9703,7 @@
     field public static final String CMAS_SEVERITY = "cmas_severity";
     field public static final String CMAS_URGENCY = "cmas_urgency";
     field @NonNull public static final android.net.Uri CONTENT_URI;
+    field public static final String DATA_CODING_SCHEME = "dcs";
     field public static final String DEFAULT_SORT_ORDER = "date DESC";
     field public static final String DELIVERY_TIME = "date";
     field public static final String ETWS_WARNING_TYPE = "etws_warning_type";
@@ -9710,9 +9711,11 @@
     field public static final String GEOMETRIES = "geometries";
     field public static final String LAC = "lac";
     field public static final String LANGUAGE_CODE = "language";
+    field public static final String LOCATION_CHECK_TIME = "location_check_time";
     field public static final String MAXIMUM_WAIT_TIME = "maximum_wait_time";
     field public static final String MESSAGE_BODY = "body";
     field public static final String MESSAGE_BROADCASTED = "message_broadcasted";
+    field public static final String MESSAGE_DISPLAYED = "message_displayed";
     field public static final String MESSAGE_FORMAT = "format";
     field @NonNull @RequiresPermission(android.Manifest.permission.READ_CELL_BROADCASTS) public static final android.net.Uri MESSAGE_HISTORY_URI;
     field public static final String MESSAGE_PRIORITY = "priority";
@@ -12047,11 +12050,12 @@
   }
 
   public final class SmsCbMessage implements android.os.Parcelable {
-    ctor public SmsCbMessage(int, int, int, @NonNull android.telephony.SmsCbLocation, int, @Nullable String, @Nullable String, int, @Nullable android.telephony.SmsCbEtwsInfo, @Nullable android.telephony.SmsCbCmasInfo, int, @Nullable java.util.List<android.telephony.CbGeoUtils.Geometry>, long, int, int);
+    ctor public SmsCbMessage(int, int, int, @NonNull android.telephony.SmsCbLocation, int, @Nullable String, int, @Nullable String, int, @Nullable android.telephony.SmsCbEtwsInfo, @Nullable android.telephony.SmsCbCmasInfo, int, @Nullable java.util.List<android.telephony.CbGeoUtils.Geometry>, long, int, int);
     method @NonNull public static android.telephony.SmsCbMessage createFromCursor(@NonNull android.database.Cursor);
     method public int describeContents();
     method @Nullable public android.telephony.SmsCbCmasInfo getCmasWarningInfo();
     method @NonNull public android.content.ContentValues getContentValues();
+    method public int getDataCodingScheme();
     method @Nullable public android.telephony.SmsCbEtwsInfo getEtwsWarningInfo();
     method public int getGeographicalScope();
     method @NonNull public java.util.List<android.telephony.CbGeoUtils.Geometry> getGeometries();
diff --git a/api/test-current.txt b/api/test-current.txt
index fec5f3d..917e938 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -2846,6 +2846,7 @@
     field public static final String CMAS_SEVERITY = "cmas_severity";
     field public static final String CMAS_URGENCY = "cmas_urgency";
     field @NonNull public static final android.net.Uri CONTENT_URI;
+    field public static final String DATA_CODING_SCHEME = "dcs";
     field public static final String DEFAULT_SORT_ORDER = "date DESC";
     field public static final String DELIVERY_TIME = "date";
     field public static final String ETWS_WARNING_TYPE = "etws_warning_type";
@@ -2853,9 +2854,11 @@
     field public static final String GEOMETRIES = "geometries";
     field public static final String LAC = "lac";
     field public static final String LANGUAGE_CODE = "language";
+    field public static final String LOCATION_CHECK_TIME = "location_check_time";
     field public static final String MAXIMUM_WAIT_TIME = "maximum_wait_time";
     field public static final String MESSAGE_BODY = "body";
     field public static final String MESSAGE_BROADCASTED = "message_broadcasted";
+    field public static final String MESSAGE_DISPLAYED = "message_displayed";
     field public static final String MESSAGE_FORMAT = "format";
     field @NonNull @RequiresPermission(android.Manifest.permission.READ_CELL_BROADCASTS) public static final android.net.Uri MESSAGE_HISTORY_URI;
     field public static final String MESSAGE_PRIORITY = "priority";
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 5ac00d0..1fdc8af 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -78,9 +78,9 @@
     // Pushed atoms start at 2.
     oneof pushed {
         // For StatsLog reasons, 1 is illegal and will not work. Must start at 2.
-        BleScanStateChanged ble_scan_state_changed = 2;
+        BleScanStateChanged ble_scan_state_changed = 2 [(module) = "bluetooth"];
         ProcessStateChanged process_state_changed = 3;
-        BleScanResultReceived ble_scan_result_received = 4;
+        BleScanResultReceived ble_scan_result_received = 4 [(module) = "bluetooth"];
         SensorStateChanged sensor_state_changed = 5;
         GpsScanStateChanged gps_scan_state_changed = 6;
         SyncStateChanged sync_state_changed = 7;
@@ -144,7 +144,8 @@
         AppDied app_died = 65;
         ResourceConfigurationChanged resource_configuration_changed = 66;
         BluetoothEnabledStateChanged bluetooth_enabled_state_changed = 67;
-        BluetoothConnectionStateChanged bluetooth_connection_state_changed = 68;
+        BluetoothConnectionStateChanged bluetooth_connection_state_changed =
+                68 [(module) = "bluetooth"];
         GpsSignalQualityChanged gps_signal_quality_changed = 69;
         UsbConnectorStateChanged usb_connector_state_changed = 70;
         SpeakerImpedanceReported speaker_impedance_reported = 71;
@@ -207,9 +208,12 @@
         RescuePartyResetReported rescue_party_reset_reported = 122;
         SignedConfigReported signed_config_reported = 123;
         GnssNiEventReported gnss_ni_event_reported = 124;
-        BluetoothLinkLayerConnectionEvent bluetooth_link_layer_connection_event = 125;
-        BluetoothAclConnectionStateChanged bluetooth_acl_connection_state_changed = 126;
-        BluetoothScoConnectionStateChanged bluetooth_sco_connection_state_changed = 127;
+        BluetoothLinkLayerConnectionEvent bluetooth_link_layer_connection_event =
+                125 [(module) = "bluetooth"];
+        BluetoothAclConnectionStateChanged bluetooth_acl_connection_state_changed =
+                126 [(module) = "bluetooth"];
+        BluetoothScoConnectionStateChanged bluetooth_sco_connection_state_changed =
+                127 [(module) = "bluetooth"];
         AppDowngraded app_downgraded = 128;
         AppOptimizedAfterDowngraded app_optimized_after_downgraded = 129;
         LowStorageStateChanged low_storage_state_changed = 130;
@@ -233,23 +237,40 @@
         BiometricSystemHealthIssueDetected biometric_system_health_issue_detected = 148;
         BubbleUIChanged bubble_ui_changed = 149 [(module) = "sysui"];
         ScheduledJobConstraintChanged scheduled_job_constraint_changed = 150;
-        BluetoothActiveDeviceChanged bluetooth_active_device_changed = 151;
-        BluetoothA2dpPlaybackStateChanged bluetooth_a2dp_playback_state_changed = 152;
-        BluetoothA2dpCodecConfigChanged bluetooth_a2dp_codec_config_changed = 153;
-        BluetoothA2dpCodecCapabilityChanged bluetooth_a2dp_codec_capability_changed = 154;
-        BluetoothA2dpAudioUnderrunReported bluetooth_a2dp_audio_underrun_reported = 155;
-        BluetoothA2dpAudioOverrunReported bluetooth_a2dp_audio_overrun_reported = 156;
-        BluetoothDeviceRssiReported bluetooth_device_rssi_reported = 157;
-        BluetoothDeviceFailedContactCounterReported bluetooth_device_failed_contact_counter_reported = 158;
-        BluetoothDeviceTxPowerLevelReported bluetooth_device_tx_power_level_reported = 159;
-        BluetoothHciTimeoutReported bluetooth_hci_timeout_reported = 160;
-        BluetoothQualityReportReported bluetooth_quality_report_reported = 161;
-        BluetoothDeviceInfoReported bluetooth_device_info_reported = 162;
-        BluetoothRemoteVersionInfoReported bluetooth_remote_version_info_reported = 163;
-        BluetoothSdpAttributeReported bluetooth_sdp_attribute_reported = 164;
-        BluetoothBondStateChanged bluetooth_bond_state_changed = 165;
-        BluetoothClassicPairingEventReported bluetooth_classic_pairing_event_reported = 166;
-        BluetoothSmpPairingEventReported bluetooth_smp_pairing_event_reported = 167;
+        BluetoothActiveDeviceChanged bluetooth_active_device_changed =
+                151 [(module) = "bluetooth"];
+        BluetoothA2dpPlaybackStateChanged bluetooth_a2dp_playback_state_changed =
+                152 [(module) = "bluetooth"];
+        BluetoothA2dpCodecConfigChanged bluetooth_a2dp_codec_config_changed =
+                153 [(module) = "bluetooth"];
+        BluetoothA2dpCodecCapabilityChanged bluetooth_a2dp_codec_capability_changed =
+                154 [(module) = "bluetooth"];
+        BluetoothA2dpAudioUnderrunReported bluetooth_a2dp_audio_underrun_reported =
+                155 [(module) = "bluetooth"];
+        BluetoothA2dpAudioOverrunReported bluetooth_a2dp_audio_overrun_reported =
+                156 [(module) = "bluetooth"];
+        BluetoothDeviceRssiReported bluetooth_device_rssi_reported =
+                157 [(module) = "bluetooth"];
+        BluetoothDeviceFailedContactCounterReported
+                bluetooth_device_failed_contact_counter_reported = 158 [(module) = "bluetooth"];
+        BluetoothDeviceTxPowerLevelReported bluetooth_device_tx_power_level_reported =
+                159 [(module) = "bluetooth"];
+        BluetoothHciTimeoutReported bluetooth_hci_timeout_reported =
+                160 [(module) = "bluetooth"];
+        BluetoothQualityReportReported bluetooth_quality_report_reported =
+                161 [(module) = "bluetooth"];
+        BluetoothDeviceInfoReported bluetooth_device_info_reported =
+                162 [(module) = "bluetooth"];
+        BluetoothRemoteVersionInfoReported bluetooth_remote_version_info_reported =
+                163 [(module) = "bluetooth"];
+        BluetoothSdpAttributeReported bluetooth_sdp_attribute_reported =
+                164 [(module) = "bluetooth"];
+        BluetoothBondStateChanged bluetooth_bond_state_changed =
+                165 [(module) = "bluetooth"];
+        BluetoothClassicPairingEventReported bluetooth_classic_pairing_event_reported =
+                166 [(module) = "bluetooth"];
+        BluetoothSmpPairingEventReported bluetooth_smp_pairing_event_reported =
+                167 [(module) = "bluetooth"];
         ScreenTimeoutExtensionReported screen_timeout_extension_reported = 168;
         ProcessStartTime process_start_time = 169;
         PermissionGrantRequestResultReported permission_grant_request_result_reported =
@@ -258,9 +279,9 @@
         DeviceIdentifierAccessDenied device_identifier_access_denied =
                 172 [(module) = "telephony_common"];
         BubbleDeveloperErrorReported bubble_developer_error_reported = 173;
-        AssistGestureStageReported assist_gesture_stage_reported = 174;
-        AssistGestureFeedbackReported assist_gesture_feedback_reported = 175;
-        AssistGestureProgressReported assist_gesture_progress_reported = 176;
+        AssistGestureStageReported assist_gesture_stage_reported = 174 [(module) = "sysui"];
+        AssistGestureFeedbackReported assist_gesture_feedback_reported = 175 [(module) = "sysui"];
+        AssistGestureProgressReported assist_gesture_progress_reported = 176 [(module) = "sysui"];
         TouchGestureClassified touch_gesture_classified = 177;
         HiddenApiUsed hidden_api_used = 178 [(allow_from_any_uid) = true];
         StyleUIChanged style_ui_changed = 179 [(module) = "sysui"];
@@ -272,7 +293,8 @@
         BiometricEnrolled biometric_enrolled = 184;
         SystemServerWatchdogOccurred system_server_watchdog_occurred = 185;
         TombStoneOccurred tomb_stone_occurred = 186;
-        BluetoothClassOfDeviceReported bluetooth_class_of_device_reported = 187;
+        BluetoothClassOfDeviceReported bluetooth_class_of_device_reported =
+                187 [(module) = "bluetooth"];
         IntelligenceEventReported intelligence_event_reported =
             188 [(module) = "intelligence"];
         ThermalThrottlingSeverityStateChanged thermal_throttling_severity_state_changed = 189;
diff --git a/core/java/android/annotation/SystemApi.java b/core/java/android/annotation/SystemApi.java
index 1a8b78f..ecbfed9 100644
--- a/core/java/android/annotation/SystemApi.java
+++ b/core/java/android/annotation/SystemApi.java
@@ -23,6 +23,7 @@
 import static java.lang.annotation.ElementType.PACKAGE;
 import static java.lang.annotation.ElementType.TYPE;
 
+import java.lang.annotation.Repeatable;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
@@ -40,6 +41,7 @@
  */
 @Target({TYPE, FIELD, METHOD, CONSTRUCTOR, ANNOTATION_TYPE, PACKAGE})
 @Retention(RetentionPolicy.RUNTIME)
+@Repeatable(SystemApi.Container.class) // TODO(b/146727827): make this non-repeatable
 public @interface SystemApi {
     enum Client {
         /**
@@ -95,4 +97,14 @@
      */
     @Deprecated
     Process process() default android.annotation.SystemApi.Process.ALL;
+
+
+    /**
+     * Container for {@link SystemApi} that allows it to be applied repeatedly to types.
+     */
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target(TYPE)
+    @interface Container {
+        SystemApi[] value();
+    }
 }
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index b346e8f..35d26ab 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -3569,8 +3569,16 @@
          * This field will be ignored by Launchers that don't support badging, don't show
          * notification content, or don't show {@link android.content.pm.ShortcutManager shortcuts}.
          *
+         * If this notification has {@link BubbleMetadata} attached that was created with
+         * {@link BubbleMetadata.Builder#createShortcutBubble(String)} a check will be performed
+         * to ensure the shortcutId supplied to bubble metadata matches the shortcutId set here,
+         * if one was set. If the shortcutId's were specified but do not match, an exception
+         * is thrown.
+         *
          * @param shortcutId the {@link ShortcutInfo#getId() id} of the shortcut this notification
          *                   supersedes
+         *
+         * @see BubbleMetadata.Builder#createShortcutBubble(String)
          */
         @NonNull
         public Builder setShortcutId(String shortcutId) {
@@ -5926,9 +5934,29 @@
         /**
          * Combine all of the options that have been set and return a new {@link Notification}
          * object.
+         *
+         * If this notification has {@link BubbleMetadata} attached that was created with
+         * {@link BubbleMetadata.Builder#createShortcutBubble(String)} a check will be performed
+         * to ensure the shortcutId supplied to bubble metadata matches the shortcutId set on the
+         * notification builder, if one was set. If the shortcutId's were specified but do not
+         * match, an exception is thrown here.
+         *
+         * @see BubbleMetadata.Builder#createShortcutBubble(String)
+         * @see #setShortcutId(String)
          */
         @NonNull
         public Notification build() {
+            // Check shortcut id matches
+            if (mN.mShortcutId != null
+                    && mN.mBubbleMetadata != null
+                    && mN.mBubbleMetadata.getShortcutId() != null
+                    && !mN.mShortcutId.equals(mN.mBubbleMetadata.getShortcutId())) {
+                throw new IllegalArgumentException(
+                        "Notification and BubbleMetadata shortcut id's don't match,"
+                                + " notification: " + mN.mShortcutId
+                                + " vs bubble: " + mN.mBubbleMetadata.getShortcutId());
+            }
+
             // first, add any extras from the calling code
             if (mUserExtras != null) {
                 mN.extras = getAllExtras();
@@ -8644,17 +8672,23 @@
         public static final int FLAG_AUTO_EXPAND_BUBBLE = 0x00000001;
 
         /**
-         * If set and the app posting the bubble is in the foreground, the bubble will
-         * be posted <b>without</b> the associated notification in the notification shade.
+         * Indicates whether the notification associated with the bubble is being visually
+         * suppressed from the notification shade. When <code>true</code> the notification is
+         * hidden, when <code>false</code> the notification shows as normal.
          *
-         * <p>This flag has no effect if the app posting the bubble is not in the foreground.
-         * The app is considered foreground if it is visible and on the screen, note that
-         * a foreground service does not qualify.
-         * </p>
+         * <p>Apps sending bubbles may set this flag so that the bubble is posted <b>without</b>
+         * the associated notification in the notification shade.</p>
          *
-         * <p>Generally this flag should only be set if the user has performed an action to request
-         * or create a bubble, or if the user has seen the content in the notification and the
-         * notification is no longer relevant.</p>
+         * <p>Apps sending bubbles can only apply this flag when the app is in the foreground,
+         * otherwise the flag is not respected. The app is considered foreground if it is visible
+         * and on the screen, note that a foreground service does not qualify.</p>
+         *
+         * <p>Generally this flag should only be set by the app if the user has performed an
+         * action to request or create a bubble, or if the user has seen the content in the
+         * notification and the notification is no longer relevant. </p>
+         *
+         * <p>The system will also update this flag with <code>true</code> to hide the notification
+         * from the user once the bubble has been expanded. </p>
          *
          * @hide
          */
@@ -8772,6 +8806,24 @@
         }
 
         /**
+         * Indicates whether the notification associated with the bubble is being visually
+         * suppressed from the notification shade. When <code>true</code> the notification is
+         * hidden, when <code>false</code> the notification shows as normal.
+         *
+         * <p>Apps sending bubbles may set this flag so that the bubble is posted <b>without</b>
+         * the associated notification in the notification shade.</p>
+         *
+         * <p>Apps sending bubbles can only apply this flag when the app is in the foreground,
+         * otherwise the flag is not respected. The app is considered foreground if it is visible
+         * and on the screen, note that a foreground service does not qualify.</p>
+         *
+         * <p>Generally the app should only set this flag if the user has performed an
+         * action to request or create a bubble, or if the user has seen the content in the
+         * notification and the notification is no longer relevant. </p>
+         *
+         * <p>The system will update this flag with <code>true</code> to hide the notification
+         * from the user once the bubble has been expanded.</p>
+         *
          * @return whether this bubble should suppress the notification when it is posted.
          *
          * @see BubbleMetadata.Builder#setSuppressNotification(boolean)
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 1aed977..b998539 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -133,6 +133,13 @@
     public int fullBackupContent = 0;
 
     /**
+     * <code>true</code> if the package is capable of presenting a unified interface representing
+     * multiple profiles.
+     * @hide
+     */
+    public boolean crossProfile;
+
+    /**
      * The default extra UI options for activities in this application.
      * Set from the {@link android.R.attr#uiOptions} attribute in the
      * activity's manifest.
@@ -1382,6 +1389,7 @@
                 pw.println(prefix + "fullBackupContent="
                         + (fullBackupContent < 0 ? "false" : "true"));
             }
+            pw.println("crossProfile=" + (crossProfile ? "true" : "false"));
             if (networkSecurityConfigRes != 0) {
                 pw.println(prefix + "networkSecurityConfigRes=0x"
                         + Integer.toHexString(networkSecurityConfigRes));
@@ -1586,6 +1594,7 @@
         uiOptions = orig.uiOptions;
         backupAgentName = orig.backupAgentName;
         fullBackupContent = orig.fullBackupContent;
+        crossProfile = orig.crossProfile;
         networkSecurityConfigRes = orig.networkSecurityConfigRes;
         category = orig.category;
         targetSandboxVersion = orig.targetSandboxVersion;
@@ -1665,6 +1674,7 @@
         dest.writeInt(descriptionRes);
         dest.writeInt(uiOptions);
         dest.writeInt(fullBackupContent);
+        dest.writeBoolean(crossProfile);
         dest.writeInt(networkSecurityConfigRes);
         dest.writeInt(category);
         dest.writeInt(targetSandboxVersion);
@@ -1741,6 +1751,7 @@
         descriptionRes = source.readInt();
         uiOptions = source.readInt();
         fullBackupContent = source.readInt();
+        crossProfile = source.readBoolean();
         networkSecurityConfigRes = source.readInt();
         category = source.readInt();
         targetSandboxVersion = source.readInt();
diff --git a/core/java/android/content/pm/parsing/PackageImpl.java b/core/java/android/content/pm/parsing/PackageImpl.java
index 9baf325..fe8307c 100644
--- a/core/java/android/content/pm/parsing/PackageImpl.java
+++ b/core/java/android/content/pm/parsing/PackageImpl.java
@@ -2382,6 +2382,7 @@
         appInfo.uiOptions = uiOptions;
         appInfo.volumeUuid = volumeUuid;
         appInfo.zygotePreloadName = zygotePreloadName;
+        appInfo.crossProfile = isCrossProfile();
 
         appInfo.setBaseCodePath(baseCodePath);
         appInfo.setBaseResourcePath(baseCodePath);
diff --git a/core/java/android/hardware/location/ContextHubManager.java b/core/java/android/hardware/location/ContextHubManager.java
index 1001f80..db16d24 100644
--- a/core/java/android/hardware/location/ContextHubManager.java
+++ b/core/java/android/hardware/location/ContextHubManager.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.RequiresFeature;
 import android.annotation.RequiresPermission;
 import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
@@ -26,6 +27,7 @@
 import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.PackageManager;
 import android.os.Handler;
 import android.os.HandlerExecutor;
 import android.os.Looper;
@@ -52,6 +54,7 @@
  */
 @SystemApi
 @SystemService(Context.CONTEXTHUB_SERVICE)
+@RequiresFeature(PackageManager.FEATURE_CONTEXTHUB)
 public final class ContextHubManager {
     private static final String TAG = "ContextHubManager";
 
diff --git a/core/java/android/os/BatteryStatsManager.java b/core/java/android/os/BatteryStatsManager.java
index 152141e..f2e16b4 100644
--- a/core/java/android/os/BatteryStatsManager.java
+++ b/core/java/android/os/BatteryStatsManager.java
@@ -42,7 +42,7 @@
  */
 @SystemApi
 @SystemService(Context.BATTERY_STATS_SERVICE)
-public class BatteryStatsManager {
+public final class BatteryStatsManager {
     /**
      * Wifi states.
      *
diff --git a/core/java/android/os/IVibratorService.aidl b/core/java/android/os/IVibratorService.aidl
index 416d692..e201e43 100644
--- a/core/java/android/os/IVibratorService.aidl
+++ b/core/java/android/os/IVibratorService.aidl
@@ -24,6 +24,8 @@
 {
     boolean hasVibrator();
     boolean hasAmplitudeControl();
+    boolean[] areEffectsSupported(in int[] effectIds);
+    boolean[] arePrimitivesSupported(in int[] primitiveIds);
     boolean setAlwaysOnEffect(int uid, String opPkg, int alwaysOnId, in VibrationEffect effect,
             in VibrationAttributes attributes);
     void vibrate(int uid, String opPkg, in VibrationEffect effect,
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 6a80788..f3d3837 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -1371,6 +1371,7 @@
      * @throws UnsupportedOperationException if userspace reboot was requested on a device that
      *                                       doesn't support it.
      */
+    @RequiresPermission(permission.REBOOT)
     public void reboot(@Nullable String reason) {
         if (REBOOT_USERSPACE.equals(reason) && !isRebootingUserspaceSupported()) {
             throw new UnsupportedOperationException(
@@ -1390,6 +1391,7 @@
      * </p>
      * @hide
      */
+    @RequiresPermission(permission.REBOOT)
     public void rebootSafeMode() {
         try {
             mService.rebootSafeMode(false, true);
diff --git a/core/java/android/os/SystemVibrator.java b/core/java/android/os/SystemVibrator.java
index 8050454..faf4a36 100644
--- a/core/java/android/os/SystemVibrator.java
+++ b/core/java/android/os/SystemVibrator.java
@@ -16,6 +16,7 @@
 
 package android.os;
 
+import android.annotation.NonNull;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.media.AudioAttributes;
@@ -104,6 +105,28 @@
     }
 
     @Override
+    public boolean[] areEffectsSupported(@VibrationEffect.EffectType int... effectIds) {
+        try {
+            return mService.areEffectsSupported(effectIds);
+        } catch (RemoteException e) {
+            Log.w(TAG, "Failed to query effect support");
+        }
+        return new boolean[effectIds.length];
+    }
+
+    @Override
+    public boolean[] arePrimitivesSupported(
+            @NonNull @VibrationEffect.Composition.Primitive int... primitiveIds) {
+        try {
+            return mService.arePrimitivesSupported(primitiveIds);
+        } catch (RemoteException e) {
+            Log.w(TAG, "Failed to query effect support");
+        }
+        return new boolean[primitiveIds.length];
+    }
+
+
+    @Override
     public void cancel() {
         if (mService == null) {
             return;
diff --git a/core/java/android/os/VibrationEffect.aidl b/core/java/android/os/VibrationEffect.aidl
index dcc79d7..89478fa 100644
--- a/core/java/android/os/VibrationEffect.aidl
+++ b/core/java/android/os/VibrationEffect.aidl
@@ -17,6 +17,4 @@
 package android.os;
 
 parcelable VibrationEffect;
-parcelable VibrationEffect.OneShotVibration;
-parcelable VibrationEffect.WaveformVibration;
-parcelable VibrationEffect.EffectVibration;
+parcelable VibrationEffect.Composition.PrimitiveEffect;
\ No newline at end of file
diff --git a/core/java/android/os/VibrationEffect.java b/core/java/android/os/VibrationEffect.java
index 75b4724..2d218f4 100644
--- a/core/java/android/os/VibrationEffect.java
+++ b/core/java/android/os/VibrationEffect.java
@@ -16,7 +16,9 @@
 
 package android.os;
 
+import android.annotation.FloatRange;
 import android.annotation.IntDef;
+import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.TestApi;
@@ -28,9 +30,14 @@
 import android.net.Uri;
 import android.util.MathUtils;
 
+import com.android.internal.util.Preconditions;
+
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
 
 /**
  * A VibrationEffect describes a haptic effect to be performed by a {@link Vibrator}.
@@ -41,6 +48,8 @@
     private static final int PARCEL_TOKEN_ONE_SHOT = 1;
     private static final int PARCEL_TOKEN_WAVEFORM = 2;
     private static final int PARCEL_TOKEN_EFFECT = 3;
+    private static final int PARCEL_TOKEN_COMPOSITION = 4;
+
 
     /**
      * The default vibration strength of the device.
@@ -359,6 +368,16 @@
         return null;
     }
 
+    /**
+     * Start composing a haptic effect.
+     *
+     * @see VibrationEffect.Composition
+     */
+    @NonNull
+    public static VibrationEffect.Composition startComposition() {
+        return new VibrationEffect.Composition();
+    }
+
     @Override
     public int describeContents() {
         return 0;
@@ -839,6 +858,331 @@
             };
     }
 
+    /** @hide */
+    public static final class Composed extends VibrationEffect implements Parcelable {
+        private final ArrayList<Composition.PrimitiveEffect> mPrimitiveEffects;
+
+        /**
+         * @hide
+         */
+        @SuppressWarnings("unchecked")
+        public Composed(@NonNull Parcel in) {
+            this(in.readArrayList(Composed.class.getClassLoader()));
+        }
+
+        /**
+         * @hide
+         */
+        public Composed(List<Composition.PrimitiveEffect> effects) {
+            mPrimitiveEffects = new ArrayList<>(Objects.requireNonNull(effects));
+        }
+
+        /**
+         * @hide
+         */
+        @NonNull
+        public List<Composition.PrimitiveEffect> getPrimitiveEffects() {
+            return mPrimitiveEffects;
+        }
+
+        @Override
+        public long getDuration() {
+            return -1;
+        }
+
+
+        /**
+         * @hide
+         */
+        @Override
+        public void validate() {
+            for (Composition.PrimitiveEffect effect : mPrimitiveEffects) {
+                Composition.checkPrimitive(effect.id);
+                Preconditions.checkArgumentInRange(
+                        effect.scale, 0.0f, 1.0f, "scale");
+            }
+        }
+
+        @Override
+        public void writeToParcel(@NonNull Parcel out, int flags) {
+            out.writeInt(PARCEL_TOKEN_COMPOSITION);
+            out.writeList(mPrimitiveEffects);
+        }
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+            Composed composed = (Composed) o;
+            return mPrimitiveEffects.equals(composed.mPrimitiveEffects);
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(mPrimitiveEffects);
+        }
+
+        @Override
+        public String toString() {
+            return "Composed{mPrimitiveEffects=" + mPrimitiveEffects + '}';
+        }
+
+        public static final @NonNull Parcelable.Creator<Composed> CREATOR =
+                new Parcelable.Creator<Composed>() {
+                    @Override
+                    public Composed createFromParcel(@NonNull Parcel in) {
+                        // Skip the type token
+                        in.readInt();
+                        return new Composed(in);
+                    }
+
+                    @Override
+                    @NonNull
+                    public Composed[] newArray(int size) {
+                        return new Composed[size];
+                    }
+                };
+    }
+
+    /**
+     * A composition of haptic primitives that, when combined, create a single haptic effect.
+     *
+     * @see VibrationEffect#startComposition()
+     */
+    public static class Composition {
+        /** @hide */
+        @IntDef(prefix = { "PRIMITIVE_" }, value = {
+                PRIMITIVE_CLICK,
+                PRIMITIVE_THUD,
+                PRIMITIVE_SPIN,
+                PRIMITIVE_QUICK_RISE,
+                PRIMITIVE_SLOW_RISE,
+                PRIMITIVE_QUICK_FALL,
+                PRIMITIVE_LIGHT_TICK,
+        })
+        @Retention(RetentionPolicy.SOURCE)
+        public @interface Primitive {}
+
+        /**
+         * No haptic effect. Used to generate extended delays between primitives.
+         * @hide
+         */
+        public static final int PRIMITIVE_NOOP = 0;
+        /**
+         * This effect should produce a sharp, crisp click sensation.
+         */
+        public static final int PRIMITIVE_CLICK = 1;
+        /**
+         * A haptic effect that simulates downwards movement with gravity. Often
+         * followed by extra energy of hitting and reverberation to augment
+         * physicality.
+         */
+        public static final int PRIMITIVE_THUD = 2;
+        /**
+         * A haptic effect that simulates spinning momentum.
+         */
+        public static final int PRIMITIVE_SPIN = 3;
+        /**
+         * A haptic effect that simulates quick upward movement against gravity.
+         */
+        public static final int PRIMITIVE_QUICK_RISE = 4;
+        /**
+         * A haptic effect that simulates slow upward movement against gravity.
+         */
+        public static final int PRIMITIVE_SLOW_RISE = 5;
+        /**
+         * A haptic effect that simulates quick downwards movement with gravity.
+         */
+        public static final int PRIMITIVE_QUICK_FALL = 6;
+        /**
+         * This very short effect should produce a light crisp sensation intended
+         * to be used repetitively for dynamic feedback.
+         */
+        public static final int PRIMITIVE_LIGHT_TICK = 7;
+
+
+        private ArrayList<PrimitiveEffect> mEffects = new ArrayList<>();
+
+        /**
+         * Add a haptic primitive to the end of the current composition.
+         *
+         * Similar to {@link #addPrimitive(int, float, int)}, but with no delay and a
+         * default scale applied.
+         *
+         * @param primitiveId The primitive to add
+         *
+         * @return The {@link Composition} object to enable adding multiple primitives in one chain.
+         */
+        @Nullable
+        public Composition addPrimitive(@Primitive int primitiveId) {
+            addPrimitive(primitiveId, /*scale*/ 1.0f, /*delay*/ 0);
+            return this;
+        }
+
+        /**
+         * Add a haptic primitive to the end of the current composition.
+         *
+         * Similar to {@link #addPrimitive(int, float, int)}, but with no delay.
+         *
+         * @param primitiveId The primitive to add
+         * @param scale The scale to apply to the intensity of the primitive.
+         *
+         * @return The {@link Composition} object to enable adding multiple primitives in one chain.
+         */
+        @Nullable
+        public Composition addPrimitive(@Primitive int primitiveId,
+                @FloatRange(from = 0f, to = 1f) float scale) {
+            addPrimitive(primitiveId, scale, /*delay*/ 0);
+            return this;
+        }
+
+        /**
+         * Add a haptic primitive to the end of the current composition.
+         *
+         * @param primitiveId The primitive to add
+         * @param scale The scale to apply to the intensity of the primitive.
+         * @param delay The amount of time, in milliseconds, to wait before playing the prior
+         *              primitive and this one
+         * @return The {@link Composition} object to enable adding multiple primitives in one chain.
+         */
+        @Nullable
+        public Composition addPrimitive(@Primitive int primitiveId,
+                @FloatRange(from = 0f, to = 1f) float scale, @IntRange(from = 0) int delay) {
+            mEffects.add(new PrimitiveEffect(checkPrimitive(primitiveId), scale, delay));
+            return this;
+        }
+
+        /**
+         * Compose all of the added primitives together into a single {@link VibrationEffect}.
+         *
+         * The {@link Composition} object is still valid after this call, so you can continue adding
+         * more primitives to it and generating more {@link VibrationEffect}s by calling this method
+         * again.
+         *
+         * @return The {@link VibrationEffect} resulting from the composition of the primitives.
+         */
+        @NonNull
+        public VibrationEffect compose() {
+            if (mEffects.isEmpty()) {
+                throw new IllegalStateException(
+                        "Composition must have at least one element to compose.");
+            }
+            return new VibrationEffect.Composed(mEffects);
+        }
+
+        /**
+         * @throws IllegalArgumentException throws if the primitive ID is not within the valid range
+         * @hide
+         *
+         */
+        static int checkPrimitive(int primitiveId) {
+            Preconditions.checkArgumentInRange(primitiveId, PRIMITIVE_NOOP, PRIMITIVE_LIGHT_TICK,
+                    "primitiveId");
+            return primitiveId;
+        }
+
+        /**
+         * Convert the primitive ID to a human readable string for debugging
+         * @param id The ID to convert
+         * @return The ID in a human readable format.
+         * @hide
+         */
+        public static String primitiveToString(@Primitive int id) {
+            switch (id) {
+                case PRIMITIVE_NOOP:
+                    return "PRIMITIVE_NOOP";
+                case PRIMITIVE_CLICK:
+                    return "PRIMITIVE_CLICK";
+                case PRIMITIVE_THUD:
+                    return "PRIMITIVE_THUD";
+                case PRIMITIVE_SPIN:
+                    return "PRIMITIVE_SPIN";
+                case PRIMITIVE_QUICK_RISE:
+                    return "PRIMITIVE_QUICK_RISE";
+                case PRIMITIVE_SLOW_RISE:
+                    return "PRIMITIVE_SLOW_RISE";
+                case PRIMITIVE_QUICK_FALL:
+                    return "PRIMITIVE_QUICK_FALL";
+                case PRIMITIVE_LIGHT_TICK:
+                    return "PRIMITIVE_LIGHT_TICK";
+
+                default:
+                    return Integer.toString(id);
+
+            }
+        }
+
+
+        /**
+         * @hide
+         */
+        public static class PrimitiveEffect implements Parcelable {
+            public int id;
+            public float scale;
+            public int delay;
+
+            PrimitiveEffect(int id, float scale, int delay) {
+                this.id = id;
+                this.scale = scale;
+                this.delay = delay;
+            }
+
+            @Override
+            public void writeToParcel(Parcel dest, int flags) {
+                dest.writeInt(id);
+                dest.writeFloat(scale);
+                dest.writeInt(delay);
+            }
+
+            @Override
+            public int describeContents() {
+                return 0;
+            }
+
+            @Override
+            public String toString() {
+                return "PrimitiveEffect{"
+                        + "id=" + primitiveToString(id)
+                        + ", scale=" + scale
+                        + ", delay=" + delay
+                        + '}';
+            }
+
+            @Override
+            public boolean equals(Object o) {
+                if (this == o) return true;
+                if (o == null || getClass() != o.getClass()) return false;
+                PrimitiveEffect that = (PrimitiveEffect) o;
+                return id == that.id
+                        && Float.compare(that.scale, scale) == 0
+                        && delay == that.delay;
+            }
+
+            @Override
+            public int hashCode() {
+                return Objects.hash(id, scale, delay);
+            }
+
+
+            public static final @NonNull Parcelable.Creator<PrimitiveEffect> CREATOR =
+                    new Parcelable.Creator<PrimitiveEffect>() {
+                        @Override
+                        public PrimitiveEffect createFromParcel(Parcel in) {
+                            return new PrimitiveEffect(in.readInt(), in.readFloat(), in.readInt());
+                        }
+                        @Override
+                        public PrimitiveEffect[] newArray(int size) {
+                            return new PrimitiveEffect[size];
+                        }
+                    };
+        }
+    }
+
     public static final @NonNull Parcelable.Creator<VibrationEffect> CREATOR =
             new Parcelable.Creator<VibrationEffect>() {
                 @Override
@@ -850,6 +1194,8 @@
                         return new Waveform(in);
                     } else if (token == PARCEL_TOKEN_EFFECT) {
                         return new Prebaked(in);
+                    } else if (token == PARCEL_TOKEN_COMPOSITION) {
+                        return new Composed(in);
                     } else {
                         throw new IllegalStateException(
                                 "Unexpected vibration event type token in parcel.");
diff --git a/core/java/android/os/Vibrator.java b/core/java/android/os/Vibrator.java
index ae75f3d..f055c60 100644
--- a/core/java/android/os/Vibrator.java
+++ b/core/java/android/os/Vibrator.java
@@ -17,6 +17,7 @@
 package android.os;
 
 import android.annotation.IntDef;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemService;
@@ -41,37 +42,42 @@
 
     /**
      * Vibration intensity: no vibrations.
+     *
      * @hide
      */
     public static final int VIBRATION_INTENSITY_OFF = 0;
 
     /**
      * Vibration intensity: low.
+     *
      * @hide
      */
     public static final int VIBRATION_INTENSITY_LOW = 1;
 
     /**
      * Vibration intensity: medium.
+     *
      * @hide
      */
     public static final int VIBRATION_INTENSITY_MEDIUM = 2;
 
     /**
      * Vibration intensity: high.
+     *
      * @hide
      */
     public static final int VIBRATION_INTENSITY_HIGH = 3;
 
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
-    @IntDef(prefix = { "VIBRATION_INTENSITY_" }, value = {
-        VIBRATION_INTENSITY_OFF,
-        VIBRATION_INTENSITY_LOW,
-        VIBRATION_INTENSITY_MEDIUM,
-        VIBRATION_INTENSITY_HIGH
+    @IntDef(prefix = {"VIBRATION_INTENSITY_"}, value = {
+            VIBRATION_INTENSITY_OFF,
+            VIBRATION_INTENSITY_LOW,
+            VIBRATION_INTENSITY_MEDIUM,
+            VIBRATION_INTENSITY_HIGH
     })
-    public @interface VibrationIntensity{}
+    public @interface VibrationIntensity {
+    }
 
     private final String mPackageName;
     // The default vibration intensity level for haptic feedback.
@@ -117,6 +123,7 @@
 
     /**
      * Get the default vibration intensity for haptic feedback.
+     *
      * @hide
      */
     public int getDefaultHapticFeedbackIntensity() {
@@ -125,13 +132,16 @@
 
     /**
      * Get the default vibration intensity for notifications.
+     *
      * @hide
      */
     public int getDefaultNotificationVibrationIntensity() {
         return mDefaultNotificationVibrationIntensity;
     }
 
-    /** Get the default vibration intensity for ringtones.
+    /**
+     * Get the default vibration intensity for ringtones.
+     *
      * @hide
      */
     public int getDefaultRingVibrationIntensity() {
@@ -156,11 +166,12 @@
      * Configure an always-on haptics effect.
      *
      * @param alwaysOnId The board-specific always-on ID to configure.
-     * @param effect Vibration effect to assign to always-on id. Passing null will disable it.
+     * @param effect     Vibration effect to assign to always-on id. Passing null will disable it.
      * @param attributes {@link AudioAttributes} corresponding to the vibration. For example,
-     *        specify {@link AudioAttributes#USAGE_ALARM} for alarm vibrations or
-     *        {@link AudioAttributes#USAGE_NOTIFICATION_RINGTONE} for
-     *        vibrations associated with incoming calls. May only be null when effect is null.
+     *                   specify {@link AudioAttributes#USAGE_ALARM} for alarm vibrations or
+     *                   {@link AudioAttributes#USAGE_NOTIFICATION_RINGTONE} for
+     *                   vibrations associated with incoming calls. May only be null when effect is
+     *                   null.
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.VIBRATE_ALWAYS_ON)
@@ -183,7 +194,6 @@
      * Vibrate constantly for the specified period of time.
      *
      * @param milliseconds The number of milliseconds to vibrate.
-     *
      * @deprecated Use {@link #vibrate(VibrationEffect)} instead.
      */
     @Deprecated
@@ -196,11 +206,10 @@
      * Vibrate constantly for the specified period of time.
      *
      * @param milliseconds The number of milliseconds to vibrate.
-     * @param attributes {@link AudioAttributes} corresponding to the vibration. For example,
-     *        specify {@link AudioAttributes#USAGE_ALARM} for alarm vibrations or
-     *        {@link AudioAttributes#USAGE_NOTIFICATION_RINGTONE} for
-     *        vibrations associated with incoming calls.
-     *
+     * @param attributes   {@link AudioAttributes} corresponding to the vibration. For example,
+     *                     specify {@link AudioAttributes#USAGE_ALARM} for alarm vibrations or
+     *                     {@link AudioAttributes#USAGE_NOTIFICATION_RINGTONE} for
+     *                     vibrations associated with incoming calls.
      * @deprecated Use {@link #vibrate(VibrationEffect, AudioAttributes)} instead.
      */
     @Deprecated
@@ -231,9 +240,8 @@
      * </p>
      *
      * @param pattern an array of longs of times for which to turn the vibrator on or off.
-     * @param repeat the index into pattern at which to repeat, or -1 if
-     *        you don't want to repeat.
-     *
+     * @param repeat  the index into pattern at which to repeat, or -1 if
+     *                you don't want to repeat.
      * @deprecated Use {@link #vibrate(VibrationEffect)} instead.
      */
     @Deprecated
@@ -256,14 +264,13 @@
      * to start the repeat, or -1 to disable repeating.
      * </p>
      *
-     * @param pattern an array of longs of times for which to turn the vibrator on or off.
-     * @param repeat the index into pattern at which to repeat, or -1 if
-     *        you don't want to repeat.
+     * @param pattern    an array of longs of times for which to turn the vibrator on or off.
+     * @param repeat     the index into pattern at which to repeat, or -1 if
+     *                   you don't want to repeat.
      * @param attributes {@link AudioAttributes} corresponding to the vibration. For example,
-     *        specify {@link AudioAttributes#USAGE_ALARM} for alarm vibrations or
-     *        {@link AudioAttributes#USAGE_NOTIFICATION_RINGTONE} for
-     *        vibrations associated with incoming calls.
-     *
+     *                   specify {@link AudioAttributes#USAGE_ALARM} for alarm vibrations or
+     *                   {@link AudioAttributes#USAGE_NOTIFICATION_RINGTONE} for
+     *                   vibrations associated with incoming calls.
      * @deprecated Use {@link #vibrate(VibrationEffect, AudioAttributes)} instead.
      */
     @Deprecated
@@ -295,8 +302,9 @@
     }
 
     /**
-     * Like {@link #vibrate(int, String, VibrationEffect, AudioAttributes)}, but allows the
+     * Like {@link #vibrate(VibrationEffect, AudioAttributes)}, but allows the
      * caller to specify the vibration is owned by someone else and set reason for vibration.
+     *
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.VIBRATE)
@@ -304,6 +312,85 @@
             String reason, AudioAttributes attributes);
 
     /**
+     * Query whether the vibrator supports the given effects.
+     *
+     * If the returned array is {@code null}, the hardware doesn't support querying its supported
+     * effects. It may support any or all effects, but there's no way to programmatically know
+     * whether a {@link #vibrate} call will be successful.
+     *
+     * If the returned array is non-null, then it will be the same length as the query array and
+     * the value at a given index will contain whether the effect at that same index in the
+     * querying array is supported or not.
+     *
+     * @param effectIds Which effects to query for.
+     * @return Whether the effects are supported. Null when the hardware doesn't tell us what it
+     *         supports.
+     */
+    @Nullable
+    public boolean[] areEffectsSupported(
+            @NonNull @VibrationEffect.EffectType int... effectIds) {
+        return new boolean[effectIds.length];
+    }
+
+    /**
+     * Query whether the vibrator supports all of the given effects.
+     *
+     * If the result is {@code null}, the hardware doesn't support querying its supported
+     * effects. It may support any or all effects, but there's no way to programmatically know
+     * whether a {@link #vibrate} call will be successful.
+     *
+     * If the returned array is non-null, then it will return whether all of the effects are
+     * supported by the hardware.
+     *
+     * @param effectIds Which effects to query for.
+     * @return Whether the effects are supported. {@code null} when the hardware doesn't tell us
+     *         what it supports.
+     */
+    @Nullable
+    public Boolean areAllEffectsSupported(
+            @NonNull @VibrationEffect.EffectType int... effectIds) {
+        for (boolean supported : areEffectsSupported(effectIds)) {
+            if (!supported) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+
+    /**
+     * Query whether the vibrator supports the given primitives.
+     *
+     * The returned array will be the same length as the query array and the value at a given index
+     * will contain whether the effect at that same index in the querying array is supported or
+     * not.
+     *
+     * @param primitiveIds Which primitives to query for.
+     * @return Whether the primitives are supported.
+     */
+    @NonNull
+    public boolean[] arePrimitivesSupported(
+            @NonNull @VibrationEffect.Composition.Primitive int... primitiveIds) {
+        return new boolean[primitiveIds.length];
+    }
+
+    /**
+     * Query whether the vibrator supports all of the given primitives.
+     *
+     * @param primitiveIds Which primitives to query for.
+     * @return Whether primitives effects are supported.
+     */
+    public boolean areAllPrimitivesSupported(
+            @NonNull @VibrationEffect.Composition.Primitive int... primitiveIds) {
+        for (boolean supported : arePrimitivesSupported(primitiveIds)) {
+            if (!supported) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
      * Turn the vibrator off.
      */
     @RequiresPermission(android.Manifest.permission.VIBRATE)
diff --git a/core/java/android/os/incremental/IIncrementalManager.aidl b/core/java/android/os/incremental/IIncrementalManager.aidl
index 17a310a..b415bc0 100644
--- a/core/java/android/os/incremental/IIncrementalManager.aidl
+++ b/core/java/android/os/incremental/IIncrementalManager.aidl
@@ -33,5 +33,7 @@
     boolean startDataLoader(int mountId);
     void showHealthBlockedUI(int mountId);
     void destroyDataLoader(int mountId);
-    void newFileForDataLoader(int mountId, long inode, in byte[] metadata);
+
+    // fileId is a 16 byte long identifier.
+    void newFileForDataLoader(int mountId, in byte[] fileId, in byte[] metadata);
 }
diff --git a/core/java/android/os/incremental/IIncrementalManagerNative.aidl b/core/java/android/os/incremental/IIncrementalManagerNative.aidl
index 14215b1..2b6cd14 100644
--- a/core/java/android/os/incremental/IIncrementalManagerNative.aidl
+++ b/core/java/android/os/incremental/IIncrementalManagerNative.aidl
@@ -17,6 +17,7 @@
 package android.os.incremental;
 
 import android.content.pm.DataLoaderParamsParcel;
+import android.os.incremental.IncrementalNewFileParams;
 
 /** @hide */
 interface IIncrementalManagerNative {
@@ -40,7 +41,7 @@
      */
     const int BIND_TEMPORARY = 0;
     const int BIND_PERMANENT = 1;
-    int makeBindMount(int storageId, in @utf8InCpp String pathUnderStorage, in @utf8InCpp String targetFullPath, int bindType);
+    int makeBindMount(int storageId, in @utf8InCpp String sourcePath, in @utf8InCpp String targetFullPath, int bindType);
 
     /**
      * Deletes an existing bind mount on a path under a storage. Returns 0 on success, and -errno on failure.
@@ -48,49 +49,50 @@
     int deleteBindMount(int storageId, in @utf8InCpp String targetFullPath);
 
     /**
-     * Creates a directory under a storage. The target directory is specified by its relative path under the storage.
+     * Creates a directory under a storage. The target directory is specified by its path.
      */
-    int makeDirectory(int storageId, in @utf8InCpp String pathUnderStorage);
+    int makeDirectory(int storageId, in @utf8InCpp String path);
 
     /**
-     * Recursively creates a directory under a storage. The target directory is specified by its relative path under the storage.
+     * Recursively creates a directory under a storage. The target directory is specified by its path.
      * All the parent directories of the target directory will be created if they do not exist already.
      */
-    int makeDirectories(int storageId, in @utf8InCpp String pathUnderStorage);
+    int makeDirectories(int storageId, in @utf8InCpp String path);
 
     /**
-     * Creates a file under a storage, specifying its name, size and metadata.
+     * Creates a file under a storage.
      */
-    int makeFile(int storageId, in @utf8InCpp String pathUnderStorage, long size, in byte[] metadata);
+    int makeFile(int storageId, in @utf8InCpp String path, in IncrementalNewFileParams params);
 
     /**
      * Creates a file under a storage. Content of the file is from a range inside another file.
-     * Both files are specified by relative paths under storage.
+     * Both files are specified by their paths.
      */
-    int makeFileFromRange(int storageId, in @utf8InCpp String targetPathUnderStorage, in @utf8InCpp String sourcePathUnderStorage, long start, long end);
+    int makeFileFromRange(int storageId, in @utf8InCpp String targetPath, in @utf8InCpp String sourcePath, long start, long end);
 
     /**
      * Creates a hard link between two files in two storage instances.
-     * Source and dest specified by parent storage IDs and their relative paths under the storage.
+     * Source and dest specified by parent storage IDs and their paths.
      * The source and dest storage instances should be in the same fs mount.
      * Note: destStorageId can be the same as sourceStorageId.
      */
-    int makeLink(int sourceStorageId, in @utf8InCpp String sourcePathUnderStorage, int destStorageId, in @utf8InCpp String destPathUnderStorage);
+    int makeLink(int sourceStorageId, in @utf8InCpp String sourcePath, int destStorageId, in @utf8InCpp String destPath);
 
     /**
-     * Deletes a hard link in a storage, specified by the relative path of the link target under storage.
+     * Deletes a hard link in a storage, specified by its path.
      */
-    int unlink(int storageId, in @utf8InCpp String pathUnderStorage);
+    int unlink(int storageId, in @utf8InCpp String path);
 
     /**
-     * Checks if a file's certain range is loaded. File is specified by relative file path under storage.
+     * Checks if a file's certain range is loaded. File is specified by its path.
      */
-    boolean isFileRangeLoaded(int storageId, in @utf8InCpp String pathUnderStorage, long start, long end);
+    boolean isFileRangeLoaded(int storageId, in @utf8InCpp String path, long start, long end);
 
     /**
-     * Reads the metadata of a file. File is specified by relative path under storage.
+     * Reads the metadata of a file. File is specified by either its path or 16 byte id.
      */
-    byte[] getFileMetadata(int storageId, in @utf8InCpp String pathUnderStorage);
+    byte[] getMetadataByPath(int storageId, in @utf8InCpp String path);
+    byte[] getMetadataById(int storageId, in byte[] fileId);
 
     /**
      * Starts loading data for a storage.
diff --git a/core/java/android/os/incremental/IncrementalFileStorages.java b/core/java/android/os/incremental/IncrementalFileStorages.java
index 63335a0..a0bfc1b 100644
--- a/core/java/android/os/incremental/IncrementalFileStorages.java
+++ b/core/java/android/os/incremental/IncrementalFileStorages.java
@@ -134,8 +134,8 @@
         }
 
         if (!new File(mDefaultDir, apk.getName()).exists()) {
-            mDefaultStorage.makeFile(apk.getName(), apk.getSize(),
-                    apk.getMetadata());
+            mDefaultStorage.makeFile(apk.getName(), apk.getSize(), null,
+                    apk.getMetadata(), 0, null, null, null);
         }
         // Assuming APK files are already named properly, e.g., "base.apk"
         mDefaultStorage.makeLink(apk.getName(), mApkStorage, apk.getName());
@@ -167,7 +167,8 @@
             current += '/';
         }
         String libFilePath = current + Paths.get(lib.getName()).getFileName();
-        mDefaultStorage.makeFile(libFilePath, lib.getSize(), lib.getMetadata());
+        mDefaultStorage.makeFile(libFilePath, lib.getSize(), null, lib.getMetadata(), 0, null, null,
+                                 null);
         mDefaultStorage.makeLink(libFilePath, mApkStorage, libFilePath);
     }
 
@@ -183,7 +184,8 @@
                     IncrementalManager.CREATE_MODE_CREATE
                             | IncrementalManager.CREATE_MODE_TEMPORARY_BIND);
         }
-        mDefaultStorage.makeFile(obb.getName(), obb.getSize(), obb.getMetadata());
+        mDefaultStorage.makeFile(obb.getName(), obb.getSize(), null, obb.getMetadata(), 0, null,
+                                 null, null);
         mDefaultStorage.makeLink(obb.getName(), mObbStorage, obb.getName());
     }
 
diff --git a/core/java/android/os/incremental/IncrementalFileSystemControlParcel.aidl b/core/java/android/os/incremental/IncrementalFileSystemControlParcel.aidl
index 0ae353d..6018ad1 100644
--- a/core/java/android/os/incremental/IncrementalFileSystemControlParcel.aidl
+++ b/core/java/android/os/incremental/IncrementalFileSystemControlParcel.aidl
@@ -17,11 +17,12 @@
 package android.os.incremental;
 
 /**
- * Wraps two file descriptors that Incremental Service uses to communicate
+ * Wraps the file descriptors Incremental Service uses to communicate
  * with Incremental FileSystem.
  * @hide
  */
 parcelable IncrementalFileSystemControlParcel {
-    @nullable ParcelFileDescriptor cmd;
-    @nullable ParcelFileDescriptor log;
+    ParcelFileDescriptor cmd;
+    ParcelFileDescriptor pendingReads;
+    ParcelFileDescriptor log;
 }
diff --git a/core/java/android/os/incremental/IncrementalNewFileParams.aidl b/core/java/android/os/incremental/IncrementalNewFileParams.aidl
new file mode 100644
index 0000000..182732c
--- /dev/null
+++ b/core/java/android/os/incremental/IncrementalNewFileParams.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os.incremental;
+
+import android.os.incremental.IncrementalSignature;
+
+/**
+ * All the parameters to create a new file on IncFS
+ * FileId is a 16 byte-long identifier.
+ * @hide
+ */
+parcelable IncrementalNewFileParams {
+    long size;
+    byte[] fileId;
+    byte[] metadata;
+    @nullable IncrementalSignature signature;
+}
diff --git a/core/java/android/os/incremental/IncrementalSignature.aidl b/core/java/android/os/incremental/IncrementalSignature.aidl
new file mode 100644
index 0000000..729e8e5
--- /dev/null
+++ b/core/java/android/os/incremental/IncrementalSignature.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os.incremental;
+
+/** {@hide} */
+parcelable IncrementalSignature {
+    /*
+     * Stable AIDL doesn't support constants, but here's the possible values
+     *   const int HASH_ALGO_NONE = 0;
+     *   const int HASH_ALGO_SHA256 = 1;
+    */
+
+    int hashAlgorithm = 0;
+    byte[] rootHash;
+    byte[] additionalData;
+    byte[] signature;
+}
diff --git a/core/java/android/os/incremental/IncrementalStorage.java b/core/java/android/os/incremental/IncrementalStorage.java
index 2750868..91dda08 100644
--- a/core/java/android/os/incremental/IncrementalStorage.java
+++ b/core/java/android/os/incremental/IncrementalStorage.java
@@ -22,6 +22,8 @@
 
 import java.io.File;
 import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.UUID;
 
 /**
  * Provides operations on an Incremental File System directory, using IncrementalServiceNative.
@@ -64,14 +66,14 @@
      * Temporarily bind-mounts a subdir under the current storage directory to a target directory.
      * The bind-mount will NOT be preserved between device reboots.
      *
-     * @param sourcePathUnderStorage Source path as a relative path under current storage
-     *                               directory.
-     * @param targetPath             Absolute path to the target directory.
+     * @param sourcePath Source path as a relative path under current storage
+     *                   directory.
+     * @param targetPath Absolute path to the target directory.
      */
-    public void bind(@NonNull String sourcePathUnderStorage, @NonNull String targetPath)
+    public void bind(@NonNull String sourcePath, @NonNull String targetPath)
             throws IOException {
         try {
-            int res = mService.makeBindMount(mId, sourcePathUnderStorage, targetPath,
+            int res = mService.makeBindMount(mId, sourcePath, targetPath,
                     IIncrementalManagerNative.BIND_TEMPORARY);
             if (res < 0) {
                 throw new IOException("bind() failed with errno " + -res);
@@ -96,13 +98,13 @@
      * Permanently bind-mounts a subdir under the current storage directory to a target directory.
      * The bind-mount WILL be preserved between device reboots.
      *
-     * @param sourcePathUnderStorage Relative path under the current storage directory.
-     * @param targetPath             Absolute path to the target directory.
+     * @param sourcePath Relative path under the current storage directory.
+     * @param targetPath Absolute path to the target directory.
      */
-    public void bindPermanent(@NonNull String sourcePathUnderStorage, @NonNull String targetPath)
+    public void bindPermanent(@NonNull String sourcePath, @NonNull String targetPath)
             throws IOException {
         try {
-            int res = mService.makeBindMount(mId, sourcePathUnderStorage, targetPath,
+            int res = mService.makeBindMount(mId, sourcePath, targetPath,
                     IIncrementalManagerNative.BIND_PERMANENT);
             if (res < 0) {
                 throw new IOException("bind() permanent failed with errno " + -res);
@@ -131,11 +133,11 @@
     /**
      * Creates a sub-directory under the current storage directory.
      *
-     * @param pathUnderStorage Relative path of the sub-directory, e.g., "subdir"
+     * @param path Relative path of the sub-directory, e.g., "subdir"
      */
-    public void makeDirectory(@NonNull String pathUnderStorage) throws IOException {
+    public void makeDirectory(@NonNull String path) throws IOException {
         try {
-            int res = mService.makeDirectory(mId, pathUnderStorage);
+            int res = mService.makeDirectory(mId, path);
             if (res < 0) {
                 throw new IOException("makeDirectory() failed with errno " + -res);
             }
@@ -148,11 +150,11 @@
      * Creates a sub-directory under the current storage directory. If its parent dirs do not exist,
      * create the parent dirs as well.
      *
-     * @param pathUnderStorage Relative path of the sub-directory, e.g., "subdir/subsubdir"
+     * @param path Full path.
      */
-    public void makeDirectories(@NonNull String pathUnderStorage) throws IOException {
+    public void makeDirectories(@NonNull String path) throws IOException {
         try {
-            int res = mService.makeDirectories(mId, pathUnderStorage);
+            int res = mService.makeDirectories(mId, path);
             if (res < 0) {
                 throw new IOException("makeDirectory() failed with errno " + -res);
             }
@@ -164,15 +166,27 @@
     /**
      * Creates a file under the current storage directory.
      *
-     * @param pathUnderStorage Relative path of the new file.
+     * @param path             Relative path of the new file.
      * @param size             Size of the new file in bytes.
      * @param metadata         Metadata bytes.
      */
-    public void makeFile(@NonNull String pathUnderStorage, long size,
-            @Nullable byte[] metadata) throws IOException {
+    public void makeFile(@NonNull String path, long size, @Nullable UUID id,
+            @Nullable byte[] metadata, int hashAlgorithm, @Nullable byte[] rootHash,
+            @Nullable byte[] additionalData, @Nullable byte[] signature) throws IOException {
         try {
-            int res = mService.makeFile(mId, pathUnderStorage, size, metadata);
-            if (res < 0) {
+            final IncrementalNewFileParams params = new IncrementalNewFileParams();
+            params.size = size;
+            params.metadata = metadata;
+            params.fileId = idToBytes(id);
+            if (hashAlgorithm != 0 || signature != null) {
+                params.signature = new IncrementalSignature();
+                params.signature.hashAlgorithm = hashAlgorithm;
+                params.signature.rootHash = rootHash;
+                params.signature.additionalData = additionalData;
+                params.signature.signature = signature;
+            }
+            int res = mService.makeFile(mId, path, params);
+            if (res != 0) {
                 throw new IOException("makeFile() failed with errno " + -res);
             }
         } catch (RemoteException e) {
@@ -184,15 +198,15 @@
      * Creates a file in Incremental storage. The content of the file is mapped from a range inside
      * a source file in the same storage.
      *
-     * @param destRelativePath   Target relative path under storage.
-     * @param sourceRelativePath Source relative path under storage.
+     * @param destPath           Target full path.
+     * @param sourcePath         Source full path.
      * @param rangeStart         Starting offset (in bytes) in the source file.
      * @param rangeEnd           Ending offset (in bytes) in the source file.
      */
-    public void makeFileFromRange(@NonNull String destRelativePath,
-            @NonNull String sourceRelativePath, long rangeStart, long rangeEnd) throws IOException {
+    public void makeFileFromRange(@NonNull String destPath,
+            @NonNull String sourcePath, long rangeStart, long rangeEnd) throws IOException {
         try {
-            int res = mService.makeFileFromRange(mId, destRelativePath, sourceRelativePath,
+            int res = mService.makeFileFromRange(mId, destPath, sourcePath,
                     rangeStart, rangeEnd);
             if (res < 0) {
                 throw new IOException("makeFileFromRange() failed, errno " + -res);
@@ -206,15 +220,15 @@
      * Creates a hard-link between two paths, which can be under different storages but in the same
      * Incremental File System.
      *
-     * @param sourcePathUnderStorage The relative path of the source.
-     * @param destStorage            The target storage of the link target.
-     * @param destPathUnderStorage   The relative path of the target.
+     * @param sourcePath    The absolute path of the source.
+     * @param destStorage   The target storage of the link target.
+     * @param destPath      The absolute path of the target.
      */
-    public void makeLink(@NonNull String sourcePathUnderStorage, IncrementalStorage destStorage,
-            @NonNull String destPathUnderStorage) throws IOException {
+    public void makeLink(@NonNull String sourcePath, IncrementalStorage destStorage,
+            @NonNull String destPath) throws IOException {
         try {
-            int res = mService.makeLink(mId, sourcePathUnderStorage, destStorage.getId(),
-                    destPathUnderStorage);
+            int res = mService.makeLink(mId, sourcePath, destStorage.getId(),
+                    destPath);
             if (res < 0) {
                 throw new IOException("makeLink() failed with errno " + -res);
             }
@@ -226,11 +240,11 @@
     /**
      * Deletes a hard-link under the current storage directory.
      *
-     * @param pathUnderStorage The relative path of the target.
+     * @param path The absolute path of the target.
      */
-    public void unlink(@NonNull String pathUnderStorage) throws IOException {
+    public void unlink(@NonNull String path) throws IOException {
         try {
-            int res = mService.unlink(mId, pathUnderStorage);
+            int res = mService.unlink(mId, path);
             if (res < 0) {
                 throw new IOException("unlink() failed with errno " + -res);
             }
@@ -242,13 +256,14 @@
     /**
      * Rename an old file name to a new file name under the current storage directory.
      *
-     * @param sourcePathUnderStorage Old file path as a relative path to the storage directory.
-     * @param destPathUnderStorage   New file path as a relative path to the storage directory.
+     * @param sourcepath Old file path as a full path to the storage directory.
+     * @param destpath   New file path as a full path to the storage directory.
      */
-    public void moveFile(@NonNull String sourcePathUnderStorage,
-            @NonNull String destPathUnderStorage) throws IOException {
+    public void moveFile(@NonNull String sourcepath,
+            @NonNull String destpath) throws IOException {
+        //TODO(zyy): implement using rename(2) when confirmed that IncFS supports it.
         try {
-            int res = mService.makeLink(mId, sourcePathUnderStorage, mId, destPathUnderStorage);
+            int res = mService.makeLink(mId, sourcepath, mId, destpath);
             if (res < 0) {
                 throw new IOException("moveFile() failed at makeLink(), errno " + -res);
             }
@@ -256,7 +271,7 @@
             e.rethrowFromSystemServer();
         }
         try {
-            mService.unlink(mId, sourcePathUnderStorage);
+            mService.unlink(mId, sourcepath);
         } catch (RemoteException ignored) {
         }
     }
@@ -274,7 +289,7 @@
             throw new IOException("moveDir() requires that destination dir already exists.");
         }
         try {
-            int res = mService.makeBindMount(mId, "", destPath,
+            int res = mService.makeBindMount(mId, sourcePath, destPath,
                     IIncrementalManagerNative.BIND_PERMANENT);
             if (res < 0) {
                 throw new IOException("moveDir() failed at making bind mount, errno " + -res);
@@ -291,24 +306,24 @@
     /**
      * Checks whether a file under the current storage directory is fully loaded.
      *
-     * @param pathUnderStorage The relative path of the file.
+     * @param path The relative path of the file.
      * @return True if the file is fully loaded.
      */
-    public boolean isFileFullyLoaded(@NonNull String pathUnderStorage) {
-        return isFileRangeLoaded(pathUnderStorage, 0, -1);
+    public boolean isFileFullyLoaded(@NonNull String path) {
+        return isFileRangeLoaded(path, 0, -1);
     }
 
     /**
      * Checks whether a range in a file if loaded.
      *
-     * @param pathUnderStorage The relative path of the file.
+     * @param path The relative path of the file.
      * @param start            The starting offset of the range.
      * @param end              The ending offset of the range.
      * @return True if the file is fully loaded.
      */
-    public boolean isFileRangeLoaded(@NonNull String pathUnderStorage, long start, long end) {
+    public boolean isFileRangeLoaded(@NonNull String path, long start, long end) {
         try {
-            return mService.isFileRangeLoaded(mId, pathUnderStorage, start, end);
+            return mService.isFileRangeLoaded(mId, path, start, end);
         } catch (RemoteException e) {
             e.rethrowFromSystemServer();
             return false;
@@ -318,13 +333,65 @@
     /**
      * Returns the metadata object of an IncFs File.
      *
-     * @param pathUnderStorage The relative path of the file.
+     * @param path The relative path of the file.
      * @return Byte array that contains metadata bytes.
      */
     @Nullable
-    public byte[] getFileMetadata(@NonNull String pathUnderStorage) {
+    public byte[] getFileMetadata(@NonNull String path) {
         try {
-            return mService.getFileMetadata(mId, pathUnderStorage);
+            return mService.getMetadataByPath(mId, path);
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+            return null;
+        }
+    }
+
+    private static final int UUID_BYTE_SIZE = 16;
+
+    /**
+     * Converts UUID to a byte array usable for Incremental API calls
+     *
+     * @param id The id to convert
+     * @return Byte array that contains the same ID.
+     */
+    public static byte[] idToBytes(UUID id) {
+        if (id == null) {
+            return null;
+        }
+        final ByteBuffer buf = ByteBuffer.wrap(new byte[UUID_BYTE_SIZE]);
+        buf.putLong(id.getMostSignificantBits());
+        buf.putLong(id.getLeastSignificantBits());
+        return buf.array();
+    }
+
+    /**
+     * Converts UUID from a byte array usable for Incremental API calls
+     *
+     * @param bytes The id in byte array format, 16 bytes long
+     * @return UUID constructed from the byte array.
+     */
+    public static UUID bytesToId(byte[] bytes) {
+        if (bytes.length != UUID_BYTE_SIZE) {
+            throw new IllegalArgumentException("Expected array of size " + UUID_BYTE_SIZE
+                                               + ", got " + bytes.length);
+        }
+        final ByteBuffer buf = ByteBuffer.wrap(bytes);
+        long msb = buf.getLong();
+        long lsb = buf.getLong();
+        return new UUID(msb, lsb);
+    }
+
+    /**
+     * Returns the metadata object of an IncFs File.
+     *
+     * @param id The file id.
+     * @return Byte array that contains metadata bytes.
+     */
+    @Nullable
+    public byte[] getFileMetadata(@NonNull UUID id) {
+        try {
+            final byte[] rawId = idToBytes(id);
+            return mService.getMetadataById(mId, rawId);
         } catch (RemoteException e) {
             e.rethrowFromSystemServer();
             return null;
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index a624120..3e0b46b 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -2721,6 +2721,7 @@
                                                 }
                                             }
                                         });
+                                        currentGeneration = generation;
                                     }
                                 }
                                 if (mGenerationTracker != null && currentGeneration ==
@@ -2801,14 +2802,7 @@
                         }
                         mValues.clear();
                     } else {
-                        boolean prefixCached = false;
-                        int size = mValues.size();
-                        for (int i = 0; i < size; ++i) {
-                            if (mValues.keyAt(i).startsWith(prefix)) {
-                                prefixCached = true;
-                                break;
-                            }
-                        }
+                        boolean prefixCached = mValues.containsKey(prefix);
                         if (prefixCached) {
                             if (!names.isEmpty()) {
                                 for (String name : names) {
@@ -2817,9 +2811,11 @@
                                     }
                                 }
                             } else {
-                                for (int i = 0; i < size; ++i) {
+                                for (int i = 0; i < mValues.size(); ++i) {
                                     String key = mValues.keyAt(i);
-                                    if (key.startsWith(prefix)) {
+                                    // Explicitly exclude the prefix as it is only there to
+                                    // signal that the prefix has been cached.
+                                    if (key.startsWith(prefix) && !key.equals(prefix)) {
                                         keyValues.put(key, mValues.get(key));
                                     }
                                 }
@@ -2907,12 +2903,15 @@
                                     }
                                 }
                             });
+                            currentGeneration = generation;
                         }
                     }
                     if (mGenerationTracker != null && currentGeneration
                             == mGenerationTracker.getCurrentGeneration()) {
                         // cache the complete list of flags for the namespace
                         mValues.putAll(flagsToValues);
+                        // Adding the prefix as a signal that the prefix is cached.
+                        mValues.put(prefix, null);
                     }
                 }
                 return keyValues;
@@ -14104,7 +14103,7 @@
          * @hide
          */
         @RequiresPermission(Manifest.permission.READ_DEVICE_CONFIG)
-        static Map<String, String> getStrings(@NonNull ContentResolver resolver,
+        public static Map<String, String> getStrings(@NonNull ContentResolver resolver,
                 @NonNull String namespace, @NonNull List<String> names) {
             List<String> compositeNames = new ArrayList<>(names.size());
             for (String name : names) {
@@ -14163,8 +14162,9 @@
          * @hide
          */
         @RequiresPermission(Manifest.permission.WRITE_DEVICE_CONFIG)
-        static boolean setStrings(@NonNull ContentResolver resolver, @NonNull String namespace,
-                @NonNull Map<String, String> keyValues) throws DeviceConfig.BadConfigException {
+        public static boolean setStrings(@NonNull ContentResolver resolver,
+                @NonNull String namespace, @NonNull Map<String, String> keyValues)
+                throws DeviceConfig.BadConfigException {
             HashMap<String, String> compositeKeyValueMap = new HashMap<>(keyValues.keySet().size());
             for (Map.Entry<String, String> entry : keyValues.entrySet()) {
                 compositeKeyValueMap.put(
@@ -14241,6 +14241,12 @@
             }
         }
 
+        /** @hide */
+        public static void clearProviderForTest() {
+            sProviderHolder.clearProviderForTest();
+            sNameValueCache.clearGenerationTrackerForTest();
+        }
+
         private static String createCompositeName(@NonNull String namespace, @NonNull String name) {
             Preconditions.checkNotNull(namespace);
             Preconditions.checkNotNull(name);
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
index 9da584e..b6f5138 100644
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -1296,17 +1296,6 @@
                           "android.provider.action.EXTERNAL_PROVIDER_CHANGE";
 
             /**
-             * Same as {@link #ACTION_DEFAULT_SMS_PACKAGE_CHANGED} but it's implicit (e.g. sent to
-             * all apps) and requires
-             * {@link android.Manifest.permission#MONITOR_DEFAULT_SMS_PACKAGE} to receive.
-             *
-             * @hide
-             */
-            @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-            public static final String ACTION_DEFAULT_SMS_PACKAGE_CHANGED_INTERNAL =
-                    "android.provider.action.DEFAULT_SMS_PACKAGE_CHANGED_INTERNAL";
-
-            /**
              * Broadcast action: When SMS-MMS db is being created. If file-based encryption is
              * supported, this broadcast indicates creation of the db in credential-encrypted
              * storage. A boolean is specified in {@link #EXTRA_IS_INITIAL_CREATE} to indicate if
@@ -4038,15 +4027,6 @@
         @Retention(RetentionPolicy.SOURCE)
         public @interface EditStatus {}
 
-        /** @hide */
-        @IntDef({
-                SKIP_464XLAT_DEFAULT,
-                SKIP_464XLAT_DISABLE,
-                SKIP_464XLAT_ENABLE,
-        })
-        @Retention(RetentionPolicy.SOURCE)
-        public @interface Skip464XlatStatus {}
-
         /**
          * Compat framework change ID for the APN db read permission change.
          *
@@ -4297,6 +4277,15 @@
         public static final String LANGUAGE_CODE = "language";
 
         /**
+         * Dats coding scheme of the message.
+         * <p>
+         * The data coding scheme (dcs) value defined in 3GPP TS 23.038 section 4
+         * </p>
+         * <P>Type: INTEGER</P>
+         */
+        public static final String DATA_CODING_SCHEME = "dcs";
+
+        /**
          * Message body.
          * <P>Type: TEXT</P>
          */
@@ -4384,18 +4373,32 @@
         public static final String DEFAULT_SORT_ORDER = DELIVERY_TIME + " DESC";
 
         /**
-         * The timestamp in millisecond of when the device received the message.
+         * The timestamp in millisecond, reported by {@link System#currentTimeMillis()}, when the
+         * device received the message.
          * <P>Type: BIGINT</P>
          */
         public static final String RECEIVED_TIME = "received_time";
 
         /**
+         * The timestamp in millisecond, reported by {@link System#currentTimeMillis()}, when
+         * location was checked last time. Note this is only applicable to geo-targeting message.
+         * For non geo-targeting message. the field will be set to -1.
+         * <P>Type: BIGINT</P>
+         */
+        public static final String LOCATION_CHECK_TIME = "location_check_time";
+        /**
          * Indicates that whether the message has been broadcasted to the application.
          * <P>Type: BOOLEAN</P>
          */
         public static final String MESSAGE_BROADCASTED = "message_broadcasted";
 
         /**
+         * Indicates that whether the message has been displayed to the user.
+         * <P>Type: BOOLEAN</P>
+         */
+        public static final String MESSAGE_DISPLAYED = "message_displayed";
+
+        /**
          * The Warning Area Coordinates Elements. This element is used for geo-fencing purpose.
          *
          * The geometry and its coordinates are separated vertical bar, the first item is the
diff --git a/core/java/android/security/net/config/WfaCertificateSource.java b/core/java/android/security/net/config/WfaCertificateSource.java
index f212ef8..545e4b0 100644
--- a/core/java/android/security/net/config/WfaCertificateSource.java
+++ b/core/java/android/security/net/config/WfaCertificateSource.java
@@ -23,12 +23,15 @@
  * @hide
  */
 public final class WfaCertificateSource extends DirectoryCertificateSource {
+    private static final String CACERTS_WFA_PATH =
+            "/apex/com.android.wifi/etc/security/cacerts_wfa";
+
     private static class NoPreloadHolder {
         private static final WfaCertificateSource INSTANCE = new WfaCertificateSource();
     }
 
     private WfaCertificateSource() {
-        super(new File(System.getenv("ANDROID_ROOT") + "/etc/security/cacerts_wfa"));
+        super(new File(CACERTS_WFA_PATH));
     }
 
     public static WfaCertificateSource getInstance() {
diff --git a/core/java/android/service/autofill/FillResponse.java b/core/java/android/service/autofill/FillResponse.java
index 9333dbd..36f3a78 100644
--- a/core/java/android/service/autofill/FillResponse.java
+++ b/core/java/android/service/autofill/FillResponse.java
@@ -748,8 +748,8 @@
         parcel.writeParcelableArray(mFieldClassificationIds, flags);
         parcel.writeInt(mFlags);
         parcel.writeIntArray(mCancelIds);
-        parcel.writeInt(mRequestId);
         parcel.writeParcelable(mInlineActions, flags);
+        parcel.writeInt(mRequestId);
     }
 
     public static final @android.annotation.NonNull Parcelable.Creator<FillResponse> CREATOR =
diff --git a/core/java/android/service/quicksettings/Tile.java b/core/java/android/service/quicksettings/Tile.java
index 79c2152..40c0ac0 100644
--- a/core/java/android/service/quicksettings/Tile.java
+++ b/core/java/android/service/quicksettings/Tile.java
@@ -65,6 +65,7 @@
     private CharSequence mLabel;
     private CharSequence mSubtitle;
     private CharSequence mContentDescription;
+    private CharSequence mStateDescription;
     // Default to inactive until clients of the new API can update.
     private int mState = STATE_INACTIVE;
 
@@ -177,6 +178,14 @@
     }
 
     /**
+     * Gets the current state description for the tile.
+     */
+    @Nullable
+    public CharSequence getStateDescription() {
+        return mStateDescription;
+    }
+
+    /**
      * Sets the current content description for the tile.
      *
      * Does not take effect until {@link #updateTile()} is called.
@@ -187,6 +196,17 @@
         this.mContentDescription = contentDescription;
     }
 
+    /**
+     * Sets the current state description for the tile.
+     *
+     * Does not take effect until {@link #updateTile()} is called.
+     *
+     * @param stateDescription New state description to use.
+     */
+    public void setStateDescription(@Nullable CharSequence stateDescription) {
+        this.mStateDescription = stateDescription;
+    }
+
     @Override
     public int describeContents() {
         return 0;
@@ -215,6 +235,7 @@
         TextUtils.writeToParcel(mLabel, dest, flags);
         TextUtils.writeToParcel(mSubtitle, dest, flags);
         TextUtils.writeToParcel(mContentDescription, dest, flags);
+        TextUtils.writeToParcel(mStateDescription, dest, flags);
     }
 
     private void readFromParcel(Parcel source) {
@@ -227,6 +248,7 @@
         mLabel = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
         mSubtitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
         mContentDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
+        mStateDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
     }
 
     public static final @android.annotation.NonNull Creator<Tile> CREATOR = new Creator<Tile>() {
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index dd78c78..e9285cc 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -223,6 +223,9 @@
 
         SurfaceControl mSurfaceControl = new SurfaceControl();
 
+        // Unused relayout out-param
+        SurfaceControl mTmpSurfaceControl = new SurfaceControl();
+
         final BaseSurfaceHolder mSurfaceHolder = new BaseSurfaceHolder() {
             {
                 mRequestedFormat = PixelFormat.RGBX_8888;
@@ -902,7 +905,7 @@
                             View.VISIBLE, 0, -1, mWinFrame, mContentInsets,
                             mVisibleInsets, mStableInsets, mBackdropFrame,
                             mDisplayCutout, mMergedConfiguration, mSurfaceControl,
-                            mInsetsState, mSurfaceSize);
+                            mInsetsState, mSurfaceSize, mTmpSurfaceControl);
                     if (mSurfaceControl.isValid()) {
                         mSurfaceHolder.mSurface.copyFrom(mSurfaceControl);
                         mSurfaceControl.release();
diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java
index 6787c46..4024db1 100644
--- a/core/java/android/telephony/TelephonyRegistryManager.java
+++ b/core/java/android/telephony/TelephonyRegistryManager.java
@@ -20,8 +20,12 @@
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
+import android.compat.Compatibility;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledAfter;
 import android.content.Context;
 import android.os.Binder;
+import android.os.Build;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.telephony.Annotation.ApnType;
@@ -199,6 +203,13 @@
     }
 
     /**
+     * To check the SDK version for {@link #listenForSubscriber}.
+     */
+    @ChangeId
+    @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.P)
+    private static final long LISTEN_CODE_CHANGE = 147600208L;
+
+    /**
      * Listen for incoming subscriptions
      * @param subId Subscription ID
      * @param pkg Package name
@@ -210,6 +221,16 @@
     public void listenForSubscriber(int subId, @NonNull String pkg, @NonNull String featureId,
             @NonNull PhoneStateListener listener, int events, boolean notifyNow) {
         try {
+            // subId from PhoneStateListener is deprecated Q on forward, use the subId from
+            // TelephonyManager instance. Keep using subId from PhoneStateListener for pre-Q.
+            if (Compatibility.isChangeEnabled(LISTEN_CODE_CHANGE)) {
+                // Since mSubId in PhoneStateListener is deprecated from Q on forward, this is
+                // the only place to set mSubId and its for "informational" only.
+                listener.mSubId = (events == PhoneStateListener.LISTEN_NONE)
+                        ? SubscriptionManager.INVALID_SUBSCRIPTION_ID : subId;
+            } else if (listener.mSubId != null) {
+                subId = listener.mSubId;
+            }
             sRegistry.listenForSubscriber(
                     subId, pkg, featureId, listener.callback, events, notifyNow);
         } catch (RemoteException e) {
diff --git a/core/java/android/util/CloseGuard.java b/core/java/android/util/CloseGuard.java
index 6ac7696..ba504a3 100644
--- a/core/java/android/util/CloseGuard.java
+++ b/core/java/android/util/CloseGuard.java
@@ -26,7 +26,7 @@
  * A simple example: <pre>   {@code
  *   class Foo {
  *
- *       private final CloseGuard guard = CloseGuard.get();
+ *       private final CloseGuard guard = new CloseGuard();
  *
  *       ...
  *
@@ -64,7 +64,7 @@
  * be deferred. For example: <pre>   {@code
  *   class Bar {
  *
- *       private final CloseGuard guard = CloseGuard.get();
+ *       private final CloseGuard guard = new CloseGuard();
  *
  *       ...
  *
diff --git a/core/java/android/view/IPinnedStackController.aidl b/core/java/android/view/IPinnedStackController.aidl
index 00edb3a..cb82f16 100644
--- a/core/java/android/view/IPinnedStackController.aidl
+++ b/core/java/android/view/IPinnedStackController.aidl
@@ -53,9 +53,4 @@
      * {@param bounds} here is the final destination bounds.
      */
     void resetBoundsAnimation(in Rect bounds);
-
-    /**
-     * Reports the current default and movement bounds to controller.
-     */
-    void reportBounds(in Rect defaultBounds, in Rect movementBounds);
 }
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index e3446e1..1677357d 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -92,6 +92,9 @@
      * @param outSurface Object in which is placed the new display surface.
      * @param insetsState The current insets state in the system.
      * @param outSurfaceSize The width and height of the surface control
+     * @param outBlastSurfaceControl A BLAST SurfaceControl allocated by the WindowManager
+     * the SurfaceControl willl be managed by the client side, but the WindowManager
+     * may use it as a deferTransaction barrier.
      *
      * @return int Result flags: {@link WindowManagerGlobal#RELAYOUT_SHOW_FOCUS},
      * {@link WindowManagerGlobal#RELAYOUT_FIRST_TIME}.
@@ -103,7 +106,8 @@
             out Rect outBackdropFrame,
             out DisplayCutout.ParcelableWrapper displayCutout,
             out MergedConfiguration outMergedConfiguration, out SurfaceControl outSurfaceControl,
-            out InsetsState insetsState, out Point outSurfaceSize);
+            out InsetsState insetsState, out Point outSurfaceSize,
+            out SurfaceControl outBlastSurfaceControl);
 
     /*
      * Notify the window manager that an application is relaunching and
diff --git a/core/java/android/view/ImeInsetsSourceConsumer.java b/core/java/android/view/ImeInsetsSourceConsumer.java
index d069437..2e37751 100644
--- a/core/java/android/view/ImeInsetsSourceConsumer.java
+++ b/core/java/android/view/ImeInsetsSourceConsumer.java
@@ -87,7 +87,7 @@
      * @return @see {@link android.view.InsetsSourceConsumer.ShowResult}.
      */
     @Override
-    @ShowResult int requestShow(boolean fromIme) {
+    public @ShowResult int requestShow(boolean fromIme) {
         // TODO: ResultReceiver for IME.
         // TODO: Set mShowOnNextImeRender to automatically show IME and guard it with a flag.
         if (fromIme) {
@@ -95,7 +95,7 @@
         }
 
         return getImm().requestImeShow(null /* resultReceiver */)
-                ? ShowResult.SHOW_DELAYED : ShowResult.SHOW_FAILED;
+                ? ShowResult.IME_SHOW_DELAYED : ShowResult.IME_SHOW_FAILED;
     }
 
     /**
diff --git a/core/java/android/view/InsetsAnimationControlCallbacks.java b/core/java/android/view/InsetsAnimationControlCallbacks.java
index 27edb0b..0645c98 100644
--- a/core/java/android/view/InsetsAnimationControlCallbacks.java
+++ b/core/java/android/view/InsetsAnimationControlCallbacks.java
@@ -52,12 +52,6 @@
     void notifyFinished(InsetsAnimationControlImpl controller, boolean shown);
 
     /**
-     * Get the description of the insets state.
-     * @return {@link InsetsState} for adjusting corresponding {@link InsetsSource}.
-     */
-    InsetsState getState();
-
-    /**
      * Apply the new params to the surface.
      * @param params The {@link android.view.SyncRtSurfaceTransactionApplier.SurfaceParams} to
      *               apply.
diff --git a/core/java/android/view/InsetsAnimationControlImpl.java b/core/java/android/view/InsetsAnimationControlImpl.java
index 405eccd..e863aa0 100644
--- a/core/java/android/view/InsetsAnimationControlImpl.java
+++ b/core/java/android/view/InsetsAnimationControlImpl.java
@@ -191,13 +191,7 @@
         if (mCancelled) {
             return;
         }
-        InsetsState state = new InsetsState(mController.getState());
-        for (int i = mControls.size() - 1; i >= 0; i--) {
-            InsetsSourceControl control = mControls.valueAt(i);
-            state.getSource(control.getType()).setVisible(shown);
-        }
-        Insets insets = getInsetsFromState(state, mFrame, null /* typeSideMap */);
-        setInsetsAndAlpha(insets, 1f /* alpha */, 1f /* fraction */);
+        setInsetsAndAlpha(shown ? mShownInsets : mHiddenInsets, 1f /* alpha */, 1f /* fraction */);
         mFinished = true;
         mShownOnFinish = shown;
     }
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index c6e3835..6f76497 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -19,6 +19,7 @@
 import static android.view.InsetsState.ITYPE_IME;
 import static android.view.InsetsState.toPublicType;
 import static android.view.WindowInsets.Type.all;
+import static android.view.WindowInsets.Type.ime;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_APPEARANCE_CONTROLLED;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_BEHAVIOR_CONTROLLED;
 
@@ -31,6 +32,7 @@
 import android.annotation.Nullable;
 import android.graphics.Insets;
 import android.graphics.Rect;
+import android.os.Handler;
 import android.os.RemoteException;
 import android.util.ArraySet;
 import android.util.Log;
@@ -55,6 +57,7 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
+import java.util.function.BiFunction;
 
 /**
  * Implements {@link WindowInsetsController} on the client.
@@ -64,6 +67,7 @@
 
     private static final int ANIMATION_DURATION_SHOW_MS = 275;
     private static final int ANIMATION_DURATION_HIDE_MS = 340;
+    private static final int PENDING_CONTROL_TIMEOUT_MS = 2000;
 
     static final Interpolator INTERPOLATOR = new PathInterpolator(0.4f, 0f, 0.2f, 1f);
 
@@ -235,12 +239,36 @@
         DefaultAnimationControlListener(boolean show) {
             super(show);
         }
-
+        
         @Override
         protected void setStartingAnimation(boolean startingAnimation) {
             mStartingAnimation = startingAnimation;
         }
     }
+    /**
+     * Represents a control request that we had to defer because we are waiting for the IME to
+     * process our show request.
+     */
+    private static class PendingControlRequest {
+
+        PendingControlRequest(@InsetsType int types, WindowInsetsAnimationControlListener listener,
+                long durationMs, Interpolator interpolator, @AnimationType int animationType,
+                @LayoutInsetsDuringAnimation int layoutInsetsDuringAnimation) {
+            this.types = types;
+            this.listener = listener;
+            this.durationMs = durationMs;
+            this.interpolator = interpolator;
+            this.animationType = animationType;
+            this.layoutInsetsDuringAnimation = layoutInsetsDuringAnimation;
+        }
+
+        final @InsetsType int types;
+        final WindowInsetsAnimationControlListener listener;
+        final long durationMs;
+        final Interpolator interpolator;
+        final @AnimationType int animationType;
+        final @LayoutInsetsDuringAnimation int layoutInsetsDuringAnimation;
+    }
 
     private final String TAG = "InsetsControllerImpl";
 
@@ -248,8 +276,10 @@
     private final InsetsState mTmpState = new InsetsState();
 
     private final Rect mFrame = new Rect();
+    private final BiFunction<InsetsController, Integer, InsetsSourceConsumer> mConsumerCreator;
     private final SparseArray<InsetsSourceConsumer> mSourceConsumers = new SparseArray<>();
     private final ViewRootImpl mViewRoot;
+    private final Handler mHandler;
 
     private final SparseArray<InsetsSourceControl> mTmpControlArray = new SparseArray<>();
     private final ArrayList<RunningAnimation> mRunningAnimations = new ArrayList<>();
@@ -263,7 +293,8 @@
     private final Rect mLastLegacyContentInsets = new Rect();
     private final Rect mLastLegacyStableInsets = new Rect();
 
-    private int mPendingTypesToShow;
+    /** Pending control request that is waiting on IME to be ready to be shown */
+    private PendingControlRequest mPendingImeControlRequest;
 
     private int mLastLegacySoftInputMode;
     private int mLastLegacySystemUiFlags;
@@ -271,8 +302,26 @@
 
     private SyncRtSurfaceTransactionApplier mApplier;
 
+    private Runnable mPendingControlTimeout = this::abortPendingImeControlRequest;
+
     public InsetsController(ViewRootImpl viewRoot) {
+        this(viewRoot, (controller, type) -> {
+            if (type == ITYPE_IME) {
+                return new ImeInsetsSourceConsumer(controller.mState, Transaction::new, controller);
+            } else {
+                return new InsetsSourceConsumer(type, controller.mState, Transaction::new,
+                        controller);
+            }
+        }, viewRoot.mHandler);
+    }
+
+    @VisibleForTesting
+    public InsetsController(ViewRootImpl viewRoot,
+            BiFunction<InsetsController, Integer, InsetsSourceConsumer> consumerCreator,
+            Handler handler) {
         mViewRoot = viewRoot;
+        mConsumerCreator = consumerCreator;
+        mHandler = handler;
         mAnimCallback = () -> {
             mAnimCallbackScheduled = false;
             if (mRunningAnimations.isEmpty()) {
@@ -393,7 +442,21 @@
         show(types, false /* fromIme */);
     }
 
-    void show(@InsetsType int types, boolean fromIme) {
+    @VisibleForTesting
+    public void show(@InsetsType int types, boolean fromIme) {
+
+        // Handle pending request ready in case there was one set.
+        if (fromIme && mPendingImeControlRequest != null) {
+            PendingControlRequest pendingRequest = mPendingImeControlRequest;
+            mPendingImeControlRequest = null;
+            mHandler.removeCallbacks(mPendingControlTimeout);
+            controlAnimationUnchecked(pendingRequest.types, pendingRequest.listener, mFrame,
+                    true /* fromIme */, pendingRequest.durationMs, pendingRequest.interpolator,
+                    false /* fade */, pendingRequest.animationType,
+                    pendingRequest.layoutInsetsDuringAnimation);
+            return;
+        }
+
         // TODO: Support a ResultReceiver for IME.
         // TODO(b/123718661): Make show() work for multi-session IME.
         int typesReady = 0;
@@ -463,6 +526,7 @@
             @LayoutInsetsDuringAnimation int layoutInsetsDuringAnimation) {
         if (types == 0) {
             // nothing to animate.
+            listener.onCancelled();
             return;
         }
         cancelExistingControllers(types);
@@ -471,19 +535,18 @@
         final SparseArray<InsetsSourceControl> controls = new SparseArray<>();
 
         Pair<Integer, Boolean> typesReadyPair = collectSourceControls(
-                fromIme, internalTypes, controls, listener);
+                fromIme, internalTypes, controls);
         int typesReady = typesReadyPair.first;
-        boolean isReady = typesReadyPair.second;
-        if (!isReady) {
-            // IME isn't ready, all requested types would be shown once IME is ready.
-            mPendingTypesToShow = typesReady;
-            // TODO: listener for pending types.
+        boolean imeReady = typesReadyPair.second;
+        if (!imeReady) {
+            // IME isn't ready, all requested types will be animated once IME is ready
+            abortPendingImeControlRequest();
+            mPendingImeControlRequest = new PendingControlRequest(types, listener, durationMs,
+                    interpolator, animationType, layoutInsetsDuringAnimation);
+            mHandler.postDelayed(mPendingControlTimeout, PENDING_CONTROL_TIMEOUT_MS);
             return;
         }
 
-        // pending types from previous request.
-        typesReady = collectPendingTypes(typesReady);
-
         if (typesReady == 0) {
             listener.onCancelled();
             return;
@@ -496,13 +559,12 @@
     }
 
     /**
-     * @return Pair of (types ready to animate, is ready to animate).
+     * @return Pair of (types ready to animate, IME ready to animate).
      */
     private Pair<Integer, Boolean> collectSourceControls(boolean fromIme,
-            ArraySet<Integer> internalTypes, SparseArray<InsetsSourceControl> controls,
-            WindowInsetsAnimationControlListener listener) {
+            ArraySet<Integer> internalTypes, SparseArray<InsetsSourceControl> controls) {
         int typesReady = 0;
-        boolean isReady = true;
+        boolean imeReady = true;
         for (int i = internalTypes.size() - 1; i >= 0; i--) {
             InsetsSourceConsumer consumer = getSourceConsumer(internalTypes.valueAt(i));
             boolean setVisible = !consumer.isRequestedVisible();
@@ -512,16 +574,12 @@
                     case ShowResult.SHOW_IMMEDIATELY:
                         typesReady |= InsetsState.toPublicType(consumer.getType());
                         break;
-                    case ShowResult.SHOW_DELAYED:
-                        isReady = false;
+                    case ShowResult.IME_SHOW_DELAYED:
+                        imeReady = false;
                         break;
-                    case ShowResult.SHOW_FAILED:
+                    case ShowResult.IME_SHOW_FAILED:
                         // IME cannot be shown (since it didn't have focus), proceed
                         // with animation of other types.
-                        if (mPendingTypesToShow != 0) {
-                            // remove IME from pending because view no longer has focus.
-                            mPendingTypesToShow &= ~InsetsState.toPublicType(ITYPE_IME);
-                        }
                         break;
                 }
             } else {
@@ -538,13 +596,7 @@
                 controls.put(consumer.getType(), control);
             }
         }
-        return new Pair<>(typesReady, isReady);
-    }
-
-    private int collectPendingTypes(@InsetsType int typesReady) {
-        typesReady |= mPendingTypesToShow;
-        mPendingTypesToShow = 0;
-        return typesReady;
+        return new Pair<>(typesReady, imeReady);
     }
 
     private @LayoutInsetsDuringAnimation int getLayoutInsetsDuringAnimationMode(
@@ -577,6 +629,17 @@
                 cancelAnimation(control, true /* invokeCallback */);
             }
         }
+        if ((types & ime()) != 0) {
+            abortPendingImeControlRequest();
+        }
+    }
+
+    private void abortPendingImeControlRequest() {
+        if (mPendingImeControlRequest != null) {
+            mPendingImeControlRequest.listener.onCancelled();
+            mPendingImeControlRequest = null;
+            mHandler.removeCallbacks(mPendingControlTimeout);
+        }
     }
 
     @VisibleForTesting
@@ -608,6 +671,9 @@
                 cancelAnimation(control, true /* invokeCallback */);
             }
         }
+        if (consumer.getType() == ITYPE_IME) {
+            abortPendingImeControlRequest();
+        }
     }
 
     private void cancelAnimation(InsetsAnimationControlImpl control, boolean invokeCallback) {
@@ -635,7 +701,7 @@
         if (controller != null) {
             return controller;
         }
-        controller = createConsumerOfType(type);
+        controller = mConsumerCreator.apply(this, type);
         mSourceConsumers.put(type, controller);
         return controller;
     }
@@ -696,14 +762,6 @@
         return ANIMATION_TYPE_NONE;
     }
 
-    private InsetsSourceConsumer createConsumerOfType(int type) {
-        if (type == ITYPE_IME) {
-            return new ImeInsetsSourceConsumer(mState, Transaction::new, this);
-        } else {
-            return new InsetsSourceConsumer(type, mState, Transaction::new, this);
-        }
-    }
-
     /**
      * Sends the local visibility state back to window manager.
      */
diff --git a/core/java/android/view/InsetsSourceConsumer.java b/core/java/android/view/InsetsSourceConsumer.java
index 35a82b8..ddfd38c 100644
--- a/core/java/android/view/InsetsSourceConsumer.java
+++ b/core/java/android/view/InsetsSourceConsumer.java
@@ -36,7 +36,7 @@
 public class InsetsSourceConsumer {
 
     @Retention(RetentionPolicy.SOURCE)
-    @IntDef(value = {ShowResult.SHOW_IMMEDIATELY, ShowResult.SHOW_DELAYED, ShowResult.SHOW_FAILED})
+    @IntDef(value = {ShowResult.SHOW_IMMEDIATELY, ShowResult.IME_SHOW_DELAYED, ShowResult.IME_SHOW_FAILED})
     @interface ShowResult {
         /**
          * Window type is ready to be shown, will be shown immidiately.
@@ -46,12 +46,12 @@
          * Result will be delayed. Window needs to be prepared or request is not from controller.
          * Request will be delegated to controller and may or may not be shown.
          */
-        int SHOW_DELAYED = 1;
+        int IME_SHOW_DELAYED = 1;
         /**
          * Window will not be shown because one of the conditions couldn't be met.
          * (e.g. in IME's case, when no editor is focused.)
          */
-        int SHOW_FAILED = 2;
+        int IME_SHOW_FAILED = 2;
     }
 
     protected final InsetsController mController;
@@ -155,7 +155,8 @@
      *                       {@link android.inputmethodservice.InputMethodService}).
      * @return @see {@link ShowResult}.
      */
-    @ShowResult int requestShow(boolean fromController) {
+    @VisibleForTesting
+    public @ShowResult int requestShow(boolean fromController) {
         return ShowResult.SHOW_IMMEDIATELY;
     }
 
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index c638717..c91096e 100644
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -19,6 +19,7 @@
 import static android.view.Display.INVALID_DISPLAY;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.TestApi;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.os.Build;
@@ -1269,6 +1270,7 @@
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private int mSource;
     private int mDisplayId;
+    private @Nullable byte[] mHmac;
     @UnsupportedAppUsage
     private int mMetaState;
     @UnsupportedAppUsage
@@ -1546,6 +1548,7 @@
         mDeviceId = origEvent.mDeviceId;
         mSource = origEvent.mSource;
         mDisplayId = origEvent.mDisplayId;
+        mHmac = origEvent.mHmac == null ? null : origEvent.mHmac.clone();
         mScanCode = origEvent.mScanCode;
         mFlags = origEvent.mFlags;
         mCharacters = origEvent.mCharacters;
@@ -1573,6 +1576,7 @@
         mDeviceId = origEvent.mDeviceId;
         mSource = origEvent.mSource;
         mDisplayId = origEvent.mDisplayId;
+        mHmac = null; // Don't copy HMAC, it will be invalid because eventTime is changing
         mScanCode = origEvent.mScanCode;
         mFlags = origEvent.mFlags;
         mCharacters = origEvent.mCharacters;
@@ -1600,7 +1604,8 @@
      */
     public static KeyEvent obtain(long downTime, long eventTime, int action,
             int code, int repeat, int metaState,
-            int deviceId, int scancode, int flags, int source, int displayId, String characters) {
+            int deviceId, int scancode, int flags, int source, int displayId, @Nullable byte[] hmac,
+            String characters) {
         KeyEvent ev = obtain();
         ev.mDownTime = downTime;
         ev.mEventTime = eventTime;
@@ -1613,6 +1618,7 @@
         ev.mFlags = flags;
         ev.mSource = source;
         ev.mDisplayId = displayId;
+        ev.mHmac = hmac;
         ev.mCharacters = characters;
         return ev;
     }
@@ -1627,7 +1633,7 @@
             int code, int repeat, int metaState,
             int deviceId, int scancode, int flags, int source, String characters) {
         return obtain(downTime, eventTime, action, code, repeat, metaState, deviceId, scancode,
-                flags, source, INVALID_DISPLAY, characters);
+                flags, source, INVALID_DISPLAY, null /* hmac */, characters);
     }
 
     /**
@@ -1650,6 +1656,7 @@
         ev.mFlags = other.mFlags;
         ev.mSource = other.mSource;
         ev.mDisplayId = other.mDisplayId;
+        ev.mHmac = other.mHmac == null ? null : other.mHmac.clone();
         ev.mCharacters = other.mCharacters;
         return ev;
     }
@@ -1738,6 +1745,7 @@
         mDeviceId = origEvent.mDeviceId;
         mSource = origEvent.mSource;
         mDisplayId = origEvent.mDisplayId;
+        mHmac = null; // Don't copy the hmac, it will be invalid since action is changing
         mScanCode = origEvent.mScanCode;
         mFlags = origEvent.mFlags;
         // Don't copy mCharacters, since one way or the other we'll lose it
@@ -3091,6 +3099,7 @@
         mDeviceId = in.readInt();
         mSource = in.readInt();
         mDisplayId = in.readInt();
+        mHmac = in.createByteArray();
         mAction = in.readInt();
         mKeyCode = in.readInt();
         mRepeatCount = in.readInt();
@@ -3109,6 +3118,7 @@
         out.writeInt(mDeviceId);
         out.writeInt(mSource);
         out.writeInt(mDisplayId);
+        out.writeByteArray(mHmac);
         out.writeInt(mAction);
         out.writeInt(mKeyCode);
         out.writeInt(mRepeatCount);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index c5f4faf..5e59143 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -22,10 +22,6 @@
 import static android.util.StatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__SINGLE_TAP;
 import static android.util.StatsLog.TOUCH_GESTURE_CLASSIFIED__CLASSIFICATION__UNKNOWN_CLASSIFICATION;
 import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL;
-import static android.view.WindowInsets.Type.ime;
-import static android.view.WindowInsets.Type.systemBars;
-import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
-import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
 import static android.view.accessibility.AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED;
 
 import static java.lang.Math.max;
@@ -146,7 +142,6 @@
 import android.widget.ScrollBarDrawable;
 
 import com.android.internal.R;
-import com.android.internal.policy.DecorView;
 import com.android.internal.view.TooltipPopup;
 import com.android.internal.view.menu.MenuBuilder;
 import com.android.internal.widget.ScrollBarUtils;
@@ -21856,7 +21851,7 @@
         if (!concatMatrix &&
                 (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
                         ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
-                canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
+                canvas.quickReject(mLeft, mTop, mRight, mBottom) &&
                 (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
             mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
             return more;
@@ -22140,6 +22135,7 @@
          *      4. Draw children
          *      5. If necessary, draw the fading edges and restore layers
          *      6. Draw decorations (scrollbars for instance)
+         *      7. If necessary, draw the default focus highlight
          */
 
         // Step 1, draw the background, if needed
@@ -22346,6 +22342,9 @@
         // Step 6, draw decorations (foreground, scrollbars)
         onDrawForeground(canvas);
 
+        // Step 7, draw the default focus highlight
+        drawDefaultFocusHighlight(canvas);
+
         if (isShowingLayoutBounds()) {
             debugDrawFocus(canvas);
         }
@@ -23241,11 +23240,11 @@
     }
 
     /**
-     * Draw the default focus highlight onto the canvas.
+     * Draw the default focus highlight onto the canvas if there is one and this view is focused.
      * @param canvas the canvas where we're drawing the highlight.
      */
     private void drawDefaultFocusHighlight(Canvas canvas) {
-        if (mDefaultFocusHighlight != null) {
+        if (mDefaultFocusHighlight != null && isFocused()) {
             if (mDefaultFocusHighlightSizeChanged) {
                 mDefaultFocusHighlightSizeChanged = false;
                 final int l = mScrollX;
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 7a93dcc..841c43f 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -507,7 +507,7 @@
     @UnsupportedAppUsage
     public final Surface mSurface = new Surface();
     private final SurfaceControl mSurfaceControl = new SurfaceControl();
-    private SurfaceControl mBlastSurfaceControl;
+    private SurfaceControl mBlastSurfaceControl = new SurfaceControl();
 
     private BLASTBufferQueue mBlastBufferQueue;
 
@@ -636,6 +636,7 @@
             InputEventConsistencyVerifier.isInstrumentationEnabled() ?
                     new InputEventConsistencyVerifier(this, 0) : null;
 
+    private final InsetsController mInsetsController;
     private final ImeFocusController mImeFocusController;
 
     /**
@@ -646,7 +647,6 @@
         return mImeFocusController;
     }
 
-    private final InsetsController mInsetsController = new InsetsController(this);
 
     private final GestureExclusionTracker mGestureExclusionTracker = new GestureExclusionTracker();
 
@@ -705,6 +705,7 @@
         mFallbackEventHandler = new PhoneFallbackEventHandler(context);
         mChoreographer = Choreographer.getInstance();
         mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
+        mInsetsController = new InsetsController(this);
 
         String processorOverrideName = context.getResources().getString(
                                     R.string.config_inputEventCompatProcessorOverrideClassName);
@@ -1690,23 +1691,17 @@
                     .build();
             setBoundsLayerCrop();
             mTransaction.show(mBoundsLayer).apply();
-        }
-        return mBoundsLayer;
+        } 
+       return mBoundsLayer;
     }
 
     Surface getOrCreateBLASTSurface(int width, int height) {
         if (mSurfaceControl == null || !mSurfaceControl.isValid()) {
             return null;
         }
-        if (mBlastSurfaceControl == null) {
-            mBlastSurfaceControl = new SurfaceControl.Builder(mSurfaceSession)
-            .setParent(mSurfaceControl)
-            .setName("BLAST")
-            .setBLASTLayer()
-            .build();
+        if ((mBlastBufferQueue != null) && mBlastSurfaceControl.isValid()) {
             mBlastBufferQueue = new BLASTBufferQueue(
                 mBlastSurfaceControl, width, height);
-
         }
         mBlastBufferQueue.update(mBlastSurfaceControl, width, height);
 
@@ -3683,32 +3678,29 @@
         Trace.traceBegin(Trace.TRACE_TAG_VIEW, "draw");
 
         boolean usingAsyncReport = false;
+        boolean reportNextDraw = mReportNextDraw; // Capture the original value
         if (mAttachInfo.mThreadedRenderer != null && mAttachInfo.mThreadedRenderer.isEnabled()) {
             ArrayList<Runnable> commitCallbacks = mAttachInfo.mTreeObserver
                     .captureFrameCommitCallbacks();
-            if (mReportNextDraw) {
-                usingAsyncReport = true;
+            final boolean needFrameCompleteCallback = mNextDrawUseBLASTSyncTransaction ||
+                (commitCallbacks != null && commitCallbacks.size() > 0) ||
+                mReportNextDraw;
+            usingAsyncReport = mReportNextDraw;
+            if (needFrameCompleteCallback) {
                 final Handler handler = mAttachInfo.mHandler;
                 mAttachInfo.mThreadedRenderer.setFrameCompleteCallback((long frameNr) ->
                         handler.postAtFrontOfQueue(() -> {
                             finishBLASTSync();
-                            // TODO: Use the frame number
-                            pendingDrawFinished();
+                            if (reportNextDraw) {
+                                // TODO: Use the frame number
+                                pendingDrawFinished();
+                            }
                             if (commitCallbacks != null) {
                                 for (int i = 0; i < commitCallbacks.size(); i++) {
                                     commitCallbacks.get(i).run();
                                 }
                             }
                         }));
-            } else if (commitCallbacks != null && commitCallbacks.size() > 0) {
-                final Handler handler = mAttachInfo.mHandler;
-                mAttachInfo.mThreadedRenderer.setFrameCompleteCallback((long frameNr) ->
-                        handler.postAtFrontOfQueue(() -> {
-                            finishBLASTSync();
-                            for (int i = 0; i < commitCallbacks.size(); i++) {
-                                commitCallbacks.get(i).run();
-                            }
-                        }));
             }
         }
 
@@ -7344,7 +7336,8 @@
                 insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0, frameNumber,
                 mTmpFrame, mPendingContentInsets, mPendingVisibleInsets,
                 mPendingStableInsets, mPendingBackDropFrame, mPendingDisplayCutout,
-                mPendingMergedConfiguration, mSurfaceControl, mTempInsets, mSurfaceSize);
+                mPendingMergedConfiguration, mSurfaceControl, mTempInsets, mSurfaceSize,
+                mBlastSurfaceControl);
         if (mSurfaceControl.isValid()) {
             if (!WindowManagerGlobal.USE_BLAST_ADAPTER) {
                 mSurface.copyFrom(mSurfaceControl);
diff --git a/core/java/android/view/WindowlessWindowManager.java b/core/java/android/view/WindowlessWindowManager.java
index 9f27848..91778aa 100644
--- a/core/java/android/view/WindowlessWindowManager.java
+++ b/core/java/android/view/WindowlessWindowManager.java
@@ -161,7 +161,7 @@
             Rect outStableInsets, Rect outBackdropFrame,
             DisplayCutout.ParcelableWrapper cutout, MergedConfiguration mergedConfiguration,
             SurfaceControl outSurfaceControl, InsetsState outInsetsState,
-            Point outSurfaceSize) {
+            Point outSurfaceSize, SurfaceControl outBLASTSurfaceControl) {
         State state = null;
         synchronized (this) {
             state = mStateForWindow.get(window.asBinder());
diff --git a/core/java/android/widget/ScrollBarDrawable.java b/core/java/android/widget/ScrollBarDrawable.java
index 80e17b5..c2d4596 100644
--- a/core/java/android/widget/ScrollBarDrawable.java
+++ b/core/java/android/widget/ScrollBarDrawable.java
@@ -138,7 +138,7 @@
         }
 
         final Rect r = getBounds();
-        if (canvas.quickReject(r.left, r.top, r.right, r.bottom, Canvas.EdgeType.AA)) {
+        if (canvas.quickReject(r.left, r.top, r.right, r.bottom)) {
             return;
         }
 
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index a273633..2106712 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -210,4 +210,14 @@
      * Cancels toast with token {@code token} in {@code packageName}.
      */
     void hideToast(String packageName, IBinder token);
+
+    /**
+     * Notifies SystemUI to start tracing.
+     */
+    void startTracing();
+
+    /**
+     * Notifies SystemUI to stop tracing.
+     */
+    void stopTracing();
 }
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index a9f7b84..5ce83c2 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -78,6 +78,7 @@
             in int notificationLocation, boolean modifiedBeforeSending);
     void onNotificationSettingsViewed(String key);
     void onNotificationBubbleChanged(String key, boolean isBubble);
+    void onBubbleNotificationSuppressionChanged(String key, boolean isSuppressed);
     void grantInlineReplyUriPermission(String key, in Uri uri, in UserHandle user, String packageName);
     void clearInlineReplyUriPermissions(String key);
 
@@ -123,4 +124,19 @@
      * Dismiss the warning that the device is about to go to sleep due to user inactivity.
      */
     void dismissInattentiveSleepWarning(boolean animated);
+
+    /**
+     * Notifies SystemUI to start tracing.
+     */
+    void startTracing();
+
+    /**
+     * Notifies SystemUI to stop tracing.
+     */
+    void stopTracing();
+
+    /**
+     * Returns whether SystemUI tracing is enabled.
+     */
+    boolean isTracing();
 }
diff --git a/core/java/com/android/internal/util/TraceBuffer.java b/core/java/com/android/internal/util/TraceBuffer.java
new file mode 100644
index 0000000..fe8a59e
--- /dev/null
+++ b/core/java/com/android/internal/util/TraceBuffer.java
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.util;
+
+import android.util.proto.ProtoOutputStream;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayDeque;
+import java.util.Arrays;
+import java.util.Queue;
+import java.util.function.Consumer;
+
+/**
+ * Buffer used for tracing and logging.
+ *
+ * @param <P> The class type of the proto provider
+ * @param <S> The proto class type of the encapsulating proto
+ * @param <T> The proto class type of the individual entry protos in the buffer
+ *
+ * {@hide}
+ */
+public class TraceBuffer<P, S extends P, T extends P> {
+    private final Object mBufferLock = new Object();
+
+    private final ProtoProvider<P, S, T> mProtoProvider;
+    private final Queue<T> mBuffer = new ArrayDeque<>();
+    private final Consumer mProtoDequeuedCallback;
+    private int mBufferUsedSize;
+    private int mBufferCapacity;
+
+    /**
+     * An interface to get protos from different sources (ie. fw-proto/proto-lite/nano-proto) for
+     * the trace buffer.
+     *
+     * @param <P> The class type of the proto provider
+     * @param <S> The proto class type of the encapsulating proto
+     * @param <T> The proto class type of the individual protos in the buffer
+     */
+    public interface ProtoProvider<P, S extends P, T extends P> {
+        /**
+         * @return The size of the given proto.
+         */
+        int getItemSize(P proto);
+
+        /**
+         * @return The bytes of the given proto.
+         */
+        byte[] getBytes(P proto);
+
+        /**
+         * Writes the given encapsulating proto and buffer of protos to the given output
+         * stream.
+         */
+        void write(S encapsulatingProto, Queue<T> buffer, OutputStream os) throws IOException;
+    }
+
+    /**
+     * An implementation of the ProtoProvider that uses only the framework ProtoOutputStream.
+     */
+    private static class ProtoOutputStreamProvider implements
+            ProtoProvider<ProtoOutputStream, ProtoOutputStream, ProtoOutputStream> {
+        @Override
+        public int getItemSize(ProtoOutputStream proto) {
+            return proto.getRawSize();
+        }
+
+        @Override
+        public byte[] getBytes(ProtoOutputStream proto) {
+            return proto.getBytes();
+        }
+
+        @Override
+        public void write(ProtoOutputStream encapsulatingProto, Queue<ProtoOutputStream> buffer,
+                OutputStream os) throws IOException {
+            os.write(encapsulatingProto.getBytes());
+            for (ProtoOutputStream protoOutputStream : buffer) {
+                byte[] protoBytes = protoOutputStream.getBytes();
+                os.write(protoBytes);
+            }
+        }
+    }
+
+    public TraceBuffer(int bufferCapacity) {
+        this(bufferCapacity, new ProtoOutputStreamProvider(), null);
+    }
+
+    public TraceBuffer(int bufferCapacity, ProtoProvider protoProvider,
+            Consumer<T> protoDequeuedCallback) {
+        mBufferCapacity = bufferCapacity;
+        mProtoProvider = protoProvider;
+        mProtoDequeuedCallback = protoDequeuedCallback;
+        resetBuffer();
+    }
+
+    public int getAvailableSpace() {
+        return mBufferCapacity - mBufferUsedSize;
+    }
+
+    /**
+     * Returns buffer size.
+     */
+    public int size() {
+        return mBuffer.size();
+    }
+
+    public void setCapacity(int capacity) {
+        mBufferCapacity = capacity;
+    }
+
+    /**
+     * Inserts the specified element into this buffer.
+     *
+     * @param proto the element to add
+     * @throws IllegalStateException if the element cannot be added because it is larger
+     *                               than the buffer size.
+     */
+    public void add(T proto) {
+        int protoLength = mProtoProvider.getItemSize(proto);
+        if (protoLength > mBufferCapacity) {
+            throw new IllegalStateException("Trace object too large for the buffer. Buffer size:"
+                    + mBufferCapacity + " Object size: " + protoLength);
+        }
+        synchronized (mBufferLock) {
+            discardOldest(protoLength);
+            mBuffer.add(proto);
+            mBufferUsedSize += protoLength;
+            mBufferLock.notify();
+        }
+    }
+
+    @VisibleForTesting
+    public boolean contains(byte[] other) {
+        return mBuffer.stream()
+                .anyMatch(p -> Arrays.equals(mProtoProvider.getBytes(p), other));
+    }
+
+    /**
+     * Writes the trace buffer to disk inside the encapsulatingProto.
+     */
+    public void writeTraceToFile(File traceFile, S encapsulatingProto)
+            throws IOException {
+        synchronized (mBufferLock) {
+            traceFile.delete();
+            try (OutputStream os = new FileOutputStream(traceFile)) {
+                traceFile.setReadable(true /* readable */, false /* ownerOnly */);
+                mProtoProvider.write(encapsulatingProto, mBuffer, os);
+                os.flush();
+            }
+        }
+    }
+
+    /**
+     * Checks if the element can be added to the buffer. The element is already certain to be
+     * smaller than the overall buffer size.
+     *
+     * @param protoLength byte array representation of the Proto object to add
+     */
+    private void discardOldest(int protoLength) {
+        long availableSpace = getAvailableSpace();
+
+        while (availableSpace < protoLength) {
+
+            P item = mBuffer.poll();
+            if (item == null) {
+                throw new IllegalStateException("No element to discard from buffer");
+            }
+            mBufferUsedSize -= mProtoProvider.getItemSize(item);
+            availableSpace = getAvailableSpace();
+
+            if (mProtoDequeuedCallback != null) {
+                mProtoDequeuedCallback.accept(item);
+            }
+        }
+    }
+
+    /**
+     * Removes all elements form the buffer
+     */
+    public void resetBuffer() {
+        synchronized (mBufferLock) {
+            if (mProtoDequeuedCallback != null) {
+                for (T item : mBuffer) {
+                    mProtoDequeuedCallback.accept(item);
+                }
+            }
+            mBuffer.clear();
+            mBufferUsedSize = 0;
+        }
+    }
+
+    @VisibleForTesting
+    public int getBufferSize() {
+        return mBufferUsedSize;
+    }
+
+    /**
+     * Returns the buffer status in human-readable form.
+     */
+    public String getStatus() {
+        synchronized (mBufferLock) {
+            return "Buffer size: " + mBufferCapacity + " bytes" + "\n"
+                    + "Buffer usage: " + mBufferUsedSize + " bytes" + "\n"
+                    + "Elements in the buffer: " + mBuffer.size();
+        }
+    }
+}
diff --git a/core/jni/android_content_res_ApkAssets.cpp b/core/jni/android_content_res_ApkAssets.cpp
index 5d13cf8..b55dc68 100644
--- a/core/jni/android_content_res_ApkAssets.cpp
+++ b/core/jni/android_content_res_ApkAssets.cpp
@@ -221,7 +221,7 @@
     return nullptr;
   }
 
-  jstring actor_string = env->NewStringUTF(actor->first.c_str());
+  jstring actor_string = env->NewStringUTF(actor->second.c_str());
   if (env->ExceptionCheck() || actor_string == nullptr) {
     jniThrowException(env, "java/io/IOException", "Error reading overlayable from APK");
     return 0;
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index fb8e633..e77c25e 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -537,9 +537,10 @@
         LOGDEATH("Receiving binderDied() on JavaDeathRecipient %p\n", this);
         if (mObject != NULL) {
             JNIEnv* env = javavm_to_jnienv(mVM);
-            jobject jBinderProxy = javaObjectForIBinder(env, who.promote());
+            ScopedLocalRef<jobject> jBinderProxy(env, javaObjectForIBinder(env, who.promote()));
             env->CallStaticVoidMethod(gBinderProxyOffsets.mClass,
-                                      gBinderProxyOffsets.mSendDeathNotice, mObject, jBinderProxy);
+                                      gBinderProxyOffsets.mSendDeathNotice, mObject,
+                                      jBinderProxy.get());
             if (env->ExceptionCheck()) {
                 jthrowable excep = env->ExceptionOccurred();
                 report_exception(env, excep,
diff --git a/core/jni/android_view_InputEventSender.cpp b/core/jni/android_view_InputEventSender.cpp
index f90d1cf..84acf9a 100644
--- a/core/jni/android_view_InputEventSender.cpp
+++ b/core/jni/android_view_InputEventSender.cpp
@@ -113,10 +113,13 @@
     }
 
     uint32_t publishedSeq = mNextPublishedSeq++;
-    status_t status = mInputPublisher.publishKeyEvent(publishedSeq,
-            event->getDeviceId(), event->getSource(), event->getDisplayId(), event->getAction(),
-            event->getFlags(), event->getKeyCode(), event->getScanCode(), event->getMetaState(),
-            event->getRepeatCount(), event->getDownTime(), event->getEventTime());
+    status_t status =
+            mInputPublisher.publishKeyEvent(publishedSeq, event->getDeviceId(), event->getSource(),
+                                            event->getDisplayId(), event->getHmac(),
+                                            event->getAction(), event->getFlags(),
+                                            event->getKeyCode(), event->getScanCode(),
+                                            event->getMetaState(), event->getRepeatCount(),
+                                            event->getDownTime(), event->getEventTime());
     if (status) {
         ALOGW("Failed to send key event on channel '%s'.  status=%d",
                 getInputChannelName().c_str(), status);
@@ -134,17 +137,24 @@
     uint32_t publishedSeq;
     for (size_t i = 0; i <= event->getHistorySize(); i++) {
         publishedSeq = mNextPublishedSeq++;
-        status_t status = mInputPublisher.publishMotionEvent(publishedSeq,
-                event->getDeviceId(), event->getSource(), event->getDisplayId(),
-                event->getAction(), event->getActionButton(), event->getFlags(),
-                event->getEdgeFlags(), event->getMetaState(), event->getButtonState(),
-                event->getClassification(),
-                event->getXOffset(), event->getYOffset(),
-                event->getXPrecision(), event->getYPrecision(),
-                event->getRawXCursorPosition(), event->getRawYCursorPosition(),
-                event->getDownTime(), event->getHistoricalEventTime(i),
-                event->getPointerCount(), event->getPointerProperties(),
-                event->getHistoricalRawPointerCoords(0, i));
+        status_t status =
+                mInputPublisher.publishMotionEvent(publishedSeq, event->getDeviceId(),
+                                                   event->getSource(), event->getDisplayId(),
+                                                   event->getHmac(), event->getAction(),
+                                                   event->getActionButton(), event->getFlags(),
+                                                   event->getEdgeFlags(), event->getMetaState(),
+                                                   event->getButtonState(),
+                                                   event->getClassification(), event->getXScale(),
+                                                   event->getYScale(), event->getXOffset(),
+                                                   event->getYOffset(), event->getXPrecision(),
+                                                   event->getYPrecision(),
+                                                   event->getRawXCursorPosition(),
+                                                   event->getRawYCursorPosition(),
+                                                   event->getDownTime(),
+                                                   event->getHistoricalEventTime(i),
+                                                   event->getPointerCount(),
+                                                   event->getPointerProperties(),
+                                                   event->getHistoricalRawPointerCoords(0, i));
         if (status) {
             ALOGW("Failed to send motion event sample on channel '%s'.  status=%d",
                     getInputChannelName().c_str(), status);
diff --git a/core/jni/android_view_KeyEvent.cpp b/core/jni/android_view_KeyEvent.cpp
index f010772..57979bd 100644
--- a/core/jni/android_view_KeyEvent.cpp
+++ b/core/jni/android_view_KeyEvent.cpp
@@ -20,15 +20,53 @@
 
 #include <android_runtime/AndroidRuntime.h>
 #include <android_runtime/Log.h>
-#include <utils/Log.h>
 #include <input/Input.h>
+#include <nativehelper/ScopedPrimitiveArray.h>
 #include <nativehelper/ScopedUtfChars.h>
+#include <utils/Log.h>
+#include <optional>
 #include "android_view_KeyEvent.h"
 
 #include "core_jni_helpers.h"
 
 namespace android {
 
+/**
+ * Convert an std::array of bytes into a Java object.
+ */
+template <size_t N>
+static ScopedLocalRef<jbyteArray> toJbyteArray(JNIEnv* env, const std::array<uint8_t, N>& data) {
+    ScopedLocalRef<jbyteArray> array(env, env->NewByteArray(N));
+    if (array.get() == nullptr) {
+        jniThrowException(env, "java/lang/OutOfMemoryError", nullptr);
+        return array;
+    }
+    static_assert(sizeof(char) == sizeof(uint8_t));
+    env->SetByteArrayRegion(array.get(), 0, N, reinterpret_cast<const signed char*>(data.data()));
+    return array;
+}
+
+/**
+ * Convert a Java object into an std::array of bytes of size N.
+ * If the object is null,  or the length is unexpected, return std::nullopt.
+ */
+template <size_t N>
+static std::optional<std::array<uint8_t, N>> fromJobject(JNIEnv* env, jobject object) {
+    if (object == nullptr) {
+        return std::nullopt;
+    }
+    jbyteArray javaArray = reinterpret_cast<jbyteArray>(object);
+    ScopedByteArrayRO bytes(env, javaArray);
+    if (bytes.size() != N) {
+        ALOGE("Could not initialize array from java object, expected length %zu but got %zu", N,
+              bytes.size());
+        return std::nullopt;
+    }
+    std::array<uint8_t, N> array;
+    std::move(bytes.get(), bytes.get() + N, array.begin());
+    return array;
+}
+
 // ----------------------------------------------------------------------------
 
 static struct {
@@ -40,6 +78,7 @@
     jfieldID mDeviceId;
     jfieldID mSource;
     jfieldID mDisplayId;
+    jfieldID mHmac;
     jfieldID mMetaState;
     jfieldID mAction;
     jfieldID mKeyCode;
@@ -54,20 +93,16 @@
 // ----------------------------------------------------------------------------
 
 jobject android_view_KeyEvent_fromNative(JNIEnv* env, const KeyEvent* event) {
-    jobject eventObj = env->CallStaticObjectMethod(gKeyEventClassInfo.clazz,
-            gKeyEventClassInfo.obtain,
-            nanoseconds_to_milliseconds(event->getDownTime()),
-            nanoseconds_to_milliseconds(event->getEventTime()),
-            event->getAction(),
-            event->getKeyCode(),
-            event->getRepeatCount(),
-            event->getMetaState(),
-            event->getDeviceId(),
-            event->getScanCode(),
-            event->getFlags(),
-            event->getSource(),
-            event->getDisplayId(),
-            NULL);
+    ScopedLocalRef<jbyteArray> hmac = toJbyteArray(env, event->getHmac());
+    jobject eventObj =
+            env->CallStaticObjectMethod(gKeyEventClassInfo.clazz, gKeyEventClassInfo.obtain,
+                                        nanoseconds_to_milliseconds(event->getDownTime()),
+                                        nanoseconds_to_milliseconds(event->getEventTime()),
+                                        event->getAction(), event->getKeyCode(),
+                                        event->getRepeatCount(), event->getMetaState(),
+                                        event->getDeviceId(), event->getScanCode(),
+                                        event->getFlags(), event->getSource(),
+                                        event->getDisplayId(), hmac.get(), NULL);
     if (env->ExceptionCheck()) {
         ALOGE("An exception occurred while obtaining a key event.");
         LOGE_EX(env);
@@ -82,6 +117,11 @@
     jint deviceId = env->GetIntField(eventObj, gKeyEventClassInfo.mDeviceId);
     jint source = env->GetIntField(eventObj, gKeyEventClassInfo.mSource);
     jint displayId = env->GetIntField(eventObj, gKeyEventClassInfo.mDisplayId);
+    jobject hmacObj = env->GetObjectField(eventObj, gKeyEventClassInfo.mHmac);
+    std::optional<std::array<uint8_t, 32>> hmac = fromJobject<32>(env, hmacObj);
+    if (!hmac) {
+        hmac = INVALID_HMAC;
+    }
     jint metaState = env->GetIntField(eventObj, gKeyEventClassInfo.mMetaState);
     jint action = env->GetIntField(eventObj, gKeyEventClassInfo.mAction);
     jint keyCode = env->GetIntField(eventObj, gKeyEventClassInfo.mKeyCode);
@@ -91,10 +131,9 @@
     jlong downTime = env->GetLongField(eventObj, gKeyEventClassInfo.mDownTime);
     jlong eventTime = env->GetLongField(eventObj, gKeyEventClassInfo.mEventTime);
 
-    event->initialize(deviceId, source, displayId, action, flags, keyCode, scanCode, metaState,
-            repeatCount,
-            milliseconds_to_nanoseconds(downTime),
-            milliseconds_to_nanoseconds(eventTime));
+    event->initialize(deviceId, source, displayId, *hmac, action, flags, keyCode, scanCode,
+                      metaState, repeatCount, milliseconds_to_nanoseconds(downTime),
+                      milliseconds_to_nanoseconds(eventTime));
     return OK;
 }
 
@@ -134,8 +173,9 @@
     jclass clazz = FindClassOrDie(env, "android/view/KeyEvent");
     gKeyEventClassInfo.clazz = MakeGlobalRefOrDie(env, clazz);
 
-    gKeyEventClassInfo.obtain = GetStaticMethodIDOrDie(env, gKeyEventClassInfo.clazz,
-            "obtain", "(JJIIIIIIIIILjava/lang/String;)Landroid/view/KeyEvent;");
+    gKeyEventClassInfo.obtain =
+            GetStaticMethodIDOrDie(env, gKeyEventClassInfo.clazz, "obtain",
+                                   "(JJIIIIIIIII[BLjava/lang/String;)Landroid/view/KeyEvent;");
     gKeyEventClassInfo.recycle = GetMethodIDOrDie(env, gKeyEventClassInfo.clazz,
             "recycle", "()V");
 
@@ -143,6 +183,7 @@
     gKeyEventClassInfo.mSource = GetFieldIDOrDie(env, gKeyEventClassInfo.clazz, "mSource", "I");
     gKeyEventClassInfo.mDisplayId = GetFieldIDOrDie(env, gKeyEventClassInfo.clazz, "mDisplayId",
                                                     "I");
+    gKeyEventClassInfo.mHmac = GetFieldIDOrDie(env, gKeyEventClassInfo.clazz, "mHmac", "[B");
     gKeyEventClassInfo.mMetaState = GetFieldIDOrDie(env, gKeyEventClassInfo.clazz, "mMetaState",
                                                     "I");
     gKeyEventClassInfo.mAction = GetFieldIDOrDie(env, gKeyEventClassInfo.clazz, "mAction", "I");
diff --git a/core/jni/android_view_KeyEvent.h b/core/jni/android_view_KeyEvent.h
index 586eb2f..dab6bb7 100644
--- a/core/jni/android_view_KeyEvent.h
+++ b/core/jni/android_view_KeyEvent.h
@@ -42,4 +42,4 @@
 
 } // namespace android
 
-#endif // _ANDROID_OS_KEYEVENT_H
+#endif // _ANDROID_VIEW_KEYEVENT_H
diff --git a/core/jni/android_view_MotionEvent.cpp b/core/jni/android_view_MotionEvent.cpp
index feb9fe3..3335fb2 100644
--- a/core/jni/android_view_MotionEvent.cpp
+++ b/core/jni/android_view_MotionEvent.cpp
@@ -330,14 +330,12 @@
 
 // ----------------------------------------------------------------------------
 
-static jlong android_view_MotionEvent_nativeInitialize(JNIEnv* env, jclass clazz,
-        jlong nativePtr,
-        jint deviceId, jint source, jint displayId, jint action, jint flags, jint edgeFlags,
-        jint metaState, jint buttonState, jint classification,
-        jfloat xOffset, jfloat yOffset, jfloat xPrecision, jfloat yPrecision,
-        jlong downTimeNanos, jlong eventTimeNanos,
-        jint pointerCount, jobjectArray pointerPropertiesObjArray,
-        jobjectArray pointerCoordsObjArray) {
+static jlong android_view_MotionEvent_nativeInitialize(
+        JNIEnv* env, jclass clazz, jlong nativePtr, jint deviceId, jint source, jint displayId,
+        jint action, jint flags, jint edgeFlags, jint metaState, jint buttonState,
+        jint classification, jfloat xOffset, jfloat yOffset, jfloat xPrecision, jfloat yPrecision,
+        jlong downTimeNanos, jlong eventTimeNanos, jint pointerCount,
+        jobjectArray pointerPropertiesObjArray, jobjectArray pointerCoordsObjArray) {
     if (!validatePointerCount(env, pointerCount)
             || !validatePointerPropertiesArray(env, pointerPropertiesObjArray, pointerCount)
             || !validatePointerCoordsObjArray(env, pointerCoordsObjArray, pointerCount)) {
@@ -371,11 +369,12 @@
         env->DeleteLocalRef(pointerCoordsObj);
     }
 
-    event->initialize(deviceId, source, displayId, action, 0, flags, edgeFlags, metaState,
-            buttonState, static_cast<MotionClassification>(classification),
-            xOffset, yOffset, xPrecision, yPrecision,
-            AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
-            downTimeNanos, eventTimeNanos, pointerCount, pointerProperties, rawPointerCoords);
+    event->initialize(deviceId, source, displayId, INVALID_HMAC, action, 0, flags, edgeFlags,
+                      metaState, buttonState, static_cast<MotionClassification>(classification),
+                      1 /*xScale*/, 1 /*yScale*/, xOffset, yOffset, xPrecision, yPrecision,
+                      AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+                      downTimeNanos, eventTimeNanos, pointerCount, pointerProperties,
+                      rawPointerCoords);
 
     return reinterpret_cast<jlong>(event);
 
@@ -757,155 +756,76 @@
 // ----------------------------------------------------------------------------
 
 static const JNINativeMethod gMotionEventMethods[] = {
-    /* name, signature, funcPtr */
-    { "nativeInitialize",
-            "(JIIIIIIIIIFFFFJJI[Landroid/view/MotionEvent$PointerProperties;"
-                    "[Landroid/view/MotionEvent$PointerCoords;)J",
-            (void*)android_view_MotionEvent_nativeInitialize },
-    { "nativeDispose",
-            "(J)V",
-            (void*)android_view_MotionEvent_nativeDispose },
-    { "nativeAddBatch",
-            "(JJ[Landroid/view/MotionEvent$PointerCoords;I)V",
-            (void*)android_view_MotionEvent_nativeAddBatch },
-    { "nativeReadFromParcel",
-            "(JLandroid/os/Parcel;)J",
-            (void*)android_view_MotionEvent_nativeReadFromParcel },
-    { "nativeWriteToParcel",
-            "(JLandroid/os/Parcel;)V",
-            (void*)android_view_MotionEvent_nativeWriteToParcel },
-    { "nativeAxisToString", "(I)Ljava/lang/String;",
-            (void*)android_view_MotionEvent_nativeAxisToString },
-    { "nativeAxisFromString", "(Ljava/lang/String;)I",
-            (void*)android_view_MotionEvent_nativeAxisFromString },
-    { "nativeGetPointerProperties",
-            "(JILandroid/view/MotionEvent$PointerProperties;)V",
-            (void*)android_view_MotionEvent_nativeGetPointerProperties },
-    { "nativeGetPointerCoords",
-            "(JIILandroid/view/MotionEvent$PointerCoords;)V",
-            (void*)android_view_MotionEvent_nativeGetPointerCoords },
+        /* name, signature, funcPtr */
+        {"nativeInitialize",
+         "(JIIIIIIIIIFFFFJJI[Landroid/view/MotionEvent$PointerProperties;"
+         "[Landroid/view/MotionEvent$PointerCoords;)J",
+         (void*)android_view_MotionEvent_nativeInitialize},
+        {"nativeDispose", "(J)V", (void*)android_view_MotionEvent_nativeDispose},
+        {"nativeAddBatch", "(JJ[Landroid/view/MotionEvent$PointerCoords;I)V",
+         (void*)android_view_MotionEvent_nativeAddBatch},
+        {"nativeReadFromParcel", "(JLandroid/os/Parcel;)J",
+         (void*)android_view_MotionEvent_nativeReadFromParcel},
+        {"nativeWriteToParcel", "(JLandroid/os/Parcel;)V",
+         (void*)android_view_MotionEvent_nativeWriteToParcel},
+        {"nativeAxisToString", "(I)Ljava/lang/String;",
+         (void*)android_view_MotionEvent_nativeAxisToString},
+        {"nativeAxisFromString", "(Ljava/lang/String;)I",
+         (void*)android_view_MotionEvent_nativeAxisFromString},
+        {"nativeGetPointerProperties", "(JILandroid/view/MotionEvent$PointerProperties;)V",
+         (void*)android_view_MotionEvent_nativeGetPointerProperties},
+        {"nativeGetPointerCoords", "(JIILandroid/view/MotionEvent$PointerCoords;)V",
+         (void*)android_view_MotionEvent_nativeGetPointerCoords},
 
-    // --------------- @FastNative ----------------------
-    { "nativeGetPointerId",
-            "(JI)I",
-            (void*)android_view_MotionEvent_nativeGetPointerId },
-    { "nativeGetToolType",
-            "(JI)I",
-            (void*)android_view_MotionEvent_nativeGetToolType },
-    { "nativeGetEventTimeNanos",
-            "(JI)J",
-            (void*)android_view_MotionEvent_nativeGetEventTimeNanos },
-    { "nativeGetRawAxisValue",
-            "(JIII)F",
-            (void*)android_view_MotionEvent_nativeGetRawAxisValue },
-    { "nativeGetAxisValue",
-            "(JIII)F",
-            (void*)android_view_MotionEvent_nativeGetAxisValue },
-    { "nativeTransform",
-            "(JLandroid/graphics/Matrix;)V",
-            (void*)android_view_MotionEvent_nativeTransform },
+        // --------------- @FastNative ----------------------
+        {"nativeGetPointerId", "(JI)I", (void*)android_view_MotionEvent_nativeGetPointerId},
+        {"nativeGetToolType", "(JI)I", (void*)android_view_MotionEvent_nativeGetToolType},
+        {"nativeGetEventTimeNanos", "(JI)J",
+         (void*)android_view_MotionEvent_nativeGetEventTimeNanos},
+        {"nativeGetRawAxisValue", "(JIII)F", (void*)android_view_MotionEvent_nativeGetRawAxisValue},
+        {"nativeGetAxisValue", "(JIII)F", (void*)android_view_MotionEvent_nativeGetAxisValue},
+        {"nativeTransform", "(JLandroid/graphics/Matrix;)V",
+         (void*)android_view_MotionEvent_nativeTransform},
 
-    // --------------- @CriticalNative ------------------
+        // --------------- @CriticalNative ------------------
 
-    { "nativeCopy",
-            "(JJZ)J",
-            (void*)android_view_MotionEvent_nativeCopy },
-    { "nativeGetDeviceId",
-            "(J)I",
-            (void*)android_view_MotionEvent_nativeGetDeviceId },
-    { "nativeGetSource",
-            "(J)I",
-            (void*)android_view_MotionEvent_nativeGetSource },
-    { "nativeSetSource",
-            "(JI)V",
-            (void*)android_view_MotionEvent_nativeSetSource },
-    { "nativeGetDisplayId",
-            "(J)I",
-            (void*)android_view_MotionEvent_nativeGetDisplayId },
-    { "nativeSetDisplayId",
-            "(JI)V",
-            (void*)android_view_MotionEvent_nativeSetDisplayId },
-    { "nativeGetAction",
-            "(J)I",
-            (void*)android_view_MotionEvent_nativeGetAction },
-    { "nativeSetAction",
-            "(JI)V",
-            (void*)android_view_MotionEvent_nativeSetAction },
-    { "nativeGetActionButton",
-            "(J)I",
-            (void*)android_view_MotionEvent_nativeGetActionButton},
-    { "nativeSetActionButton",
-            "(JI)V",
-            (void*)android_view_MotionEvent_nativeSetActionButton},
-    { "nativeIsTouchEvent",
-            "(J)Z",
-            (void*)android_view_MotionEvent_nativeIsTouchEvent },
-    { "nativeGetFlags",
-            "(J)I",
-            (void*)android_view_MotionEvent_nativeGetFlags },
-    { "nativeSetFlags",
-            "(JI)V",
-            (void*)android_view_MotionEvent_nativeSetFlags },
-    { "nativeGetEdgeFlags",
-            "(J)I",
-            (void*)android_view_MotionEvent_nativeGetEdgeFlags },
-    { "nativeSetEdgeFlags",
-            "(JI)V",
-            (void*)android_view_MotionEvent_nativeSetEdgeFlags },
-    { "nativeGetMetaState",
-            "(J)I",
-            (void*)android_view_MotionEvent_nativeGetMetaState },
-    { "nativeGetButtonState",
-            "(J)I",
-            (void*)android_view_MotionEvent_nativeGetButtonState },
-    { "nativeSetButtonState",
-            "(JI)V",
-            (void*)android_view_MotionEvent_nativeSetButtonState },
-    { "nativeGetClassification",
-            "(J)I",
-            (void*)android_view_MotionEvent_nativeGetClassification },
-    { "nativeOffsetLocation",
-            "(JFF)V",
-            (void*)android_view_MotionEvent_nativeOffsetLocation },
-    { "nativeGetXOffset",
-            "(J)F",
-            (void*)android_view_MotionEvent_nativeGetXOffset },
-    { "nativeGetYOffset",
-            "(J)F",
-            (void*)android_view_MotionEvent_nativeGetYOffset },
-    { "nativeGetXPrecision",
-            "(J)F",
-            (void*)android_view_MotionEvent_nativeGetXPrecision },
-    { "nativeGetYPrecision",
-            "(J)F",
-            (void*)android_view_MotionEvent_nativeGetYPrecision },
-    { "nativeGetXCursorPosition",
-            "(J)F",
-            (void*)android_view_MotionEvent_nativeGetXCursorPosition },
-    { "nativeGetYCursorPosition",
-            "(J)F",
-            (void*)android_view_MotionEvent_nativeGetYCursorPosition },
-    { "nativeSetCursorPosition",
-            "(JFF)V",
-            (void*)android_view_MotionEvent_nativeSetCursorPosition },
-    { "nativeGetDownTimeNanos",
-            "(J)J",
-            (void*)android_view_MotionEvent_nativeGetDownTimeNanos },
-    { "nativeSetDownTimeNanos",
-            "(JJ)V",
-            (void*)android_view_MotionEvent_nativeSetDownTimeNanos },
-    { "nativeGetPointerCount",
-            "(J)I",
-            (void*)android_view_MotionEvent_nativeGetPointerCount },
-    { "nativeFindPointerIndex",
-            "(JI)I",
-            (void*)android_view_MotionEvent_nativeFindPointerIndex },
-    { "nativeGetHistorySize",
-            "(J)I",
-            (void*)android_view_MotionEvent_nativeGetHistorySize },
-    { "nativeScale",
-            "(JF)V",
-            (void*)android_view_MotionEvent_nativeScale },
+        {"nativeCopy", "(JJZ)J", (void*)android_view_MotionEvent_nativeCopy},
+        {"nativeGetDeviceId", "(J)I", (void*)android_view_MotionEvent_nativeGetDeviceId},
+        {"nativeGetSource", "(J)I", (void*)android_view_MotionEvent_nativeGetSource},
+        {"nativeSetSource", "(JI)V", (void*)android_view_MotionEvent_nativeSetSource},
+        {"nativeGetDisplayId", "(J)I", (void*)android_view_MotionEvent_nativeGetDisplayId},
+        {"nativeSetDisplayId", "(JI)V", (void*)android_view_MotionEvent_nativeSetDisplayId},
+        {"nativeGetAction", "(J)I", (void*)android_view_MotionEvent_nativeGetAction},
+        {"nativeSetAction", "(JI)V", (void*)android_view_MotionEvent_nativeSetAction},
+        {"nativeGetActionButton", "(J)I", (void*)android_view_MotionEvent_nativeGetActionButton},
+        {"nativeSetActionButton", "(JI)V", (void*)android_view_MotionEvent_nativeSetActionButton},
+        {"nativeIsTouchEvent", "(J)Z", (void*)android_view_MotionEvent_nativeIsTouchEvent},
+        {"nativeGetFlags", "(J)I", (void*)android_view_MotionEvent_nativeGetFlags},
+        {"nativeSetFlags", "(JI)V", (void*)android_view_MotionEvent_nativeSetFlags},
+        {"nativeGetEdgeFlags", "(J)I", (void*)android_view_MotionEvent_nativeGetEdgeFlags},
+        {"nativeSetEdgeFlags", "(JI)V", (void*)android_view_MotionEvent_nativeSetEdgeFlags},
+        {"nativeGetMetaState", "(J)I", (void*)android_view_MotionEvent_nativeGetMetaState},
+        {"nativeGetButtonState", "(J)I", (void*)android_view_MotionEvent_nativeGetButtonState},
+        {"nativeSetButtonState", "(JI)V", (void*)android_view_MotionEvent_nativeSetButtonState},
+        {"nativeGetClassification", "(J)I",
+         (void*)android_view_MotionEvent_nativeGetClassification},
+        {"nativeOffsetLocation", "(JFF)V", (void*)android_view_MotionEvent_nativeOffsetLocation},
+        {"nativeGetXOffset", "(J)F", (void*)android_view_MotionEvent_nativeGetXOffset},
+        {"nativeGetYOffset", "(J)F", (void*)android_view_MotionEvent_nativeGetYOffset},
+        {"nativeGetXPrecision", "(J)F", (void*)android_view_MotionEvent_nativeGetXPrecision},
+        {"nativeGetYPrecision", "(J)F", (void*)android_view_MotionEvent_nativeGetYPrecision},
+        {"nativeGetXCursorPosition", "(J)F",
+         (void*)android_view_MotionEvent_nativeGetXCursorPosition},
+        {"nativeGetYCursorPosition", "(J)F",
+         (void*)android_view_MotionEvent_nativeGetYCursorPosition},
+        {"nativeSetCursorPosition", "(JFF)V",
+         (void*)android_view_MotionEvent_nativeSetCursorPosition},
+        {"nativeGetDownTimeNanos", "(J)J", (void*)android_view_MotionEvent_nativeGetDownTimeNanos},
+        {"nativeSetDownTimeNanos", "(JJ)V", (void*)android_view_MotionEvent_nativeSetDownTimeNanos},
+        {"nativeGetPointerCount", "(J)I", (void*)android_view_MotionEvent_nativeGetPointerCount},
+        {"nativeFindPointerIndex", "(JI)I", (void*)android_view_MotionEvent_nativeFindPointerIndex},
+        {"nativeGetHistorySize", "(J)I", (void*)android_view_MotionEvent_nativeGetHistorySize},
+        {"nativeScale", "(JF)V", (void*)android_view_MotionEvent_nativeScale},
 };
 
 int register_android_view_MotionEvent(JNIEnv* env) {
diff --git a/core/jni/android_view_MotionEvent.h b/core/jni/android_view_MotionEvent.h
index 0cf1fb2..9ce4bf3 100644
--- a/core/jni/android_view_MotionEvent.h
+++ b/core/jni/android_view_MotionEvent.h
@@ -38,4 +38,4 @@
 
 } // namespace android
 
-#endif // _ANDROID_OS_KEYEVENT_H
+#endif // _ANDROID_VIEW_MOTIONEVENT_H
diff --git a/core/proto/android/server/activitymanagerservice.proto b/core/proto/android/server/activitymanagerservice.proto
index 60f2fc8..1426932 100644
--- a/core/proto/android/server/activitymanagerservice.proto
+++ b/core/proto/android/server/activitymanagerservice.proto
@@ -109,7 +109,7 @@
     // To be removed soon.
     optional .com.android.server.wm.ConfigurationContainerProto configuration_container = 1 [deprecated=true];
     optional int32 id = 2;
-    repeated ActivityRecordProto activities = 3;
+    repeated .com.android.server.wm.ActivityRecordProto activities = 3;
     optional int32 stack_id = 4;
     optional .android.graphics.RectProto last_non_fullscreen_bounds = 5;
     optional string real_activity = 6;
@@ -123,21 +123,6 @@
     optional .com.android.server.wm.TaskProto task = 14;
 }
 
-message ActivityRecordProto {
-    option (.android.msg_privacy).dest = DEST_AUTOMATIC;
-
-    // To be removed soon.
-    optional .com.android.server.wm.ConfigurationContainerProto configuration_container = 1 [deprecated=true];
-    optional .com.android.server.wm.IdentifierProto identifier = 2;
-    optional string state = 3;
-    optional bool visible_requested = 4;
-    optional bool front_of_task = 5;
-    optional int32 proc_id = 6;
-    optional bool translucent = 7;
-    optional .com.android.server.wm.AppWindowTokenProto app_window_token = 8;
-    optional bool visible = 9;
-}
-
 message KeyguardControllerProto {
     option (.android.msg_privacy).dest = DEST_AUTOMATIC;
 
diff --git a/core/proto/android/server/windowmanagerservice.proto b/core/proto/android/server/windowmanagerservice.proto
index 0c74842..c0743e5 100644
--- a/core/proto/android/server/windowmanagerservice.proto
+++ b/core/proto/android/server/windowmanagerservice.proto
@@ -147,7 +147,8 @@
     optional int32 id = 2;
     repeated StackProto stacks = 3;
     optional DockedStackDividerControllerProto docked_stack_divider_controller = 4;
-    optional PinnedStackControllerProto pinned_stack_controller = 5;
+    // Will be removed soon.
+    optional PinnedStackControllerProto pinned_stack_controller = 5 [deprecated=true];
     /* non app windows */
     repeated WindowTokenProto above_app_windows = 6;
     repeated WindowTokenProto below_app_windows = 7;
@@ -184,8 +185,8 @@
 message PinnedStackControllerProto {
     option (.android.msg_privacy).dest = DEST_AUTOMATIC;
 
-    optional .android.graphics.RectProto default_bounds = 1;
-    optional .android.graphics.RectProto movement_bounds = 2;
+    optional .android.graphics.RectProto default_bounds = 1 [deprecated=true];
+    optional .android.graphics.RectProto movement_bounds = 2 [deprecated=true];
 }
 
 /* represents TaskStack */
@@ -213,7 +214,7 @@
 
     optional WindowContainerProto window_container = 1;
     optional int32 id = 2;
-    repeated AppWindowTokenProto app_window_tokens = 3;
+    repeated ActivityRecordProto activity = 3;
     optional bool fills_parent = 4;
     optional .android.graphics.RectProto bounds = 5;
     optional .android.graphics.RectProto displayed_bounds = 6;
@@ -223,12 +224,12 @@
     optional int32 surface_height = 9;
 }
 
-/* represents AppWindowToken */
-message AppWindowTokenProto {
+/* represents ActivityRecordProto */
+message ActivityRecordProto {
     option (.android.msg_privacy).dest = DEST_AUTOMATIC;
 
-    /* obtained from ActivityRecord */
     optional string name = 1 [ (.android.privacy).dest = DEST_EXPLICIT ];
+
     optional WindowTokenProto window_token = 2;
     optional bool last_surface_showing = 3;
     optional bool is_waiting_for_transition_start = 4;
@@ -253,6 +254,13 @@
     optional bool visible_set_from_transferred_starting_window = 22;
     repeated .android.graphics.RectProto frozen_bounds = 23;
     optional bool visible = 24;
+    // To be removed soon.
+    optional .com.android.server.wm.ConfigurationContainerProto configuration_container = 25 [deprecated=true];
+    optional .com.android.server.wm.IdentifierProto identifier = 26;
+    optional string state = 27;
+    optional bool front_of_task = 28;
+    optional int32 proc_id = 29;
+    optional bool translucent = 30;
 }
 
 /* represents WindowToken */
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index e9d5b2b..4d319df 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -4856,6 +4856,19 @@
     <permission android:name="android.permission.ACCESS_SHARED_LIBRARIES"
                 android:protectionLevel="signature|installer" />
 
+    <!-- Allows an app to log compat change usage.
+         @hide  <p>Not for use by third-party applications.</p> -->
+    <permission android:name="android.permission.LOG_COMPAT_CHANGE"
+                android:protectionLevel="signature" />
+    <!-- Allows an app to read compat change config.
+         @hide  <p>Not for use by third-party applications.</p> -->
+    <permission android:name="android.permission.READ_COMPAT_CHANGE_CONFIG"
+                android:protectionLevel="signature" />
+    <!-- Allows an app to override compat change config.
+         @hide  <p>Not for use by third-party applications.</p> -->
+    <permission android:name="android.permission.OVERRIDE_COMPAT_CHANGE_CONFIG"
+                android:protectionLevel="signature" />
+
     <!-- Allows input events to be monitored. Very dangerous!  @hide -->
     <permission android:name="android.permission.MONITOR_INPUT"
                 android:protectionLevel="signature" />
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index de8f55b..c34a485 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Jy het jou ontsluitpatroon <xliff:g id="NUMBER_0">%1$d</xliff:g> keer verkeerdelik geteken. Na nog <xliff:g id="NUMBER_1">%2$d</xliff:g> onsuksesvolle pogings, sal jy gevra word om jou foon te ontsluit deur middel van \'n e-posrekening.\n\n Probeer weer oor <xliff:g id="NUMBER_2">%3$d</xliff:g> sekondes."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Verwyder"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Verhoog volume bo aanbevole vlak?\n\nOm lang tydperke teen hoë volume te luister, kan jou gehoor beskadig."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Gebruik toeganklikheidkortpad?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Wanneer die kortpad aan is, sal \'n toeganklikheidkenmerk begin word as albei volumeknoppies 3 sekondes lank gedruk word.\n\n Bestaande toeganklikheidkenmerk:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Jy kan die kenmerk in Instellings &gt; Toeganklikheid verander."</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index ec9abfe..23e6ccd 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"የመክፈቻ ስርዓተ ጥለቱን <xliff:g id="NUMBER_0">%1$d</xliff:g> ጊዜ በትክክል አልሳሉትም። ከ<xliff:g id="NUMBER_1">%2$d</xliff:g> ተጨማሪ ያልተሳኩ ሙከራዎች በኋላ የኢሜይል መለያ ተጠቅመው ስልክዎን እንዲከፍቱ ይጠየቃሉ።\n\nእባክዎ ከ<xliff:g id="NUMBER_2">%3$d</xliff:g> ሰከንዶች በኋላ እንደገና ይሞክሩ።"</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"አስወግድ"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"ድምጹ ከሚመከረው መጠን በላይ ከፍ ይበል?\n\nበከፍተኛ ድምጽ ለረጅም ጊዜ ማዳመጥ ጆሮዎን ሊጎዳው ይችላል።"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"የተደራሽነት አቋራጭ ጥቅም ላይ ይዋል?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"አቋራጩ ሲበራ ሁለቱንም የድምፅ አዝራሮች ለ3 ሰከንዶች ተጭኖ መቆየት የተደራሽነት ባህሪን ያስጀምረዋል።\n\n አሁን ያለ የተደራሽነት ባህሪ፦\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n ባህሪውን በቅንብሮች &gt; ተደራሽነት ውስጥ ሊለውጡት ይችላሉ።"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 0d70a11..80c04eb 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -222,7 +222,7 @@
     <string name="reboot_to_update_prepare" msgid="6978842143587422365">"جارٍ الإعداد للتحديث…"</string>
     <string name="reboot_to_update_package" msgid="4644104795527534811">"جارٍ معالجة حزمة التحديث…"</string>
     <string name="reboot_to_update_reboot" msgid="4474726009984452312">"جارٍ إعادة التشغيل…"</string>
-    <string name="reboot_to_reset_title" msgid="2226229680017882787">"إعادة الضبط بحسب بيانات المصنع"</string>
+    <string name="reboot_to_reset_title" msgid="2226229680017882787">"إعادة الضبط على الإعدادات الأصلية"</string>
     <string name="reboot_to_reset_message" msgid="3347690497972074356">"جارٍ إعادة التشغيل…"</string>
     <string name="shutdown_progress" msgid="5017145516412657345">"جارٍ إيقاف التشغيل..."</string>
     <string name="shutdown_confirm" product="tablet" msgid="2872769463279602432">"سيتم إيقاف تشغيل الجهاز اللوحي."</string>
@@ -320,7 +320,7 @@
     <string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"استرداد محتوى النافذة"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="6195610527625237661">"فحص محتوى نافذة يتم التفاعل معها"</string>
     <string name="capability_title_canRequestTouchExploration" msgid="327598364696316213">"تشغيل الاستكشاف باللمس"</string>
-    <string name="capability_desc_canRequestTouchExploration" msgid="4394677060796752976">"سيتم نطق العناصر التي تم النقر عليها بصوت عال ويمكن استكشاف الشاشة باستخدام الإيماءات."</string>
+    <string name="capability_desc_canRequestTouchExploration" msgid="4394677060796752976">"سيتم قول العناصر التي تم النقر عليها بصوت عال ويمكن استكشاف الشاشة باستخدام الإيماءات."</string>
     <string name="capability_title_canRequestFilterKeyEvents" msgid="2772371671541753254">"ملاحظة النص الذي تكتبه"</string>
     <string name="capability_desc_canRequestFilterKeyEvents" msgid="2381315802405773092">"يتضمن بيانات شخصية مثل أرقام بطاقات الائتمان وكلمات المرور."</string>
     <string name="capability_title_canControlMagnification" msgid="7701572187333415795">"التحكم في تكبير الشاشة"</string>
@@ -676,8 +676,8 @@
     <string name="policylab_forceLock" msgid="7360335502968476434">"قفل الشاشة"</string>
     <string name="policydesc_forceLock" msgid="1008844760853899693">"التحكّم في طريقة ووقت قفل الشاشة"</string>
     <string name="policylab_wipeData" msgid="1359485247727537311">"محو جميع البيانات"</string>
-    <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"يمكنك محو بيانات الجهاز اللوحي بدون تحذير، وذلك عبر إجراء إعادة الضبط بحسب بيانات المصنع."</string>
-    <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"‏يمكنك محو بيانات جهاز Android TV بدون تحذير عن طريق تنفيذ إعادة الضبط بحسب بيانات المصنع."</string>
+    <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"يمكنك محو بيانات الجهاز اللوحي بدون تحذير، وذلك عبر إجراء إعادة الضبط على الإعدادات الأصلية."</string>
+    <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"‏يمكنك محو بيانات جهاز Android TV بدون تحذير عن طريق تنفيذ إعادة الضبط على الإعدادات الأصلية."</string>
     <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"محو بيانات الهاتف بدون تحذير، وذلك من خلال إعادة ضبط البيانات على الإعدادات الأصلية"</string>
     <string name="policylab_wipeData_secondaryUser" msgid="413813645323433166">"محو بيانات المستخدم"</string>
     <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="2336676480090926470">"لمحو بيانات هذا المستخدم على هذا الجهاز اللوحي بدون تحذير."</string>
@@ -1701,6 +1701,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"لقد رسمت نقش فتح القفل بشكل غير صحيح <xliff:g id="NUMBER_0">%1$d</xliff:g> مرة. بعد إجراء <xliff:g id="NUMBER_1">%2$d</xliff:g> من المحاولات غير الناجحة الأخرى، ستُطالب بإلغاء تأمين الهاتف باستخدام حساب بريد إلكتروني لإلغاء تأمين الهاتف.\n\n أعد المحاولة خلال <xliff:g id="NUMBER_2">%3$d</xliff:g> ثانية."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"إزالة"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"هل تريد رفع مستوى الصوت فوق المستوى الموصى به؟\n\nقد يضر سماع صوت عالٍ لفترات طويلة بسمعك."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"هل تريد استخدام اختصار \"سهولة الاستخدام\"؟"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"عند تشغيل الاختصار، يؤدي الضغط على زرّي مستوى الصوت لمدة 3 ثوانٍ إلى تفعيل ميزة \"سهولة الاستخدام\".\n\n ميزة \"سهولة الاستخدام\" الحالية:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n يمكنك تغيير الميزة من \"الإعدادات\" &gt; \"سهولة الاستخدام\"."</string>
@@ -1932,7 +1934,7 @@
     <string name="zen_mode_default_events_name" msgid="2280682960128512257">"حدث"</string>
     <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"النوم"</string>
     <string name="muted_by" msgid="91464083490094950">"يعمل <xliff:g id="THIRD_PARTY">%1$s</xliff:g> على كتم بعض الأصوات."</string>
-    <string name="system_error_wipe_data" msgid="5910572292172208493">"حدثت مشكلة داخلية في جهازك، وقد لا يستقر وضعه حتى إجراء إعادة الضبط بحسب بيانات المصنع."</string>
+    <string name="system_error_wipe_data" msgid="5910572292172208493">"حدثت مشكلة داخلية في جهازك، وقد لا يستقر وضعه حتى إجراء إعادة الضبط على الإعدادات الأصلية."</string>
     <string name="system_error_manufacturer" msgid="703545241070116315">"حدثت مشكلة داخلية في جهازك. يمكنك الاتصال بالمصنِّع للحصول على تفاصيل."</string>
     <string name="stk_cc_ussd_to_dial" msgid="3139884150741157610">"‏تم تغيير طلب USSD إلى مكالمة عادية."</string>
     <string name="stk_cc_ussd_to_ss" msgid="4826846653052609738">"‏تم تغيير طلب USSD إلى طلب SS."</string>
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index ad11a37..73e32b8 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"আপুনি আপোনাৰ ল\'ক খোলাৰ আৰ্হিটো <xliff:g id="NUMBER_0">%1$d</xliff:g>বাৰ ভুলকৈ আঁকিছে। <xliff:g id="NUMBER_1">%2$d</xliff:g>তকৈ বেছি বাৰ ভুল আৰ্হি আঁকিলে আপোনাৰ ফ\'নটো কোনো একাউণ্টৰ জৰিয়তে আনলক কৰিবলৈ কোৱা হ\'ব।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> ছেকেণ্ডৰ পিছত আকৌ চেষ্টা কৰক।"</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"আঁতৰাওক"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"অনুমোদিত স্তৰতকৈ ওপৰলৈ ভলিউম বঢ়াব নেকি?\n\nদীৰ্ঘ সময়ৰ বাবে উচ্চ ভলিউমত শুনাৰ ফলত শ্ৰৱণ ক্ষমতাৰ ক্ষতি হ\'ব পাৰে।"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"দিব্যাংগসকলৰ সুবিধাৰ শ্বৰ্টকাট ব্যৱহাৰ কৰেনে?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"শ্বৰ্টকাট অন হৈ থকাৰ সময়ত দুয়োটা ভলিউম বুটামত ৩ ছেকেণ্ডৰ বাবে ছাপ দি থাকিলে দিব্যাংগসকলৰ বাবে থকা সুবিধা এটা আৰম্ভ হ\'ব। \n\n চলিত দিব্যাংগসকলৰ সুবিধা:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n আপুনি এই সুবিধাটো ছেটিংসমূহ &gt; দিব্যাংগসকলৰ বাবে সুবিধা-লৈ গৈ সলনি কৰিব পাৰে।"</string>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index a535f1f..c894c29 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Siz artıq modeli <xliff:g id="NUMBER_0">%1$d</xliff:g> dəfə yanlış daxil etmisiniz.<xliff:g id="NUMBER_1">%2$d</xliff:g> dəfə də yanlış daxil etsəniz, telefonun kilidinin açılması üçün elektron poçt ünvanınız tələb olunacaq.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> saniyə ərzində yenidən cəhd edin."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" - "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Yığışdır"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Səsin həcmi tövsiyə olunan səviyyədən artıq olsun?\n\nYüksək səsi uzun zaman dinləmək eşitmə qabiliyyətinizə zərər vura bilər."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Əlçatımlılıq Qısayolu istifadə edilsin?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Qısayol aktiv olduqda hər iki səs düyməsinə 3 saniyə basıb saxlamaqla əlçatımlılıq funksiyası işə başlayacaq.\n\n Cari əlçatımlılıq funksiyası:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Funksiyanı Ayarlar və Əçatımlılıq bölməsində dəyişə bilərsiniz."</string>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 249e5af..909c315 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -1635,6 +1635,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Nacrtali ste šablon za otključavanje netačno <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Posle još <xliff:g id="NUMBER_1">%2$d</xliff:g> neuspešna(ih) pokušaja, od vas će biti zatraženo da otključate telefon pomoću naloga e-pošte.\n\nProbajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunde/i."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Ukloni"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Želite da pojačate zvuk iznad preporučenog nivoa?\n\nSlušanje glasne muzike duže vreme može da vam ošteti sluh."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Želite li da koristite prečicu za pristupačnost?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Kada je prečica uključena, pritisnite oba dugmeta za jačinu zvuka da biste pokrenuli funkciju pristupačnosti.\n\n Aktuelna funkcija pristupačnosti:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Možete da promenite funkciju u odeljku Podešavanja &gt; Pristupačnost."</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index dc4c56e..19dcf92 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -1657,6 +1657,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Вы няправільна ўвялі графічны ключ разблакiроўкi пэўную колькасць разоў: <xliff:g id="NUMBER_0">%1$d</xliff:g>. Пасля яшчэ некалькiх няўдалых спроб (<xliff:g id="NUMBER_1">%2$d</xliff:g>) вам будзе прапанавана разблакiраваць тэлефон, увайшоўшы ў Google.\n\n Паўтарыце спробу праз <xliff:g id="NUMBER_2">%3$d</xliff:g> с."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Выдалiць"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Павялiчыць гук вышэй рэкамендаванага ўзроўню?\n\nДоўгае праслухоўванне музыкi на вялiкай гучнасцi можа пашкодзiць ваш слых."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Выкарыстоўваць камбінацыю хуткага доступу для спецыяльных магчымасцей?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Калі камбінацыя хуткага доступу ўключана, вы можаце націснуць абедзве кнопкі гучнасці і ўтрымліваць іх 3 секунды, каб уключыць функцыю спецыяльных магчымасцей.\n\n Бягучая функцыя спецыяльных магчымасцей:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Вы можаце змяніць гэту функцыю ў меню \"Налады &gt; Спецыяльныя магчымасці\"."</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 30b7d30..8a68766 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Начертахте неправилно фигурата си за отключване <xliff:g id="NUMBER_0">%1$d</xliff:g> пъти. След още <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешни опита ще бъдете помолени да отключите телефона посредством имейл адрес.\n\n Опитайте отново след <xliff:g id="NUMBER_2">%3$d</xliff:g> секунди."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Премахване"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Да се увеличи ли силата на звука над препоръчителното ниво?\n\nПродължителното слушане при висока сила на звука може да увреди слуха ви."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Искате ли да използвате пряк път към функцията за достъпност?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Когато прекият път е включен, можете да стартирате дадена функция за достъпност, като натиснете двата бутона за промяна на силата на звука и ги задържите 3 секунди.\n\n Текущата функция за достъпност е:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Можете да промените функцията от „Настройки“ &gt; „Достъпност“."</string>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index d85b5d6..9ca383d 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"আপনি আপনার আনলকের প্যাটার্ন আঁকার ক্ষেত্রে <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুল করেছেন৷ আর <xliff:g id="NUMBER_1">%2$d</xliff:g> বার অসফল প্রচেষ্টা করা হলে আপনাকে একটি ইমেল অ্যাকাউন্ট মারফত আপনার ফোন আনলক করতে বলা হবে৷\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> সেকেন্ডের মধ্যে আবার চেষ্টা করুন৷"</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"সরান"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"প্রস্তাবিত স্তরের চেয়ে বেশি উঁচুতে ভলিউম বাড়াবেন?\n\nউঁচু ভলিউমে বেশি সময় ধরে কিছু শুনলে আপনার শ্রবনশক্তির ক্ষতি হতে পারে।"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"অ্যাক্সেসযোগ্যতা শর্টকাট ব্যবহার করবেন?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"শর্টকাটটি চালু থাকলে দুটি ভলিউম বোতাম একসাথে ৩ সেকেন্ড টিপে ধরে রাখলে একটি অ্যাকসেসিবিলিটি বৈশিষ্ট্য চালু হবে।\n\n বর্তমান অ্যাকসেসিবিলিটি বৈশিষ্ট্য:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n আপনি এই বৈশিষ্ট্যটি সেটিংস &gt; অ্যাকসেসিবিলিটিতে গিয়ে পরিবর্তন করতে পারবেন।"</string>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index c8c65bb..5f83aa4 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -1637,6 +1637,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Pogrešno ste nacrtali uzorak za otključavanje <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Ako napravite još <xliff:g id="NUMBER_1">%2$d</xliff:g> pokušaja bez uspjeha, od vas će se tražiti da otključate telefon pomoću e-pošte. \n\n Pokušajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Ukloni"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Želite li pojačati zvuk iznad preporučenog nivoa?\n\nDužim slušanjem glasnog zvuka možete oštetiti sluh."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Želite li koristiti Prečicu za pristupačnost?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Kada je prečica uključena, pritiskom na oba dugmeta za podešavanje jačine zvuka u trajanju od 3 sekunde pokrenut će se funkcija za pristupačnost.\n\n Trenutna funkcija za pristupačnost je:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Funkciju možete promijeniti ako odete u Postavke &gt; Pristupačnost."</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 42bebe1..930065b 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Has dibuixat el patró de desbloqueig <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades de manera incorrecta. Si falles <xliff:g id="NUMBER_1">%2$d</xliff:g> vegades més, se\'t demanarà que desbloquegis el telèfon amb un compte de correu electrònic.\n\n Torna-ho a provar d\'aquí a <xliff:g id="NUMBER_2">%3$d</xliff:g> segons."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Elimina"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Vols apujar el volum per sobre del nivell recomanat?\n\nSi escoltes música a un volum alt durant períodes llargs, pots danyar-te l\'oïda."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Vols fer servir la drecera d\'accessibilitat?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Si la drecera està activada, prem els dos botons de volum durant 3 segons, per iniciar una funció d\'accessibilitat.\n\n Funció d\'accessibilitat actual:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Pots canviar la funció a Configuració &gt; Accessibilitat."</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 2c16291..2c017dd 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -1657,6 +1657,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Již <xliff:g id="NUMBER_0">%1$d</xliff:g>krát jste nesprávně nakreslili své heslo odemknutí. Po <xliff:g id="NUMBER_1">%2$d</xliff:g> dalších neúspěšných pokusech budete požádáni o odemčení telefonu pomocí e-mailového účtu.\n\n Zkuste to znovu za <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Odebrat"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Zvýšit hlasitost nad doporučenou úroveň?\n\nDlouhodobý poslech hlasitého zvuku může poškodit sluch."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Použít zkratku přístupnosti?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Když je tato zkratka zapnutá, můžete funkci přístupnosti spustit tím, že na tři sekundy podržíte obě tlačítka hlasitosti.\n\n Aktuální funkce přístupnosti:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Funkci můžete změnit v Nastavení &gt; Přístupnost."</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index f86db77..4ebea89 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Du har tegnet dit oplåsningsmønster forkert <xliff:g id="NUMBER_0">%1$d</xliff:g> gange. Efter <xliff:g id="NUMBER_1">%2$d</xliff:g> yderligere mislykkede forsøg til vil du blive bedt om at låse din telefon op ved hjælp af en mailkonto.\n\n Prøv igen om <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunder."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Fjern"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Vil du skrue højere op end det anbefalede lydstyrkeniveau?\n\nDu kan skade hørelsen ved at lytte til meget høj musik over længere tid."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Vil du bruge genvejen til Hjælpefunktioner?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Når genvejen er slået til, kan du starte en hjælpefunktion ved at trykke på begge lydstyrkeknapper i tre sekunder.\n\n Nuværende hjælpefunktion:\n<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Du kan skifte funktion i Indstillinger &gt; Hjælpefunktioner."</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index d6a9a01..6fa0ac1 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Du hast dein Entsperrungsmuster <xliff:g id="NUMBER_0">%1$d</xliff:g>-mal falsch gezeichnet. Nach <xliff:g id="NUMBER_1">%2$d</xliff:g> weiteren erfolglosen Versuchen wirst du aufgefordert, dein Telefon mithilfe eines E-Mail-Kontos zu entsperren.\n\n Versuche es in <xliff:g id="NUMBER_2">%3$d</xliff:g> Sekunden erneut."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Entfernen"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Lautstärke über den Schwellenwert anheben?\n\nWenn du über einen längeren Zeitraum Musik in hoher Lautstärke hörst, kann dies dein Gehör schädigen."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Verknüpfung für Bedienungshilfen verwenden?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Wenn die Verknüpfung aktiviert ist, kannst du die beiden Lautstärketasten drei Sekunden lang gedrückt halten, um eine Bedienungshilfe zu starten.\n\n Aktuelle Bedienungshilfe:\n<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Du kannst die Bedienungshilfe unter \"Einstellungen\" &gt; \"Bedienungshilfen\" ändern."</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 67285e9..81a16f2 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Σχεδιάσατε το μοτίβο ξεκλειδώματος εσφαλμένα <xliff:g id="NUMBER_0">%1$d</xliff:g> φορές. Μετά από <xliff:g id="NUMBER_1">%2$d</xliff:g> ανεπιτυχείς προσπάθειες ακόμη, θα σας ζητηθεί να ξεκλειδώσετε το τηλέφωνό σας με τη χρήση ενός λογαριασμού ηλεκτρονικού ταχυδρομείου.\n\n Δοκιμάστε ξανά σε <xliff:g id="NUMBER_2">%3$d</xliff:g> δευτερόλεπτα."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Κατάργηση"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Αυξάνετε την ένταση ήχου πάνω από το επίπεδο ασφαλείας;\n\nΑν ακούτε μουσική σε υψηλή ένταση για μεγάλο χρονικό διάστημα ενδέχεται να προκληθεί βλάβη στην ακοή σας."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Να χρησιμοποιείται η συντόμευση προσβασιμότητας;"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Όταν η συντόμευση είναι ενεργοποιημένη, το πάτημα και των δύο κουμπιών έντασης ήχου για 3 δευτερόλεπτα θα ξεκινήσει μια λειτουργία προσβασιμότητας.\n\n Τρέχουσα λειτουργία προσβασιμότητας:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Μπορείτε να αλλάξετε τη λειτουργία από τις Ρυθμίσεις &gt; Προσβασιμότητα."</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index ed31c22..87e0c90 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, you will be asked to unlock your phone using an email account.\n\n Try again in <xliff:g id="NUMBER_2">%3$d</xliff:g> seconds."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Remove"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Raise volume above recommended level?\n\nListening at high volume for long periods may damage your hearing."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Use Accessibility Shortcut?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"When the shortcut is on, pressing both volume buttons for 3 seconds will start an accessibility feature.\n\n Current accessibility feature:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n You can change the feature in Settings &gt; Accessibility."</string>
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index 6ae46b4..008ad8a 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, you will be asked to unlock your phone using an email account.\n\n Try again in <xliff:g id="NUMBER_2">%3$d</xliff:g> seconds."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Remove"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Raise volume above recommended level?\n\nListening at high volume for long periods may damage your hearing."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Use Accessibility Shortcut?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"When the shortcut is on, pressing both volume buttons for 3 seconds will start an accessibility feature.\n\n Current accessibility feature:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n You can change the feature in Settings &gt; Accessibility."</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index ed31c22..87e0c90 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, you will be asked to unlock your phone using an email account.\n\n Try again in <xliff:g id="NUMBER_2">%3$d</xliff:g> seconds."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Remove"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Raise volume above recommended level?\n\nListening at high volume for long periods may damage your hearing."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Use Accessibility Shortcut?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"When the shortcut is on, pressing both volume buttons for 3 seconds will start an accessibility feature.\n\n Current accessibility feature:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n You can change the feature in Settings &gt; Accessibility."</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index ed31c22..87e0c90 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%1$d</xliff:g> times. After <xliff:g id="NUMBER_1">%2$d</xliff:g> more unsuccessful attempts, you will be asked to unlock your phone using an email account.\n\n Try again in <xliff:g id="NUMBER_2">%3$d</xliff:g> seconds."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Remove"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Raise volume above recommended level?\n\nListening at high volume for long periods may damage your hearing."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Use Accessibility Shortcut?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"When the shortcut is on, pressing both volume buttons for 3 seconds will start an accessibility feature.\n\n Current accessibility feature:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n You can change the feature in Settings &gt; Accessibility."</string>
diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml
index 07cb6c7..777107a 100644
--- a/core/res/res/values-en-rXC/strings.xml
+++ b/core/res/res/values-en-rXC/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‏‎‎‏‎‎‏‎‏‏‏‎‏‏‏‎‎‏‏‏‏‎‎‏‎‏‏‏‏‎‏‏‏‏‏‏‎‎‏‏‏‏‎‎‏‎‎‎‎‎‏‏‎‏‏‎‎‎You have incorrectly drawn your unlock pattern ‎‏‎‎‏‏‎<xliff:g id="NUMBER_0">%1$d</xliff:g>‎‏‎‎‏‏‏‎ times. After ‎‏‎‎‏‏‎<xliff:g id="NUMBER_1">%2$d</xliff:g>‎‏‎‎‏‏‏‎ more unsuccessful attempts, you will be asked to unlock your phone using an email account.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎ Try again in ‎‏‎‎‏‏‎<xliff:g id="NUMBER_2">%3$d</xliff:g>‎‏‎‎‏‏‏‎ seconds.‎‏‎‎‏‎"</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" ‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‎‏‎‎‎‎‎‎‎‎‏‏‎‎‎‏‏‎‏‎‏‏‏‏‏‏‎‏‎‏‏‎‎‎‏‎‏‎‏‏‏‏‏‎‏‎‏‏‏‎‏‏‎‎‎‏‎‎ — ‎‏‎‎‏‎ "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‎‎‎‏‏‏‎‏‏‎‏‏‏‏‏‎‏‏‏‏‏‎‏‎‎‎‎‎‎‎‏‏‏‎‎‎‎‏‏‎‏‏‏‎‏‏‎‎‎‎‎‎‎‎‎‏‎‎Remove‎‏‎‎‏‎"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‎‎‎‎‏‎‎‎‎‏‎‏‎‎‎‏‎‎‎‏‏‎‎‎‏‏‏‎‎‏‏‏‏‏‏‎‎‏‏‎‏‎‎‏‎‏‎‏‏‎‎‎‎‏‎‏‎‎Raise volume above recommended level?‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎Listening at high volume for long periods may damage your hearing.‎‏‎‎‏‎"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‏‏‏‎‎‎‎‏‎‏‏‎‎‏‎‎‏‏‏‏‎‏‏‎‏‎‎‎‏‎‏‏‎‏‎‏‎‏‎‏‎‏‎‏‏‏‎‎‎‎‏‎‏‎‏‎‏‎Use Accessibility Shortcut?‎‏‎‎‏‎"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‎‏‎‎‎‏‎‏‏‎‏‏‎‎‎‎‏‏‎‏‏‏‎‏‎‎‎‏‏‎‎‏‎‏‎‎‎‎‏‏‏‎‎‏‎‏‎‏‎‎‏‎‏‏‎‎‎When the shortcut is on, pressing both volume buttons for 3 seconds will start an accessibility feature.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎ Current accessibility feature:‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎ ‎‏‎‎‏‏‎<xliff:g id="SERVICE_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎ You can change the feature in Settings &gt; Accessibility.‎‏‎‎‏‎"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 6f83551..4335c2b 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Dibujaste incorrectamente tu patrón de desbloqueo <xliff:g id="NUMBER_0">%1$d</xliff:g> veces. Luego de <xliff:g id="NUMBER_1">%2$d</xliff:g> intentos incorrectos más, se te solicitará que desbloquees tu dispositivo mediante el uso de una cuenta de correo.\n\n Vuelve a intentarlo en <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Eliminar"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"¿Quieres subir el volumen por encima del nivel recomendado?\n\nEscuchar a un alto volumen durante largos períodos puede dañar tu audición."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"¿Usar acceso directo de accesibilidad?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Cuando el acceso directo está activado, puedes presionar los botones de volumen durante 3 segundos para iniciar una función de accesibilidad.\n\n Función de accesibilidad actual:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Puedes cambiar la función en Configuración &gt; Accesibilidad."</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 737a83b..8d750ca 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Has fallado <xliff:g id="NUMBER_0">%1$d</xliff:g> veces al dibujar el patrón de desbloqueo. Si fallas otras <xliff:g id="NUMBER_1">%2$d</xliff:g> veces, deberás usar una cuenta de correo electrónico para desbloquear el teléfono.\n\n Inténtalo de nuevo en <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Quitar"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"¿Quieres subir el volumen por encima del nivel recomendado?\n\nEscuchar sonidos fuertes durante mucho tiempo puede dañar los oídos."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"¿Utilizar acceso directo de accesibilidad?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Si el acceso directo está activado, pulsa los dos botones de volumen durante tres segundos para iniciar una función de accesibilidad.\n\n Función de accesibilidad actual:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Puedes cambiar la función en Ajustes &gt; Accesibilidad."</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 021985f..7f423e9 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Joonistasite oma avamismustri <xliff:g id="NUMBER_0">%1$d</xliff:g> korda valesti. Pärast veel <xliff:g id="NUMBER_1">%2$d</xliff:g> ebaõnnestunud katset palutakse teil telefon avada meilikontoga.\n\n Proovige uuesti <xliff:g id="NUMBER_2">%3$d</xliff:g> sekundi pärast."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Eemalda"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Kas suurendada helitugevuse taset üle soovitatud taseme?\n\nPikaajaline valju helitugevusega kuulamine võib kuulmist kahjustada."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Kas kasutada juurdepääsetavuse otseteed?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Kui otsetee on sisse lülitatud, käivitab mõlema helitugevuse nupu kolm sekundit all hoidmine juurdepääsetavuse funktsiooni.\n\n Praegune juurdepääsetavuse funktsioon:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Saate seda funktsiooni muuta valikutega Seaded &gt; Juurdepääsetavus."</string>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index 8ecdd07..9d014a3 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Desblokeatzeko eredua oker marraztu duzu <xliff:g id="NUMBER_0">%1$d</xliff:g> aldiz. Beste <xliff:g id="NUMBER_1">%2$d</xliff:g> aldiz oker marrazten baduzu, telefonoa posta-kontu baten bidez desblokeatzeko eskatuko dizugu.\n\n Saiatu berriro <xliff:g id="NUMBER_2">%3$d</xliff:g> segundo barru."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Kendu"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Bolumena gomendatutako mailatik gora igo nahi duzu?\n\nMusika bolumen handian eta denbora luzez entzuteak entzumena kalte diezazuke."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Erabilerraztasun-lasterbidea erabili nahi duzu?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Lasterbidea aktibatuta dagoenean, bi bolumen-botoiak hiru segundoz sakatuta abiaraziko da erabilerraztasun-eginbidea.\n\n Uneko erabilerraztasun-eginbidea:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Eginbidea aldatzeko, joan Ezarpenak &gt; Erabilerraztasuna atalera."</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 9c3403b..58ce7a7 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"‏شما الگوی بازگشایی قفل خود را <xliff:g id="NUMBER_0">%1$d</xliff:g> بار اشتباه کشیده‌اید. پس از <xliff:g id="NUMBER_1">%2$d</xliff:g> تلاش ناموفق، از شما خواسته می‎شود که با استفاده از یک حساب ایمیل قفل تلفن خود را باز کنید.\n\n لطفاً پس از <xliff:g id="NUMBER_2">%3$d</xliff:g> ثانیه دوباره امتحان کنید."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"حذف"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"میزان صدا را به بالاتر از حد توصیه شده افزایش می‌دهید؟\n\nگوش دادن به صداهای بلند برای مدت طولانی می‌تواند به شنوایی‌تان آسیب وارد کند."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"از میان‌بر دسترس‌پذیری استفاده شود؟"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"وقتی میان‌بر روشن است،‌ اگر هر دو دکمه صدا را ۳ ثانیه فشار دهید یکی از قابلیت‌های دسترس‌پذیری شروع می‌شود.\n\n قابلیت دسترس‌پذیری کنونی:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n می‌توانید در «تنظیمات &gt; دسترس‌پذیری»، قابلیت را تغییر دهید."</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index a42b87d..e0f4ed4 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Piirsit lukituksenpoistokuvion väärin <xliff:g id="NUMBER_0">%1$d</xliff:g> kertaa. Jos piirrät kuvion väärin vielä <xliff:g id="NUMBER_1">%2$d</xliff:g> kertaa, sinua pyydetään poistamaan puhelimesi lukitus sähköpostitilin avulla.\n\n Yritä uudelleen <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunnin kuluttua."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Poista"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Nostetaanko äänenvoimakkuus suositellun tason yläpuolelle?\n\nPitkäkestoinen kova äänenvoimakkuus saattaa heikentää kuuloa."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Käytetäänkö esteettömyyden pikanäppäintä?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Kun pikanäppäin on käytössä, voit käynnistää esteettömyystoiminnon pitämällä molempia äänenvoimakkuuspainikkeita painettuna kolmen sekunnin ajan.\n\n Tällä hetkellä valittu esteettömyystoiminto:\n<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Voit vaihtaa toimintoa valitsemalla Asetukset &gt; Esteettömyys."</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 47f4184..5d99db1 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Vous avez dessiné un schéma de déverrouillage incorrect à <xliff:g id="NUMBER_0">%1$d</xliff:g> reprises. Si vous échouez encore <xliff:g id="NUMBER_1">%2$d</xliff:g> fois, vous devrez déverrouiller votre téléphone à l\'aide d\'un compte de messagerie électronique.\n\n Veuillez réessayer dans <xliff:g id="NUMBER_2">%3$d</xliff:g> secondes."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Supprimer"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Augmenter le volume au-dessus du niveau recommandé?\n\nL\'écoute prolongée à un volume élevé peut endommager vos facultés auditives."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Utiliser le raccourci d\'accessibilité?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Quand le raccourci est activé, appuyez sur les deux boutons de volume pendant trois secondes pour lancer une fonctionnalité d\'accessibilité.\n\n Fonctionnalité d\'accessibilité utilisée actuellement :\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Vous pouvez changer de fonctionnalité sous Paramètres &gt; Accessibilité."</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 7898e79..3f4f3e6 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Vous avez dessiné un schéma de déverrouillage incorrect à <xliff:g id="NUMBER_0">%1$d</xliff:g> reprises. Si vous échouez encore <xliff:g id="NUMBER_1">%2$d</xliff:g> fois, vous devrez déverrouiller votre téléphone à l\'aide d\'un compte de messagerie électronique.\n\n Veuillez réessayer dans <xliff:g id="NUMBER_2">%3$d</xliff:g> secondes."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Supprimer"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Augmenter le volume au dessus du niveau recommandé ?\n\nL\'écoute prolongée à un volume élevé peut endommager vos facultés auditives."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Utiliser le raccourci d\'accessibilité ?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Quand le raccourci est activé, appuyez sur les deux boutons de volume pendant trois secondes pour lancer une fonctionnalité d\'accessibilité.\n\n Fonctionnalité d\'accessibilité utilisée actuellement :\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Vous pouvez changer de fonctionnalité dans Paramètres &gt; Accessibilité."</string>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index e7498b9..2e5052c 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Debuxaches o padrón de desbloqueo incorrectamente <xliff:g id="NUMBER_0">%1$d</xliff:g> veces. Se realizas <xliff:g id="NUMBER_1">%2$d</xliff:g> intentos incorrectos máis, terás que desbloquear o teléfono a través dunha conta de correo electrónico.\n\n Téntao de novo dentro de <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Eliminar"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Queres subir o volume máis do nivel recomendado?\n\nA reprodución de son a un volume elevado durante moito tempo pode provocar danos nos oídos."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Queres utilizar o atallo de accesibilidade?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Cando o atallo está activado, podes premer os dous botóns de volume durante 3 segundos para iniciar unha función de accesibilidade.\n\n Función de accesibilidade actual:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Podes cambiar a función en Configuración &gt; Accesibilidade."</string>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index b52d99ef..8081ef2 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"તમે તમારી અનલૉક પૅટર્ન <xliff:g id="NUMBER_0">%1$d</xliff:g> વખત ખોટી રીતે દોરી. હજી <xliff:g id="NUMBER_1">%2$d</xliff:g> અસફળ પ્રયાસ પછી, તમને ઇમેઇલ એકાઉન્ટનો ઉપયોગ કરીને ફોનને અનલૉક કરવાનું કહેવામાં આવશે.\n\n<xliff:g id="NUMBER_2">%3$d</xliff:g> સેકન્ડમાં ફરીથી પ્રયાસ કરો."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"દૂર કરો"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"ભલામણ કરેલ સ્તરની ઉપર વૉલ્યૂમ વધાર્યો?\n\nલાંબા સમય સુધી ઊંચા અવાજે સાંભળવું તમારી શ્રવણક્ષમતાને નુકસાન પહોંચાડી શકે છે."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ઍક્સેસિબિલિટી શૉર્ટકટનો ઉપયોગ કરીએ?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"જ્યારે શૉર્ટકટ ચાલુ હોય, ત્યારે બન્ને વૉલ્યૂમ બટનને 3 સેકન્ડ સુધી દબાવી રાખવાથી ઍક્સેસિબિલિટી સુવિધા શરૂ થઈ જશે.\n\n વર્તમાન ઍક્સેસિબિલિટી સુવિધા:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n તમે સેટિંગ્સ &gt; ઍક્સેસિબિલિટીમાં જઈને આ સુવિધા બદલી શકો છો."</string>
@@ -1987,8 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g> સ્પ્રેડશીટ"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"પ્રસ્તુતિ"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g> પ્રસ્તુતિ"</string>
-    <!-- no translation found for bluetooth_airplane_mode_toast (2066399056595768554) -->
-    <skip />
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"એરપ્લેન મોડ દરમિયાન બ્લૂટૂથ ચાલુ રહેશે"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"લોડિંગ"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="one"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> ફાઇલ</item>
@@ -2009,8 +2010,7 @@
     <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
     <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g>નું કૅપ્શન બાર."</string>
-    <!-- no translation found for as_app_forced_to_restricted_bucket (8233871289353898964) -->
-    <skip />
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g>ને પ્રતિબંધિત સમૂહમાં મૂકવામાં આવ્યું છે"</string>
     <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
     <skip />
     <!-- no translation found for resolver_work_tab (2690019516263167035) -->
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 3140c76..05efcd8 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"आपने अपने अनलॉक आकार को <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से आरेखित किया है. <xliff:g id="NUMBER_1">%2$d</xliff:g> और असफल प्रयासों के बाद, आपसे अपने फ़ोन को किसी ईमेल खाते का उपयोग करके अनलॉक करने के लिए कहा जाएगा.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकंड में फिर से प्रयास करें."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"निकालें"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"वॉल्यूम को सुझाए गए स्तर से ऊपर बढ़ाएं?\n\nअत्यधिक वॉल्यूम पर ज़्यादा समय तक सुनने से आपकी सुनने की क्षमता को नुकसान हो सकता है."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"सुलभता शॉर्टकट का इस्तेमाल करना चाहते हैं?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"इस शॉर्टकट के चालू होने पर, दोनों वॉल्यूम बटनों को 3 सेकंड तक दबाने से सुलभता सुविधा शुरू हो जाएगी.\n\n मौजूदा सुलभता सुविधा:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n आप इस सुविधा को सेटिंग &gt; सुलभता पर जाकर बदल सकते हैं."</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index feb29e2..e4cefe8 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -1635,6 +1635,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Netočno ste iscrtali obrazac za otključavanje <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Nakon još ovoliko neuspješnih pokušaja: <xliff:g id="NUMBER_1">%2$d</xliff:g> morat ćete otključati telefon pomoću računa e-pošte.\n\n Pokušajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Ukloni"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Želite li pojačati zvuk iznad preporučene razine?\n\nDugotrajno slušanje glasne glazbe može vam oštetiti sluh."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Želite li upotrebljavati prečac za pristupačnost?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Kada je taj prečac uključen, pritiskom na obje tipke za glasnoću na 3 sekunde pokrenut će se značajka pristupačnosti.\n\n Trenutačna značajka pristupačnosti:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Značajku možete promijeniti u Postavkama &gt; Pristupačnost."</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 20d38ae..08cb1c7 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"<xliff:g id="NUMBER_0">%1$d</xliff:g> alkalommal helytelenül rajzolta le a feloldási mintát. További <xliff:g id="NUMBER_1">%2$d</xliff:g> sikertelen kísérlet után egy e-mail fiók használatával kell feloldania a telefonját.\n\n Kérjük, próbálja újra <xliff:g id="NUMBER_2">%3$d</xliff:g> másodperc múlva."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Eltávolítás"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Az ajánlott szint fölé szeretné emelni a hangerőt?\n\nHa hosszú időn át teszi ki magát nagy hangerőnek, azzal károsíthatja a hallását."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Szeretné használni a Kisegítő lehetőségek billentyűparancsot?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Ha be van kapcsolva a billentyűparancs, a két hangerőgomb 3 másodpercig tartó lenyomásával elindíthatja a kisegítő lehetőségek egyik funkcióját.\n\n A kisegítő lehetőségek jelenleg beállított funkciója:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n A funkciót a Beállítások &gt; Kisegítő lehetőségek menüpontban módosíthatja."</string>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index d13b9ea..9d33f6b 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Դուք <xliff:g id="NUMBER_0">%1$d</xliff:g> անգամ սխալ եք հավաքել ձեր ապակողպման նմուշը: <xliff:g id="NUMBER_1">%2$d</xliff:g> անգամից ավել անհաջող փորձերից հետո ձեզ կառաջարկվի ապակողպել ձեր հեռախոսը` օգտագործելով էլփոստի հաշիվ:\n\n Փորձեք կրկին <xliff:g id="NUMBER_2">%3$d</xliff:g> վայրկյանից:"</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Հեռացնել"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Ձայնը բարձրացնե՞լ խորհուրդ տրվող մակարդակից ավել:\n\nԵրկարատև բարձրաձայն լսելը կարող է վնասել ձեր լսողությունը:"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Օգտագործե՞լ Մատչելիության դյուրանցումը։"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Հատուկ գործառույթն օգտագործելու համար սեղմեք և 3 վայրկյան սեղմած պահեք ձայնի ուժգնության երկու կոճակները, երբ գործառույթը միացված է։\n\n Մատչելիության ակտիվ գործառույթը՝\n<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Գործառույթը կարող եք փոփոխել՝ անցնելով Կարգավորումներ &gt; Հատուկ գործառույթներ։"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index c2a0817..4813610 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Anda telah <xliff:g id="NUMBER_0">%1$d</xliff:g> kali salah menggambar pola pembuka kunci. Setelah <xliff:g id="NUMBER_1">%2$d</xliff:g> lagi upaya gagal, Anda akan diminta membuka kunci ponsel menggunakan akun email.\n\nCoba lagi dalam <xliff:g id="NUMBER_2">%3$d</xliff:g> detik."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Hapus"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Mengeraskan volume di atas tingkat yang disarankan?\n\nMendengarkan dengan volume keras dalam waktu yang lama dapat merusak pendengaran Anda."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Gunakan Pintasan Aksesibilitas?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Saat pintasan aktif, menekan kedua tombol volume selama 3 detik akan memulai fitur aksesibilitas.\n\n Fitur aksesibilitas saat ini:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Anda dapat mengubah fitur di Setelan &gt; Aksesibilitas."</string>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index c596c12..bf3fe87 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Þú hefur teiknað rangt opnunarmynstur <xliff:g id="NUMBER_0">%1$d</xliff:g> sinnum. Eftir <xliff:g id="NUMBER_1">%2$d</xliff:g> árangurslausar tilraunir í viðbót verður þú beðin(n) um að opna símann með tölvupóstreikningi.\n\n Reyndu aftur eftir <xliff:g id="NUMBER_2">%3$d</xliff:g> sekúndur."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Fjarlægja"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Hækka hljóðstyrk umfram ráðlagðan styrk?\n\nEf hlustað er á háum hljóðstyrk í langan tíma kann það að skaða heyrnina."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Viltu nota aðgengisflýtileið?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Þegar flýtileiðin er virk er kveikt á aðgengiseiginleikanum með því að halda báðum hljóðstyrkshnöppunum inni í þrjár sekúndur.\n\n Virkur aðgengiseiginleiki:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Hægt er að skipta um eiginleika í Stillingar &gt; Aðgengi."</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 1144995..72ca138 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"<xliff:g id="NUMBER_0">%1$d</xliff:g> tentativi errati di inserimento della sequenza di sblocco. Dopo altri <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativi falliti, ti verrà chiesto di sbloccare il telefono con un account email.\n\n Riprova tra <xliff:g id="NUMBER_2">%3$d</xliff:g> secondi."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Rimuovi"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Vuoi aumentare il volume oltre il livello consigliato?\n\nL\'ascolto ad alto volume per lunghi periodi di tempo potrebbe danneggiare l\'udito."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Usare la scorciatoia Accessibilità?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Quando la scorciatoia è attiva, puoi premere entrambi i pulsanti del volume per tre secondi per avviare una funzione di accessibilità.\n\n Funzione di accessibilità corrente:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Puoi cambiare la funzione in Impostazioni &gt; Accessibilità."</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index bce62ab..9c8d0a3 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -1657,6 +1657,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"שרטטת את קו ביטול הנעילה באופן שגוי <xliff:g id="NUMBER_0">%1$d</xliff:g> פעמים. לאחר <xliff:g id="NUMBER_1">%2$d</xliff:g> ניסיונות כושלים נוספים, תתבקש לבטל את נעילת הטלפון באמצעות חשבון אימייל‏.\n\nנסה שוב בעוד <xliff:g id="NUMBER_2">%3$d</xliff:g> שניות."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"הסר"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"האם להעלות את עוצמת הקול מעל לרמה המומלצת?\n\nהאזנה בעוצמת קול גבוהה למשכי זמן ממושכים עלולה לפגוע בשמיעה."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"להשתמש בקיצור הדרך לתכונת הנגישות?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"כשקיצור הדרך מופעל, לחיצה על שני לחצני עוצמת השמע למשך שלוש שניות מפעילה את תכונת הנגישות.\n\n תכונת הנגישות המוגדרת כרגע:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n אפשר לשנות את התכונה בקטע \'הגדרות ונגישות\'."</string>
@@ -2053,8 +2055,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"גיליון אלקטרוני <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"מצגת"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"מצגת <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
-    <!-- no translation found for bluetooth_airplane_mode_toast (2066399056595768554) -->
-    <skip />
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"‏Bluetooth יישאר מופעל במהלך מצב טיסה"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"בטעינה"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="two"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> קבצים</item>
@@ -2077,8 +2078,7 @@
     <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
     <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"סרגל כיתוב של <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
-    <!-- no translation found for as_app_forced_to_restricted_bucket (8233871289353898964) -->
-    <skip />
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> התווספה לקטגוריה \'מוגבל\'"</string>
     <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
     <skip />
     <!-- no translation found for resolver_work_tab (2690019516263167035) -->
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 1ef4a13..529d011 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"ロック解除パターンの入力を<xliff:g id="NUMBER_0">%1$d</xliff:g>回間違えました。あと<xliff:g id="NUMBER_1">%2$d</xliff:g>回間違えると、モバイルデバイスのロック解除にメールアカウントが必要になります。\n\n<xliff:g id="NUMBER_2">%3$d</xliff:g>秒後にもう一度お試しください。"</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" - "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"削除"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"推奨レベルを超えるまで音量を上げますか?\n\n大音量で長時間聞き続けると、聴力を損なう恐れがあります。"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ユーザー補助機能のショートカットの使用"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"ショートカットが ON の場合、両方の音量ボタンを 3 秒間押し続けるとユーザー補助機能が起動します。\n\n現在のユーザー補助機能:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\nユーザー補助機能は [設定] &gt; [ユーザー補助] で変更できます。"</string>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index 41b2388..3f97338 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"თქვენ არასწორად დახატეთ თქვენი განბლოკვის ნიმუში <xliff:g id="NUMBER_0">%1$d</xliff:g>-ჯერ. კიდევ <xliff:g id="NUMBER_1">%2$d</xliff:g> წარუმატებელი ცდის შემდეგ, დაგჭირდებათ თქვენი ტელეფონის განბლოკვა ელფოსტის ანგარიშის გამოყენებით.\n\n ხელახლა სცადეთ <xliff:g id="NUMBER_2">%3$d</xliff:g> წამში."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"ამოშლა"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"გსურთ ხმის რეკომენდებულ დონეზე მაღლა აწევა?\n\nხანგრძლივად ხმამაღლა მოსმენით შესაძლოა სმენადობა დაიზიანოთ."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"გსურთ მარტივი წვდომის მალსახმობის გამოყენება?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"მალსახმობის ჩართვის შემთხვევაში, ხმის ორივე ღილაკზე 3 წამის განმავლობაში დაჭერით მარტივი წვდომის ფუნქცია ჩაირთვება.\n\n მარტივი წვდომის ამჟამინდელი ფუნქციაა:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n ამ ფუნქციის შეცვლა შეგიძლიათ აქ: პარამეტრები &gt; მარტივი წვდომა."</string>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index 3ea4d351..bccd3f4 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Бекітпені ашу кескінін <xliff:g id="NUMBER_0">%1$d</xliff:g> рет қате сыздыңыз. <xliff:g id="NUMBER_1">%2$d</xliff:g> сәтсіз әрекеттен кейін телефоныңызды есептік жазба арқылы ашу өтінішін аласыз. \n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундтан кейін қайта әрекеттеніңіз."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Алып тастау"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Дыбыс деңгейін ұсынылған деңгейден көтеру керек пе?\n\nЖоғары дыбыс деңгейінде ұзақ кезеңдер бойы тыңдау есту қабілетіңізге зиян тигізуі мүмкін."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Арнайы мүмкіндік төте жолын пайдалану керек пе?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Бұл төте жол қосулы кезде дыбыс деңгейі түймелерінің екеуін де 3 секунд бойы басқанда арнайы мүмкіндік іске қосылады.\n\n Ағымдағы арнайы мүмкіндік:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Бұл мүмкіндікті \"Параметрлер\" &gt; \"Арнайы мүмкіндіктер\" тармағында өзгертуге болады."</string>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index 4f7c0fe..ee451e9 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -1615,6 +1615,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"អ្នក​បាន​គូរ​លំនាំ​ដោះ​​សោ​របស់​អ្នក​មិន​ត្រឹមត្រូវ​ចំនួន <xliff:g id="NUMBER_0">%1$d</xliff:g> ដង។ បន្ទាប់​ពី​ការ​ព្យាយាម​មិន​ជោគជ័យ​​ច្រើនជាង <xliff:g id="NUMBER_1">%2$d</xliff:g> ដង អ្នក​នឹង​ត្រូវ​បាន​​ស្នើ​ឲ្យ​ដោះ​សោ​ទូរស័ព្ទ​របស់​អ្នក​ដោយ​ប្រើ​គណនី​អ៊ីមែល។\n\n ព្យាយាម​ម្ដង​ទៀត​ក្នុង​រយៈ​ពេល <xliff:g id="NUMBER_2">%3$d</xliff:g> វិនាទី។"</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"លុប​ចេញ"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"បង្កើន​កម្រិត​សំឡេង​លើស​ពី​កម្រិត​បាន​ផ្ដល់​យោបល់?\n\nការ​ស្ដាប់​នៅ​កម្រិត​សំឡេង​ខ្លាំង​យូរ​អាច​ធ្វើឲ្យ​ខូច​ត្រចៀក។"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ប្រើប្រាស់​ផ្លូវកាត់​ភាព​ងាយស្រួល?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"នៅពេល​ផ្លូវកាត់​នេះបើក ការ​ចុច​ប៊ូតុង​កម្រិត​សំឡេង​ទាំង​ពីរ​ឲ្យ​ជាប់​រយៈពេល​ 3 វិនាទីនឹង​ចាប់ផ្តើម​មុខងារ​ភាពងាយស្រួល។\n\n មុខងារ​ភាពងាយស្រួល​បច្ចុប្បន្ន៖\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n អ្នក​អាច​ផ្លាស់​ប្តូរ​មុខងារ​នេះ​បាន​នៅក្នុង​ការ កំណត់ &gt; ភាព​ងាយស្រួល។"</string>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index 9efa857..7528284 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"ನಿಮ್ಮ ಅನ್‍‍ಲಾಕ್ ಪ್ಯಾಟರ್ನ್ ಅನ್ನು ನೀವು <xliff:g id="NUMBER_0">%1$d</xliff:g> ಬಾರಿ ತಪ್ಪಾಗಿ ಡ್ರಾ ಮಾಡಿರುವಿರಿ. <xliff:g id="NUMBER_1">%2$d</xliff:g> ಹೆಚ್ಚಿನ ವಿಫಲ ಪ್ರಯತ್ನಗಳ ಬಳಿಕ, ನಿಮ್ಮ ಇಮೇಲ್ ಖಾತೆಯನ್ನು ಬಳಸಿಕೊಂಡು ನಿಮ್ಮ ಫೋನ್ ಅನ್‌ಲಾಕ್ ಮಾಡುವಂತೆ ನಿಮ್ಮಲ್ಲಿ ಕೇಳಿಕೊಳ್ಳಲಾಗುತ್ತದೆ.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> ಸೆಕೆಂಡುಗಳಲ್ಲಿ ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"ತೆಗೆದುಹಾಕು"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"ವಾಲ್ಯೂಮ್‌ ಅನ್ನು ಶಿಫಾರಸು ಮಾಡಲಾದ ಮಟ್ಟಕ್ಕಿಂತಲೂ ಹೆಚ್ಚು ಮಾಡುವುದೇ?\n\nದೀರ್ಘ ಅವಧಿಯವರೆಗೆ ಹೆಚ್ಚಿನ ವಾಲ್ಯೂಮ್‌ನಲ್ಲಿ ಆಲಿಸುವುದರಿಂದ ನಿಮ್ಮ ಆಲಿಸುವಿಕೆ ಸಾಮರ್ಥ್ಯಕ್ಕೆ ಹಾನಿಯುಂಟು ಮಾಡಬಹುದು."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ಪ್ರವೇಶಿಸುವಿಕೆ ಶಾರ್ಟ್‌ಕಟ್ ಬಳಸುವುದೇ?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"ಶಾರ್ಟ್‌ಕಟ್ ಆನ್ ಆಗಿರುವಾಗ ಪ್ರವೇಶಿಸುವಿಕೆ ವೈಶಿಷ್ಟ್ಯ ಆನ್ ಮಾಡಲು, ಎರಡೂ ವಾಲ್ಯೂಮ್ ಬಟನ್‌ಗಳನ್ನು ನೀವು 3 ಸೆಕೆಂಡುಗಳ ಕಾಲ ಒತ್ತಬೇಕು.\n\nಪ್ರಸ್ತುತ ಪ್ರವೇಶಿಸುವಿಕೆ ವೈಶಿಷ್ಟ್ಯ: \n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n ಸೆಟ್ಟಿಂಗ್‌ಗಳು ಮತ್ತು ಪ್ರವೇಶಿಸುವಿಕೆಯಲ್ಲಿ ನೀವು ವೈಶಿಷ್ಟ್ಯವನ್ನು ಬದಲಾಯಿಸಬಹುದು."</string>
@@ -1987,8 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g> ಸ್ಪ್ರೆಡ್‌ಶೀಟ್"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"ಪ್ರಸ್ತುತಿ"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g> ಪ್ರಸ್ತುತಿ"</string>
-    <!-- no translation found for bluetooth_airplane_mode_toast (2066399056595768554) -->
-    <skip />
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"ಏರ್‌ಪ್ಲೇನ್ ಮೋಡ್‌ನಲ್ಲಿರುವಾಗಲೂ ಬ್ಲೂಟೂತ್ ಆನ್ ಆಗಿರುತ್ತದೆ"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"ಲೋಡ್ ಆಗುತ್ತಿದೆ"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="one"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> ಫೈಲ್‌ಗಳು</item>
@@ -2009,8 +2010,7 @@
     <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
     <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಆ್ಯಪ್‌ನ ಶೀರ್ಷಿಕೆಯ ಪಟ್ಟಿ."</string>
-    <!-- no translation found for as_app_forced_to_restricted_bucket (8233871289353898964) -->
-    <skip />
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> ಅನ್ನು ನಿರ್ಬಂಧಿತ ಬಕೆಟ್‌ಗೆ ಹಾಕಲಾಗಿದೆ"</string>
     <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
     <skip />
     <!-- no translation found for resolver_work_tab (2690019516263167035) -->
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 90fa0fa..d5b4507 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"잠금해제 패턴을 <xliff:g id="NUMBER_0">%1$d</xliff:g>회 잘못 그렸습니다. <xliff:g id="NUMBER_1">%2$d</xliff:g>회 더 실패하면 이메일 계정을 사용하여 휴대전화를 잠금해제해야 합니다.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g>초 후에 다시 시도해 주세요."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"삭제"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"권장 수준 이상으로 볼륨을 높이시겠습니까?\n\n높은 볼륨으로 장시간 청취하면 청력에 손상이 올 수 있습니다."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"접근성 단축키를 사용하시겠습니까?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"단축키가 사용 설정된 경우 두 개의 볼륨 버튼을 3초간 누르면 접근성 기능이 시작됩니다.\n\n 현재 접근성 기능:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n \'설정 &gt; 접근성\'에서 기능을 변경할 수 있습니다."</string>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index 07a6e3f..533e0b8 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -540,7 +540,7 @@
     <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Манжа изин күтүү мөөнөтү бүттү. Кайра аракет кылыңыз."</string>
     <string name="fingerprint_error_canceled" msgid="540026881380070750">"Манжа изи иш-аракети жокко чыгарылды."</string>
     <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Манжа изи операциясын колдонуучу жокко чыгарды."</string>
-    <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Аракеттер өтө көп болду. Кийинчерээк кайра аракет кылыңыз."</string>
+    <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Аракеттер өтө көп болду. Бир аздан кийин кайталап көрүңүз."</string>
     <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Өтө көп жолу аракет жасадыңыз. Манжа изинин сенсору өчүрүлдү."</string>
     <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Кайра бир аракеттениңиз."</string>
     <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Бир да манжа изи катталган эмес."</string>
@@ -583,7 +583,7 @@
     <string name="face_error_no_space" msgid="5649264057026021723">"Жаңы жүздү сактоо мүмкүн эмес. Адегенде эскисин өчүрүңүз."</string>
     <string name="face_error_canceled" msgid="2164434737103802131">"Жүздүн аныктыгын текшерүү жокко чыгарылды."</string>
     <string name="face_error_user_canceled" msgid="8553045452825849843">"Жүзүнөн таануу функциясын колдонуучу өчүрүп салды."</string>
-    <string name="face_error_lockout" msgid="7864408714994529437">"Өтө көп жолу аракет жасадыңыз. Кийинчерээк кайра аракет кылыңыз."</string>
+    <string name="face_error_lockout" msgid="7864408714994529437">"Өтө көп жолу аракет жасадыңыз. Бир аздан кийин кайталап көрүңүз."</string>
     <string name="face_error_lockout_permanent" msgid="8277853602168960343">"Өтө көп жолу аракет кылдыңыз. Жүзүнөн таануу функциясы өчүрүлдү."</string>
     <string name="face_error_unable_to_process" msgid="5723292697366130070">"Жүз ырасталбай жатат. Кайра аракет кылыңыз."</string>
     <string name="face_error_not_enrolled" msgid="7369928733504691611">"Жүзүнөн таануу функциясын жөндөй элексиз."</string>
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Графикалык ачкычты <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес көрсөттүңүз. <xliff:g id="NUMBER_1">%2$d</xliff:g> жолу туура эмес көрсөтүлгөндөн кийин, телефондун кулпусун ачуу үчүн Google аккаунтуңузга кирүүгө туура келет.\n\n<xliff:g id="NUMBER_2">%3$d</xliff:g> секундадан кийин кайталап көрсөңүз болот."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Алып салуу"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Сунушталган деңгээлден да катуулатып уккуңуз келеби?\n\nМузыканы узакка чейин катуу уксаңыз, угууңуз начарлап кетиши мүмкүн."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Ыкчам иштетесизби?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Атайын мүмкүнчүлүктөр функциясын пайдалануу үчүн, ал күйгүзүлгөндө, үндү катуулатып/акырындаткан эки баскычты тең үч секунддай кое бербей басып туруңуз.\n\n Учурдагы атайын мүмкүнчүлүктөрдүн жөндөөлөрү:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\nЖөндөөлөр &gt; Атайын мүмкүнчүлүктөр бөлүмүнөн өзгөртө аласыз."</string>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index 05f9698..7a3e85e 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"ທ່ານແຕ້ມຮູບແບບປົດລັອກຂອງທ່ານຜິດ <xliff:g id="NUMBER_0">%1$d</xliff:g> ເທື່ອແລ້ວ. ຫຼັງຈາກຄວາມພະຍາຍາມອີກ <xliff:g id="NUMBER_1">%2$d</xliff:g> ເທື່ອ ທ່ານຈະຖືກຖາມໃຫ້ປົດລັອກໂທລະສັບຂອງທ່ານດ້ວຍບັນຊີອີເມວ.\n\n ລອງໃໝ່ອີກຄັ້ງໃນ <xliff:g id="NUMBER_2">%3$d</xliff:g> ວິນາທີ."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"ລຶບອອກ"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"ເພີ່ມ​ລະ​ດັບ​ສຽງ​ໃຫ້​ເກີນກວ່າ​ລະ​ດັບ​ທີ່​ແນະ​ນຳ​ບໍ?\n\n​ການ​ຮັບ​ຟັງ​ສຽງ​ໃນ​ລະ​ດັບ​ທີ່​ສູງ​ເປັນ​ໄລ​ຍະ​ເວ​ລາ​ດົນ​​ອາດ​ເຮັດ​ໃຫ້​ການ​ຟັງ​ຂອງ​ທ່ານ​ມີ​ບັນ​ຫາ​ໄດ້."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ໃຊ້ປຸ່ມລັດການຊ່ວຍເຂົ້າເຖິງບໍ?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"ເມື່ອເປີດໃຊ້ປຸ່ມລັດແລ້ວ, ໃຫ້ກົດປຸ່ມສຽງທັງສອງຄ້າງໄວ້ 3 ວິນາທີເພື່ອເລີ່ມຄຸນສົມບັດການຊ່ວຍເຂົ້າເຖິງ.\n\n ຄຸນສົມບັດການຊ່ວຍເຂົ້າເຖິງປັດຈຸບັນ:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n ທ່ານສາມາດປ່ຽນຄຸນສົມບັດໄດ້ໃນການຕັ້ງຄ່າ &gt; ການຊ່ວຍເຂົ້າເຖິງ."</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 4f48685..265c97e 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -1657,6 +1657,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Netinkamai nupiešėte atrakinimo piešinį <xliff:g id="NUMBER_0">%1$d</xliff:g> k. Po dar <xliff:g id="NUMBER_1">%2$d</xliff:g> nesėkm. band. būsite paprašyti atrakinti telefoną naudodami „Google“ prisijungimo duomenis.\n\n Bandykite dar kartą po <xliff:g id="NUMBER_2">%3$d</xliff:g> sek."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Pašalinti"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Padidinti garsą daugiau nei rekomenduojamas lygis?\n\nIlgai klausydami dideliu garsu galite pažeisti klausą."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Naudoti spartųjį pritaikymo neįgaliesiems klavišą?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Kai spartusis klavišas įjungtas, spaudžiant abu garsumo mygtukus 3 sekundes bus paleista pritaikymo neįgaliesiems funkcija.\n\n Dabartinė pritaikymo neįgaliesiems funkcija:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>„\n“\n Funkciją galite pakeisti skiltyje „Nustatymai“ &gt; „Pritaikymas neįgaliesiems“."</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index ae9abc6..a535f6d 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -1635,6 +1635,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Jūs nepareizi norādījāt atbloķēšanas kombināciju <xliff:g id="NUMBER_0">%1$d</xliff:g> reizes. Pēc vēl <xliff:g id="NUMBER_1">%2$d</xliff:g> neveiksmīgiem mēģinājumiem tālrunis būs jāatbloķē, izmantojot e-pasta kontu.\n\nMēģiniet vēlreiz pēc <xliff:g id="NUMBER_2">%3$d</xliff:g> sekundēm."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">"  — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Noņemt"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Vai palielināt skaļumu virs ieteicamā līmeņa?\n\nIlgstoši klausoties skaņu lielā skaļumā, var tikt bojāta dzirde."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Vai izmantot pieejamības saīsni?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Ja saīsne ir iespējota, vienlaikus nospiežot abas skaļuma regulēšanas pogas un trīs sekundes turot tās, tiks palaista pieejamības funkcija.\n\n Pašreiz iestatītā pieejamības funkcija:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Šo funkciju var mainīt sadaļā Iestatījumi &gt; Pieejamība."</string>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index f1e5406..2f75269 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -1615,6 +1615,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Погрешно сте ја употребиле вашата шема на отклучување <xliff:g id="NUMBER_0">%1$d</xliff:g> пати. По <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешни обиди, ќе побараат од вас да го отклучите телефонот со користење сметка на е-пошта.\n\n Обидете се повторно за <xliff:g id="NUMBER_2">%3$d</xliff:g> секунди."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Отстрани"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Да го зголемиме звукот над препорачаното ниво?\n\nСлушањето звуци со голема јачина подолги периоди може да ви го оштети сетилото за слух."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Да се користи кратенка за „Пристапност“?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Кога е вклучена кратенката, ако ги притиснете двете копчиња за јачина на звук во времетраење од 3 секунди, ќе се стартува функција на пристапност.\n\n Тековна функција на пристапност:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Функцијата може да ја промените во „Поставки“ &gt; „Пристапност“."</string>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index f0cc48c..25d7212 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"നിങ്ങളുടെ അൺലോക്ക് പാറ്റേൺ <xliff:g id="NUMBER_0">%1$d</xliff:g> തവണ തെറ്റായി വരച്ചു. <xliff:g id="NUMBER_1">%2$d</xliff:g> ശ്രമങ്ങൾ കൂടി വിജയിച്ചില്ലെങ്കിൽ, ഒരു ഇമെയിൽ അക്കൗണ്ട് ഉപയോഗിച്ച് ഫോൺ അൺലോക്ക് ചെയ്യാൻ നിങ്ങളോട് ആവശ്യപ്പെടും.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> സെക്കൻഡിനുള്ള വീണ്ടും ശ്രമിക്കുക."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"നീക്കംചെയ്യുക"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"മുകളിൽക്കൊടുത്തിരിക്കുന്ന ശുപാർശചെയ്‌ത ലെവലിലേക്ക് വോളിയം വർദ്ധിപ്പിക്കണോ?\n\nഉയർന്ന വോളിയത്തിൽ ദീർഘനേരം കേൾക്കുന്നത് നിങ്ങളുടെ ശ്രവണ ശേഷിയെ ദോഷകരമായി ബാധിക്കാം."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ഉപയോഗസഹായി കുറുക്കുവഴി ഉപയോഗിക്കണോ?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"കുറുക്കുവഴി ഓണാണെങ്കിൽ, രണ്ട് വോളിയം ബട്ടണുകളും 3 സെക്കൻഡ് നേരത്തേക്ക് അമർത്തുന്നത് ഉപയോഗസഹായി ഫീച്ചർ ആരംഭിക്കും.\n\n നിലവിലെ  ഉപയോഗസഹായി ഫീച്ചർ:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n ക്രമീകരണം &gt; ഉപയോഗസഹായി എന്നതിൽ ഏത് സമയത്തും നിങ്ങൾക്ക് ഫീച്ചർ മാറ്റാവുന്നതാണ്."</string>
@@ -1987,8 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g> സ്പ്രെഡ്ഷീറ്റ്"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"അവതരണം"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g> അവതരണം"</string>
-    <!-- no translation found for bluetooth_airplane_mode_toast (2066399056595768554) -->
-    <skip />
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"ഫ്ലൈറ്റ് മോഡ് ഓണാക്കിയിരിക്കുമ്പോഴും Bluetooth ലഭ്യമാകും"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"ലോഡ് ചെയ്യുന്നു"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> ഫയലുകൾ</item>
@@ -2009,8 +2010,7 @@
     <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
     <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g> എന്നതിന്റെ അടിക്കുറിപ്പ് ബാർ."</string>
-    <!-- no translation found for as_app_forced_to_restricted_bucket (8233871289353898964) -->
-    <skip />
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> നിയന്ത്രിത ബക്കറ്റിലേക്ക് നീക്കി"</string>
     <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
     <skip />
     <!-- no translation found for resolver_work_tab (2690019516263167035) -->
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 3be3a04..3acdb72 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Та тайлах хээг <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу зурлаа. <xliff:g id="NUMBER_1">%2$d</xliff:g> удаа дахин буруу оруулбал, та утсаа тайлахын тулд имэйл бүртгэлээ ашиглах шаардлагатай болно.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундын дараа дахин оролдоно уу."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Устгах"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Дууг санал болгосноос чанга болгож өсгөх үү?\n\nУрт хугацаанд чанга хөгжим сонсох нь таны сонсголыг муутгаж болно."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Хүртээмжийн товчлолыг ашиглах уу?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Товчлолыг асаасан үед дуун товчлуурыг 3 секунд дарснаар хүртээмжийн онцлогийг эхлүүлнэ.\n\n Одоогийн хүртээмжийн онцлог:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Онцлогийг Тохиргоо &gt; Хүртээмж хэсэгт өөрчлөх боломжтой."</string>
@@ -1987,8 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g>-н хүснэгт"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"Үзүүлэн"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g>-н үзүүлэн"</string>
-    <!-- no translation found for bluetooth_airplane_mode_toast (2066399056595768554) -->
-    <skip />
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Нислэгийн горимын үеэр Bluetooth асаалттай байх болно"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"Ачаалж байна"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> файл</item>
@@ -2009,8 +2010,7 @@
     <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
     <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g>-н гарчгийн талбар."</string>
-    <!-- no translation found for as_app_forced_to_restricted_bucket (8233871289353898964) -->
-    <skip />
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g>-г ХЯЗГААРЛАСАН сагс руу орууллаа"</string>
     <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
     <skip />
     <!-- no translation found for resolver_work_tab (2690019516263167035) -->
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index a2bf479..ff9f3e7 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"तुम्ही तुमचा अनलॉक पॅटर्न <xliff:g id="NUMBER_0">%1$d</xliff:g> वेळा अयोग्यपणे काढला आहे. आणखी <xliff:g id="NUMBER_1">%2$d</xliff:g> अयशस्वी प्रयत्नांनंतर, तुम्हाला ईमेल खाते वापरून तुमचा फोन अनलॉक करण्यास सांगितले जाईल.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकंदांमध्ये पुन्हा प्रयत्न करा."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"काढा"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"शिफारस केलेल्‍या पातळीच्या वर आवाज वाढवायचा?\n\nउच्च आवाजात दीर्घ काळ ऐकण्‍याने आपल्‍या श्रवणशक्तीची हानी होऊ शकते."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"प्रवेशयोग्यता शॉर्टकट वापरायचा?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"शॉर्टकट चालू असताना, दोन्ही आवाज बटणे 3 सेकंद दाबल्याने प्रवेशयोग्यता वैशिष्ट्य सुरू होईल.\n\n वर्तमान प्रवेशयोग्यता वैशिष्ट्य:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n तुम्ही सेटिंग्ज &gt; प्रवेशयोग्यता मध्ये वैशिष्ट्य बदलू शकता."</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index f7626db..e436408 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Anda telah tersilap lukis corak buka kunci sebanyak <xliff:g id="NUMBER_0">%1$d</xliff:g> kali. Selepas <xliff:g id="NUMBER_1">%2$d</xliff:g> lagi percubaan yang tidak berjaya, anda akan diminta membuka kunci telefon anda menggunakan log masuk Google anda.\n\n Cuba lagi dalam <xliff:g id="NUMBER_2">%3$d</xliff:g> saat."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Alih keluar"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Naikkan kelantangan melebihi paras yang disyokorkan?\n\nMendengar pada kelantangan yang tinggi untuk tempoh yang lama boleh merosakkan pendengaran anda."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Gunakan Pintasan Kebolehaksesan?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Apabila pintasan dihidupkan, tindakan menekan kedua-dua butang kelantangan selama 3 saat akan memulakan ciri kebolehaksesan.\n\n Ciri kebolehaksesan semasa:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Anda boleh menukar ciri itu dalam Tetapan &gt; Kebolehaksesan."</string>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index 556837e..56f49c2 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"သင် ပုံဖော်၍သော့ဖွင့်ခြင်းကို <xliff:g id="NUMBER_0">%1$d</xliff:g> အကြိမ် မှန်ကန်စွာ မပြုလုပ်နိုင်ပါ။ နောက်ထပ် <xliff:g id="NUMBER_1">%2$d</xliff:g> အကြိမ် မမှန်ကန်ပါက သင့်ဖုန်းအား အီးမေးလ်အသုံးပြု၍ သော့ဖွင့်ရန် တောင်းဆိုပါလိမ့်မည်။ \n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> စက္ကန့်အကြာတွင် ပြန်လည် ကြိုးစားပါ"</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"ဖယ်ရှားရန်"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"အသံကို အကြံပြုထားသည့် ပမာဏထက် မြှင့်ပေးရမလား?\n\nအသံကို မြင့်သည့် အဆင့်မှာ ကြာရှည်စွာ နားထောင်ခြင်းက သင်၏ နားကို ထိခိုက်စေနိုင်သည်။"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"အများသုံးစွဲနိုင်မှု ဖြတ်လမ်းလင့်ခ်ကို အသုံးပြုလိုပါသလား။"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"ဖြတ်လမ်းလင့်ခ်ကို ဖွင့်ထားစဉ် အသံအတိုးအလျှော့ခလုတ် နှစ်ခုစလုံးကို ၃ စက္ကန့်ခန့် ဖိထားခြင်းဖြင့် အများသုံးစွဲနိုင်မှုဆိုင်ရာ ဝန်ဆောင်မှုကို ဖွင့်နိုင်သည်။\n\n လက်ရှိ အများသုံးစွဲနိုင်မှုဆိုင်ရာ ဝန်ဆောင်မှု−\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n ဝန်ဆောင်မှုကို ဆက်တင်များ &gt; အများသုံးစွဲနိုင်မှုတွင် ပြောင်းလဲနိုင်ပါသည်။"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 6f3b6c2..bb3d52f 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Du har tegnet opplåsningsmønsteret feil <xliff:g id="NUMBER_0">%1$d</xliff:g> ganger. Etter ytterligere <xliff:g id="NUMBER_1">%2$d</xliff:g> gale forsøk, blir du bedt om å låse opp telefonen via en e-postkonto.\n\n Prøv på nytt om <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunder."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Fjern"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Vil du øke volumet til over anbefalt nivå?\n\nHvis du hører på et høyt volum over lengre perioder, kan det skade hørselen din."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Vil du bruke tilgjengelighetssnarveien?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Når snarveien er på, starter en tilgjengelighetsfunksjon når du trykker inn begge volumknappene i tre sekunder.\n\n Nåværende tilgjengelighetsfunksjon:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Du kan endre funksjonen i Innstillinger &gt; Tilgjengelighet."</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index ebbf50b..b3d6cde 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -1619,6 +1619,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"तपाईँले आफ्नो अनलक ढाँचा गलत रूपमा <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक तान्नु भएको छ। <xliff:g id="NUMBER_1">%2$d</xliff:g> धेरै असफल प्रयासहरूपछि, तपाईँलाई एउटा इमेल खाताको प्रयोग गरेर तपाईँको फोन अनलक गर्न सोधिने छ।\n\n फेरि <xliff:g id="NUMBER_2">%3$d</xliff:g> सेकेन्डमा प्रयास गर्नुहोस्।"</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"हटाउनुहोस्"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"सिफारिस तहभन्दा आवाज ठुलो गर्नुहुन्छ?\n\nलामो समय सम्म उच्च आवाजमा सुन्दा तपाईँको सुन्ने शक्तिलाई हानी गर्न सक्छ।"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"पहुँच सम्बन्धी सर्टकट प्रयोग गर्ने हो?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"सर्टकट सक्रिय हुँदा, भोल्युमका दुवै बटनहरूलाई ३ सेकेन्डसम्म थिची राख्नाले पहुँच सम्बन्धी कुनै सुविधा सुरु हुनेछ।\n\n हाल व्यवहारमा रहेको पहुँच सम्बन्धी सुविधा:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n तपाईं सेटिङहरू अन्तर्गतको पहुँच सम्बन्धी विकल्पमा गई उक्त सुविधालाई बदल्न सक्नुहुन्छ।"</string>
@@ -1993,8 +1995,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g> स्प्रेडसिट"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"प्रस्तुति"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g> प्रस्तुति"</string>
-    <!-- no translation found for bluetooth_airplane_mode_toast (2066399056595768554) -->
-    <skip />
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"हवाइजहाज मोडमा ब्लुटुथ सक्रिय रहने छ"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"लोड गर्दै"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> फाइलहरू</item>
@@ -2015,8 +2016,7 @@
     <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
     <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g> को क्याप्सन बार।"</string>
-    <!-- no translation found for as_app_forced_to_restricted_bucket (8233871289353898964) -->
-    <skip />
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> लाई प्रतिबन्धित बाल्टीमा राखियो"</string>
     <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
     <skip />
     <!-- no translation found for resolver_work_tab (2690019516263167035) -->
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 0635c21..47de950 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Je hebt je ontgrendelingspatroon <xliff:g id="NUMBER_0">%1$d</xliff:g> keer onjuist getekend. Na nog eens <xliff:g id="NUMBER_1">%2$d</xliff:g> mislukte pogingen wordt u gevraagd je telefoon te ontgrendelen via een e-mailaccount.\n\n Probeer het over <xliff:g id="NUMBER_2">%3$d</xliff:g> seconden opnieuw."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Verwijderen"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Volume verhogen tot boven het aanbevolen niveau?\n\nAls je langere tijd op hoog volume naar muziek luistert, raakt je gehoor mogelijk beschadigd."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Snelkoppeling toegankelijkheid gebruiken?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Wanneer de snelkoppeling is ingeschakeld, kun je drie seconden op beide volumeknoppen drukken om een toegankelijkheidsfunctie te starten.\n\n Huidige toegankelijkheidsfunctie:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Je kunt de functie wijzigen in Instellingen &gt; Toegankelijkheid."</string>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index 03a7ea3..1242188 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"ଆପଣଙ୍କ ଅନଲକ୍‍ ପାଟର୍ନକୁ ଆପଣ <xliff:g id="NUMBER_0">%1$d</xliff:g> ଥର ଭୁଲ ଭାବେ ଅଙ୍କନ କରିଛନ୍ତି। ଆଉ <xliff:g id="NUMBER_1">%2$d</xliff:g>ଟି ଭୁଲ ପ୍ରୟାସ ପରେ ଏକ ଇମେଲ୍‍ ଆକାଉଣ୍ଟ ବ୍ୟବହାର କରି ନିଜ ଫୋନ୍‌କୁ ଅନଲକ୍‌ କରିବା ପାଇଁ କୁହାଯିବ।\n\n<xliff:g id="NUMBER_2">%3$d</xliff:g> ସେକେଣ୍ଡ ପରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"ବାହାର କରନ୍ତୁ"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"ମାତ୍ରା ବଢ଼ାଇ ସୁପାରିଶ ସ୍ତର ବଢ଼ାଉଛନ୍ତି? \n\n ଲମ୍ବା ସମୟ ପର୍ଯ୍ୟନ୍ତ ଉଚ୍ଚ ଶବ୍ଦରେ ଶୁଣିଲେ ଆପଣଙ୍କ ଶ୍ରବଣ ଶକ୍ତି ଖରାପ ହୋଇପାରେ।"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ଆକ୍ସେସବିଲିଟି ଶର୍ଟକଟ୍‍ ବ୍ୟବହାର କରିବେ?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"ସର୍ଟକଟ୍‌ ଅନ୍‌ ଥିବା ବେଳେ, ଉଭୟ ଭଲ୍ୟୁମ୍‍ ବଟନ୍‍ 3 ସେକେଣ୍ଡ ପାଇଁ ଦବାଇବା ଦ୍ୱାରା ଆକ୍ସେସବିଲିଟି ବୈଶିଷ୍ଟ ଆରମ୍ଭ ହେବ।\n\n ସମ୍ପ୍ରତି ଆକ୍ସେସବିଲିଟି ବୈଶିଷ୍ଟ୍ୟ:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n ସେଟିଙ୍ଗ ଓ ଆକ୍ସେସବିଲିଟିରେ ଆପଣ ବୈଶିଷ୍ଟ୍ୟ ବଦଳାଇ ପାରିବେ।"</string>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index b2cca4d..b6513c3 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਆਪਣਾ ਅਣਲਾਕ ਪੈਟਰਨ ਗਲਤ ਢੰਗ ਨਾਲ ਡ੍ਰਾ ਕੀਤਾ ਹੈ। <xliff:g id="NUMBER_1">%2$d</xliff:g> ਹੋਰ ਅਸਫਲ ਕੋਸ਼ਿਸ਼ਾਂ ਤੋਂ ਬਾਅਦ, ਤੁਹਾਨੂੰ ਇੱਕ ਈਮੇਲ ਖਾਤਾ ਵਰਤਦੇ ਹੋਏ ਆਪਣਾ ਫ਼ੋਨ ਅਣਲਾਕ ਕਰਨ ਲਈ ਕਿਹਾ ਜਾਏਗਾ।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"ਹਟਾਓ"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"ਕੀ ਵੌਲਿਊਮ  ਸਿਫ਼ਾਰਸ਼  ਕੀਤੇ ਪੱਧਰ ਤੋਂ ਵਧਾਉਣੀ ਹੈ?\n\nਲੰਮੇ ਸਮੇਂ ਤੱਕ ਉੱਚ ਵੌਲਿਊਮ ਤੇ ਸੁਣਨ ਨਾਲ ਤੁਹਾਡੀ ਸੁਣਨ ਸ਼ਕਤੀ ਨੂੰ ਨੁਕਸਾਨ ਪਹੁੰਚ ਸਕਦਾ ਹੈ।"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ਕੀ ਪਹੁੰਚਯੋਗਤਾ ਸ਼ਾਰਟਕੱਟ ਵਰਤਣਾ ਹੈ?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"ਸ਼ਾਰਟਕੱਟ ਚਾਲੂ ਹੋਣ \'ਤੇ, ਕਿਸੇ ਪਹੁੰਚਯੋਗਤਾ ਵਿਸ਼ੇਸ਼ਤਾ ਨੂੰ ਸ਼ੁਰੂ ਕਰਨ ਲਈ ਅਵਾਜ਼ ਬਟਨਾਂ ਨੂੰ 3 ਸਕਿੰਟ ਲਈ ਦਬਾ ਕੇ ਰੱਖੋ।\n\n ਵਰਤਮਾਨ ਪਹੁੰਚਯੋਗਤਾ ਵਿਸ਼ੇਸ਼ਤਾ:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n ਤੁਸੀਂ ਸੈਟਿੰਗਾਂ &gt; ਪਹੁੰਚਯੋਗਤਾ ਵਿੱਚ ਵਿਸ਼ੇਸ਼ਤਾ ਨੂੰ ਬਦਲ ਸਕਦੇ ਹੋ।"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 94fd851..964c973 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -1657,6 +1657,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Po raz <xliff:g id="NUMBER_0">%1$d</xliff:g> nieprawidłowo narysowałeś wzór odblokowania. Po kolejnych <xliff:g id="NUMBER_1">%2$d</xliff:g> nieudanych próbach konieczne będzie odblokowanie telefonu przy użyciu danych logowania na konto Google.\n\n Spróbuj ponownie za <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Usuń"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Zwiększyć głośność ponad zalecany poziom?\n\nSłuchanie głośno przez długi czas może uszkodzić Twój słuch."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Użyć skrótu do ułatwień dostępu?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Gdy skrót jest włączony, jednoczesne naciśnięcie przez trzy sekundy obu klawiszy sterowania głośnością uruchomi funkcję ułatwień dostępu.\n\nBieżąca funkcja ułatwień dostępu:\n<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\nFunkcję możesz zmienić, wybierając Ustawienia &gt; Ułatwienia dostępu."</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index 72a3ce9..a6fd0fe 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Você desenhou sua sequência de desbloqueio incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Se fizer mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas incorretas, será solicitado que você use o login do Google para desbloquear.\n\n Tente novamente em <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Remover"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Aumentar o volume acima do nível recomendado?\n\nOuvir em volume alto por longos períodos pode danificar sua audição."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Usar atalho de Acessibilidade?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Quando o atalho está ativado, pressione os dois botões de volume por três segundos para iniciar um recurso de acessibilidade.\n\n Recurso de acessibilidade atual:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n É possível alterar o recurso em Configurações &gt; Acessibilidade."</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 4f45517..81f5ced 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Desenhou o padrão de desbloqueio incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Depois de mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas sem sucesso, ser-lhe-á pedido para desbloquear o telemóvel através de uma conta de email.\n\n Tente novamente dentro de <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" - "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Remover"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Aumentar o volume acima do nível recomendado?\n\nOuvir com um volume elevado durante longos períodos poderá ser prejudicial para a sua audição."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Pretende utilizar o atalho de acessibilidade?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Quando o atalho está ativado, premir ambos os botões de volume durante 3 segundos inicia uma funcionalidade de acessibilidade.\n\n Funcionalidade de acessibilidade atual:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Pode alterar a funcionalidade em Definições &gt; Acessibilidade."</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 72a3ce9..a6fd0fe 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Você desenhou sua sequência de desbloqueio incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. Se fizer mais <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativas incorretas, será solicitado que você use o login do Google para desbloquear.\n\n Tente novamente em <xliff:g id="NUMBER_2">%3$d</xliff:g> segundos."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Remover"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Aumentar o volume acima do nível recomendado?\n\nOuvir em volume alto por longos períodos pode danificar sua audição."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Usar atalho de Acessibilidade?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Quando o atalho está ativado, pressione os dois botões de volume por três segundos para iniciar um recurso de acessibilidade.\n\n Recurso de acessibilidade atual:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n É possível alterar o recurso em Configurações &gt; Acessibilidade."</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index d7cdade..cb8d3fe 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -1635,6 +1635,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Ați desenat incorect modelul pentru deblocare de <xliff:g id="NUMBER_0">%1$d</xliff:g> ori. După încă <xliff:g id="NUMBER_1">%2$d</xliff:g> încercări nereușite, vi se va solicita să deblocați telefonul cu ajutorul unui cont de e-mail.\n\n Încercați din nou peste <xliff:g id="NUMBER_2">%3$d</xliff:g>   secunde."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Eliminați"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Ridicați volumul mai sus de nivelul recomandat?\n\nAscultarea la volum ridicat pe perioade lungi de timp vă poate afecta auzul."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Utilizați comanda rapidă pentru accesibilitate?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Când comanda rapidă este activată, dacă apăsați ambele butoane de volum timp de 3 secunde, veți lansa o funcție de accesibilitate.\n\n Funcția actuală de accesibilitate:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Puteți schimba funcția în Setări &gt; Accesibilitate."</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 91b7ca6..4821c7f 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -1657,6 +1657,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Вы <xliff:g id="NUMBER_0">%1$d</xliff:g> раз неверно указали графический ключ. После <xliff:g id="NUMBER_1">%2$d</xliff:g> неверных попыток для разблокировки телефона потребуется войти в аккаунт Google.\n\nПовтор через <xliff:g id="NUMBER_2">%3$d</xliff:g> сек."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Удалить"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Установить громкость выше рекомендуемого уровня?\n\nВоздействие громкого звука в течение долгого времени может привести к повреждению слуха."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Использовать быстрое включение?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Чтобы использовать функцию специальных возможностей, когда она включена, нажмите и удерживайте три секунды обе кнопки регулировки громкости.\n\nТекущая функция специальных возможностей:\n<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\nВы можете изменить ее в разделе \"Настройки &gt; Специальные возможности\"."</string>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index 601f9b9..df14036 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -1615,6 +1615,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"ඔබ වැරදියට <xliff:g id="NUMBER_0">%1$d</xliff:g> වතාවක් ඔබගේ අගුළු හැරීමේ රටාව ඇඳ ඇත. අසාර්ථක උත්සහ කිරීම් <xliff:g id="NUMBER_1">%2$d</xliff:g> න් පසුව, ඔබගේ ඊ-තැපැල් ලිපිනය භාවිතයෙන් ඔබගේ දුරකථනය අගුළු හැරීමට ඔබගෙන් අසයි.\n\n තත්පර <xliff:g id="NUMBER_2">%3$d</xliff:g> න් පසුව නැවත උත්සහ කරන්න."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"ඉවත් කරන්න"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"නිර්දේශිතයි මට්ටමට වඩා ශබ්දය වැඩිද?\n\nදිගු කාලයක් සඳහා ඉහළ ශබ්දයක් ඇසීමෙන් ඇතැම් විට ඔබගේ ඇසීමට හානි විය හැක."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ප්‍රවේශ්‍යතා කෙටිමඟ භාවිතා කරන්නද?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"කෙටිමඟ සක්‍රිය විට, හඬ බොත්තම් දෙකම තත්පර 3ක් අල්ලාගෙන සිටීමෙන් ප්‍රවේශ්‍යත අංගයක් ඇරඹේ.\n\n වත්මන් ප්‍රවේශ්‍යතා අංගය:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n සැකසීම් &gt; ප්‍රවේශ්‍යතාව තුළ ඔබට අංගය වෙනස් කළ හැක."</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index fb81855..b0dc5f3 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -1657,6 +1657,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"<xliff:g id="NUMBER_0">%1$d</xliff:g>-krát ste nesprávne nakreslili svoj bezpečnostný vzor. Po <xliff:g id="NUMBER_1">%2$d</xliff:g> ďalších neúspešných pokusoch sa zobrazí výzva na odomknutie telefónu pomocou e-mailového účtu.\n\n Skúste to znova o <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Odstrániť"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Zvýšiť hlasitosť nad odporúčanú úroveň?\n\nDlhodobé počúvanie pri vysokej hlasitosti môže poškodiť váš sluch."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Použiť skratku dostupnosti?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Keď je skratka zapnutá, stlačením obidvoch tlačidiel hlasitosti na tri sekundy spustíte funkciu dostupnosti.\n\n Aktuálna funkcia dostupnosti:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Funkciu môžete zmeniť v časti Nastavenia &gt; Dostupnosť."</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 9405fb2..bdd5925 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -1657,6 +1657,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Vzorec za odklepanje ste <xliff:g id="NUMBER_0">%1$d</xliff:g>-krat napačno vnesli. Po nadaljnjih <xliff:g id="NUMBER_1">%2$d</xliff:g> neuspešnih poskusih boste pozvani, da odklenete telefon z Googlovimi podatki za prijavo.\n\nPoskusite znova čez <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Odstrani"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Ali želite povečati glasnost nad priporočeno raven?\n\nDolgotrajno poslušanje pri veliki glasnosti lahko poškoduje sluh."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Želite uporabljati bližnjico funkcij za ljudi s posebnimi potrebami?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Ko je bližnjica vklopljena, pritisnite gumba za glasnost in ju pridržite tri sekunde, če želite zagnati funkcijo za ljudi s posebnimi potrebami.\n\n Trenutna funkcija za ljudi s posebnimi potrebami:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Funkcijo lahko spremenite v »Nastavitve &gt; Funkcije za ljudi s posebnimi potrebami«."</string>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index fe167da..fd8dda0 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Ke vizatuar <xliff:g id="NUMBER_0">%1$d</xliff:g> herë pa sukses motivin tënd. Pas <xliff:g id="NUMBER_1">%2$d</xliff:g> tentativave të tjera të pasuksesshme, do të të duhet ta shkyçësh telefonin duke përdorur një llogari mail-i.\n\n Provo sërish për <xliff:g id="NUMBER_2">%3$d</xliff:g> sekonda."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" - "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Hiq"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Të ngrihet volumi mbi nivelin e rekomanduar?\n\nDëgjimi me volum të lartë për periudha të gjata mund të dëmtojë dëgjimin."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Të përdoret shkurtorja e qasshmërisë?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Kur shkurtorja është e aktivizuar, shtypja e të dy butonave për 3 sekonda do të nisë një funksion qasshmërie.\n\n Funksioni aktual i qasshmërisë:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Mund ta ndryshosh funksionin te Cilësimet &gt; Qasshmëria."</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 564612c..d82faa6 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -1635,6 +1635,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Нацртали сте шаблон за откључавање нетачно <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. После још <xliff:g id="NUMBER_1">%2$d</xliff:g> неуспешна(их) покушаја, од вас ће бити затражено да откључате телефон помоћу налога е-поште.\n\nПробајте поново за <xliff:g id="NUMBER_2">%3$d</xliff:g> секунде/и."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Уклони"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Желите да појачате звук изнад препорученог нивоа?\n\nСлушање гласне музике дуже време може да вам оштети слух."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Желите ли да користите пречицу за приступачност?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Када је пречица укључена, притисните оба дугмета за јачину звука да бисте покренули функцију приступачности.\n\n Актуелна функција приступачности:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Можете да промените функцију у одељку Подешавања &gt; Приступачност."</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 4332352..9c7e1e5 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Du har ritat ditt grafiska lösenord fel <xliff:g id="NUMBER_0">%1$d</xliff:g> gånger. Efter ytterligare <xliff:g id="NUMBER_1">%2$d</xliff:g> försök ombeds du låsa upp mobilen med hjälp av ett e-postkonto.\n\n Försök igen om <xliff:g id="NUMBER_2">%3$d</xliff:g> sekunder."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Ta bort"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Vill du höja volymen över den rekommenderade nivån?\n\nAtt lyssna med stark volym långa stunder åt gången kan skada hörseln."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Vill du använda Aktivera tillgänglighet snabbt?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"När kortkommandot har aktiverats startar du en tillgänglighetsfunktion genom att trycka ned båda volymknapparna i tre sekunder.\n\n Aktuell tillgänglighetsfunktion:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Du kan ändra funktionen i Inställningar &gt; Tillgänglighet."</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index d1bff3f5..f53efe0 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Umekosea kuchora mchoro wako wa kufungua mara <xliff:g id="NUMBER_0">%1$d</xliff:g>. Baada ya majaribio <xliff:g id="NUMBER_1">%2$d</xliff:g> yasiyofaulu, utaombwa kufungua simu yako kwa kutumia akaunti ya barua pepe.\n\n Jaribu tena baada ya sekunde <xliff:g id="NUMBER_2">%3$d</xliff:g>."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Ondoa"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Ungependa kupandisha sauti zaidi ya kiwango kinachopendekezwa?\n\nKusikiliza kwa sauti ya juu kwa muda mrefu kunaweza kuharibu uwezo wako wa kusikia."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Ungependa kutumia njia ya mkato ya ufikivu?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Unapowasha kipengele cha njia ya mkato, hatua ya kubonyeza vitufe vyote viwili vya sauti kwa dakika 3 itafungua kipengele cha ufikivu.\n\n Kipengele cha ufikivu kilichopo kwa sasa:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Unaweza kubadilisha kipengele hiki katika Mipangilio &gt; Zana za ufikivu."</string>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index 5444f36..c7c4ea3 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"திறப்பதற்கான வடிவத்தை <xliff:g id="NUMBER_0">%1$d</xliff:g> முறை தவறாக வரைந்துள்ளீர்கள். மேலும் <xliff:g id="NUMBER_1">%2$d</xliff:g> தோல்வி முயற்சிகளுக்குப் பிறகு, மின்னஞ்சல் கணக்கைப் பயன்படுத்தி உங்கள் மொபைலைத் திறக்கக் கேட்கப்படுவீர்கள்.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> வினாடிகள் கழித்து முயற்சிக்கவும்."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"அகற்று"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"பரிந்துரைத்த அளவை விட ஒலியை அதிகரிக்கவா?\n\nநீண்ட நேரத்திற்கு அதிகளவில் ஒலி கேட்பது கேட்கும் திறனைப் பாதிக்கலாம்."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"அணுகல்தன்மை ஷார்ட்கட்டைப் பயன்படுத்தவா?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"ஷார்ட்கட் இயக்கத்தில் இருந்தால், இரண்டு ஒலியளவு பொத்தான்களையும் 3 வினாடிகள் அழுத்தி, அணுகல்தன்மை அம்சத்தை இயக்கலாம்.\n\n தற்போதைய அணுகல்தன்மை அம்சம்:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n அமைப்புகள் &gt; அணுகல்தன்மை என்பதற்குச் சென்று, அம்சத்தை மாற்றலாம்."</string>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index f9f6479..9c77ccd 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"మీరు మీ అన్‌లాక్ నమూనాను <xliff:g id="NUMBER_0">%1$d</xliff:g> సార్లు తప్పుగా గీసారు. మరో <xliff:g id="NUMBER_1">%2$d</xliff:g> విఫల ప్రయత్నాల తర్వాత, ఇమెయిల్ ఖాతాను ఉపయోగించి మీ ఫోన్‌ను అన్‌లాక్ చేయాల్సిందిగా మిమ్మల్ని అడుగుతారు.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> సెకన్లలో మళ్లీ ప్రయత్నించండి."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"తీసివేయి"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"వాల్యూమ్‌ను సిఫార్సు చేయబడిన స్థాయి కంటే ఎక్కువగా పెంచాలా?\n\nసుదీర్ఘ వ్యవధుల పాటు అధిక వాల్యూమ్‌లో వినడం వలన మీ వినికిడి శక్తి దెబ్బ తినవచ్చు."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"యాక్సెస్ సామర్థ్యం షార్ట్‌కట్‌ను ఉపయోగించాలా?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"షార్ట్‌కట్ ఆన్‌లో ఉన్నప్పుడు, రెండు వాల్యూమ్ బటన్‌లను 3 సెకన్ల పాటు నొక్కితే యాక్సెస్ సామర్థ్య ఫీచర్ ప్రారంభం అవుతుంది.\n\n ప్రస్తుత యాక్సెస్ సామర్థ్య ఫీచర్:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n సెట్టింగ్‌లు &gt; యాక్సెస్ సామర్థ్యంలో మీరు ఫీచర్‌ను మార్చవచ్చు."</string>
@@ -1987,8 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g> స్ప్రెడ్‌షీట్"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"ప్రదర్శన"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g> ప్రదర్శన"</string>
-    <!-- no translation found for bluetooth_airplane_mode_toast (2066399056595768554) -->
-    <skip />
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"విమానం మోడ్‌లో బ్లూటూత్ ఆన్‌లో ఉంటుంది"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"లోడవుతోంది"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> ఫైల్‌లు</item>
@@ -2009,8 +2010,7 @@
     <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
     <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g> క్యాప్షన్ బార్."</string>
-    <!-- no translation found for as_app_forced_to_restricted_bucket (8233871289353898964) -->
-    <skip />
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> పరిమితం చేయబడిన బకెట్‌లో ఉంచబడింది"</string>
     <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
     <skip />
     <!-- no translation found for resolver_work_tab (2690019516263167035) -->
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 7796b03..efff25b 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"คุณวาดรูปแบบการปลดล็อกไม่ถูกต้อง <xliff:g id="NUMBER_0">%1$d</xliff:g> ครั้งแล้ว หากทำไม่สำเร็จอีก <xliff:g id="NUMBER_1">%2$d</xliff:g> ครั้ง ระบบจะขอให้คุณปลดล็อกโทรศัพท์โดยใช้ับัญชีอีเมล\n\n โปรดลองอีกครั้งในอีก <xliff:g id="NUMBER_2">%3$d</xliff:g> วินาที"</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"ลบ"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"นี่เป็นการเพิ่มระดับเสียงเกินระดับที่แนะนำ\n\nการฟังเสียงดังเป็นเวลานานอาจทำให้การได้ยินของคุณบกพร่องได้"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ใช้ทางลัดการช่วยเหลือพิเศษไหม"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"เมื่อทางลัดเปิดอยู่ การกดปุ่มปรับระดับเสียงทั้ง 2 ปุ่มเป็นเวลา 3 วินาทีจะเริ่มฟีเจอร์การช่วยเหลือพิเศษ\n\n ฟีเจอร์การช่วยเหลือพิเศษปัจจุบัน:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n คุณสามารถเปลี่ยนฟีเจอร์ในการตั้งค่า &gt; การช่วยเหลือพิเศษ"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index d15bcd7..7cfa7b0 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Naguhit mo nang hindi tama ang iyong pattern sa pag-unlock nang <xliff:g id="NUMBER_0">%1$d</xliff:g> (na) beses. Pagkatapos ng <xliff:g id="NUMBER_1">%2$d</xliff:g> pang hindi matagumpay na pagtatangka, hihilingin sa iyong i-unlock ang telepono mo gamit ang isang email account.\n\n Subukang muli sa loob ng <xliff:g id="NUMBER_2">%3$d</xliff:g> (na) segundo."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Alisin"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Lakasan ang volume nang lagpas sa inirerekomendang antas?\n\nMaaaring mapinsala ng pakikinig sa malakas na volume sa loob ng mahahabang panahon ang iyong pandinig."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Gagamitin ang Shortcut sa Pagiging Accessible?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Kapag naka-on ang shortcut, magsisimula ang isang feature ng pagiging naa-access kapag pinindot ang parehong button ng volume sa loob ng 3 segundo.\n\n Kasalukuyang feature ng pagiging naa-access:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Maaari mong baguhin ang feature sa Mga Setting &gt; Pagiging Accessible."</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index e5559c5..b47eb4b 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Kilit açma deseninizi <xliff:g id="NUMBER_0">%1$d</xliff:g> kez yanlış çizdiniz. <xliff:g id="NUMBER_1">%2$d</xliff:g> başarısız denemeden sonra telefonunuzu bir e-posta hesabı kullanarak açmanız istenir.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> saniye içinde tekrar deneyin."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Kaldır"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Ses seviyesi önerilen düzeyin üzerine yükseltilsin mi?\n\nUzun süre yüksek ses seviyesinde dinlemek işitme duyunuza zarar verebilir."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Erişilebilirlik Kısayolu Kullanılsın mı?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Kısayol açık olduğunda, ses düğmelerinin ikisini birden 3 saniyeliğine basılı tutmanız bir erişilebilirlik özelliğini başlatır.\n\n Geçerli erişilebilirlik özelliği:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Özelliği, Ayarlar &gt; Erişilebilirlik seçeneğinden değiştirebilirsiniz."</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 7c06892e..22aa199 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -1657,6 +1657,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Ключ розблокування неправильно намальовано стільки разів: <xliff:g id="NUMBER_0">%1$d</xliff:g>. У вас є ще стільки спроб: <xliff:g id="NUMBER_1">%2$d</xliff:g>. У разі невдачі з’явиться запит розблокувати телефон за допомогою облікового запису електронної пошти.\n\n Повторіть спробу через <xliff:g id="NUMBER_2">%3$d</xliff:g> сек."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" – "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Вилучити"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Збільшити гучність понад рекомендований рівень?\n\nЯкщо слухати надто гучну музику тривалий час, можна пошкодити слух."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Використовувати швидке ввімкнення?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Коли ярлик увімкнено, після натискання обох клавіш гучності й утримування їх протягом 3 секунд увімкнеться функція спеціальних можливостей.\n\n Поточна функція спеціальних можливостей:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Цю функцію можна змінити в меню \"Налаштування\" &gt; \"Спеціальні можливості\"."</string>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index 1b00720..a88d6c5 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"آپ نے اپنا غیر مقفل کرنے کا پیٹرن <xliff:g id="NUMBER_0">%1$d</xliff:g> بار غلط طریقے سے ڈرا کیا ہے۔ <xliff:g id="NUMBER_1">%2$d</xliff:g> مزید ناکام کوششوں کے بعد، آپ سے ایک ای میل اکاؤنٹ استعمال کرکے اپنا فون غیر مقفل کرنے کو کہا جائے گا۔\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> سیکنڈ میں دوبارہ کوشش کریں۔"</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"ہٹائیں"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"والیوم کو تجویز کردہ سطح سے زیادہ کریں؟\n\nزیادہ وقت تک اونچی آواز میں سننے سے آپ کی سماعت کو نقصان پہنچ سکتا ہے۔"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"ایکسیسبیلٹی شارٹ کٹ استعمال کریں؟"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"شارٹ کٹ آن ہونے پر، 3 سیکنڈ تک دونوں والیوم بٹنز کو دبانے سے ایک ایکسیسبیلٹی خصوصیت شروع ہو جائے گی۔\n\n موجودہ ایکسیسبیلٹی خصوصیت:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n آپ خصوصیت کو ترتیبات &gt; ایکسیسبیلٹی میں جا کر تبدیل کر سکتے ہیں۔"</string>
@@ -1987,8 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g> اسپریڈشیٹ"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"پیشکش"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g> پیشکش"</string>
-    <!-- no translation found for bluetooth_airplane_mode_toast (2066399056595768554) -->
-    <skip />
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"ہوائی جہاز وضع کے دوران بلوٹوتھ آن رہے گا"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"لوڈ ہو رہا ہے"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> فائلز</item>
@@ -2009,8 +2010,7 @@
     <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
     <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g> کی کیپشن بار۔"</string>
-    <!-- no translation found for as_app_forced_to_restricted_bucket (8233871289353898964) -->
-    <skip />
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> کو پابند کردہ بکٹ میں رکھ دیا گیا ہے"</string>
     <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
     <skip />
     <!-- no translation found for resolver_work_tab (2690019516263167035) -->
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index 1193d27..a08b178 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Siz grafik kalitni <xliff:g id="NUMBER_0">%1$d</xliff:g> marta noto‘g‘ri chizdingiz. <xliff:g id="NUMBER_1">%2$d</xliff:g> marta muvaffaqiyatsiz urinishdan so‘ng, sizdan e-pochtangizdan foydalanib, telefon qulfini ochishingiz so‘raladi.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> soniyadan so‘ng yana urinib ko‘ring."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Olib tashlash"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Tovush balandligi tavsiya etilgan darajadan ham yuqori qilinsinmi?\n\nUzoq vaqt davomida baland ovozda tinglash eshitish qobiliyatingizga salbiy ta’sir ko‘rsatishi mumkin."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Tezkor ishga tushirishdan foydalanilsinmi?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Maxsus imkoniyatlar funksiyasidan foydalanish uchun u yoniqligida ikkala ovoz balandligini boshqarish tugmasini 3 soniya bosib turing.\n\n Joriy maxsus imkoniyatlar funksiyasi:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Bu funksiyani Sozlamalar &gt; Maxsus imkoniyatlar orqali o‘zgartirish mumkin."</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 7cfd870..db55613 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Bạn đã <xliff:g id="NUMBER_0">%1$d</xliff:g> lần vẽ không chính xác hình mở khóa của mình. Sau <xliff:g id="NUMBER_1">%2$d</xliff:g> lần thử không thành công nữa, bạn sẽ được yêu cầu mở khóa điện thoại bằng tài khoản email.\n\n Vui lòng thử lại sau <xliff:g id="NUMBER_2">%3$d</xliff:g> giây."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Xóa"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Bạn tăng âm lượng lên quá mức khuyên dùng?\n\nViệc nghe ở mức âm lượng cao trong thời gian dài có thể gây tổn thương thính giác của bạn."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Sử dụng phím tắt Hỗ trợ tiếp cận?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Khi phím tắt được bật, nhấn cả hai nút âm lượng trong 3 giây sẽ bắt đầu một tính năng trợ năng.\n\n Tính năng trợ năng hiện tại:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Bạn có thể thay đổi tính năng trong Cài đặt &gt; Trợ năng."</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 5d7ad5a..08d2326 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"您已连续 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次画错解锁图案。如果再尝试 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次后仍不成功,系统就会要求您使用自己的电子邮件帐号解锁手机。\n\n请在 <xliff:g id="NUMBER_2">%3$d</xliff:g> 秒后重试。"</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"删除"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"要将音量调高到建议的音量以上吗?\n\n长时间保持高音量可能会损伤听力。"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"要使用无障碍快捷方式吗?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"开启快捷方式后,同时按下两个音量按钮 3 秒钟即可启动所设定的无障碍功能。\n\n当前设定的无障碍功能:\n<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n如需更改设定的功能,请依次转到“设置”&gt;“无障碍”。"</string>
@@ -1987,8 +1989,7 @@
     <string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"<xliff:g id="EXTENSION">%1$s</xliff:g> 电子表格"</string>
     <string name="mime_type_presentation" msgid="1145384236788242075">"演示文稿"</string>
     <string name="mime_type_presentation_ext" msgid="8761049335564371468">"<xliff:g id="EXTENSION">%1$s</xliff:g> 演示文稿"</string>
-    <!-- no translation found for bluetooth_airplane_mode_toast (2066399056595768554) -->
-    <skip />
+    <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"在飞行模式下,蓝牙将保持开启状态"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"正在加载"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> 个文件</item>
@@ -2009,8 +2010,7 @@
     <!-- no translation found for accessibility_system_action_accessibility_menu_label (8436484650391125184) -->
     <skip />
     <string name="accessibility_freeform_caption" msgid="8377519323496290122">"<xliff:g id="APP_NAME">%1$s</xliff:g>的标题栏。"</string>
-    <!-- no translation found for as_app_forced_to_restricted_bucket (8233871289353898964) -->
-    <skip />
+    <string name="as_app_forced_to_restricted_bucket" msgid="8233871289353898964">"<xliff:g id="PACKAGE_NAME">%1$s</xliff:g> 已被放入受限存储分区"</string>
     <!-- no translation found for resolver_personal_tab (2051260504014442073) -->
     <skip />
     <!-- no translation found for resolver_work_tab (2690019516263167035) -->
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 361eb4c..ea106c6 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"您已畫錯解鎖圖案 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次,如果再嘗試 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次仍未成功,系統會要求您透過電郵帳戶解開上鎖的手機。\n\n請在 <xliff:g id="NUMBER_2">%3$d</xliff:g> 秒後再試一次。"</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"移除"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"要調高音量 (比建議的音量更大聲) 嗎?\n\n長時間聆聽高分貝音量可能會導致您的聽力受損。"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"要使用無障礙功能快速鍵嗎?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"快速鍵開啟後,同時按住音量按鈕 3 秒,無障礙功能便會啟用。\n\n目前的無障礙功能:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n如要變更功能,請前往「設定」&gt;「無障礙功能」。"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 2bcae59..7065181 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"你的解鎖圖案已畫錯 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次,如果再嘗試 <xliff:g id="NUMBER_1">%2$d</xliff:g> 次仍未成功,系統就會要求你透過電子郵件帳戶解除手機的鎖定狀態。\n\n請在 <xliff:g id="NUMBER_2">%3$d</xliff:g> 秒後再試一次。"</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"移除"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"要調高音量,比建議的音量更大聲嗎?\n\n長時間聆聽高分貝音量可能會使你的聽力受損。"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"要使用無障礙捷徑嗎?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"啟用捷徑功能後,只要同時按下兩個音量鍵 3 秒,就能啟動無障礙功能。\n\n 目前設定的無障礙功能為:\n<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n 如要變更設定的功能,請依序輕觸 [設定] &gt; [無障礙設定]。"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index e96696e..1cb67e1 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -1613,6 +1613,8 @@
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"Ukulayisha ungenisa iphathini yakho yokuvula ngendlela engalungile izikhathi ezi-<xliff:g id="NUMBER_0">%1$d</xliff:g> Emva kweminye imizamo engu-<xliff:g id="NUMBER_1">%2$d</xliff:g>, uzocelwa ukuvula ifoni yakho usebenzisa ukungena ngemvume ku-Google\n\n Zame futhi emumva kwengu- <xliff:g id="NUMBER_2">%3$d</xliff:g> amasekhondi."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Susa"</string>
+    <!-- no translation found for allow_while_in_use_permission_in_fgs (4101339676785053656) -->
+    <skip />
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Khuphukisa ivolumu ngaphezu kweleveli enconyiwe?\n\nUkulalela ngevolumu ephezulu izikhathi ezide kungahle kulimaze ukuzwa kwakho."</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Sebenzisa isinqamuleli sokufinyelela?"</string>
     <string name="accessibility_shortcut_toogle_warning" msgid="8306239551412868396">"Uma kuvulwe isinqamuleli, ukucindezela zombili izinkinobho zevolumu amasekhondi angu-3 kuzoqala isici sokufinyelela.\n\n Isici samanje sokufinyelela:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n Ungashintsha isici kuzilungiselelo &gt; Ukufinyelela."</string>
diff --git a/core/tests/coretests/Android.bp b/core/tests/coretests/Android.bp
index 3836d6f..38454ec 100644
--- a/core/tests/coretests/Android.bp
+++ b/core/tests/coretests/Android.bp
@@ -41,6 +41,7 @@
         "truth-prebuilt",
         "print-test-util-lib",
         "testng",
+        "servicestests-utils"
     ],
 
     libs: [
diff --git a/core/tests/coretests/src/android/app/PullAtomMetadataTest.java b/core/tests/coretests/src/android/app/PullAtomMetadataTest.java
index 2e3f892..0ae6134 100644
--- a/core/tests/coretests/src/android/app/PullAtomMetadataTest.java
+++ b/core/tests/coretests/src/android/app/PullAtomMetadataTest.java
@@ -32,7 +32,7 @@
 
     @Test
     public void testEmpty() {
-        PullAtomMetadata metadata = PullAtomMetadata.newBuilder().build();
+        PullAtomMetadata metadata = new PullAtomMetadata.Builder().build();
         assertThat(metadata.getTimeoutNs()).isEqualTo(StatsManager.DEFAULT_TIMEOUT_NS);
         assertThat(metadata.getCoolDownNs()).isEqualTo(StatsManager.DEFAULT_COOL_DOWN_NS);
         assertThat(metadata.getAdditiveFields()).isNull();
@@ -42,7 +42,7 @@
     public void testSetTimeoutNs() {
         long timeoutNs = 500_000_000L;
         PullAtomMetadata metadata =
-                PullAtomMetadata.newBuilder().setTimeoutNs(timeoutNs).build();
+                new PullAtomMetadata.Builder().setTimeoutNs(timeoutNs).build();
         assertThat(metadata.getTimeoutNs()).isEqualTo(timeoutNs);
         assertThat(metadata.getCoolDownNs()).isEqualTo(StatsManager.DEFAULT_COOL_DOWN_NS);
         assertThat(metadata.getAdditiveFields()).isNull();
@@ -52,7 +52,7 @@
     public void testSetCoolDownNs() {
         long coolDownNs = 10_000_000_000L;
         PullAtomMetadata metadata =
-                PullAtomMetadata.newBuilder().setCoolDownNs(coolDownNs).build();
+                new PullAtomMetadata.Builder().setCoolDownNs(coolDownNs).build();
         assertThat(metadata.getTimeoutNs()).isEqualTo(StatsManager.DEFAULT_TIMEOUT_NS);
         assertThat(metadata.getCoolDownNs()).isEqualTo(coolDownNs);
         assertThat(metadata.getAdditiveFields()).isNull();
@@ -62,7 +62,7 @@
     public void testSetAdditiveFields() {
         int[] fields = {2, 4, 6};
         PullAtomMetadata metadata =
-                PullAtomMetadata.newBuilder().setAdditiveFields(fields).build();
+                new PullAtomMetadata.Builder().setAdditiveFields(fields).build();
         assertThat(metadata.getTimeoutNs()).isEqualTo(StatsManager.DEFAULT_TIMEOUT_NS);
         assertThat(metadata.getCoolDownNs()).isEqualTo(StatsManager.DEFAULT_COOL_DOWN_NS);
         assertThat(metadata.getAdditiveFields()).isEqualTo(fields);
@@ -73,7 +73,7 @@
         long timeoutNs = 300L;
         long coolDownNs = 9572L;
         int[] fields = {3, 2};
-        PullAtomMetadata metadata = PullAtomMetadata.newBuilder()
+        PullAtomMetadata metadata = new PullAtomMetadata.Builder()
                 .setTimeoutNs(timeoutNs)
                 .setCoolDownNs(coolDownNs)
                 .setAdditiveFields(fields)
diff --git a/core/tests/coretests/src/android/content/integrity/AtomicFormulaTest.java b/core/tests/coretests/src/android/content/integrity/AtomicFormulaTest.java
index c0d9be5..7328f35 100644
--- a/core/tests/coretests/src/android/content/integrity/AtomicFormulaTest.java
+++ b/core/tests/coretests/src/android/content/integrity/AtomicFormulaTest.java
@@ -16,10 +16,10 @@
 
 package android.content.integrity;
 
-import static android.content.integrity.TestUtils.assertExpectException;
-
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.testng.Assert.expectThrows;
+
 import android.content.integrity.AtomicFormula.BooleanAtomicFormula;
 import android.content.integrity.AtomicFormula.StringAtomicFormula;
 import android.os.Parcel;
@@ -133,35 +133,38 @@
 
     @Test
     public void testInvalidAtomicFormula_stringValue() {
-        assertExpectException(
-                IllegalArgumentException.class,
-                /* expectedExceptionMessageRegex */
-                String.format("Key VERSION_CODE cannot be used with StringAtomicFormula"),
-                () ->
-                        new StringAtomicFormula(
-                                AtomicFormula.VERSION_CODE,
-                                "test-value",
-                                /* isHashedValue= */ false));
+        Exception e =
+                expectThrows(
+                        IllegalArgumentException.class,
+                        () ->
+                                new StringAtomicFormula(
+                                        AtomicFormula.VERSION_CODE,
+                                        "test-value",
+                                        /* isHashedValue= */ false));
+        assertThat(e.getMessage()).matches(
+                "Key VERSION_CODE cannot be used with StringAtomicFormula");
     }
 
     @Test
     public void testInvalidAtomicFormula_longValue() {
-        assertExpectException(
-                IllegalArgumentException.class,
-                /* expectedExceptionMessageRegex */
-                String.format("Key PACKAGE_NAME cannot be used with LongAtomicFormula"),
-                () ->
-                        new AtomicFormula.LongAtomicFormula(
-                                AtomicFormula.PACKAGE_NAME, AtomicFormula.EQ, 1));
+        Exception e =
+                expectThrows(
+                        IllegalArgumentException.class,
+                        () ->
+                                new AtomicFormula.LongAtomicFormula(
+                                        AtomicFormula.PACKAGE_NAME, AtomicFormula.EQ, 1));
+        assertThat(e.getMessage()).matches(
+                "Key PACKAGE_NAME cannot be used with LongAtomicFormula");
     }
 
     @Test
     public void testInvalidAtomicFormula_boolValue() {
-        assertExpectException(
-                IllegalArgumentException.class,
-                /* expectedExceptionMessageRegex */
-                String.format("Key PACKAGE_NAME cannot be used with BooleanAtomicFormula"),
-                () -> new BooleanAtomicFormula(AtomicFormula.PACKAGE_NAME, true));
+        Exception e =
+                expectThrows(
+                        IllegalArgumentException.class,
+                        () -> new BooleanAtomicFormula(AtomicFormula.PACKAGE_NAME, true));
+        assertThat(e.getMessage()).matches(
+                "Key PACKAGE_NAME cannot be used with BooleanAtomicFormula");
     }
 
     @Test
@@ -205,20 +208,24 @@
 
     @Test
     public void testInvalidAtomicFormula_invalidKey() {
-        assertExpectException(
-                IllegalArgumentException.class,
-                /* expectedExceptionMessageRegex */ "Unknown key: -1",
-                () -> new AtomicFormula.LongAtomicFormula(/* key= */ -1, AtomicFormula.EQ, 0));
+        Exception e =
+                expectThrows(
+                        IllegalArgumentException.class,
+                        () -> new AtomicFormula.LongAtomicFormula(/* key= */ -1,
+                                AtomicFormula.EQ, /* value= */0));
+        assertThat(e.getMessage()).matches("Unknown key: -1");
     }
 
     @Test
     public void testInvalidAtomicFormula_invalidOperator() {
-        assertExpectException(
-                IllegalArgumentException.class,
-                /* expectedExceptionMessageRegex */ "Unknown operator: -1",
-                () ->
-                        new AtomicFormula.LongAtomicFormula(
-                                AtomicFormula.VERSION_CODE, /* operator= */ -1, 0));
+        Exception e =
+                expectThrows(
+                        IllegalArgumentException.class,
+                        () ->
+                                new AtomicFormula.LongAtomicFormula(
+                                        AtomicFormula.VERSION_CODE, /* operator= */ -1, /* value= */
+                                        0));
+        assertThat(e.getMessage()).matches("Unknown operator: -1");
     }
 
     @Test
diff --git a/core/tests/coretests/src/android/content/integrity/CompoundFormulaTest.java b/core/tests/coretests/src/android/content/integrity/CompoundFormulaTest.java
index fa3d671..4054c49 100644
--- a/core/tests/coretests/src/android/content/integrity/CompoundFormulaTest.java
+++ b/core/tests/coretests/src/android/content/integrity/CompoundFormulaTest.java
@@ -16,11 +16,9 @@
 
 package android.content.integrity;
 
-import static android.content.integrity.TestUtils.assertExpectException;
-
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.junit.Assert.assertEquals;
+import static org.testng.Assert.expectThrows;
 
 import android.os.Parcel;
 
@@ -46,32 +44,32 @@
                 new CompoundFormula(
                         CompoundFormula.AND, Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2));
 
-        assertEquals(CompoundFormula.AND, compoundFormula.getConnector());
-        assertEquals(
-                Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2), compoundFormula.getFormulas());
+        assertThat(compoundFormula.getConnector()).isEqualTo(CompoundFormula.AND);
+        assertThat(compoundFormula.getFormulas()).containsAllOf(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2);
     }
 
     @Test
     public void testValidateAuxiliaryFormula_binaryConnectors() {
-        assertExpectException(
-                IllegalArgumentException.class,
-                /* expectedExceptionMessageRegex */
-                "Connector AND must have at least 2 formulas",
-                () ->
-                        new CompoundFormula(
-                                CompoundFormula.AND, Collections.singletonList(ATOMIC_FORMULA_1)));
+        Exception e =
+                expectThrows(
+                        IllegalArgumentException.class,
+                        () ->
+                                new CompoundFormula(
+                                        CompoundFormula.AND,
+                                        Collections.singletonList(ATOMIC_FORMULA_1)));
+        assertThat(e.getMessage()).matches("Connector AND must have at least 2 formulas");
     }
 
     @Test
     public void testValidateAuxiliaryFormula_unaryConnectors() {
-        assertExpectException(
-                IllegalArgumentException.class,
-                /* expectedExceptionMessageRegex */
-                "Connector NOT must have 1 formula only",
-                () ->
-                        new CompoundFormula(
-                                CompoundFormula.NOT,
-                                Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2)));
+        Exception e =
+                expectThrows(
+                        IllegalArgumentException.class,
+                        () ->
+                                new CompoundFormula(
+                                        CompoundFormula.NOT,
+                                        Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2)));
+        assertThat(e.getMessage()).matches("Connector NOT must have 1 formula only");
     }
 
     @Test
@@ -82,20 +80,20 @@
         Parcel p = Parcel.obtain();
         formula.writeToParcel(p, 0);
         p.setDataPosition(0);
-        CompoundFormula newFormula = CompoundFormula.CREATOR.createFromParcel(p);
 
-        assertEquals(formula, newFormula);
+        assertThat(CompoundFormula.CREATOR.createFromParcel(p)).isEqualTo(formula);
     }
 
     @Test
     public void testInvalidCompoundFormula_invalidConnector() {
-        assertExpectException(
-                IllegalArgumentException.class,
-                /* expectedExceptionMessageRegex */ "Unknown connector: -1",
-                () ->
-                        new CompoundFormula(
-                                /* connector= */ -1,
-                                Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2)));
+        Exception e =
+                expectThrows(
+                        IllegalArgumentException.class,
+                        () ->
+                                new CompoundFormula(
+                                        /* connector= */ -1,
+                                        Arrays.asList(ATOMIC_FORMULA_1, ATOMIC_FORMULA_2)));
+        assertThat(e.getMessage()).matches("Unknown connector: -1");
     }
 
     @Test
diff --git a/core/tests/coretests/src/android/content/integrity/IntegrityUtilsTest.java b/core/tests/coretests/src/android/content/integrity/IntegrityUtilsTest.java
index 639adf6..e6f6686 100644
--- a/core/tests/coretests/src/android/content/integrity/IntegrityUtilsTest.java
+++ b/core/tests/coretests/src/android/content/integrity/IntegrityUtilsTest.java
@@ -18,6 +18,7 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.testng.Assert.expectThrows;
 import static org.testng.internal.junit.ArrayAsserts.assertArrayEquals;
 
 import org.junit.Test;
@@ -43,15 +44,20 @@
     }
 
     @Test
-    public void testInvalidHexDigest() {
-        TestUtils.assertExpectException(
-                IllegalArgumentException.class,
-                "must have even length",
-                () -> IntegrityUtils.getBytesFromHexDigest("ABC"));
+    public void testInvalidHexDigest_mustHaveEvenLength() {
+        Exception e =
+                expectThrows(
+                        IllegalArgumentException.class,
+                        () -> IntegrityUtils.getBytesFromHexDigest("ABC"));
+        assertThat(e.getMessage()).containsMatch("must have even length");
+    }
 
-        TestUtils.assertExpectException(
-                IllegalArgumentException.class,
-                "Invalid hex char",
-                () -> IntegrityUtils.getBytesFromHexDigest("GH"));
+    @Test
+    public void testInvalidHexDigest_invalidHexChar() {
+        Exception e =
+                expectThrows(
+                        IllegalArgumentException.class,
+                        () -> IntegrityUtils.getBytesFromHexDigest("GH"));
+        assertThat(e.getMessage()).containsMatch("Invalid hex char");
     }
 }
diff --git a/core/tests/coretests/src/android/content/integrity/RuleTest.java b/core/tests/coretests/src/android/content/integrity/RuleTest.java
index 8c4cfca..8faf8ba 100644
--- a/core/tests/coretests/src/android/content/integrity/RuleTest.java
+++ b/core/tests/coretests/src/android/content/integrity/RuleTest.java
@@ -16,10 +16,9 @@
 
 package android.content.integrity;
 
-import static android.content.integrity.TestUtils.assertExpectException;
+import static com.google.common.truth.Truth.assertThat;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
+import static org.testng.Assert.expectThrows;
 
 import android.os.Parcel;
 
@@ -50,16 +49,16 @@
     public void testValidRule() {
         Rule validRule = new Rule(PACKAGE_NAME_ATOMIC_FORMULA, DENY_EFFECT);
 
-        assertEquals(PACKAGE_NAME_ATOMIC_FORMULA, validRule.getFormula());
-        assertEquals(DENY_EFFECT, validRule.getEffect());
+        assertThat(validRule.getFormula()).isEqualTo(PACKAGE_NAME_ATOMIC_FORMULA);
+        assertThat(validRule.getEffect()).isEqualTo(DENY_EFFECT);
     }
 
     @Test
     public void testInvalidRule_invalidFormula() {
-        assertExpectException(
-                NullPointerException.class,
-                /* expectedExceptionMessageRegex */ null,
-                () -> new Rule(null, DENY_EFFECT));
+        Exception e =
+                expectThrows(
+                        NullPointerException.class,
+                        () -> new Rule(null, DENY_EFFECT));
     }
 
     @Test
@@ -70,27 +69,23 @@
                         Arrays.asList(PACKAGE_NAME_ATOMIC_FORMULA, APP_CERTIFICATE_ATOMIC_FORMULA));
         Rule rule = new Rule(compoundFormula, Rule.DENY);
 
-        assertEquals(
-                String.format(
-                        "Rule: (PACKAGE_NAME EQ %s) AND (APP_CERTIFICATE EQ %s), DENY",
-                        PACKAGE_NAME, APP_CERTIFICATE),
-                rule.toString());
+        assertThat(rule.toString())
+                .isEqualTo(
+                        String.format(
+                                "Rule: (PACKAGE_NAME EQ %s) AND (APP_CERTIFICATE EQ %s), DENY",
+                                PACKAGE_NAME, APP_CERTIFICATE));
     }
 
     @Test
     public void testEquals_trueCase() {
-        Rule rule1 = new Rule(PACKAGE_NAME_ATOMIC_FORMULA, DENY_EFFECT);
-        Rule rule2 = new Rule(PACKAGE_NAME_ATOMIC_FORMULA, DENY_EFFECT);
-
-        assertEquals(rule1, rule2);
+        assertThat(new Rule(PACKAGE_NAME_ATOMIC_FORMULA, DENY_EFFECT))
+                .isEqualTo(new Rule(PACKAGE_NAME_ATOMIC_FORMULA, DENY_EFFECT));
     }
 
     @Test
     public void testEquals_falseCase() {
-        Rule rule1 = new Rule(PACKAGE_NAME_ATOMIC_FORMULA, DENY_EFFECT);
-        Rule rule2 = new Rule(APP_CERTIFICATE_ATOMIC_FORMULA, DENY_EFFECT);
-
-        assertNotEquals(rule1, rule2);
+        assertThat(new Rule(PACKAGE_NAME_ATOMIC_FORMULA, DENY_EFFECT))
+                .isNotEqualTo(new Rule(APP_CERTIFICATE_ATOMIC_FORMULA, DENY_EFFECT));
     }
 
     @Test
@@ -108,16 +103,16 @@
         Parcel p = Parcel.obtain();
         rule.writeToParcel(p, 0);
         p.setDataPosition(0);
-        Rule newRule = Rule.CREATOR.createFromParcel(p);
 
-        assertEquals(newRule, rule);
+        assertThat(Rule.CREATOR.createFromParcel(p)).isEqualTo(rule);
     }
 
     @Test
     public void testInvalidRule_invalidEffect() {
-        assertExpectException(
-                IllegalArgumentException.class,
-                /* expectedExceptionMessageRegex */ "Unknown effect: -1",
-                () -> new Rule(PACKAGE_NAME_ATOMIC_FORMULA, /* effect= */ -1));
+        Exception e =
+                expectThrows(
+                        IllegalArgumentException.class,
+                        () -> new Rule(PACKAGE_NAME_ATOMIC_FORMULA, /* effect= */ -1));
+        assertThat(e.getMessage()).isEqualTo("Unknown effect: -1");
     }
 }
diff --git a/core/tests/coretests/src/android/content/integrity/TestUtils.java b/core/tests/coretests/src/android/content/integrity/TestUtils.java
deleted file mode 100644
index af984cf..0000000
--- a/core/tests/coretests/src/android/content/integrity/TestUtils.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.content.integrity;
-
-import android.test.MoreAsserts;
-
-import junit.framework.Assert;
-
-/** Helper methods used in tests. */
-class TestUtils {
-    private TestUtils() {}
-
-    public interface ExceptionRunnable {
-        void run() throws Exception;
-    }
-
-    public static void assertExpectException(
-            Class<? extends Throwable> expectedExceptionType,
-            String expectedExceptionMessageRegex,
-            ExceptionRunnable r) {
-        try {
-            r.run();
-        } catch (Throwable e) {
-            Assert.assertTrue(
-                    "Expected exception type was "
-                            + expectedExceptionType.getName()
-                            + " but caught "
-                            + e.getClass().getName(),
-                    expectedExceptionType.isAssignableFrom(e.getClass()));
-            if (expectedExceptionMessageRegex != null) {
-                MoreAsserts.assertContainsRegex(expectedExceptionMessageRegex, e.getMessage());
-            }
-            return; // Pass.
-        }
-        Assert.fail(
-                "Expected exception type " + expectedExceptionType.getName() + " was not thrown");
-    }
-}
diff --git a/core/tests/coretests/src/android/provider/NameValueCacheTest.java b/core/tests/coretests/src/android/provider/NameValueCacheTest.java
new file mode 100644
index 0000000..4212ef2
--- /dev/null
+++ b/core/tests/coretests/src/android/provider/NameValueCacheTest.java
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.provider;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+
+import android.content.ContentProvider;
+import android.content.IContentProvider;
+import android.os.Bundle;
+import android.platform.test.annotations.Presubmit;
+import android.test.mock.MockContentResolver;
+import android.util.MemoryIntArray;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * These tests are verifying that Settings#NameValueCache is working as expected with DeviceConfig.
+ * Due to how the classes are structured, we have to test it in a somewhat roundabout way. We're
+ * mocking out the contentProvider and are handcrafting very specific Bundles to answer the queries.
+ */
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class NameValueCacheTest {
+
+    private static final String NAMESPACE = "namespace";
+    private static final String NAMESPACE2 = "namespace2";
+
+    @Mock
+    private IContentProvider mMockIContentProvider;
+    @Mock
+    private ContentProvider mMockContentProvider;
+    private MockContentResolver mMockContentResolver;
+    private MemoryIntArray mCacheGenerationStore;
+    private int mCurrentGeneration = 123;
+
+    private HashMap<String, HashMap<String, String>> mStorage;
+
+    @Before
+    public void setUp() throws Exception {
+        Settings.Config.clearProviderForTest();
+        MockitoAnnotations.initMocks(this);
+        when(mMockContentProvider.getIContentProvider()).thenReturn(mMockIContentProvider);
+        mMockContentResolver = new MockContentResolver();
+        mMockContentResolver.addProvider(DeviceConfig.CONTENT_URI.getAuthority(),
+                mMockContentProvider);
+        mCacheGenerationStore = new MemoryIntArray(1);
+        mStorage = new HashMap<>();
+
+        // Stores keyValues for a given prefix and increments the generation. (Note that this
+        // increments the generation no matter what, it doesn't pay attention to if anything
+        // actually changed).
+        when(mMockIContentProvider.call(any(), any(), eq(DeviceConfig.CONTENT_URI.getAuthority()),
+                eq(Settings.CALL_METHOD_SET_ALL_CONFIG),
+                any(), any(Bundle.class))).thenAnswer(invocationOnMock -> {
+                    Bundle incomingBundle = invocationOnMock.getArgument(5);
+                    HashMap<String, String> keyValues =
+                            (HashMap<String, String>) incomingBundle.getSerializable(
+                                    Settings.CALL_METHOD_FLAGS_KEY);
+                    String prefix = incomingBundle.getString(Settings.CALL_METHOD_PREFIX_KEY);
+                    mStorage.put(prefix, keyValues);
+                    mCacheGenerationStore.set(0, ++mCurrentGeneration);
+
+                    Bundle result = new Bundle();
+                    result.putBoolean(Settings.KEY_CONFIG_SET_RETURN, true);
+                    return result;
+                });
+
+        // Returns the keyValues corresponding to a namespace, or an empty map if the namespace
+        // doesn't have anything stored for it. Returns the generation key if the caller asked
+        // for one.
+        when(mMockIContentProvider.call(any(), any(), eq(DeviceConfig.CONTENT_URI.getAuthority()),
+                eq(Settings.CALL_METHOD_LIST_CONFIG),
+                any(), any(Bundle.class))).thenAnswer(invocationOnMock -> {
+                    Bundle incomingBundle = invocationOnMock.getArgument(5);
+
+                    String prefix = incomingBundle.getString(Settings.CALL_METHOD_PREFIX_KEY);
+
+                    if (!mStorage.containsKey(prefix)) {
+                        mStorage.put(prefix, new HashMap<>());
+                    }
+                    HashMap<String, String> keyValues = mStorage.get(prefix);
+
+                    Bundle bundle = new Bundle();
+                    bundle.putSerializable(Settings.NameValueTable.VALUE, keyValues);
+
+                    if (incomingBundle.containsKey(Settings.CALL_METHOD_TRACK_GENERATION_KEY)) {
+                        bundle.putParcelable(Settings.CALL_METHOD_TRACK_GENERATION_KEY,
+                                mCacheGenerationStore);
+                        bundle.putInt(Settings.CALL_METHOD_GENERATION_INDEX_KEY, 0);
+                        bundle.putInt(Settings.CALL_METHOD_GENERATION_KEY,
+                                mCacheGenerationStore.get(0));
+                    }
+                    return bundle;
+                });
+    }
+
+    @Test
+    public void testCaching_singleNamespace() throws Exception {
+        HashMap<String, String> keyValues = new HashMap<>();
+        keyValues.put("a", "b");
+        Settings.Config.setStrings(mMockContentResolver, NAMESPACE, keyValues);
+        verify(mMockIContentProvider).call(any(), any(), any(),
+                eq(Settings.CALL_METHOD_SET_ALL_CONFIG),
+                any(), any(Bundle.class));
+
+        Map<String, String> returnedValues = Settings.Config.getStrings(mMockContentResolver,
+                NAMESPACE,
+                Collections.emptyList());
+        verify(mMockIContentProvider).call(any(), any(), any(),
+                eq(Settings.CALL_METHOD_LIST_CONFIG),
+                any(), any(Bundle.class));
+        assertThat(returnedValues).containsExactlyEntriesIn(keyValues);
+
+        Map<String, String> cachedKeyValues = Settings.Config.getStrings(mMockContentResolver,
+                NAMESPACE, Collections.emptyList());
+        verifyNoMoreInteractions(mMockIContentProvider);
+        assertThat(cachedKeyValues).containsExactlyEntriesIn(keyValues);
+
+        // Modify the value to invalidate the cache.
+        keyValues.put("a", "c");
+        Settings.Config.setStrings(mMockContentResolver, NAMESPACE, keyValues);
+        verify(mMockIContentProvider, times(2)).call(any(), any(), any(),
+                eq(Settings.CALL_METHOD_SET_ALL_CONFIG),
+                any(), any(Bundle.class));
+
+        Map<String, String> returnedValues2 = Settings.Config.getStrings(mMockContentResolver,
+                NAMESPACE, Collections.emptyList());
+        verify(mMockIContentProvider, times(2)).call(any(), any(), any(),
+                eq(Settings.CALL_METHOD_LIST_CONFIG),
+                any(), any(Bundle.class));
+        assertThat(returnedValues2).containsExactlyEntriesIn(keyValues);
+
+        Map<String, String> cachedKeyValues2 = Settings.Config.getStrings(mMockContentResolver,
+                NAMESPACE, Collections.emptyList());
+        verifyNoMoreInteractions(mMockIContentProvider);
+        assertThat(cachedKeyValues2).containsExactlyEntriesIn(keyValues);
+    }
+
+    @Test
+    public void testCaching_multipleNamespaces() throws Exception {
+        HashMap<String, String> keyValues = new HashMap<>();
+        keyValues.put("a", "b");
+        Settings.Config.setStrings(mMockContentResolver, NAMESPACE, keyValues);
+        verify(mMockIContentProvider).call(any(), any(), any(),
+                eq(Settings.CALL_METHOD_SET_ALL_CONFIG),
+                any(), any(Bundle.class));
+
+        HashMap<String, String> keyValues2 = new HashMap<>();
+        keyValues2.put("c", "d");
+        keyValues2.put("e", "f");
+        Settings.Config.setStrings(mMockContentResolver, NAMESPACE2, keyValues2);
+        verify(mMockIContentProvider, times(2)).call(any(), any(), any(),
+                eq(Settings.CALL_METHOD_SET_ALL_CONFIG),
+                any(), any(Bundle.class));
+
+        Map<String, String> returnedValues = Settings.Config.getStrings(mMockContentResolver,
+                NAMESPACE,
+                Collections.emptyList());
+        verify(mMockIContentProvider).call(any(), any(), any(),
+                eq(Settings.CALL_METHOD_LIST_CONFIG),
+                any(), any(Bundle.class));
+        assertThat(returnedValues).containsExactlyEntriesIn(keyValues);
+
+        Map<String, String> returnedValues2 = Settings.Config.getStrings(mMockContentResolver,
+                NAMESPACE2,
+                Collections.emptyList());
+        verify(mMockIContentProvider, times(2)).call(any(), any(), any(),
+                eq(Settings.CALL_METHOD_LIST_CONFIG),
+                any(), any(Bundle.class));
+        assertThat(returnedValues2).containsExactlyEntriesIn(keyValues2);
+
+        Map<String, String> cachedKeyValues = Settings.Config.getStrings(mMockContentResolver,
+                NAMESPACE, Collections.emptyList());
+        verifyNoMoreInteractions(mMockIContentProvider);
+        assertThat(cachedKeyValues).containsExactlyEntriesIn(keyValues);
+
+        Map<String, String> cachedKeyValues2 = Settings.Config.getStrings(mMockContentResolver,
+                NAMESPACE2, Collections.emptyList());
+        verifyNoMoreInteractions(mMockIContentProvider);
+        assertThat(cachedKeyValues2).containsExactlyEntriesIn(keyValues2);
+    }
+
+    @Test
+    public void testCaching_emptyNamespace() throws Exception {
+        Map<String, String> returnedValues = Settings.Config.getStrings(mMockContentResolver,
+                NAMESPACE,
+                Collections.emptyList());
+        verify(mMockIContentProvider).call(any(), any(), any(),
+                eq(Settings.CALL_METHOD_LIST_CONFIG),
+                any(), any(Bundle.class));
+        assertThat(returnedValues).isEmpty();
+
+        Map<String, String> cachedKeyValues = Settings.Config.getStrings(mMockContentResolver,
+                NAMESPACE, Collections.emptyList());
+        verifyNoMoreInteractions(mMockIContentProvider);
+        assertThat(cachedKeyValues).isEmpty();
+    }
+
+}
diff --git a/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java b/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
index bcf0b8c..169716f 100644
--- a/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
+++ b/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
@@ -176,8 +176,6 @@
         when(mMockController.getState()).thenReturn(mInsetsState);
         mController.finish(true /* shown */);
         mController.applyChangeInsets(mInsetsState);
-        assertTrue(mInsetsState.getSource(ITYPE_STATUS_BAR).isVisible());
-        assertTrue(mInsetsState.getSource(ITYPE_NAVIGATION_BAR).isVisible());
         assertEquals(Insets.of(0, 100, 100, 0), mController.getCurrentInsets());
         verify(mMockController).notifyFinished(eq(mController), eq(true /* shown */));
     }
diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java
index f720c98..e68c4b8 100644
--- a/core/tests/coretests/src/android/view/InsetsControllerTest.java
+++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java
@@ -19,10 +19,13 @@
 import static android.view.InsetsController.ANIMATION_TYPE_HIDE;
 import static android.view.InsetsController.ANIMATION_TYPE_NONE;
 import static android.view.InsetsController.ANIMATION_TYPE_SHOW;
+import static android.view.InsetsSourceConsumer.ShowResult.IME_SHOW_DELAYED;
+import static android.view.InsetsSourceConsumer.ShowResult.SHOW_IMMEDIATELY;
 import static android.view.InsetsState.ITYPE_IME;
 import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
 import static android.view.InsetsState.ITYPE_STATUS_BAR;
 import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL;
+import static android.view.WindowInsets.Type.ime;
 import static android.view.WindowInsets.Type.statusBars;
 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
 
@@ -32,6 +35,8 @@
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.notNull;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
@@ -41,6 +46,7 @@
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
+import android.view.SurfaceControl.Transaction;
 import android.view.WindowInsets.Type;
 import android.view.WindowManager.BadTokenException;
 import android.view.WindowManager.LayoutParams;
@@ -48,6 +54,9 @@
 import android.view.test.InsetsModeSession;
 import android.widget.TextView;
 
+import com.android.server.testutils.OffsettableClock;
+import com.android.server.testutils.TestHandler;
+
 import androidx.test.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
 
@@ -59,6 +68,7 @@
 import org.mockito.ArgumentCaptor;
 
 import java.util.concurrent.CountDownLatch;
+import java.util.function.Supplier;
 
 /**
  * Tests for {@link InsetsController}.
@@ -77,6 +87,8 @@
     private SurfaceSession mSession = new SurfaceSession();
     private SurfaceControl mLeash;
     private ViewRootImpl mViewRoot;
+    private TestHandler mTestHandler;
+    private OffsettableClock mTestClock;
     private static InsetsModeSession sInsetsModeSession;
 
     @BeforeClass
@@ -103,7 +115,26 @@
             } catch (BadTokenException e) {
                 // activity isn't running, we will ignore BadTokenException.
             }
-            mController = new InsetsController(mViewRoot);
+            mTestClock = new OffsettableClock();
+            mTestHandler = new TestHandler(null, mTestClock);
+            mController = new InsetsController(mViewRoot, (controller, type) -> {
+                if (type == ITYPE_IME) {
+                    return new InsetsSourceConsumer(type, controller.getState(),
+                            Transaction::new, controller) {
+                        @Override
+                        public int requestShow(boolean fromController) {
+                            if (fromController) {
+                                return SHOW_IMMEDIATELY;
+                            } else {
+                                return IME_SHOW_DELAYED;
+                            }
+                        }
+                    };
+                } else {
+                    return new InsetsSourceConsumer(type, controller.getState(), Transaction::new,
+                            controller);
+                }
+            }, mTestHandler);
             final Rect rect = new Rect(5, 5, 5, 5);
             mController.getState().getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 10));
             mController.getState().getSource(ITYPE_NAVIGATION_BAR).setFrame(
@@ -395,6 +426,71 @@
         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
     }
 
+    @Test
+    public void testControlImeNotReady() {
+        prepareControls();
+        InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+            WindowInsetsAnimationControlListener listener =
+                    mock(WindowInsetsAnimationControlListener.class);
+            mController.controlInputMethodAnimation(0, new LinearInterpolator(), listener);
+
+            // Ready gets deferred until next predraw
+            mViewRoot.getView().getViewTreeObserver().dispatchOnPreDraw();
+
+            verify(listener, never()).onReady(any(), anyInt());
+
+            // Pretend that IME is calling.
+            mController.show(ime(), true);
+
+            // Ready gets deferred until next predraw
+            mViewRoot.getView().getViewTreeObserver().dispatchOnPreDraw();
+
+            verify(listener).onReady(notNull(), eq(ime()));
+
+        });
+    }
+
+    @Test
+    public void testControlImeNotReady_controlRevoked() {
+        prepareControls();
+        InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+            WindowInsetsAnimationControlListener listener =
+                    mock(WindowInsetsAnimationControlListener.class);
+            mController.controlInputMethodAnimation(0, new LinearInterpolator(), listener);
+
+            // Ready gets deferred until next predraw
+            mViewRoot.getView().getViewTreeObserver().dispatchOnPreDraw();
+
+            verify(listener, never()).onReady(any(), anyInt());
+
+            // Pretend that we are losing control
+            mController.onControlsChanged(new InsetsSourceControl[0]);
+
+            verify(listener).onCancelled();
+        });
+    }
+
+    @Test
+    public void testControlImeNotReady_timeout() {
+        prepareControls();
+        InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+            WindowInsetsAnimationControlListener listener =
+                    mock(WindowInsetsAnimationControlListener.class);
+            mController.controlInputMethodAnimation(0, new LinearInterpolator(), listener);
+
+            // Ready gets deferred until next predraw
+            mViewRoot.getView().getViewTreeObserver().dispatchOnPreDraw();
+
+            verify(listener, never()).onReady(any(), anyInt());
+
+            // Pretend that timeout is happening
+            mTestClock.fastForward(2500);
+            mTestHandler.timeAdvance();
+
+            verify(listener).onCancelled();
+        });
+    }
+
     private void waitUntilNextFrame() throws Exception {
         final CountDownLatch latch = new CountDownLatch(1);
         Choreographer.getMainThreadInstance().postCallback(Choreographer.CALLBACK_COMMIT,
diff --git a/core/tests/coretests/src/android/view/KeyEventTest.java b/core/tests/coretests/src/android/view/KeyEventTest.java
index 88d3bdb..14999c7 100644
--- a/core/tests/coretests/src/android/view/KeyEventTest.java
+++ b/core/tests/coretests/src/android/view/KeyEventTest.java
@@ -20,8 +20,10 @@
 
 import static org.junit.Assert.assertEquals;
 
+import android.os.Parcel;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -40,6 +42,7 @@
     private static final int SCAN_CODE = 0;
     private static final int FLAGS = 0;
     private static final int SOURCE = InputDevice.SOURCE_KEYBOARD;
+    private static final byte[] HMAC = null;
     private static final String CHARACTERS = null;
 
     @Test
@@ -65,25 +68,15 @@
         KeyEvent keyEvent = KeyEvent.obtain(DOWN_TIME, EVENT_TIME, ACTION, KEYCODE, REPEAT,
                 METASTATE, DEVICE_ID, SCAN_CODE, FLAGS, SOURCE, CHARACTERS);
         KeyEvent keyEvent2 = KeyEvent.obtain(keyEvent);
-        assertEquals(keyEvent.getDownTime(), keyEvent2.getDownTime());
-        assertEquals(keyEvent.getEventTime(), keyEvent2.getEventTime());
-        assertEquals(keyEvent.getAction(), keyEvent2.getAction());
-        assertEquals(keyEvent.getKeyCode(), keyEvent2.getKeyCode());
-        assertEquals(keyEvent.getRepeatCount(), keyEvent2.getRepeatCount());
-        assertEquals(keyEvent.getMetaState(), keyEvent2.getMetaState());
-        assertEquals(keyEvent.getDeviceId(), keyEvent2.getDeviceId());
-        assertEquals(keyEvent.getScanCode(), keyEvent2.getScanCode());
-        assertEquals(keyEvent.getFlags(), keyEvent2.getFlags());
-        assertEquals(keyEvent.getSource(), keyEvent2.getSource());
-        assertEquals(keyEvent.getDisplayId(), keyEvent2.getDisplayId());
-        assertEquals(keyEvent.getCharacters(), keyEvent2.getCharacters());
+        compareKeys(keyEvent, keyEvent2);
     }
 
     @Test
     public void testObtainWithDisplayId() {
         final int displayId = 5;
         KeyEvent keyEvent = KeyEvent.obtain(DOWN_TIME, EVENT_TIME, ACTION, KEYCODE, REPEAT,
-                METASTATE, DEVICE_ID, SCAN_CODE, FLAGS, SOURCE, displayId, CHARACTERS);
+                METASTATE, DEVICE_ID, SCAN_CODE, FLAGS, SOURCE, displayId, null /* hmac*/,
+                CHARACTERS);
         assertEquals(DOWN_TIME, keyEvent.getDownTime());
         assertEquals(EVENT_TIME, keyEvent.getEventTime());
         assertEquals(ACTION, keyEvent.getAction());
@@ -97,4 +90,44 @@
         assertEquals(displayId, keyEvent.getDisplayId());
         assertEquals(CHARACTERS, keyEvent.getCharacters());
     }
+
+    @Test
+    public void testParcelUnparcel() {
+        KeyEvent key1 = createKey();
+        Parcel parcel = Parcel.obtain();
+        key1.writeToParcel(parcel, 0 /*flags*/);
+        parcel.setDataPosition(0);
+
+        KeyEvent key2 = KeyEvent.CREATOR.createFromParcel(parcel);
+        parcel.recycle();
+
+        compareKeys(key1, key2);
+    }
+
+    @Test
+    public void testConstructor() {
+        KeyEvent key1 = createKey();
+        KeyEvent key2 = new KeyEvent(key1);
+        compareKeys(key1, key2);
+    }
+
+    private static KeyEvent createKey() {
+        return KeyEvent.obtain(DOWN_TIME, EVENT_TIME, ACTION, KEYCODE, REPEAT,
+                METASTATE, DEVICE_ID, SCAN_CODE, FLAGS, SOURCE, INVALID_DISPLAY, HMAC, CHARACTERS);
+    }
+
+    private static void compareKeys(KeyEvent key1, KeyEvent key2) {
+        assertEquals(key1.getDownTime(), key2.getDownTime());
+        assertEquals(key1.getEventTime(), key2.getEventTime());
+        assertEquals(key1.getAction(), key2.getAction());
+        assertEquals(key1.getKeyCode(), key2.getKeyCode());
+        assertEquals(key1.getRepeatCount(), key2.getRepeatCount());
+        assertEquals(key1.getMetaState(), key2.getMetaState());
+        assertEquals(key1.getDeviceId(), key2.getDeviceId());
+        assertEquals(key1.getScanCode(), key2.getScanCode());
+        assertEquals(key1.getFlags(), key2.getFlags());
+        assertEquals(key1.getSource(), key2.getSource());
+        assertEquals(key1.getDisplayId(), key2.getDisplayId());
+        assertEquals(key1.getCharacters(), key2.getCharacters());
+    }
 }
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index 9a0ca3e..d949444 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -1162,6 +1162,7 @@
      * @see #quickReject(float, float, float, float, EdgeType)
      * @see #quickReject(Path, EdgeType)
      * @see #quickReject(RectF, EdgeType)
+     * @deprecated quickReject no longer uses this.
      */
     public enum EdgeType {
 
@@ -1197,13 +1198,30 @@
      *              non-antialiased ({@link Canvas.EdgeType#BW}).
      * @return      true if the rect (transformed by the canvas' matrix)
      *              does not intersect with the canvas' clip
+     * @deprecated The EdgeType is ignored. Use {@link #quickReject(RectF)} instead.
      */
+    @Deprecated
     public boolean quickReject(@NonNull RectF rect, @NonNull EdgeType type) {
         return nQuickReject(mNativeCanvasWrapper,
                 rect.left, rect.top, rect.right, rect.bottom);
     }
 
     /**
+     * Return true if the specified rectangle, after being transformed by the
+     * current matrix, would lie completely outside of the current clip. Call
+     * this to check if an area you intend to draw into is clipped out (and
+     * therefore you can skip making the draw calls).
+     *
+     * @param rect  the rect to compare with the current clip
+     * @return      true if the rect (transformed by the canvas' matrix)
+     *              does not intersect with the canvas' clip
+     */
+    public boolean quickReject(@NonNull RectF rect) {
+        return nQuickReject(mNativeCanvasWrapper,
+                rect.left, rect.top, rect.right, rect.bottom);
+    }
+
+    /**
      * Return true if the specified path, after being transformed by the
      * current matrix, would lie completely outside of the current clip. Call
      * this to check if an area you intend to draw into is clipped out (and
@@ -1217,12 +1235,30 @@
      *                    non-antialiased ({@link Canvas.EdgeType#BW}).
      * @return            true if the path (transformed by the canvas' matrix)
      *                    does not intersect with the canvas' clip
+     * @deprecated The EdgeType is ignored. Use {@link #quickReject(Path)} instead.
      */
+    @Deprecated
     public boolean quickReject(@NonNull Path path, @NonNull EdgeType type) {
         return nQuickReject(mNativeCanvasWrapper, path.readOnlyNI());
     }
 
     /**
+     * Return true if the specified path, after being transformed by the
+     * current matrix, would lie completely outside of the current clip. Call
+     * this to check if an area you intend to draw into is clipped out (and
+     * therefore you can skip making the draw calls). Note: for speed it may
+     * return false even if the path itself might not intersect the clip
+     * (i.e. the bounds of the path intersects, but the path does not).
+     *
+     * @param path        The path to compare with the current clip
+     * @return            true if the path (transformed by the canvas' matrix)
+     *                    does not intersect with the canvas' clip
+     */
+    public boolean quickReject(@NonNull Path path) {
+        return nQuickReject(mNativeCanvasWrapper, path.readOnlyNI());
+    }
+
+    /**
      * Return true if the specified rectangle, after being transformed by the
      * current matrix, would lie completely outside of the current clip. Call
      * this to check if an area you intend to draw into is clipped out (and
@@ -1241,13 +1277,37 @@
      *                    non-antialiased ({@link Canvas.EdgeType#BW}).
      * @return            true if the rect (transformed by the canvas' matrix)
      *                    does not intersect with the canvas' clip
+     * @deprecated The EdgeType is ignored. Use {@link #quickReject(float, float, float, float)}
+     *             instead.
      */
+    @Deprecated
     public boolean quickReject(float left, float top, float right, float bottom,
             @NonNull EdgeType type) {
         return nQuickReject(mNativeCanvasWrapper, left, top, right, bottom);
     }
 
     /**
+     * Return true if the specified rectangle, after being transformed by the
+     * current matrix, would lie completely outside of the current clip. Call
+     * this to check if an area you intend to draw into is clipped out (and
+     * therefore you can skip making the draw calls).
+     *
+     * @param left        The left side of the rectangle to compare with the
+     *                    current clip
+     * @param top         The top of the rectangle to compare with the current
+     *                    clip
+     * @param right       The right side of the rectangle to compare with the
+     *                    current clip
+     * @param bottom      The bottom of the rectangle to compare with the
+     *                    current clip
+     * @return            true if the rect (transformed by the canvas' matrix)
+     *                    does not intersect with the canvas' clip
+     */
+    public boolean quickReject(float left, float top, float right, float bottom) {
+        return nQuickReject(mNativeCanvasWrapper, left, top, right, bottom);
+    }
+
+    /**
      * Return the bounds of the current clip (in local coordinates) in the
      * bounds parameter, and return true if it is non-empty. This can be useful
      * in a way similar to quickReject, in that it tells you that drawing
diff --git a/media/java/android/media/audiopolicy/AudioProductStrategy.java b/media/java/android/media/audiopolicy/AudioProductStrategy.java
index 612f83a..60b3fc6 100644
--- a/media/java/android/media/audiopolicy/AudioProductStrategy.java
+++ b/media/java/android/media/audiopolicy/AudioProductStrategy.java
@@ -134,7 +134,9 @@
                             + "DO NOT USE STREAM TO CONTROL THE VOLUME");
                     return AudioSystem.STREAM_MUSIC;
                 }
-                return streamType;
+                if (streamType < AudioSystem.getNumStreamTypes()) {
+                    return streamType;
+                }
             }
         }
         return AudioSystem.STREAM_MUSIC;
diff --git a/media/java/android/media/tv/ITvInputManager.aidl b/media/java/android/media/tv/ITvInputManager.aidl
index c199c6f..508a46f4 100644
--- a/media/java/android/media/tv/ITvInputManager.aidl
+++ b/media/java/android/media/tv/ITvInputManager.aidl
@@ -89,7 +89,7 @@
     void timeShiftEnablePositionTracking(in IBinder sessionToken, boolean enable, int userId);
 
     // For the recording session
-    void startRecording(in IBinder sessionToken, in Uri programUri, int userId);
+    void startRecording(in IBinder sessionToken, in Uri programUri, in Bundle params, int userId);
     void stopRecording(in IBinder sessionToken, int userId);
 
     // For TV input hardware binding
diff --git a/media/java/android/media/tv/ITvInputSession.aidl b/media/java/android/media/tv/ITvInputSession.aidl
index 356ec3c..24b87d5 100644
--- a/media/java/android/media/tv/ITvInputSession.aidl
+++ b/media/java/android/media/tv/ITvInputSession.aidl
@@ -56,6 +56,6 @@
     void timeShiftEnablePositionTracking(boolean enable);
 
     // For the recording session
-    void startRecording(in Uri programUri);
+    void startRecording(in Uri programUri, in Bundle params);
     void stopRecording();
 }
diff --git a/media/java/android/media/tv/ITvInputSessionWrapper.java b/media/java/android/media/tv/ITvInputSessionWrapper.java
index 07cfbda..e89d33d 100644
--- a/media/java/android/media/tv/ITvInputSessionWrapper.java
+++ b/media/java/android/media/tv/ITvInputSessionWrapper.java
@@ -216,7 +216,8 @@
                 break;
             }
             case DO_START_RECORDING: {
-                mTvInputRecordingSessionImpl.startRecording((Uri) msg.obj);
+                SomeArgs args = (SomeArgs) msg.obj;
+                mTvInputRecordingSessionImpl.startRecording((Uri) args.arg1, (Bundle) args.arg2);
                 break;
             }
             case DO_STOP_RECORDING: {
@@ -352,8 +353,9 @@
     }
 
     @Override
-    public void startRecording(@Nullable Uri programUri) {
-        mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_START_RECORDING, programUri));
+    public void startRecording(@Nullable Uri programUri, @Nullable Bundle params) {
+        mCaller.executeOrSendMessage(mCaller.obtainMessageOO(DO_START_RECORDING, programUri,
+                params));
     }
 
     @Override
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index bb86763..2589521 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -2381,12 +2381,23 @@
          *            {@link TvContract#buildProgramUri(long)}. Can be {@code null}.
          */
         void startRecording(@Nullable Uri programUri) {
+            startRecording(programUri, null);
+        }
+
+        /**
+         * Starts TV program recording in the current recording session.
+         *
+         * @param programUri The URI for the TV program to record as a hint, built by
+         *            {@link TvContract#buildProgramUri(long)}. Can be {@code null}.
+         * @param params A set of extra parameters which might be handled with this event.
+         */
+        void startRecording(@Nullable Uri programUri, @Nullable Bundle params) {
             if (mToken == null) {
                 Log.w(TAG, "The session has been already released");
                 return;
             }
             try {
-                mService.startRecording(mToken, programUri, mUserId);
+                mService.startRecording(mToken, programUri, params, mUserId);
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
index 7e1f44c..62c7e51 100755
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -1818,6 +1818,30 @@
         public abstract void onStartRecording(@Nullable Uri programUri);
 
         /**
+         * Called when the application requests to start TV program recording. Recording must start
+         * immediately when this method is called.
+         *
+         * <p>The application may supply the URI for a TV program for filling in program specific
+         * data fields in the {@link android.media.tv.TvContract.RecordedPrograms} table.
+         * A non-null {@code programUri} implies the started recording should be of that specific
+         * program, whereas null {@code programUri} does not impose such a requirement and the
+         * recording can span across multiple TV programs. In either case, the application must call
+         * {@link TvRecordingClient#stopRecording()} to stop the recording.
+         *
+         * <p>The session must call {@link #notifyError(int)} if the start request cannot be
+         * fulfilled.
+         *
+         * @param programUri The URI for the TV program to record, built by
+         *            {@link TvContract#buildProgramUri(long)}. Can be {@code null}.
+         * @param params Domain-specific data for this tune request. Keys <em>must</em> be a scoped
+         *            name, i.e. prefixed with a package name you own, so that different developers
+         *            will not create conflicting keys.
+         */
+        public void onStartRecording(@Nullable Uri programUri, @NonNull Bundle params) {
+            onStartRecording(programUri);
+        }
+
+        /**
          * Called when the application requests to stop TV program recording. Recording must stop
          * immediately when this method is called.
          *
@@ -1867,11 +1891,11 @@
         }
 
         /**
-         * Calls {@link #onStartRecording(Uri)}.
+         * Calls {@link #onStartRecording(Uri, Bundle)}.
          *
          */
-        void startRecording(@Nullable  Uri programUri) {
-            onStartRecording(programUri);
+        void startRecording(@Nullable  Uri programUri, @NonNull Bundle params) {
+            onStartRecording(programUri, params);
         }
 
         /**
diff --git a/media/java/android/media/tv/TvRecordingClient.java b/media/java/android/media/tv/TvRecordingClient.java
index 5aadeb6..8ae98ae 100644
--- a/media/java/android/media/tv/TvRecordingClient.java
+++ b/media/java/android/media/tv/TvRecordingClient.java
@@ -170,11 +170,37 @@
      * @throws IllegalStateException If {@link #tune} request hasn't been handled yet.
      */
     public void startRecording(@Nullable Uri programUri) {
+        startRecording(programUri, Bundle.EMPTY);
+    }
+
+    /**
+     * Starts TV program recording in the current recording session. Recording is expected to start
+     * immediately when this method is called. If the current recording session has not yet tuned to
+     * any channel, this method throws an exception.
+     *
+     * <p>The application may supply the URI for a TV program for filling in program specific data
+     * fields in the {@link android.media.tv.TvContract.RecordedPrograms} table.
+     * A non-null {@code programUri} implies the started recording should be of that specific
+     * program, whereas null {@code programUri} does not impose such a requirement and the
+     * recording can span across multiple TV programs. In either case, the application must call
+     * {@link TvRecordingClient#stopRecording()} to stop the recording.
+     *
+     * <p>The recording session will respond by calling {@link RecordingCallback#onError(int)} if
+     * the start request cannot be fulfilled.
+     *
+     * @param programUri The URI for the TV program to record, built by
+     *            {@link TvContract#buildProgramUri(long)}. Can be {@code null}.
+     * @param params Domain-specific data for this request. Keys <em>must</em> be a scoped
+     *            name, i.e. prefixed with a package name you own, so that different developers will
+     *            not create conflicting keys.
+     * @throws IllegalStateException If {@link #tune} request hasn't been handled yet.
+     */
+    public void startRecording(@Nullable Uri programUri, @NonNull Bundle params) {
         if (!mIsTuned) {
             throw new IllegalStateException("startRecording failed - not yet tuned");
         }
         if (mSession != null) {
-            mSession.startRecording(programUri);
+            mSession.startRecording(programUri, params);
             mIsRecordingStarted = true;
         }
     }
diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp
index 4f1125f..007d367 100644
--- a/media/jni/android_media_tv_Tuner.cpp
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -314,7 +314,7 @@
 
     JNIEnv *env = AndroidRuntime::getJNIEnv();
     return env->NewObject(
-            env->FindClass("android/media/tv/tuner/Tuner$Lnb"),
+            env->FindClass("android/media/tv/tuner/Lnb"),
             gFields.lnbInitID,
             mObject,
             id);
@@ -373,7 +373,7 @@
     JNIEnv *env = AndroidRuntime::getJNIEnv();
     jobject descramblerObj =
             env->NewObject(
-                    env->FindClass("android/media/tv/tuner/Tuner$Descrambler"),
+                    env->FindClass("android/media/tv/tuner/Descrambler"),
                     gFields.descramblerInitID,
                     mObject);
 
@@ -408,7 +408,7 @@
     JNIEnv *env = AndroidRuntime::getJNIEnv();
     jobject filterObj =
             env->NewObject(
-                    env->FindClass("android/media/tv/tuner/Tuner$Filter"),
+                    env->FindClass("android/media/tv/tuner/filter/Filter"),
                     gFields.filterInitID,
                     mObject,
                     (jint) fId);
@@ -443,7 +443,7 @@
     JNIEnv *env = AndroidRuntime::getJNIEnv();
     jobject dvrObj =
             env->NewObject(
-                    env->FindClass("android/media/tv/tuner/Tuner$Dvr"),
+                    env->FindClass("android/media/tv/tuner/dvr/Dvr"),
                     gFields.dvrInitID,
                     mObject);
     sp<Dvr> dvrSp = new Dvr(iDvrSp, dvrObj);
@@ -495,14 +495,14 @@
 
 static FrontendSettings getFrontendSettings(JNIEnv *env, int type, jobject settings) {
     FrontendSettings frontendSettings;
-    jclass clazz = env->FindClass("android/media/tv/tuner/FrontendSettings");
+    jclass clazz = env->FindClass("android/media/tv/tuner/frontend/FrontendSettings");
     jfieldID freqField = env->GetFieldID(clazz, "mFrequency", "I");
     uint32_t freq = static_cast<uint32_t>(env->GetIntField(clazz, freqField));
 
     // TODO: handle the other 8 types of settings
     if (type == 1) {
         // analog
-        clazz = env->FindClass("android/media/tv/tuner/FrontendSettings$FrontendAnalogSettings");
+        clazz = env->FindClass("android/media/tv/tuner/frontend/AnalogFrontendSettings");
         FrontendAnalogType analogType =
                 static_cast<FrontendAnalogType>(
                         env->GetIntField(settings, env->GetFieldID(clazz, "mAnalogType", "I")));
@@ -525,7 +525,7 @@
 
 static DvrSettings getDvrSettings(JNIEnv *env, jobject settings) {
     DvrSettings dvrSettings;
-    jclass clazz = env->FindClass("android/media/tv/tuner/DvrSettings");
+    jclass clazz = env->FindClass("android/media/tv/tuner/dvr/DvrSettings");
     uint32_t statusMask =
             static_cast<uint32_t>(env->GetIntField(
                     settings, env->GetFieldID(clazz, "mStatusMask", "I")));
@@ -585,23 +585,23 @@
     gFields.frontendInitID =
             env->GetMethodID(frontendClazz, "<init>", "(Landroid/media/tv/tuner/Tuner;I)V");
 
-    jclass lnbClazz = env->FindClass("android/media/tv/tuner/Tuner$Lnb");
+    jclass lnbClazz = env->FindClass("android/media/tv/tuner/Lnb");
     gFields.lnbInitID =
             env->GetMethodID(lnbClazz, "<init>", "(Landroid/media/tv/tuner/Tuner;I)V");
 
-    jclass filterClazz = env->FindClass("android/media/tv/tuner/Tuner$Filter");
+    jclass filterClazz = env->FindClass("android/media/tv/tuner/filter/Filter");
     gFields.filterContext = env->GetFieldID(filterClazz, "mNativeContext", "J");
     gFields.filterInitID =
             env->GetMethodID(filterClazz, "<init>", "(Landroid/media/tv/tuner/Tuner;I)V");
     gFields.onFilterStatusID =
             env->GetMethodID(filterClazz, "onFilterStatus", "(I)V");
 
-    jclass descramblerClazz = env->FindClass("android/media/tv/tuner/Tuner$Descrambler");
+    jclass descramblerClazz = env->FindClass("android/media/tv/tuner/Descrambler");
     gFields.descramblerContext = env->GetFieldID(descramblerClazz, "mNativeContext", "J");
     gFields.descramblerInitID =
             env->GetMethodID(descramblerClazz, "<init>", "(Landroid/media/tv/tuner/Tuner;)V");
 
-    jclass dvrClazz = env->FindClass("android/media/tv/tuner/Tuner$Dvr");
+    jclass dvrClazz = env->FindClass("android/media/tv/tuner/dvr/Dvr");
     gFields.dvrContext = env->GetFieldID(dvrClazz, "mNativeContext", "J");
     gFields.dvrInitID = env->GetMethodID(dvrClazz, "<init>", "(Landroid/media/tv/tuner/Tuner;)V");
 }
@@ -649,7 +649,7 @@
     return 0;
 }
 
-static jobjectArray android_media_tv_Tuner_get_frontend_status(JNIEnv, jobject, jintArray) {
+static jobject android_media_tv_Tuner_get_frontend_status(JNIEnv, jobject, jintArray) {
     return NULL;
 }
 
@@ -684,7 +684,7 @@
 }
 
 static jobject android_media_tv_Tuner_open_filter(
-        JNIEnv *env, jobject thiz, jint type, jint subType, jint bufferSize) {
+        JNIEnv *env, jobject thiz, jint type, jint subType, jlong bufferSize) {
     sp<JTuner> tuner = getTuner(env, thiz);
     DemuxFilterType filterType {
         .mainType = static_cast<DemuxFilterMainType>(type),
@@ -708,17 +708,17 @@
             env->GetObjectField(
                     filterSettingsObj,
                     env->GetFieldID(
-                            env->FindClass("android/media/tv/tuner/FilterSettings"),
+                            env->FindClass("android/media/tv/tuner/filter/FilterConfiguration"),
                             "mSettings",
-                            "Landroid/media/tv/tuner/FilterSettings$Settings;"));
+                            "Landroid/media/tv/tuner/filter/Settings;"));
     if (type == (int)DemuxFilterMainType::TS) {
         // DemuxTsFilterSettings
-        jclass clazz = env->FindClass("android/media/tv/tuner/FilterSettings$TsFilterSettings");
+        jclass clazz = env->FindClass("android/media/tv/tuner/filter/TsFilterConfiguration");
         int tpid = env->GetIntField(filterSettingsObj, env->GetFieldID(clazz, "mTpid", "I"));
         if (subtype == (int)DemuxTsFilterType::PES) {
             // DemuxFilterPesDataSettings
             jclass settingClazz =
-                    env->FindClass("android/media/tv/tuner/FilterSettings$PesSettings");
+                    env->FindClass("android/media/tv/tuner/filter/PesSettings");
             int streamId = env->GetIntField(
                     settingsObj, env->GetFieldID(settingClazz, "mStreamId", "I"));
             bool isRaw = (bool)env->GetBooleanField(
@@ -831,7 +831,7 @@
 }
 
 static int android_media_tv_Tuner_read_filter_fmq(
-        JNIEnv *env, jobject filter, jbyteArray buffer, jint offset, jint size) {
+        JNIEnv *env, jobject filter, jbyteArray buffer, jlong offset, jlong size) {
     sp<Filter> filterSp = getFilter(env, filter);
     if (filterSp == NULL) {
         ALOGD("Failed to read filter FMQ: filter not found");
@@ -901,9 +901,14 @@
     return 0;
 }
 
-static jobject android_media_tv_Tuner_open_dvr(JNIEnv *env, jobject thiz, jint type, jint bufferSize) {
-    sp<JTuner> tuner = getTuner(env, thiz);
-    return tuner->openDvr(static_cast<DvrType>(type), bufferSize);
+static jobject android_media_tv_Tuner_open_dvr_recorder(
+        JNIEnv* /* env */, jobject /* thiz */, jlong /* bufferSize */) {
+    return NULL;
+}
+
+static jobject android_media_tv_Tuner_open_dvr_playback(
+        JNIEnv* /* env */, jobject /* thiz */, jlong /* bufferSize */) {
+    return NULL;
 }
 
 static jobject android_media_tv_Tuner_get_demux_caps(JNIEnv*, jobject) {
@@ -1019,35 +1024,35 @@
     ALOGD("set fd = %d", dvrSp->mFd);
 }
 
-static int android_media_tv_Tuner_read_dvr(JNIEnv *env, jobject dvr, jint size) {
+static jlong android_media_tv_Tuner_read_dvr(JNIEnv *env, jobject dvr, jlong size) {
     sp<Dvr> dvrSp = getDvr(env, dvr);
     if (dvrSp == NULL) {
         ALOGD("Failed to read dvr: dvr not found");
     }
 
-    int available = dvrSp->mDvrMQ->availableToWrite();
-    int write = std::min(size, available);
+    long available = dvrSp->mDvrMQ->availableToWrite();
+    long write = std::min((long) size, available);
 
     DvrMQ::MemTransaction tx;
-    int ret = 0;
+    long ret = 0;
     if (dvrSp->mDvrMQ->beginWrite(write, &tx)) {
         auto first = tx.getFirstRegion();
         auto data = first.getAddress();
-        int length = first.getLength();
-        int firstToWrite = std::min(length, write);
+        long length = first.getLength();
+        long firstToWrite = std::min(length, write);
         ret = read(dvrSp->mFd, data, firstToWrite);
         if (ret < firstToWrite) {
-            ALOGW("[DVR] file to MQ, first region: %d bytes to write, but %d bytes written",
+            ALOGW("[DVR] file to MQ, first region: %ld bytes to write, but %ld bytes written",
                     firstToWrite, ret);
         } else if (firstToWrite < write) {
-            ALOGD("[DVR] write second region: %d bytes written, %d bytes in total", ret, write);
+            ALOGD("[DVR] write second region: %ld bytes written, %ld bytes in total", ret, write);
             auto second = tx.getSecondRegion();
             data = second.getAddress();
             length = second.getLength();
             int secondToWrite = std::min(length, write - firstToWrite);
             ret += read(dvrSp->mFd, data, secondToWrite);
         }
-        ALOGD("[DVR] file to MQ: %d bytes need to be written, %d bytes written", write, ret);
+        ALOGD("[DVR] file to MQ: %ld bytes need to be written, %ld bytes written", write, ret);
         if (!dvrSp->mDvrMQ->commitWrite(ret)) {
             ALOGE("[DVR] Error: failed to commit write!");
         }
@@ -1055,17 +1060,17 @@
     } else {
         ALOGE("dvrMq.beginWrite failed");
     }
-    return ret;
+    return (jlong) ret;
 }
 
-static int android_media_tv_Tuner_read_dvr_from_array(
-        JNIEnv /* *env */, jobject /* dvr */, jbyteArray /* bytes */, jint /* offset */,
-        jint /* size */) {
+static jlong android_media_tv_Tuner_read_dvr_from_array(
+        JNIEnv /* *env */, jobject /* dvr */, jbyteArray /* bytes */, jlong /* offset */,
+        jlong /* size */) {
     //TODO: impl
     return 0;
 }
 
-static int android_media_tv_Tuner_write_dvr(JNIEnv *env, jobject dvr, jint size) {
+static jlong android_media_tv_Tuner_write_dvr(JNIEnv *env, jobject dvr, jlong size) {
     sp<Dvr> dvrSp = getDvr(env, dvr);
     if (dvrSp == NULL) {
         ALOGW("Failed to write dvr: dvr not found");
@@ -1079,28 +1084,28 @@
 
     DvrMQ& dvrMq = dvrSp->getDvrMQ();
 
-    int available = dvrMq.availableToRead();
-    int toRead = std::min(size, available);
+    long available = dvrMq.availableToRead();
+    long toRead = std::min((long) size, available);
 
-    int ret = 0;
+    long ret = 0;
     DvrMQ::MemTransaction tx;
     if (dvrMq.beginRead(toRead, &tx)) {
         auto first = tx.getFirstRegion();
         auto data = first.getAddress();
-        int length = first.getLength();
-        int firstToRead = std::min(length, toRead);
+        long length = first.getLength();
+        long firstToRead = std::min(length, toRead);
         ret = write(dvrSp->mFd, data, firstToRead);
         if (ret < firstToRead) {
-            ALOGW("[DVR] MQ to file: %d bytes read, but %d bytes written", firstToRead, ret);
+            ALOGW("[DVR] MQ to file: %ld bytes read, but %ld bytes written", firstToRead, ret);
         } else if (firstToRead < toRead) {
-            ALOGD("[DVR] read second region: %d bytes read, %d bytes in total", ret, toRead);
+            ALOGD("[DVR] read second region: %ld bytes read, %ld bytes in total", ret, toRead);
             auto second = tx.getSecondRegion();
             data = second.getAddress();
             length = second.getLength();
             int secondToRead = toRead - firstToRead;
             ret += write(dvrSp->mFd, data, secondToRead);
         }
-        ALOGD("[DVR] MQ to file: %d bytes to be read, %d bytes written", toRead, ret);
+        ALOGD("[DVR] MQ to file: %ld bytes to be read, %ld bytes written", toRead, ret);
         if (!dvrMq.commitRead(ret)) {
             ALOGE("[DVR] Error: failed to commit read!");
         }
@@ -1109,12 +1114,12 @@
         ALOGE("dvrMq.beginRead failed");
     }
 
-    return ret;
+    return (jlong) ret;
 }
 
-static int android_media_tv_Tuner_write_dvr_to_array(
-        JNIEnv /* *env */, jobject /* dvr */, jbyteArray /* bytes */, jint /* offset */,
-        jint /* size */) {
+static jlong android_media_tv_Tuner_write_dvr_to_array(
+        JNIEnv /* *env */, jobject /* dvr */, jbyteArray /* bytes */, jlong /* offset */,
+        jlong /* size */) {
     //TODO: impl
     return 0;
 }
@@ -1126,49 +1131,51 @@
             (void *)android_media_tv_Tuner_get_frontend_ids },
     { "nativeOpenFrontendById", "(I)Landroid/media/tv/tuner/Tuner$Frontend;",
             (void *)android_media_tv_Tuner_open_frontend_by_id },
-    { "nativeTune", "(ILandroid/media/tv/tuner/FrontendSettings;)I",
+    { "nativeTune", "(ILandroid/media/tv/tuner/frontend/FrontendSettings;)I",
             (void *)android_media_tv_Tuner_tune },
     { "nativeStopTune", "()I", (void *)android_media_tv_Tuner_stop_tune },
-    { "nativeScan", "(ILandroid/media/tv/tuner/FrontendSettings;I)I",
+    { "nativeScan", "(ILandroid/media/tv/tuner/frontend/FrontendSettings;I)I",
             (void *)android_media_tv_Tuner_scan },
     { "nativeStopScan", "()I", (void *)android_media_tv_Tuner_stop_scan },
     { "nativeSetLnb", "(I)I", (void *)android_media_tv_Tuner_set_lnb },
     { "nativeSetLna", "(Z)I", (void *)android_media_tv_Tuner_set_lna },
-    { "nativeGetFrontendStatus", "([I)[Landroid/media/tv/tuner/FrontendStatus;",
+    { "nativeGetFrontendStatus", "([I)Landroid/media/tv/tuner/frontend/FrontendStatus;",
             (void *)android_media_tv_Tuner_get_frontend_status },
-    { "nativeGetAvSyncHwId", "(Landroid/media/tv/tuner/Tuner$Filter;)I",
+    { "nativeGetAvSyncHwId", "(Landroid/media/tv/tuner/Tuner/filter/Filter;)I",
             (void *)android_media_tv_Tuner_gat_av_sync_hw_id },
     { "nativeGetAvSyncTime", "(I)J", (void *)android_media_tv_Tuner_gat_av_sync_time },
     { "nativeConnectCiCam", "(I)I", (void *)android_media_tv_Tuner_connect_cicam },
     { "nativeDisconnectCiCam", "()I", (void *)android_media_tv_Tuner_disconnect_cicam },
-    { "nativeGetFrontendInfo", "(I)[Landroid/media/tv/tuner/FrontendInfo;",
+    { "nativeGetFrontendInfo", "(I)Landroid/media/tv/tuner/FrontendInfo;",
             (void *)android_media_tv_Tuner_get_frontend_info },
-    { "nativeOpenFilter", "(III)Landroid/media/tv/tuner/Tuner$Filter;",
+    { "nativeOpenFilter", "(IIJ)Landroid/media/tv/tuner/Tuner/filter/Filter;",
             (void *)android_media_tv_Tuner_open_filter },
-    { "nativeOpenTimeFilter", "()Landroid/media/tv/tuner/Tuner$TimeFilter;",
+    { "nativeOpenTimeFilter", "()Landroid/media/tv/tuner/Tuner/filter/TimeFilter;",
             (void *)android_media_tv_Tuner_open_time_filter },
     { "nativeGetLnbIds", "()Ljava/util/List;",
             (void *)android_media_tv_Tuner_get_lnb_ids },
-    { "nativeOpenLnbById", "(I)Landroid/media/tv/tuner/Tuner$Lnb;",
+    { "nativeOpenLnbById", "(I)Landroid/media/tv/tuner/Lnb;",
             (void *)android_media_tv_Tuner_open_lnb_by_id },
-    { "nativeOpenDescrambler", "()Landroid/media/tv/tuner/Tuner$Descrambler;",
+    { "nativeOpenDescrambler", "()Landroid/media/tv/tuner/Descrambler;",
             (void *)android_media_tv_Tuner_open_descrambler },
-    { "nativeOpenDvr", "(II)Landroid/media/tv/tuner/Tuner$Dvr;",
-            (void *)android_media_tv_Tuner_open_dvr },
+    { "nativeOpenDvrRecorder", "(J)Landroid/media/tv/tuner/dvr/DvrRecorder;",
+            (void *)android_media_tv_Tuner_open_dvr_recorder },
+    { "nativeOpenDvrPlayback", "(J)Landroid/media/tv/tuner/dvr/DvrPlayback;",
+            (void *)android_media_tv_Tuner_open_dvr_playback },
     { "nativeGetDemuxCapabilities", "()Landroid/media/tv/tuner/DemuxCapabilities;",
             (void *)android_media_tv_Tuner_get_demux_caps },
 };
 
 static const JNINativeMethod gFilterMethods[] = {
-    { "nativeConfigureFilter", "(IILandroid/media/tv/tuner/FilterSettings;)I",
+    { "nativeConfigureFilter", "(IILandroid/media/tv/tuner/filter/FilterConfiguration;)I",
             (void *)android_media_tv_Tuner_configure_filter },
     { "nativeGetId", "()I", (void *)android_media_tv_Tuner_get_filter_id },
-    { "nativeSetDataSource", "(Landroid/media/tv/tuner/Tuner$Filter;)I",
+    { "nativeSetDataSource", "(Landroid/media/tv/tuner/filter/Filter;)I",
             (void *)android_media_tv_Tuner_set_filter_data_source },
     { "nativeStartFilter", "()I", (void *)android_media_tv_Tuner_start_filter },
     { "nativeStopFilter", "()I", (void *)android_media_tv_Tuner_stop_filter },
     { "nativeFlushFilter", "()I", (void *)android_media_tv_Tuner_flush_filter },
-    { "nativeRead", "([BII)I", (void *)android_media_tv_Tuner_read_filter_fmq },
+    { "nativeRead", "([BJJ)I", (void *)android_media_tv_Tuner_read_filter_fmq },
     { "nativeClose", "()I", (void *)android_media_tv_Tuner_close_filter },
 };
 
@@ -1183,31 +1190,36 @@
 };
 
 static const JNINativeMethod gDescramblerMethods[] = {
-    { "nativeAddPid", "(IILandroid/media/tv/tuner/Tuner$Filter;)I",
+    { "nativeAddPid", "(IILandroid/media/tv/tuner/filter/Filter;)I",
             (void *)android_media_tv_Tuner_add_pid },
-    { "nativeRemovePid", "(IILandroid/media/tv/tuner/Tuner$Filter;)I",
+    { "nativeRemovePid", "(IILandroid/media/tv/tuner/filter/Filter;)I",
             (void *)android_media_tv_Tuner_remove_pid },
     { "nativeSetKeyToken", "([B)I", (void *)android_media_tv_Tuner_set_key_token },
     { "nativeClose", "()I", (void *)android_media_tv_Tuner_close_descrambler },
 };
 
 static const JNINativeMethod gDvrMethods[] = {
-    { "nativeAttachFilter", "(Landroid/media/tv/tuner/Tuner$Filter;)I",
+    { "nativeAttachFilter", "(Landroid/media/tv/tuner/filter/Filter;)I",
             (void *)android_media_tv_Tuner_attach_filter },
-    { "nativeDetachFilter", "(Landroid/media/tv/tuner/Tuner$Filter;)I",
+    { "nativeDetachFilter", "(Landroid/media/tv/tuner/filter/Filter;)I",
             (void *)android_media_tv_Tuner_detach_filter },
-    { "nativeConfigureDvr", "(Landroid/media/tv/tuner/DvrSettings;)I",
+    { "nativeConfigureDvr", "(Landroid/media/tv/tuner/dvr/DvrSettings;)I",
             (void *)android_media_tv_Tuner_configure_dvr },
     { "nativeStartDvr", "()I", (void *)android_media_tv_Tuner_start_dvr },
     { "nativeStopDvr", "()I", (void *)android_media_tv_Tuner_stop_dvr },
     { "nativeFlushDvr", "()I", (void *)android_media_tv_Tuner_flush_dvr },
     { "nativeClose", "()I", (void *)android_media_tv_Tuner_close_dvr },
-    { "nativeSetFileDescriptor", "(Ljava/io/FileDescriptor;)V",
-            (void *)android_media_tv_Tuner_dvr_set_fd },
-    { "nativeRead", "(I)I", (void *)android_media_tv_Tuner_read_dvr },
-    { "nativeRead", "([BII)I", (void *)android_media_tv_Tuner_read_dvr_from_array },
-    { "nativeWrite", "(I)I", (void *)android_media_tv_Tuner_write_dvr },
-    { "nativeWrite", "([BII)I", (void *)android_media_tv_Tuner_write_dvr_to_array },
+    { "nativeSetFileDescriptor", "(I)V", (void *)android_media_tv_Tuner_dvr_set_fd },
+};
+
+static const JNINativeMethod gDvrRecorderMethods[] = {
+    { "nativeWrite", "(J)J", (void *)android_media_tv_Tuner_write_dvr },
+    { "nativeWrite", "([BJJ)J", (void *)android_media_tv_Tuner_write_dvr_to_array },
+};
+
+static const JNINativeMethod gDvrPlaybackMethods[] = {
+    { "nativeRead", "(J)J", (void *)android_media_tv_Tuner_read_dvr },
+    { "nativeRead", "([BJJ)J", (void *)android_media_tv_Tuner_read_dvr_from_array },
 };
 
 static const JNINativeMethod gLnbMethods[] = {
@@ -1225,35 +1237,49 @@
         return false;
     }
     if (AndroidRuntime::registerNativeMethods(
-            env, "android/media/tv/tuner/Tuner$Filter",
+            env, "android/media/tv/tuner/filter/Filter",
             gFilterMethods,
             NELEM(gFilterMethods)) != JNI_OK) {
         ALOGE("Failed to register filter native methods");
         return false;
     }
     if (AndroidRuntime::registerNativeMethods(
-            env, "android/media/tv/tuner/Tuner$TimeFilter",
+            env, "android/media/tv/tuner/filter/TimeFilter",
             gTimeFilterMethods,
             NELEM(gTimeFilterMethods)) != JNI_OK) {
         ALOGE("Failed to register time filter native methods");
         return false;
     }
     if (AndroidRuntime::registerNativeMethods(
-            env, "android/media/tv/tuner/Tuner$Descrambler",
+            env, "android/media/tv/tuner/Descrambler",
             gDescramblerMethods,
             NELEM(gDescramblerMethods)) != JNI_OK) {
         ALOGE("Failed to register descrambler native methods");
         return false;
     }
     if (AndroidRuntime::registerNativeMethods(
-            env, "android/media/tv/tuner/Tuner$Dvr",
+            env, "android/media/tv/tuner/dvr/Dvr",
             gDvrMethods,
             NELEM(gDvrMethods)) != JNI_OK) {
         ALOGE("Failed to register dvr native methods");
         return false;
     }
     if (AndroidRuntime::registerNativeMethods(
-            env, "android/media/tv/tuner/Tuner$Lnb",
+            env, "android/media/tv/tuner/dvr/DvrRecorder",
+            gDvrRecorderMethods,
+            NELEM(gDvrRecorderMethods)) != JNI_OK) {
+        ALOGE("Failed to register dvr recorder native methods");
+        return false;
+    }
+    if (AndroidRuntime::registerNativeMethods(
+            env, "android/media/tv/tuner/dvr/DvrPlayback",
+            gDvrPlaybackMethods,
+            NELEM(gDvrPlaybackMethods)) != JNI_OK) {
+        ALOGE("Failed to register dvr playback native methods");
+        return false;
+    }
+    if (AndroidRuntime::registerNativeMethods(
+            env, "android/media/tv/tuner/Lnb",
             gLnbMethods,
             NELEM(gLnbMethods)) != JNI_OK) {
         ALOGE("Failed to register lnb native methods");
diff --git a/packages/Incremental/NativeAdbDataLoader/jni/com_android_incremental_nativeadb_DataLoaderService.cpp b/packages/Incremental/NativeAdbDataLoader/jni/com_android_incremental_nativeadb_DataLoaderService.cpp
index 4e49302..01150b7 100644
--- a/packages/Incremental/NativeAdbDataLoader/jni/com_android_incremental_nativeadb_DataLoaderService.cpp
+++ b/packages/Incremental/NativeAdbDataLoader/jni/com_android_incremental_nativeadb_DataLoaderService.cpp
@@ -32,6 +32,7 @@
 #include <utils/Log.h>
 
 #include <charconv>
+#include <span>
 #include <string>
 #include <thread>
 #include <type_traits>
@@ -92,9 +93,7 @@
 
 static_assert(COMMAND_SIZE == sizeof(RequestCommand));
 
-static bool sendRequest(int fd,
-                        RequestType requestType,
-                        FileId fileId = -1,
+static bool sendRequest(int fd, RequestType requestType, FileId fileId = -1,
                         BlockIdx blockIdx = -1) {
     const RequestCommand command{
             .requestType = static_cast<int16_t>(be16toh(requestType)),
@@ -267,25 +266,24 @@
         std::lock_guard lock{mMapsMutex};
         CHECK(mIfs);
         for (auto&& pendingRead : pendingReads) {
-            const android::dataloader::Inode ino = pendingRead.file_ino;
-            const auto blockIdx =
-                    static_cast<BlockIdx>(pendingRead.block_index);
+            const android::dataloader::FileId id = pendingRead.id;
+            const auto blockIdx = static_cast<BlockIdx>(pendingRead.block);
             /*
             ALOGI("[AdbDataLoader] Missing: %d", (int) blockIdx);
             */
-            auto fileIdOr = getFileId(ino);
+            auto fileIdOr = getFileId(id);
             if (!fileIdOr) {
-                ALOGE("[AdbDataLoader] Failed to handle event for inode=%d. "
+                ALOGE("[AdbDataLoader] Failed to handle event for fileid=%s. "
                       "Ignore.",
-                      static_cast<int>(ino));
+                      android::incfs::toString(id).c_str());
                 continue;
             }
             const FileId fileId = *fileIdOr;
             if (mRequestedFiles.insert(fileId).second) {
                 if (!sendRequest(mOutFd, PREFETCH, fileId, blockIdx)) {
                     ALOGE("[AdbDataLoader] Failed to request prefetch for "
-                          "inode=%d. Ignore.",
-                          static_cast<int>(ino));
+                          "fileid=%s. Ignore.",
+                          android::incfs::toString(id).c_str());
                     mRequestedFiles.erase(fileId);
                     mStatusListener->reportStatus(DATA_LOADER_NO_CONNECTION);
                 }
@@ -296,7 +294,7 @@
 
     struct TracedRead {
         uint64_t timestampUs;
-        uint64_t fileIno;
+        android::dataloader::FileId fileId;
         uint32_t firstBlockIdx;
         uint32_t count;
     };
@@ -307,26 +305,26 @@
             return;
         }
 
-        TracedRead last = {0, 0, 0, 0};
+        TracedRead last = {};
         std::lock_guard lock{mMapsMutex};
         for (auto&& read : pageReads) {
-            if (read.file_ino != last.fileIno ||
-                read.block_index != last.firstBlockIdx + last.count) {
+            if (read.id != last.fileId || read.block != last.firstBlockIdx + last.count) {
                 traceOrLogRead(last, trace, log);
-                last = {read.timestamp_us, read.file_ino, read.block_index, 1};
+                last = {read.bootClockTsUs, read.id, (uint32_t)read.block, 1};
             } else {
                 ++last.count;
             }
         }
         traceOrLogRead(last, trace, log);
     }
-    void onFileCreated(android::dataloader::Inode inode, const android::dataloader::RawMetadata& metadata) {
-    }
+    void onFileCreated(android::dataloader::FileId fileid,
+                       const android::dataloader::RawMetadata& metadata) {}
 
 private:
     void receiver() {
         std::vector<uint8_t> data;
-        std::vector<incfs_new_data_block> instructions;
+        std::vector<IncFsDataBlock> instructions;
+        std::unordered_map<android::dataloader::FileId, unique_fd> writeFds;
         while (!mStopReceiving) {
             const int res = waitForDataOrSignal(mInFd, mEventFd);
             if (res == 0) {
@@ -366,21 +364,32 @@
                     mStopReceiving = true;
                     break;
                 }
-                const android::dataloader::Inode ino = mIdToNodeMap[header.fileId];
-                if (!ino) {
+                const android::dataloader::FileId id = mIdToNodeMap[header.fileId];
+                if (!android::incfs::isValidFileId(id)) {
                     ALOGE("Unknown data destination for file ID %d. "
                           "Ignore.",
                           header.fileId);
                     continue;
                 }
-                auto inst = incfs_new_data_block{
-                        .file_ino = static_cast<__aligned_u64>(ino),
-                        .block_index = static_cast<uint32_t>(header.blockIdx),
-                        .data_len = static_cast<uint16_t>(header.blockSize),
-                        .data = reinterpret_cast<uint64_t>(
-                                remainingData.data()),
-                        .compression =
-                                static_cast<uint8_t>(header.compressionType)};
+
+                auto& writeFd = writeFds[id];
+                if (writeFd < 0) {
+                    writeFd.reset(this->mIfs->openWrite(id));
+                    if (writeFd < 0) {
+                        ALOGE("Failed to open file %d for writing (%d). Aboring.", header.fileId,
+                              -writeFd);
+                        break;
+                    }
+                }
+
+                const auto inst = IncFsDataBlock{
+                        .fileFd = writeFd,
+                        .pageIndex = static_cast<IncFsBlockIndex>(header.blockIdx),
+                        .compression = static_cast<IncFsCompressionKind>(header.compressionType),
+                        .kind = INCFS_BLOCK_KIND_DATA,
+                        .dataSize = static_cast<uint16_t>(header.blockSize),
+                        .data = (const char*)remainingData.data(),
+                };
                 instructions.push_back(inst);
                 remainingData = remainingData.subspan(header.blockSize);
             }
@@ -390,9 +399,8 @@
         flushReadLog();
     }
 
-    void writeInstructions(std::vector<incfs_new_data_block>& instructions) {
-        auto res = this->mIfs->writeBlocks(instructions.data(),
-                                           instructions.size());
+    void writeInstructions(std::vector<IncFsDataBlock>& instructions) {
+        auto res = this->mIfs->writeBlocks(instructions);
         if (res != instructions.size()) {
             ALOGE("[AdbDataLoader] failed to write data to Incfs (res=%d when "
                   "expecting %d)",
@@ -406,30 +414,30 @@
         FileId fileId;
     };
 
-    MetaPair* updateMapsForFile(android::dataloader::Inode ino) {
-        android::dataloader::RawMetadata meta = mIfs->getRawMetadata(ino);
+    MetaPair* updateMapsForFile(android::dataloader::FileId id) {
+        android::dataloader::RawMetadata meta = mIfs->getRawMetadata(id);
         FileId fileId;
         auto res =
                 std::from_chars(meta.data(), meta.data() + meta.size(), fileId);
         if (res.ec != std::errc{} || fileId < 0) {
-            ALOGE("[AdbDataLoader] Invalid metadata for inode=%d (%s)",
-                  static_cast<int>(ino), meta.data());
+            ALOGE("[AdbDataLoader] Invalid metadata for fileid=%s (%s)",
+                  android::incfs::toString(id).c_str(), meta.data());
             return nullptr;
         }
-        mIdToNodeMap[fileId] = ino;
-        auto& metaPair = mNodeToMetaMap[ino];
+        mIdToNodeMap[fileId] = id;
+        auto& metaPair = mNodeToMetaMap[id];
         metaPair.meta = std::move(meta);
         metaPair.fileId = fileId;
         return &metaPair;
     }
 
-    android::dataloader::RawMetadata* getMeta(android::dataloader::Inode ino) {
-        auto it = mNodeToMetaMap.find(ino);
+    android::dataloader::RawMetadata* getMeta(android::dataloader::FileId id) {
+        auto it = mNodeToMetaMap.find(id);
         if (it != mNodeToMetaMap.end()) {
             return &it->second.meta;
         }
 
-        auto metaPair = updateMapsForFile(ino);
+        auto metaPair = updateMapsForFile(id);
         if (!metaPair) {
             return nullptr;
         }
@@ -437,13 +445,13 @@
         return &metaPair->meta;
     }
 
-    FileId* getFileId(android::dataloader::Inode ino) {
-        auto it = mNodeToMetaMap.find(ino);
+    FileId* getFileId(android::dataloader::FileId id) {
+        auto it = mNodeToMetaMap.find(id);
         if (it != mNodeToMetaMap.end()) {
             return &it->second.fileId;
         }
 
-        auto* metaPair = updateMapsForFile(ino);
+        auto* metaPair = updateMapsForFile(id);
         if (!metaPair) {
             return nullptr;
         }
@@ -456,7 +464,7 @@
             return;
         }
         if (trace) {
-            auto* meta = getMeta(read.fileIno);
+            auto* meta = getMeta(read.fileId);
             auto str = android::base::StringPrintf(
                     "page_read: index=%lld count=%lld meta=%.*s",
                     static_cast<long long>(read.firstBlockIdx),
@@ -468,7 +476,7 @@
         if (log) {
             mReadLog.reserve(ReadLogBufferSize);
 
-            auto fileId = getFileId(read.fileIno);
+            auto fileId = getFileId(read.fileId);
             android::base::StringAppendF(
                     &mReadLog, "%lld:%lld:%lld:%lld\n",
                     static_cast<long long>(read.timestampUs),
@@ -501,8 +509,8 @@
     std::string mReadLog;
     std::thread mReceiverThread;
     std::mutex mMapsMutex;
-    std::unordered_map<android::dataloader::Inode, MetaPair> mNodeToMetaMap GUARDED_BY(mMapsMutex);
-    std::unordered_map<FileId, android::dataloader::Inode> mIdToNodeMap GUARDED_BY(mMapsMutex);
+    std::unordered_map<android::dataloader::FileId, MetaPair> mNodeToMetaMap GUARDED_BY(mMapsMutex);
+    std::unordered_map<FileId, android::dataloader::FileId> mIdToNodeMap GUARDED_BY(mMapsMutex);
     /** Tracks which files have been requested */
     std::unordered_set<FileId> mRequestedFiles;
     std::atomic<bool> mStopReceiving = false;
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index d40e7d4..0f35853 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -110,6 +110,7 @@
     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.WRITE_MEDIA_STORAGE" />
+    <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
     <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
     <uses-permission android:name="android.permission.CREATE_USERS" />
diff --git a/packages/SystemUI/TEST_MAPPING b/packages/SystemUI/TEST_MAPPING
index 9f13a7b..cff958f 100644
--- a/packages/SystemUI/TEST_MAPPING
+++ b/packages/SystemUI/TEST_MAPPING
@@ -16,5 +16,24 @@
         }
       ]
     }
+  ],
+  "platinum-postsubmit": [
+    {
+      "name": "PlatformScenarioTests",
+      "options": [
+        {
+            "include-filter": "android.platform.test.scenario.sysui"
+        },
+        {
+            "include-annotation": "android.platform.test.scenario.annotation.Scenario"
+        },
+        {
+            "exclude-annotation": "androidx.test.filters.FlakyTest"
+        },
+        {
+            "exclude-annotation": "android.platform.helpers.Staging"
+        }
+      ]
+    }
   ]
 }
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java
index 6518924..17f2f47 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java
@@ -133,6 +133,7 @@
         public CharSequence label;
         public CharSequence secondaryLabel;
         public CharSequence contentDescription;
+        public CharSequence stateDescription;
         public CharSequence dualLabelContentDescription;
         public boolean disabledByPolicy;
         public boolean dualTarget = false;
@@ -151,6 +152,7 @@
                     || !Objects.equals(other.label, label)
                     || !Objects.equals(other.secondaryLabel, secondaryLabel)
                     || !Objects.equals(other.contentDescription, contentDescription)
+                    || !Objects.equals(other.stateDescription, stateDescription)
                     || !Objects.equals(other.dualLabelContentDescription,
                             dualLabelContentDescription)
                     || !Objects.equals(other.expandedAccessibilityClassName,
@@ -168,6 +170,7 @@
             other.label = label;
             other.secondaryLabel = secondaryLabel;
             other.contentDescription = contentDescription;
+            other.stateDescription = stateDescription;
             other.dualLabelContentDescription = dualLabelContentDescription;
             other.expandedAccessibilityClassName = expandedAccessibilityClassName;
             other.disabledByPolicy = disabledByPolicy;
@@ -195,6 +198,7 @@
             sb.append(",label=").append(label);
             sb.append(",secondaryLabel=").append(secondaryLabel);
             sb.append(",contentDescription=").append(contentDescription);
+            sb.append(",stateDescription=").append(stateDescription);
             sb.append(",dualLabelContentDescription=").append(dualLabelContentDescription);
             sb.append(",expandedAccessibilityClassName=").append(expandedAccessibilityClassName);
             sb.append(",disabledByPolicy=").append(disabledByPolicy);
diff --git a/packages/SystemUI/res-product/values-ky/strings.xml b/packages/SystemUI/res-product/values-ky/strings.xml
index 8d96cb2..043faee 100644
--- a/packages/SystemUI/res-product/values-ky/strings.xml
+++ b/packages/SystemUI/res-product/values-ky/strings.xml
@@ -26,18 +26,18 @@
     <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"Планшетте SIM-карта жок."</string>
     <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"Телефондо SIM-карта жок."</string>
     <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"PIN-коддор дал келген жок"</string>
-    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"Планшеттин кулпусун <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> жолу ийгиликсиз аракет кылсаңыз, бул планшет баштапкы абалга келтирилип, андагы бардык маалымат жок кылынат."</string>
-    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"Телефондун кулпусун <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> жолу ийгиликсиз аракет кылсаңыз, бул телефон баштапкы абалга келтирилип, андагы бардык маалымат жок кылынат."</string>
-    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"Планшеттин кулпусун <xliff:g id="NUMBER">%d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Бул планшет баштапкы абалга келтирилип, андагы бардык маалымат жок кылынат."</string>
-    <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"Телефондун кулпусун <xliff:g id="NUMBER">%d</xliff:g> жолу туура эмес аракет жасадыңыз. Бул телефон баштапкы абалга келтирилип, андагы бардык маалымат жок кылынат."</string>
-    <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"Планшеттин кулпусун <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> жолу ийгиликсиз аракет кылсаңыз, бул колдонуучу өчүрүлүп, колдонуучунун бардык маалыматы жок кылынат."</string>
-    <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"Телефондун кулпусун <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> жолу ийгиликсиз аракет кылсаңыз, бул колдонуучу өчүрүлүп, колдонуучунун бардык маалыматы жок кылынат."</string>
-    <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"Планшеттин кулпусун <xliff:g id="NUMBER">%d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Бул колдонуучу өчүрүлүп, колдонуучунун бардык маалыматы жок кылынат."</string>
-    <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"Телефондун кулпусун <xliff:g id="NUMBER">%d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Бул колдонуучу өчүрүлүп, колдонуучунун бардык маалыматы жок кылынат."</string>
-    <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"Планшетиңиздин кулпусун <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> жолу ийгиликсиз аракет кылсаңыз, жумуш профилиңиз өчүрүлүп, профилдеги бардык маалымат жок кылынат."</string>
-    <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"Телефондун кулпусун <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> жолу ийгиликсиз аракет кылсаңыз, жумуш профилиңиз өчүрүлүп, профилдеги бардык маалымат жок кылынат."</string>
-    <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"Планшеттин кулпусун <xliff:g id="NUMBER">%d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Жумуш профили өчүрүлүп, андагы бардык маалымат жок кылынат."</string>
-    <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Телефондун кулпусун <xliff:g id="NUMBER">%d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Жумуш профили өчүрүлүп, андагы бардык маалымат жок кылынат."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"Планшеттин кулпусун <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> жолу ийгиликсиз аракет кылсаңыз, бул планшет баштапкы абалга келтирилип, андагы бардык маалымат өчүрүлөт."</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"Телефондун кулпусун <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> жолу ийгиликсиз аракет кылсаңыз, бул телефон баштапкы абалга келтирилип, андагы бардык маалымат өчүрүлөт."</string>
+    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"Планшеттин кулпусун <xliff:g id="NUMBER">%d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Бул планшет баштапкы абалга келтирилип, андагы бардык маалымат өчүрүлөт."</string>
+    <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"Телефондун кулпусун <xliff:g id="NUMBER">%d</xliff:g> жолу туура эмес аракет жасадыңыз. Бул телефон баштапкы абалга келтирилип, андагы бардык маалымат өчүрүлөт."</string>
+    <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"Планшеттин кулпусун <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> жолу ийгиликсиз аракет кылсаңыз, бул колдонуучу өчүрүлүп, колдонуучунун бардык маалыматы өчүрүлөт."</string>
+    <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"Телефондун кулпусун <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> жолу ийгиликсиз аракет кылсаңыз, бул колдонуучу өчүрүлүп, колдонуучунун бардык маалыматы өчүрүлөт."</string>
+    <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"Планшеттин кулпусун <xliff:g id="NUMBER">%d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Бул колдонуучу өчүрүлүп, колдонуучунун бардык маалыматы өчүрүлөт."</string>
+    <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"Телефондун кулпусун <xliff:g id="NUMBER">%d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Бул колдонуучу өчүрүлүп, колдонуучунун бардык маалыматы өчүрүлөт."</string>
+    <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"Планшетиңиздин кулпусун <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> жолу ийгиликсиз аракет кылсаңыз, жумуш профилиңиз өчүрүлүп, профилдеги бардык маалымат өчүрүлөт."</string>
+    <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"Телефондун кулпусун <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> жолу ийгиликсиз аракет кылсаңыз, жумуш профилиңиз өчүрүлүп, профилдеги бардык маалымат өчүрүлөт."</string>
+    <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"Планшеттин кулпусун <xliff:g id="NUMBER">%d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Жумуш профили өчүрүлүп, андагы бардык маалымат өчүрүлөт."</string>
+    <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"Телефондун кулпусун <xliff:g id="NUMBER">%d</xliff:g> жолу туура эмес ачууга аракет жасадыңыз. Жумуш профили өчүрүлүп, андагы бардык маалымат өчүрүлөт."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"Графикалык ачкычты <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес тарттыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> ийгиликсиз аракеттен кийин планшетиңизди бөгөттөн электрондук почтаңыз аркылуу чыгаруу талап кылынат.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секунддан кийин кайра аракеттениңиз."</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"Графикалык ачкычты <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес тарттыңыз. Дагы <xliff:g id="NUMBER_1">%2$d</xliff:g> ийгиликсиз аракеттен кийин телефонуңузду бөгөттөн электрондук почтаңыз аркылуу чыгаруу талап кылынат.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секунддан кийин кайра аракеттениңиз."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 4de8543..823685e 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zoem om skerm te vul"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Strek om skerm te vul"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Skermkiekie"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Prent is ingevoeg"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Stoor tans skermkiekie..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Stoor tans skermkiekie..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Skermkiekie is gestoor"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Begin opname"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Neem stemopname op"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Wys tikke"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Tik om te stop"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Stop"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Laat wag"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Hervat"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Batterybespaarder"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Aan met sonsondergang"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Tot sonsopkoms"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Aan om <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Tot <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC is gedeaktiveer"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC is geaktiveer"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Skermopname"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Begin"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Stop"</string>
     <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Swiep op om programme te wissel"</string>
     <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Sleep regs om programme vinnig te wissel"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Wissel oorsig"</string>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"Pasmaak"</string>
     <string name="notification_done" msgid="6215117625922713976">"Klaar"</string>
     <string name="inline_undo" msgid="9026953267645116526">"Ontdoen"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"Merk hierdie kennisgewing as \"nie \'n gesprek nie\""</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"Gunsteling"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"Ontmerk as gunsteling"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"Demp"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"Ontdemp"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"Wys as borrel"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"Skakel borrels af"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"Voeg by tuisskerm"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"kennisgewingkontroles"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"kennisgewing-sluimeropsies"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 87603ac..c324824 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"ማያ እንዲሞላ አጉላ"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"ማያ ለመሙለት ሳብ"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"ቅጽበታዊ ገጽ እይታ"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"ምስል ገብቷል"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"ቅጽበታዊ ገጽ እይታ በማስቀመጥ ላይ..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"ቅጽበታዊ ገጽ እይታ በማስቀመጥ ላይ..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"ቅጽበታዊ ገጽ እይታ ተቀምጧል"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"መቅረጽ ጀምር"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"ድምጽን ቅረጽ"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"መታ ማድረጎችን አሳይ"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"ለማቆም መታ ያድርጉ"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"አቁም"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"ባለበት አቁም"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"ከቆመበት ቀጥል"</string>
@@ -388,6 +390,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"ባትሪ ቆጣቢ"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"ጸሐይ ስትጠልቅ ይበራል"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"ጸሐይ እስክትወጣ ድረስ"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g> ላይ ይበራል"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"እስከ <xliff:g id="TIME">%s</xliff:g> ድረስ"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"ኤንኤፍሲ"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"ኤንኤፍሲ ተሰናክሏል"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"ኤንኤፍሲ ነቅቷል"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index c764004..113d705 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"تكبير/تصغير لملء الشاشة"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"توسيع بملء الشاشة"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"لقطة شاشة"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"تم إدراج الصورة"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"جارٍ حفظ لقطة الشاشة..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"جارٍ حفظ لقطة الشاشة..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"تم حفظ لقطة الشاشة."</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"بدء التسجيل"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"تسجيل التعليق الصوتي"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"عرض النقرات"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"انقر لإيقاف التسجيل"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"إيقاف"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"إيقاف مؤقت"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"استئناف"</string>
@@ -396,15 +398,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"توفير شحن البطارية"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"تفعيل عند غروب الشمس"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"حتى شروق الشمس"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"تفعيل الوضع في <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"حتى <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"‏الاتصالات قصيرة المدى (NFC)"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"تم إيقاف الاتصال القريب المدى"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"تم تفعيل الاتصال القريب المدى"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"تسجيل الشاشة"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"بدء"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"إيقاف"</string>
     <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"مرّر سريعًا لأعلى لتبديل التطبيقات"</string>
     <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"اسحب لليسار للتبديل السريع بين التطبيقات"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"تبديل \"النظرة العامة\""</string>
@@ -708,22 +709,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"تخصيص"</string>
     <string name="notification_done" msgid="6215117625922713976">"تم"</string>
     <string name="inline_undo" msgid="9026953267645116526">"تراجع"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"تحويل الإشعار من محادثة إلى إشعار عادي"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"المفضّلة"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"إزالة المحادثة من المفضّلة"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"كتم الصوت"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"إعادة الصوت"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"إظهار الإشعار كفقاعة تفسيرية"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"إيقاف الفقاعات التفسيرية"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"إضافة إلى الشاشة الرئيسية"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"عناصر التحكم في الإشعارات"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"خيارات تأجيل الإشعارات"</string>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index 2fc393c..975d639 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"স্ক্ৰীণ পূর্ণ কৰিবলৈ জুম কৰক"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"স্ক্ৰীণ পূর্ণ কৰিবলৈ প্ৰসাৰিত কৰক"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"স্ক্ৰীনশ্বট"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"প্ৰতিচ্ছবি ভৰোৱা হ’ল"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"স্ক্ৰীণশ্বট ছেভ কৰি থকা হৈছে…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"স্ক্ৰীণশ্বট ছেভ কৰি থকা হৈছে…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"স্ক্ৰীণশ্বট ছেভ কৰা হ’ল"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"ৰেকৰ্ডিং কৰা আৰম্ভ কৰক"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"পাৰ্শ্ব-ধ্বনি ৰেকৰ্ড কৰক"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"টিপা ঠাইসমূহ দেখুৱাওক"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"বন্ধ কৰিবলৈ টিপক"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"বন্ধ কৰক"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"প\'জ কৰক"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"ৰখোৱাৰ পৰা পুনৰ আৰম্ভ কৰক"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"বেটাৰী সঞ্চয়কাৰী"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"সূৰ্যাস্তত অন হয়"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"সূৰ্যোদয়লৈকে"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g>ত অন কৰক"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> পৰ্যন্ত"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC নিষ্ক্ৰিয় হৈ আছে"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC সক্ষম হৈ আছে"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"স্ক্ৰীন ৰেকর্ড"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"আৰম্ভ কৰক"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"বন্ধ কৰক"</string>
     <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"আনটো এপ্ ব্য়ৱহাৰ কৰিবলৈ ওপৰলৈ ছোৱাইপ কৰক"</string>
     <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"খৰতকীয়াকৈ আনটো এপ্ ব্য়ৱহাৰ কৰিবলৈ সোঁফালে টানক"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"অৱলোকন ট’গল কৰক"</string>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"নিজৰ উপযোগিতা অনুসৰি"</string>
     <string name="notification_done" msgid="6215117625922713976">"সম্পন্ন হ’ল"</string>
     <string name="inline_undo" msgid="9026953267645116526">"আনডু কৰক"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"এই জাননীখন এটা বার্তালাপ নহয় বুলি চিহ্নিত কৰক"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"অপ্ৰিয় হিচাপে চিহ্নিত কৰক"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"অপ্ৰিয় হিচাপে চিহ্নিত কৰক"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"মিউট কৰক"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"আনমিউট কৰক"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"বাবল হিচাপে দেখুৱাওক"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"বাবলসমূহ অফ কৰক"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"গৃহ স্ক্ৰীনত যোগ কৰক"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"জাননীৰ নিয়ন্ত্ৰণসমূহ"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"জাননীক স্নুজ কৰাৰ বিকল্পসমূহ"</string>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index de9c605..d98d939 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Ekranı doldurmaq üçün yaxınlaşdır"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Ekranı doldurmaq üçün uzat"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Ekran şəkli"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Şəkil daxil edildi"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Skrinşot yadda saxlanılır..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Skrinşot yadda saxlanır..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Skrinşot yadda saxlandı"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Ekranın Video Çəkimini Başladın"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Ekranın səsli video çəkimi"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Klikləmələri göstərin"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Dayandırmaq üçün toxunun"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Dayandırın"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Dayandırın"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Davam edin"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Enerjiyə qənaət"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Qürubda aktiv olacaq"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Şəfəq vaxtına qədər"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Bu vaxt aktiv olur: <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Bu vaxtadək: <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC deaktiv edilib"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC aktiv edilib"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Ekran yazması"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Başlayın"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Dayandırın"</string>
     <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Tətbiqi dəyişmək üçün yuxarı sürüşdürün"</string>
     <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Tətbiqləri cəld dəyişmək üçün sağa çəkin"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"İcmala Keçin"</string>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"Fərdiləşdirin"</string>
     <string name="notification_done" msgid="6215117625922713976">"Hazırdır"</string>
     <string name="inline_undo" msgid="9026953267645116526">"Ləğv edin"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"Bu bildirişi \"söhbət deyil\" kimi qeyd edin."</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"Sevimli"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"Sevimlilərdən silin"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"Səssiz"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"Susdurmayın"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"Qabarcıq kimi göstərin"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"Qabarcıqları deaktiv edin"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"Əsas ekrana əlavə edin"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"bildiriş nəzarəti"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"bildiriş təxirə salma seçimləri"</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index a895f35..ff03bb9 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zumiraj na celom ekranu"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Razvuci na ceo ekran"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Snimak ekrana"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Slika je umetnuta"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Čuvanje snimka ekrana..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Čuvanje snimka ekrana..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Snimak ekrana je sačuvan"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Započni snimanje"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Snimi prenos glasa"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Prikazuj dodire"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Dodirnite da biste zaustavili"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Zaustavi"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Pauziraj"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Nastavi"</string>
@@ -390,6 +392,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Ušteda baterije"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Uključuje se po zalasku sunca"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Do izlaska sunca"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Uključuje se u <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Do <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC je onemogućen"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC je omogućen"</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index 67aa899..1ebbb5e 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Павял. на ўвесь экран"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Расцягн. на ўвесь экран"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Здымак экрана"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Відарыс устаўлены"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Захаванне скрыншота..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Захаванне скрыншота..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Здымак экрана захаваны"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Пачаць запіс"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Закадравае агучванне запісу"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Паказваць дотыкі"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Націсніце, каб спыніць"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Спыніць"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Прыпыніць"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Узнавіць"</string>
@@ -394,15 +396,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Эканомія зараду"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Уключана ўвечары"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Да ўсходу сонца"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Уключана ў <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Да <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC адключаны"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC уключаны"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Запіс экрана"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Пачаць"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Спыніць"</string>
     <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Правядзіце ўверх, каб пераключыць праграмы"</string>
     <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Каб хутка пераключыцца паміж праграмамі, перацягніце ўправа"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Уключыць/выключыць агляд"</string>
@@ -704,22 +705,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"Наладзіць"</string>
     <string name="notification_done" msgid="6215117625922713976">"Гатова"</string>
     <string name="inline_undo" msgid="9026953267645116526">"Адрабіць"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"Не пазначаць гэта апавяшчэнне як размову"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"У абранае"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"Выдаліць з абранага"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"Ігнараваць"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"Уключыць паказ"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"Паказваць як усплывальнае апавяшчэнне"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"Выключыць усплывальныя апавяшчэнні"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"Дадаць на галоўны экран"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"кіраванне апавяшчэннямі"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"параметры адкладвання апавяшчэнняў"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index f83bf96..5cfea60 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Мащаб – запълва екрана"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Разпъване – запълва екрана"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Екранна снимка"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Изображението бе вмъкнато"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Екранната снимка се запазва..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Екранната снимка се запазва..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Екранната снимка е запазена"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Стартиране на записа"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Записване на озвучаване"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Показване на докосванията"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Докоснете за спиране"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Спиране"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Поставяне на пауза"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Възобновяване"</string>
@@ -388,6 +390,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Запазв. на батерията"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Ще се вкл. по залез"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"До изгрев"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Ще се включи в <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"До <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"КБП"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"КБП е деактивирана"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"КБП е активирана"</string>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 10479b1..f1e49ce 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"স্ক্রীণ পূরণ করতে জুম করুন"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"ফুল স্ক্রিন করুন"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"স্ক্রিনশট"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"ছবি যোগ করা হয়েছে"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"স্ক্রিনশট সেভ করা হচ্ছে..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"স্ক্রিনশট সেভ করা হচ্ছে..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"স্ক্রিনশট সেভ করা হয়েছে"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"রেকর্ডিং শুরু করুন"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"ভয়েসওভার রেকর্ড করুন"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"ট্যাপগুলি দেখুন"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"বন্ধ করতে ট্যাপ করুন"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"বন্ধ করুন"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"পজ করুন"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"আবার চালু করুন"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"ব্যাটারি সেভার"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"সূর্যাস্তে চালু হবে"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"সূর্যোদয় পর্যন্ত"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g>-এ চালু হবে"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> পর্যন্ত"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC অক্ষম করা আছে"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC সক্ষম করা আছে"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"স্ক্রিন রেকর্ড"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"শুরু করুন"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"বন্ধ করুন"</string>
     <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"অন্য অ্যাপে যেতে উপরের দিকে সোয়াইপ করুন"</string>
     <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"একটি অ্যাপ ছেড়ে দ্রুত অন্য অ্যাপে যেতে ডান দিকে টেনে আনুন"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"\'এক নজরে\' বৈশিষ্ট্যটি চালু বা বন্ধ করুন"</string>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"কাস্টমাইজ করুন"</string>
     <string name="notification_done" msgid="6215117625922713976">"সম্পন্ন"</string>
     <string name="inline_undo" msgid="9026953267645116526">"আগের অবস্থায় ফিরে যান"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"কথোপকথন হিসেবে এই বিজ্ঞপ্তি চিহ্নিত করবেন না"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"পছন্দসই"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"পছন্দসই থেকে সরান"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"মিউট করুন"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"আনমিউট করুন"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"পপ-আপ হিসেবে দেখুন"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"পপ-আপ বন্ধ করুন"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"হোম স্ক্রিনে যোগ করুন"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"বিজ্ঞপ্তির নিয়ন্ত্রণগুলি"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"বিজ্ঞপ্তি মনে করিয়ে দেওয়ার বিকল্পগুলি"</string>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 6c89d97..cabe87f 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Uvećaj prikaz na ekran"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Razvuci prikaz na ekran"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Snimak ekrana"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Slika je umetnuta"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Spašavanje snimka ekrana..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Spašavanje snimka ekrana..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Snimak ekrana je sačuvan"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Započni snimanje"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Govor snimka"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Prikaži dodire"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Dodirnite za zaustavljanje"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Zaustavi"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Pauza"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Nastavi"</string>
@@ -390,6 +392,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Ušteda baterije"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Uključuje se u sumrak"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Do svitanja"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Uključuje se u <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Do <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC je onemogućen"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC je omogućen"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index f675e20..3e25795 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zoom per omplir pantalla"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Estira per omplir pant."</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Captura de pantalla"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Imatge inserida"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"S\'està desant captura de pantalla..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"S\'està desant la captura de pantalla..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"S\'ha desat la captura de pantalla"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Inicia la gravació"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Grava la veu en off"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Mostra els tocs"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Toca per aturar"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Atura"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Posa en pausa"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Reprèn"</string>
@@ -388,6 +390,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Estalvi de bateria"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Al vespre"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Fins a l\'alba"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"S\'activarà a les <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Fins a les <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"L\'NFC està desactivada"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"L\'NFC està activada"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 354ccf4..3c85880 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Přiblížit na celou obrazovku"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Na celou obrazovku"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Snímek obrazovky"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Vložen obrázek"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Ukládání snímku obrazovky..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Ukládání snímku obrazovky..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Snímek obrazovky byl uložen"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Spustit nahrávání"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Nahrávat komentář"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Zobrazovat klepnutí"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Klepnutím zastavíte"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Zastavit"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Pozastavit"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Obnovit"</string>
@@ -392,6 +394,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Spořič baterie"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Při soumraku"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Do svítání"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Zapnout v <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Do <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC je vypnuto"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC je zapnuto"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 04e83d4..f2ffdaa 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zoom til fuld skærm"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Stræk til fuld skærm"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Billedet blev indsat"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Gemmer screenshot..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Gemmer screenshot..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshottet blev gemt"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Start optagelse"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Optag voiceover"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Vis tryk"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Tryk for at stoppe"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Stop"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Sæt på pause"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Genoptag"</string>
@@ -388,6 +390,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Batterisparefunktion"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Til ved solnedgang"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Indtil solopgang"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Tænd kl. <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Indtil kl. <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC er deaktiveret"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC er aktiveret"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index baf3e7c..58caef2 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zoom auf Bildschirmgröße"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Auf Bildschirmgröße anpassen"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Bild eingefügt"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Screenshot wird gespeichert..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Screenshot wird gespeichert..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshot gespeichert"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Aufzeichnung starten"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Voice-over aufnehmen"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Fingertipps anzeigen"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Zum Stoppen tippen"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Anhalten"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Pausieren"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Fortsetzen"</string>
@@ -392,15 +394,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Energiesparmodus"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"An bei Sonnenuntergang"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Bis Sonnenaufgang"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"An um <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Bis <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC ist deaktiviert"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC ist aktiviert"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Bildschirmaufnahme"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Starten"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Beenden"</string>
     <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Nach oben wischen, um Apps zu wechseln"</string>
     <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Zum schnellen Wechseln der Apps nach rechts ziehen"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Übersicht ein-/ausblenden"</string>
@@ -700,22 +701,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"Anpassen"</string>
     <string name="notification_done" msgid="6215117625922713976">"Fertig"</string>
     <string name="inline_undo" msgid="9026953267645116526">"Rückgängig machen"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"Diese Benachrichtigung als keine Unterhaltung markieren"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"Favorit"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"Aus Favoriten entfernen"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"Stummschalten"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"Stummschaltung aufheben"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"Als Infofeld anzeigen"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"Infofelder deaktivieren"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"Zum Startbildschirm hinzufügen"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g> – <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"Benachrichtigungseinstellungen"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"Optionen für spätere Erinnerung bei Benachrichtigungen"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 45ad302..d3686c8 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Ζουμ σε πλήρη οθόνη"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Προβoλή σε πλήρη οθ."</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Στιγμιότυπο οθόνης"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Έγινε εισαγωγή εικόνας"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Αποθήκ. στιγμιότυπου οθόνης..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Αποθήκευση στιγμιότυπου οθόνης..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Το στιγμιότυπο οθόνης αποθηκεύτηκε"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Έναρξη εγγραφής"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Εγγραφή σπικάζ"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Εμφάνιση πατημάτων"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Πατήστε για διακοπή"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Διακοπή"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Παύση"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Συνέχιση"</string>
@@ -388,6 +390,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Εξοικονόμ. μπαταρίας"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Κατά τη δύση"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Μέχρι την ανατολή"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Ενεργοποίηση στις <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Έως <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"Το NFC είναι απενεργοποιημένο"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"Το NFC είναι ενεργοποιημένο"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index b6a5d15..4f61daa 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zoom to fill screen"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Stretch to fill screen"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Image inserted"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Saving screenshot…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Saving screenshot…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshot saved"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Start Recording"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Record voiceover"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Show taps"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Tap to stop"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Stop"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Pause"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Resume"</string>
@@ -388,6 +390,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Battery Saver"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"On at sunset"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Until sunrise"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"On at <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Until <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC is disabled"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC is enabled"</string>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index e194e69..34a2f19 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zoom to fill screen"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Stretch to fill screen"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Image inserted"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Saving screenshot…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Saving screenshot…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshot saved"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Start Recording"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Record voiceover"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Show taps"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Tap to stop"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Stop"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Pause"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Resume"</string>
@@ -388,6 +390,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Battery Saver"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"On at sunset"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Until sunrise"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"On at <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Until <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC is disabled"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC is enabled"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index b6a5d15..4f61daa 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zoom to fill screen"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Stretch to fill screen"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Image inserted"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Saving screenshot…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Saving screenshot…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshot saved"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Start Recording"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Record voiceover"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Show taps"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Tap to stop"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Stop"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Pause"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Resume"</string>
@@ -388,6 +390,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Battery Saver"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"On at sunset"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Until sunrise"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"On at <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Until <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC is disabled"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC is enabled"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index b6a5d15..4f61daa 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zoom to fill screen"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Stretch to fill screen"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Image inserted"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Saving screenshot…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Saving screenshot…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshot saved"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Start Recording"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Record voiceover"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Show taps"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Tap to stop"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Stop"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Pause"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Resume"</string>
@@ -388,6 +390,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Battery Saver"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"On at sunset"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Until sunrise"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"On at <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Until <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC is disabled"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC is enabled"</string>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index e3a569a..2bb5131 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‎‏‏‏‎‎‎‏‎‏‎‏‎‎‏‎‏‎‎‎‎‎‏‏‎‏‎‎‏‏‏‎‏‏‎‏‎‏‏‎‎‏‏‎‎‎‏‏‏‎‏‏‏‎‏‎‎‎Zoom to fill screen‎‏‎‎‏‎"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‎‏‏‏‎‏‏‎‎‏‎‏‎‎‎‏‏‏‎‎‎‎‎‎‎‎‏‎‎‏‎‏‏‎‏‏‏‏‏‎‎‎‏‏‎‏‏‏‎‎‏‎‎‏‎Stretch to fill screen‎‏‎‎‏‎"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‎‎‏‎‎‏‏‏‎‎‏‏‏‎‎‎‎‏‎‏‏‏‎‏‎‎‏‏‎‎‏‏‎‎‏‏‎‏‎‎‏‏‏‎‏‎‎‎‏‏‎‎‎‎‏‏‎‎Screenshot‎‏‎‎‏‎"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‎‎‎‎‎‎‏‎‏‎‏‎‎‏‏‎‎‏‏‎‏‎‏‏‏‏‎‏‏‏‎‎‏‎‏‏‏‏‎‎‎‏‏‏‏‎‏‎‏‎‏‎‎‏‏‎‏‎Image inserted‎‏‎‎‏‎"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‎‎‏‏‏‏‎‎‎‏‏‎‎‏‏‎‏‏‏‏‏‏‏‏‎‎‏‎‎‏‎‏‎‏‎‎‎‎‏‏‏‎‎‎‎‏‏‎‏‎‎‎‏‎‏‎‎‎Saving screenshot…‎‏‎‎‏‎"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‎‏‏‎‎‎‎‎‏‏‏‏‎‎‏‏‏‏‎‎‎‎‏‏‎‏‎‏‏‎‏‎‎‎‎‏‏‎‎‎‏‎‏‎‎‏‎‏‎Saving screenshot…‎‏‎‎‏‎"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‏‏‎‏‎‏‏‎‎‏‏‏‎‏‏‏‏‎‎‏‏‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎‎‎‎‏‏‎‏‎‏‏‏‎‎‏‎‎‎‏‎Screenshot saved‎‏‎‎‏‎"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‏‎‏‎‏‏‎‏‏‏‏‎‎‏‏‎‎‎‎‏‏‏‏‎‏‏‎‏‏‏‎‏‎‏‏‏‏‎‏‎‏‏‎‎‎‏‏‏‎‎‎‎‎‎‎‏‎‎Start Recording‎‏‎‎‏‎"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‎‏‎‎‎‎‏‎‎‎‎‏‏‎‎‏‎‏‎‎‏‏‏‎‏‏‏‎‎‎‎‎‏‏‎‎‏‎‎‎‏‏‏‏‏‎‎‏‎‎‏‎‎‎‎‎Record voiceover‎‏‎‎‏‎"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‏‎‏‏‏‏‎‎‏‎‏‎‎‏‏‎‎‏‏‏‎‎‏‎‏‏‎‏‎‏‎‏‎‎‎‏‎‏‎‏‏‎‏‏‏‏‎‏‏‏‏‏‎‏‎‏‎‎‎Show taps‎‏‎‎‏‎"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‏‏‎‎‎‏‏‏‎‏‏‏‏‏‏‎‏‎‏‏‏‎‏‎‎‎‎‏‏‎‏‎‏‏‏‏‏‎‏‏‏‏‏‏‏‎‏‏‏‎‏‎‏‏‎‎Tap to stop‎‏‎‎‏‎"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‎‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‏‏‏‏‏‏‎‏‏‎‏‏‏‏‏‎‎‎‏‎‏‏‏‏‏‎‎‎‏‎‏‎‎‎‏‎‏‏‎‏‎‏‎Stop‎‏‎‎‏‎"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‏‎‏‎‏‎‎‏‎‏‎‏‏‎‎‎‎‎‎‏‎‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‎‏‎‎‎‎‏‎‏‏‎‏‏‏‏‏‎‎‎‎‏‎Pause‎‏‎‎‏‎"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‎‎‎‎‎‎‎‏‏‏‎‎‎‏‎‏‎‎‎‎‎‏‏‏‎‏‎‏‎‎‏‏‎‎‎‎‎‏‏‎‎‎‎‎‎‎‎‎‏‏‏‎‏‏‏‎Resume‎‏‎‎‏‎"</string>
@@ -388,6 +390,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‏‎‎‎‎‏‎‏‎‎‏‎‎‏‎‏‏‎‎‏‎‏‎‎‏‎‎‎‏‎‎‎‎‎‏‎‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‏‎Battery Saver‎‏‎‎‏‎"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‎‏‏‎‏‏‏‏‏‏‎‏‏‎‎‎‏‎‎‎‎‎‏‏‎‏‎‎‎‎‏‎‎‏‏‎‏‏‎‏‏‏‏‎‎On at sunset‎‏‎‎‏‎"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‏‎‎‏‎‎‎‎‏‎‏‎‎‏‎‏‏‏‎‏‎‎‎‏‎‎‎‏‎‎‏‎‎‏‎‏‎‎‏‏‎‎‏‎‎‎‎‎‏‏‎‏‏‏‎‎‎‎Until sunrise‎‏‎‎‏‎"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‏‎‎‏‎‏‏‎‏‎‎‎‎‎‎‏‎‏‏‏‏‏‎‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‏‏‎‎‎‎‎‏‏‏‎‏‎‏‏‏‏‏‏‎On at ‎‏‎‎‏‏‎<xliff:g id="TIME">%s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‏‏‎‎‎‏‏‎‏‏‏‎‏‎‎‏‏‏‏‎‎‏‏‏‏‎‎‎‏‎‏‏‏‏‎‎‏‎‏‎‎‏‏‎‏‏‎‏‏‎‎‏‎‏‎‏‎Until ‎‏‎‎‏‏‎<xliff:g id="TIME">%s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‏‎‏‎‎‎‎‏‏‎‏‏‎‎‎‎‎‎‎‏‏‎‏‎‏‎‏‎‎‎‏‎‎‏‎‏‏‏‏‎‏‏‎‏‎‎‎‏‏‏‎‏‎‏‎‏‎NFC‎‏‎‎‏‎"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎‎‎‎‏‎‏‏‎‎‎‏‎‎‏‏‏‎‎‏‏‎‎‎‏‏‏‏‎‎‎‏‎‏‎‎‎‎‏‎‏‎‎‎‎‎‏‎‏‏‎‎‏‎‏‏‏‎NFC is disabled‎‏‎‎‏‎"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‏‏‏‏‏‎‎‏‎‎‏‏‎‎‏‎‎‏‏‏‎‎‏‏‏‎‎‏‏‏‏‏‎‎‏‎‏‎‏‏‏‏‎‏‏‏‏‎‎‏‎‏‏‎‏‏‎‎NFC is enabled‎‏‎‎‏‎"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 255db92..e2bf6ef 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zoom para ocupar la pantalla"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Estirar p/ ocupar la pantalla"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Captura de pantalla"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Se insertó la imagen"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Guardando captura de pantalla"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Guardando la captura de pantalla..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Se guardó la captura de pantalla"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Iniciar grabación"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Grabar voz superpuesta"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Mostrar toques"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Presiona para detener"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Detener"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Pausar"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Reanudar"</string>
@@ -388,6 +390,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Ahorro de batería"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Al atardecer"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Hasta el amanecer"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"A la(s) <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Hasta la(s) <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"La tecnología NFC está inhabilitada"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"La tecnología NFC está habilitada"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index d1d959c..40d7fe3 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zoom para ajustar"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Expandir para ajustar"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Captura de pantalla"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Se ha insertado la imagen"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Guardando captura..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Guardando captura..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Se ha guardado la captura de pantalla"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Iniciar grabación"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Grabar voz en off"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Mostrar toques"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Toca para detener"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Detener"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Pausar"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Seguir"</string>
@@ -388,6 +390,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Ahorro de batería"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Al anochecer"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Hasta el amanecer"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"A las <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Hasta las <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"El NFC está desactivado"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"El NFC está activado"</string>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 6f69a17..d8f546c 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Suumi ekraani täitmiseks"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Venita ekraani täitmiseks"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Ekraanipilt"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Pilt on sisestatud"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Kuvatõmmise salvestamine ..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Kuvatõmmise salvestamine ..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Ekraanipilt salvestati"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Alusta salvestamist"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Salvesta hääl"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Kuva puudutused"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Puudutage peatamiseks"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Peata"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Peata"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Jätka"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Akusäästja"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Sisse päikeselooj."</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Kuni päikesetõusuni"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Sisse kell <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Kuni <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC on keelatud"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC on lubatud"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Ekraanikirje"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Alustage"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Peatage"</string>
     <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Rakenduste vahetamiseks pühkige üles"</string>
     <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Lohistage paremale, et rakendusi kiiresti vahetada"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Lehe Ülevaade sisse- ja väljalülitamine"</string>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"Kohandamine"</string>
     <string name="notification_done" msgid="6215117625922713976">"Valmis"</string>
     <string name="inline_undo" msgid="9026953267645116526">"Võta tagasi"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"Eemalda see meeldetuletus vestlustest"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"Lisa lemmikutesse"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"Tühista lemmikutesse lisamine"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"Vaigista"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"Tühista vaigistus"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"Kuva mullina"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"Lülita mullid välja"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"Lisa avakuvale"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g>, <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"märguannete juhtnupud"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"märguannete edasilükkamise valikud"</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 1b89c5a..9dceb5f 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Handiagotu pantaila betetzeko"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Luzatu pantaila betetzeko"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Pantaila-argazkia"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Irudi bat txertatu da"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Pantaila-argazkia gordetzen…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Pantaila-argazkia gordetzen…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Gorde da pantaila-argazkia"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Hasi grabatzen"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Grabatu off ahotsa"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Erakutsi sakatzeak"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Sakatu gelditzeko"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Gelditu"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Pausatu"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Berrekin"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Bateria-aurrezlea"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Ilunabarrean aktibatuko da"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Egunsentira arte"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Aktibatze-ordua: <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Desaktibatze-ordua: <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"Desgaituta dago NFC"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"Gaituta dago NFC"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Pantaila-grabaketa"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Hasi"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Gelditu"</string>
     <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Egin gora aplikazioa aldatzeko"</string>
     <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Arrastatu eskuinera aplikazioa azkar aldatzeko"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Aldatu ikuspegi orokorra"</string>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"Pertsonalizatu"</string>
     <string name="notification_done" msgid="6215117625922713976">"Eginda"</string>
     <string name="inline_undo" msgid="9026953267645116526">"Desegin"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"Markatu jakinarazpen hau ez dela elkarrizketa bat"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"Markatu gogoko gisa"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"Kendu gogokoetatik"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"Ezkutatu"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"Erakutsi"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"Markatu burbuila gisa"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"Desaktibatu burbuilak"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"Gehitu hasierako pantailan"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"jakinarazpena kontrolatzeko aukerak"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"jakinarazpena atzeratzeko aukerak"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 2b76557..d27b420 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"بزرگ‌نمایی برای پر کردن صفحه"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"گسترده کردن برای پر کردن صفحه"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"عکس صفحه‌نمایش"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"تصویر درج شد"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"در حال ذخیره عکس صفحه‌نمایش..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"درحال ذخیره عکس صفحه‌نمایش…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"عکس صفحه‌نمایش ذخیره شد"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"شروع ضبط"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"ضبط صدا روی تصویر"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"نمایش ضربه‌ها"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"ضربه برای توقف"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"توقف"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"مکث"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"ازسرگیری"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"بهینه‌سازی باتری"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"غروب روشن می‌شود"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"تا طلوع آفتاب"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"ساعت <xliff:g id="TIME">%s</xliff:g> روشن می‌شود"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"تا<xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"‏NFC غیرفعال است"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"‏NFC فعال است"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"ضبط کردن صفحه‌نمایش"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"شروع"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"توقف"</string>
     <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"برای تغییر برنامه‌ها،‌ تند به بالا بکشید"</string>
     <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"برای جابه‌جایی سریع میان برنامه‌ها، به چپ بکشید"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"تغییر وضعیت نمای کلی"</string>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"سفارشی کردن"</string>
     <string name="notification_done" msgid="6215117625922713976">"تمام"</string>
     <string name="inline_undo" msgid="9026953267645116526">"واگرد"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"علامت‌گذاری این اعلان به‌عنوان غیرمکالمه"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"مورد دلخواه"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"حذف از موارد دلخواه"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"صامت کردن"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"باصدا کردن"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"نمایش به‌شکل ابزارک اعلان"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"خاموش کردن ابزارک‌های اعلان"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"افزودن به صفحه اصلی"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"کنترل‌های اعلان"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"گزینه‌های تعویق اعلان"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 9b76f39..cf01efd 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zoomaa koko näyttöön"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Venytä koko näyttöön"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Kuvakaappaus"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Kuva lisätty"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Tallennetaan kuvakaappausta..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Tallennetaan kuvakaappausta..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Kuvakaappaus tallennettu"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Aloita tallennus"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Äänitä taustaselostus"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Näytä napautukset"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Lopeta napauttamalla"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Lopeta"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Keskeytä"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Jatka"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Virransäästö"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Auringon laskiessa"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Auringonnousuun"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Päälle klo <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> asti"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC on poistettu käytöstä"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC on käytössä"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Näytön tallentaminen"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Aloita"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Lopeta"</string>
     <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Vaihda sovellusta pyyhkäisemällä ylös"</string>
     <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Vaihda sovellusta nopeasti vetämällä oikealle"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Näytä/piilota viimeisimmät"</string>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"Muokkaa"</string>
     <string name="notification_done" msgid="6215117625922713976">"Valmis"</string>
     <string name="inline_undo" msgid="9026953267645116526">"Kumoa"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"Merkitse, että tämä ilmoitus ei ole keskustelu"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"Suosikki"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"Poista suosikeista"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"Ohita"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"Poista ohitus"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"Näytä ohjekuplana"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"Laita ohjekuplat pois päältä"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"Lisää aloitusnäytölle"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"Ilmoitusten hallinta"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"Ilmoitusten torkkuasetukset"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 55eb39e..5f7a358 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zoomer pour remplir l\'écran"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Étirer pour remplir l\'écran"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Capture d\'écran"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Image insérée"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Enregistrement capture écran…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Enregistrement capture écran…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Capture d\'écran enregistrée"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Commencer l\'enregistrement"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Enregistrer la voix hors champ"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Afficher les éléments sélectionnés"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Toucher pour arrêter"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Arrêter"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Pause"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Reprendre"</string>
@@ -388,6 +390,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Économiseur de pile"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Activé la nuit"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Jusqu\'à l\'aube"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Actif à <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Jusqu\'à <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC désactivée"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC activée"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 5b12612..3c12f66 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zoomer pour remplir l\'écran"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Étirer pour remplir l\'écran"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Capture d\'écran"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Image insérée"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Enregistrement capture écran…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Enregistrement de la capture d\'écran…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Capture d\'écran enregistrée"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Démarrer l\'enregistrement"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Enregistrer une voix off"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Afficher les éléments sélectionnés"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Appuyez ici pour arrêter"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Arrêter"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Pause"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Reprendre"</string>
@@ -388,6 +390,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Économiseur batterie"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Activé la nuit"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Jusqu\'à l\'aube"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"À partir de <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Jusqu\'à <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC désactivée"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"La technologie NFC est activée"</string>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 74ee202..0c444e4 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Ampliar ata ocupar todo"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Estirar ata ocupar todo"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Crear captura"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Engadiuse a imaxe"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Gardando captura de pantalla…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Gardando captura de pantalla…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Gardouse a captura de pantalla"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Iniciar gravación"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Gravar voz en off"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Mostrar toques"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Toca para deter a gravación"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Deter"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Pór en pausa"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Retomar"</string>
@@ -388,6 +390,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Aforro de batería"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Activación ao solpor"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Ata o amencer"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Activarase ás: <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Utilizarase ata as: <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"A opción NFC está desactivada"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"A opción NFC está activada"</string>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index 4b5dd25..9dde523 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"સ્ક્રીન ભરવા માટે ઝૂમ કરો"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"સ્ક્રીન ભરવા માટે ખેંચો"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"સ્ક્રીનશૉટ"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"છબી શામેલ કરી"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"સ્ક્રીનશોટ સાચવી રહ્યું છે…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"સ્ક્રીનશોટ સાચવી રહ્યું છે…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"સ્ક્રીનશૉટ સાચવ્યો"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"રેકોર્ડિંગ શરૂ કરો"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"વૉઇસઓવર રેકોર્ડ કરો"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"ટૅપ કર્યાની સંખ્યા બતાવો"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"રોકવા માટે ટૅપ કરો"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"રોકો"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"થોભાવો"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"ફરી શરૂ કરો"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"બૅટરી સેવર"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"સૂર્યાસ્ત વખતે"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"સૂર્યોદય સુધી"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g> વાગ્યે ચાલુ"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> વાગ્યા સુધી"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC અક્ષમ કરેલ છે"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC સક્ષમ કરેલ છે"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"સ્ક્રીન રેકૉર્ડ કરો"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"શરૂ કરો"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"રોકો"</string>
     <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"ઍપ સ્વિચ કરવા માટે ઉપરની તરફ સ્વાઇપ કરો"</string>
     <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"ઍપને ઝડપથી સ્વિચ કરવા માટે જમણે ખેંચો"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"ઝલકને ટૉગલ કરો"</string>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"કસ્ટમાઇઝ કરો"</string>
     <string name="notification_done" msgid="6215117625922713976">"થઈ ગયું"</string>
     <string name="inline_undo" msgid="9026953267645116526">"રદ કરો"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"આ નોટિફિકેશન વાતચીત ન હોવા તરીકે માર્ક કરો"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"મનપસંદ"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"મનપસંદમાંથી કાઢી નાખો"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"મ્યૂટ કરો"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"અનમ્યૂટ કરો"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"બબલ તરીકે બતાવો"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"બબલ બંધ કરો"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"હોમ સ્ક્રીન પર ઉમેરો"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"સૂચના નિયંત્રણો"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"સૂચના સ્નૂઝ કરવાના વિકલ્પો"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index c22d234..5522605 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"स्‍क्रीन भरने के लिए ज़ूम करें"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"स्‍क्रीन भरने के लिए खींचें"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"स्क्रीनशॉट"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"इमेज डाली गई"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"स्क्रीनशॉट सहेजा जा रहा है..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"स्क्रीनशॉट सहेजा जा रहा है..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"स्क्रीनशॉट सेव किया गया"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"रिकॉर्डिंग शुरू करें"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"वॉइसओवर रिकॉर्ड करें"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"टैप दिखाएं"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"रोकने के लिए टैप करें"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"रोकें"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"रोकें"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"फिर से शुरू करें"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"बैटरी सेवर"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"शाम को चालू होगा"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"सुबह तक चालू रहेगी"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g> बजे चालू हाेगी"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> बजे तक चालू रहेगी"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"एनएफ़सी"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC बंद है"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC चालू है"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"स्क्रीन रिकॉर्ड"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"शुरू करें"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"रोकें"</string>
     <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"ऐप्लिकेशन बदलने के लिए ऊपर स्वाइप करें"</string>
     <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"ऐप्लिकेशन को झटपट स्विच करने के लिए उसे दाईं ओर खींचें और छोड़ें"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"खास जानकारी टॉगल करें"</string>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"पसंद के मुताबिक बनाएं"</string>
     <string name="notification_done" msgid="6215117625922713976">"हो गया"</string>
     <string name="inline_undo" msgid="9026953267645116526">"पहले जैसा करें"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"इस सूचना को \'बातचीत नहीं\' के रूप में मार्क करें"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"पसंदीदा के रूप में मार्क करें"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"पसंदीदा से हटाएं"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"म्यूट करें"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"अनम्यूट करें"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"बबल के रूप में दिखाएं"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"बबल्स को बंद करें"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"होम स्क्रीन पर जोड़ें"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"सूचना नियंत्रण"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"सूचना को स्नूज़ (थोड़ी देर के लिए चुप करना) करने के विकल्प"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 1286709..55a0e78 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zumiraj i ispuni zaslon"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Rastegni i ispuni zaslon"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Snimka zaslona"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Umetnuta je slika"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Spremanje snimke zaslona..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Spremanje snimke zaslona..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Snimka zaslona spremljena"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Započni snimanje"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Snimi glasovni zapis"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Prikaži dodire"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Dodirnite da biste zaustavili"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Zaustavi"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Pauza"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Nastavi"</string>
@@ -390,6 +392,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Štednja baterije"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Uključuje se u suton"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Do izlaska sunca"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Uključuje se u <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Do <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC je onemogućen"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC je omogućen"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index a3b6d3f..a9b2d03 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Nagyítás a kitöltéshez"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Nyújtás kitöltéshez"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Képernyőkép"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Kép beszúrva"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Képernyőkép mentése..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Képernyőkép mentése..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"A képernyőkép mentése sikerült"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Rögzítés indítása"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Hang rögzítése"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Koppintások megjelenítése"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Koppintson a leállításhoz"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Leállítás"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Szünet"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Folytatás"</string>
@@ -388,6 +390,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Akkumulátorkímélő"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Be: napnyugta"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Napfelkeltéig"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Be: <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Eddig: <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"Az NFC ki van kapcsolva"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"Az NFC be van kapcsolva"</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 5c73ed1..78acb2e 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Խոշորացնել` էկրանը լցնելու համար"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Ձգել` էկրանը լցնելու համար"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Սքրինշոթ"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Պատկերը զետեղվեց"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Սքրինշոթը պահվում է…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Սքրինշոթը պահվում է..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Սքրինշոթը պահվեց"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Սկսել տեսագրումը"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Ձայնագրել ուղեկցող ձայները"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Ցույց տալ հպումները"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Հպեք՝ դադարեցնելու համար"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Կանգնեցնել"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Դադարեցնել"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Վերսկսել"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Մարտկոցի տնտեսում"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Կմիացվի մայրամուտին"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Մինչև լուսաբաց"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Կմիանա՝ <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Մինչև <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC-ն անջատված է"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC-ն միացված է"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Էկրանի ձայնագրում"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Սկսել"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Կանգնեցնել"</string>
     <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Սահեցրեք վերև՝ մյուս հավելվածին անցնելու համար"</string>
     <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Քաշեք աջ՝ հավելվածների միջև անցնելու համար"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Միացնել/անջատել համատեսքը"</string>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"Կարգավորել"</string>
     <string name="notification_done" msgid="6215117625922713976">"Պատրաստ է"</string>
     <string name="inline_undo" msgid="9026953267645116526">"Հետարկել"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"Նշել այս ծանուցումը որպես ոչ խոսակցություն"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"Ավելացնել ընտրանիում"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"Հեռացնել ընտրանուց"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"Անջատել ծանուցումները"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"Միացնել ծանուցումները"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"Ցուցադրել որպես ամպիկ"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"Անջատել ամպիկները"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"Ավելացնել հիմնական էկրանին"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"ծանուցման կառավարներ"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"ծանուցման հետաձգման ընտրանքներ"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index bad3e67..95c16c8 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Perbesar utk mengisi layar"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Rentangkn utk mngisi layar"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Gambar disisipkan"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Menyimpan screenshot..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Menyimpan screenshot..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshot disimpan"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Mulai Merekam"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Rekam voiceover"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Tampilkan sentuhan"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Ketuk untuk menghentikan"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Stop"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Jeda"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Lanjutkan"</string>
@@ -388,6 +390,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Penghemat Baterai"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Aktif saat malam"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Sampai pagi"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Aktif pada <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Sampai <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC dinonaktifkan"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC diaktifkan"</string>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 68f04fb..985f62d 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Fylla skjá með aðdrætti"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Teygja yfir allan skjáinn"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Skjámynd"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Mynd sett inn"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Vistar skjámynd…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Vistar skjámynd…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Skjámynd vistuð"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Hefja upptöku"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Taka upp talsetningu"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Sýna snertingar"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Ýttu til að stöðva"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Stöðva"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Hlé"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Halda áfram"</string>
@@ -388,6 +390,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Rafhlöðusparnaður"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Kveikt við sólsetur"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Til sólarupprásar"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Virkt kl. <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Til <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"Slökkt á NFC"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"Kveikt á NFC"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index bdf93fa..870e6b7 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zoom per riempire schermo"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Estendi per riemp. schermo"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Immagine inserita"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Salvataggio screenshot..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Salvataggio screenshot..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshot salvato"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Avvia registrazione"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Registra voce fuori campo"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Mostra tocchi"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Tocca per interrompere"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Interrompi"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Pausa"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Riprendi"</string>
@@ -388,6 +390,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Risparmio energetico"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Attivato al tramonto"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Fino all\'alba"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Attivazione alle <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Fino alle <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC non attiva"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC attiva"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 9cfd0b3..775be02 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"הגדל תצוגה כדי למלא את המסך"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"מתח כדי למלא את המסך"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"צילום מסך"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"התמונה התווספה"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"שומר צילום מסך..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"שומר צילום מסך..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"צילום המסך נשמר"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"הפעלת ההקלטה"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"‏הקלטת voiceover"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"הצגת הקשות"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"אפשר להקיש כדי להפסיק"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"עצירה"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"השהיה"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"המשך"</string>
@@ -392,15 +394,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"חיסכון בסוללה"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"מופעל בשקיעה"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"עד הזריחה"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"יתחיל בשעה <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"עד <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"‏NFC מושבת"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"‏NFC מופעל"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"הקלטת המסך"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"התחלה"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"עצירה"</string>
     <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"יש להחליק מעלה כדי להחליף אפליקציות"</string>
     <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"יש לגרור ימינה כדי לעבור במהירות בין אפליקציות"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"החלפת מצב של מסכים אחרונים"</string>
@@ -702,22 +703,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"התאמה אישית"</string>
     <string name="notification_done" msgid="6215117625922713976">"סיום"</string>
     <string name="inline_undo" msgid="9026953267645116526">"ביטול"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"סימון ההתראה הזו כהתראה שאינה משיחה"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"סימון כמועדפת"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"הסרה מהמועדפים"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"השתקה"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"ביטול ההשתקה"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"הצגה בתור בועה"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"כיבוי הבועות"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"הוספה למסך הבית"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"בקרת התראות"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"אפשרויות של דחיית התראות לטיפול בהמשך"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 0c57372..7af3f86 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"画面サイズに合わせて拡大"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"画面サイズに合わせて拡大"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"スクリーンショット"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"画像を挿入しました"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"スクリーンショットを保存中..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"スクリーンショットを保存しています..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"スクリーンショットを保存しました"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"録画を開始"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"ナレーションの録音"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"タップの表示"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"タップして停止"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"停止"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"一時停止"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"再開"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"バッテリー セーバー"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"日の入りに ON"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"日の出まで"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g>にオン"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g>まで"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC は無効です"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC は有効です"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"スクリーン レコード"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"開始"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"停止"</string>
     <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"アプリを切り替えるには上にスワイプ"</string>
     <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"右にドラッグするとアプリを素早く切り替えることができます"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"概要を切り替え"</string>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"カスタマイズ"</string>
     <string name="notification_done" msgid="6215117625922713976">"完了"</string>
     <string name="inline_undo" msgid="9026953267645116526">"元に戻す"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"この通知を会話ではないとマーク"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"お気に入り"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"お気に入りから削除"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"ミュート"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"ミュートを解除"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"ふきだしとして表示"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"ふきだしを OFF にする"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"ホーム画面に追加"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"通知管理"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"通知スヌーズ設定"</string>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index a3827d2..2433f9e 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"მასშტაბი შეცვალეთ ეკრანის შესავსებად."</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"გაწიეთ ეკრანის შესავსებად."</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"ეკრანის ანაბეჭდი"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"სურათი ჩასმულია"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"სკრინშოტის შენახვა…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"ეკრანის სურათის შენახვა…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"ეკრანის ანაბეჭდი შენახულია"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"ჩაწერის დაწყება"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"ხმის ჩაწერა"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"შეხებების ჩვენება"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"შეეხეთ შესაწყვეტად"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"შეწყვეტა"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"პაუზა"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"გაგრძელება"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"ბატარეის დამზოგი"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"ჩაირთოს მზის ჩასვლისას"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"მზის ამოსვლამდე"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"ჩაირთოს <xliff:g id="TIME">%s</xliff:g>-ზე"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g>-მდე"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC გათიშულია"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC ჩართულია"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"ეკრანის ჩანაწერი"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"დაწყება"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"შეწყვეტა"</string>
     <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"გადაფურცლეთ ზემოთ აპების გადასართავად"</string>
     <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"აპების სწრაფად გადასართავად ჩავლებით გადაიტანეთ მარჯვნივ"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"მიმოხილვის გადართვა"</string>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"მორგება"</string>
     <string name="notification_done" msgid="6215117625922713976">"მზადაა"</string>
     <string name="inline_undo" msgid="9026953267645116526">"მოქმედების გაუქმება"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"ამ შეტყობინების მონიშვნა, როგორც არა მიმოწერის"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"რჩეული"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"რჩეულებიდან ამოღება"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"დადუმება"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"დადუმების მოხსნა"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"ბუშტის სახით ჩვენება"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"ბუშტების გამორთვა"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"მთავარ ეკრანზე დამატება"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"შეტყობინებების მართვის საშუალებები"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"შეტყობინებების ჩაჩუმების ვარიანტები"</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index 19ae4e2..be93c18 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Экранды толтыру үшін ұлғайту"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Экранды толтыру үшін созу"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Скриншот"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Сурет енгізілді"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Скриншотты сақтауда…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Скриншотты сақтауда…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Скриншот сақталды"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Жазуды бастау"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Кадр сыртындағы дыбысты жазу"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Түрту әрекеттерін көрсету"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Тоқтату үшін түртіңіз"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Тоқтату"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Тоқтата тұру"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Жалғастыру"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Battery Saver"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Күн батқанда қосу"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Күн шыққанға дейін"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Қосылу уақыты: <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> дейін"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC өшірулі"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC қосулы"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Экранды жазу"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Бастау"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Тоқтату"</string>
     <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Қолданбалар арасында ауысу үшін жоғары сырғытыңыз"</string>
     <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Қолданбаларды жылдам ауыстырып қосу үшін оңға қарай сүйреңіз"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Шолуды қосу/өшіру"</string>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"Реттеу"</string>
     <string name="notification_done" msgid="6215117625922713976">"Дайын"</string>
     <string name="inline_undo" msgid="9026953267645116526">"Қайтару"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"Хабарландыруды сөйлесу емес деп белгілеу"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"Таңдаулы"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"Таңдаулылар тізімінен шығару"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"Дыбысын өшіру"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"Дыбысын қосу"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"Қалқымалы анықтама ретінде көрсету"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"Қалқымалы анықтамаларды өшіру"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"Негізгі экранға қосу"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"хабарландыруларды басқару элементтері"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"хабарландыруды кідірту опциялары"</string>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index d6ec177..413125c 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"ពង្រីក​​ដើម្បី​ឲ្យ​ពេញ​អេក្រង់"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"ទាញ​ដើម្បី​ឲ្យ​ពេញ​អេក្រង់"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"រូបថតអេក្រង់"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"បាន​បញ្ចូល​រូបភាព"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"កំពុង​រក្សាទុក​រូបថត​អេក្រង់…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"កំពុង​រក្សាទុក​រូបថត​អេក្រង់..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"បានរក្សាទុក​រូបថតអេក្រង់"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"ចាប់​ផ្តើមថត"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"ថត​ការបញ្ចូល​សំឡេង"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"បង្ហាញការចុច"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"ចុច ដើម្បីបញ្ឈប់"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"ឈប់"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"ផ្អាក"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"បន្ត"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"កម្មវិធីសន្សំថ្ម"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"បើក​នៅពេល​ថ្ងៃលិច"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"រហូត​ដល់​ពេល​ថ្ងៃរះ"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"បើកនៅម៉ោង <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"រហូតដល់ម៉ោង <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"បាន​បិទ NFC"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"បាន​បើក NFC"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"ការថត​អេក្រង់"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"ចាប់ផ្ដើម"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"ឈប់"</string>
     <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"អូស​ឡើង​លើ​ដើម្បី​ប្តូរ​កម្មវិធី"</string>
     <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"អូសទៅស្ដាំដើម្បីប្ដូរកម្មវិធីបានរហ័ស"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"បិទ/បើក​ទិដ្ឋភាពរួម"</string>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"ប្ដូរតាមបំណង"</string>
     <string name="notification_done" msgid="6215117625922713976">"រួចរាល់"</string>
     <string name="inline_undo" msgid="9026953267645116526">"ត្រឡប់វិញ"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"សម្គាល់​ការជូន​ដំណឹង​នេះ​ថា​មិនមែនជា​ការសន្ទនា"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"សំណព្វ"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"ដក​ចេញ​ពី​សំណព្វ"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"បិទ​សំឡេង"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"បើក​សំឡេង"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"បង្ហាញ​ជា​សារ​លេចឡើង"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"បិទ​សារ​លេចឡើង"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"បញ្ចូល​ទៅក្នុង​អេក្រង់​ដើម"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"ការគ្រប់គ្រង​ការជូន​ដំណឹង"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"ជម្រើស​ផ្អាកការ​ជូនដំណឹង"</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index fc0f8e6..0b98e06 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"ಪರದೆ ತುಂಬಿಸಲು ಝೂಮ್ ಮಾಡು"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"ಪರದೆ ತುಂಬಿಸಲು ವಿಸ್ತಾರಗೊಳಿಸು"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"ಚಿತ್ರವನ್ನು ಸೇರಿಸಲಾಗಿದೆ"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ಉಳಿಸಲಾಗುತ್ತಿದೆ…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ಉಳಿಸಲಾಗುತ್ತಿದೆ…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್‌ ಅನ್ನು ಉಳಿಸಲಾಗಿದೆ"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"ರೆಕಾರ್ಡಿಂಗ್ ಆರಂಭಿಸಿ"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"voiceover ಅನ್ನು ರೆಕಾರ್ಡ್ ಮಾಡಿ"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"ಟ್ಯಾಪ್‌ಗಳನ್ನು ತೋರಿಸಿ"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"ನಿಲ್ಲಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"ನಿಲ್ಲಿಸಿ"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"ವಿರಾಮಗೊಳಿಸಿ"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"ಮುಂದುವರಿಸಿ"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"ಬ್ಯಾಟರಿ ಸೇವರ್"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"ಸೂರ್ಯಾಸ್ತ ಸಮಯದಲ್ಲಿ"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"ಸೂರ್ಯೋದಯದವರೆಗೆ"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g> ಸಮಯದಲ್ಲಿ"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> ವರೆಗೂ"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC ನಿಷ್ಕ್ರಿಯಗೊಂಡಿದೆ"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC ಸಕ್ರಿಯಗೊಂಡಿದೆ"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"ಸ್ಕ್ರೀನ್ ರೆಕಾರ್ಡ್"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"ಪ್ರಾರಂಭಿಸಿ"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"ನಿಲ್ಲಿಸಿ"</string>
     <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ಬದಲಾಯಿಸಲು ಸ್ವೈಪ್ ಮಾಡಿ"</string>
     <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ಬದಲಿಸಲು ತ್ವರಿತವಾಗಿ ಬಲಕ್ಕೆ ಡ್ರ್ಯಾಗ್ ಮಾಡಿ"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"ಟಾಗಲ್ ನ ಅವಲೋಕನ"</string>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"ಕಸ್ಟಮೈಜ್‌ ಮಾಡಿ"</string>
     <string name="notification_done" msgid="6215117625922713976">"ಮುಗಿದಿದೆ"</string>
     <string name="inline_undo" msgid="9026953267645116526">"ರದ್ದುಮಾಡಿ"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"ಈ ಅಧಿಸೂಚನೆಯನ್ನು ಸಂಭಾಷಣೆಯಲ್ಲ ಎಂಬುದಾಗಿ ಗುರುತಿಸಿ"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"ಮೆಚ್ಚಿನದು"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"ಮೆಚ್ಚಿನದಲ್ಲದ್ದು"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"ಮ್ಯೂಟ್ ಮಾಡಿ"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"ಅನ್‌ಮ್ಯೂಟ್ ಮಾಡಿ"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"ಗುಳ್ಳೆಯಾಗಿ ತೋರಿಸಿ"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"ಗುಳ್ಳೆಗಳನ್ನು ಆಫ್ ಮಾಡಿ"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"ಮುಖಪುಟದ ಪರದೆಗೆ ಸೇರಿಸಿ"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"ಅಧಿಸೂಚನೆ ನಿಯಂತ್ರಣಗಳು"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"ಅಧಿಸೂಚನೆ ಸ್ನೂಜ್ ಆಯ್ಕೆಗಳು"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index eb3ebc9..54b055d 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"전체화면 모드로 확대"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"전체화면 모드로 확대"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"스크린샷"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"이미지 삽입됨"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"캡쳐화면 저장 중..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"캡쳐화면 저장 중..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"스크린샷 저장됨"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"녹화 시작"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"음성 해설 녹음"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"탭한 항목 표시"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"탭하여 중지하기"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"중지"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"일시중지"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"재개"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"절전 모드"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"일몰에"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"일출까지"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g>에"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g>까지"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC 사용 중지됨"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC 사용 설정됨"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"화면 녹화"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"시작"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"중지"</string>
     <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"위로 스와이프하여 앱 전환"</string>
     <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"앱을 빠르게 전환하려면 오른쪽으로 드래그"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"최근 사용 버튼 전환"</string>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"맞춤설정"</string>
     <string name="notification_done" msgid="6215117625922713976">"완료"</string>
     <string name="inline_undo" msgid="9026953267645116526">"실행취소"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"이 알림을 대화가 아닌 일반 알림으로 표시"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"즐겨찾기"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"즐겨찾기 해제"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"숨기기"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"숨기기 취소"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"버블로 표시"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"버블 사용 중지"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"홈 화면에 추가"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"알림 관리"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"알림 일시 중지 옵션"</string>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index 06f8161..ed6b918 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Экрнд тлтр ү. чен өлч өзг"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Экранды толтуруу ү-н чоюу"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Скриншот"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Сүрөт киргизилди"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Скриншот сакталууда…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Скриншот сакталууда..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Скриншот сакталды"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Жаздырып баштоо"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Үн коштоону жаздыруу"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Басылган жерди көрсөтүү"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Токтотуш үчүн басыңыз"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Токтотуу"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Тындыруу"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Улантуу"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Батареяны үнөмдөгүч"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Күн батканда күйөт"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Күн чыкканга чейин"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Саат <xliff:g id="TIME">%s</xliff:g> күйөт"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> чейин"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC өчүрүлгөн"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC иштетилген"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Экранды жаздыруу"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Старт"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Токтотуу"</string>
     <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Колдонмолорду которуштуруу үчүн өйдө сүрүңүз"</string>
     <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Колдонмолорду тез которуштуруу үчүн оңго сүйрөңүз"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Сереп салууну өчүрүү/күйгүзүү"</string>
@@ -444,7 +445,7 @@
     <string name="guest_new_guest" msgid="962155336259570156">"Конок кошуу"</string>
     <string name="guest_exit_guest" msgid="4030840507598850886">"Конокту алып салуу"</string>
     <string name="guest_exit_guest_dialog_title" msgid="5015697561580641422">"Конокту алып саласызбы?"</string>
-    <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Бул сеанстагы бардык колдонмолор жана дайындар жок кылынат."</string>
+    <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Бул сеанстагы бардык колдонмолор жана дайындар өчүрүлөт."</string>
     <string name="guest_exit_guest_dialog_remove" msgid="7505817591242703757">"Алып салуу"</string>
     <string name="guest_wipe_session_title" msgid="7147965814683990944">"Кайтып келишиңиз менен, конок!"</string>
     <string name="guest_wipe_session_message" msgid="3393823610257065457">"Сеансыңызды улантасызбы?"</string>
@@ -464,7 +465,7 @@
       <item quantity="one">Бир колдонуучуну гана кошууга болот.</item>
     </plurals>
     <string name="user_remove_user_title" msgid="9124124694835811874">"Колдонуучу алынып салынсынбы?"</string>
-    <string name="user_remove_user_message" msgid="6702834122128031833">"Бул колдонуучунун бардык колдонмолору жана дайындары жок кылынат."</string>
+    <string name="user_remove_user_message" msgid="6702834122128031833">"Бул колдонуучунун бардык колдонмолору жана дайындары өчүрүлөт."</string>
     <string name="user_remove_user_remove" msgid="8387386066949061256">"Алып салуу"</string>
     <string name="battery_saver_notification_title" msgid="8419266546034372562">"Батареяны үнөмдөгүч режими күйүк"</string>
     <string name="battery_saver_notification_text" msgid="2617841636449016951">"Иштин майнаптуулугун начарлатып, фондук дайындарды чектейт"</string>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"Ыңгайлаштыруу"</string>
     <string name="notification_done" msgid="6215117625922713976">"Бүттү"</string>
     <string name="inline_undo" msgid="9026953267645116526">"Кайтаруу"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"Бул билдирме \"жазышуу эмес\" катары белгиленсин"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"Сүйүктүүлөргө кошуу"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"Сүйүктүүлөрдөн чыгаруу"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"Үнүн басуу"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"Үнүн чыгаруу"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"Көбүк катары көрсөтүү"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"Көбүктөрдү өчүрүү"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"Башкы экранга кошуу"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"эскертмелерди башкаруу каражаттары"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"эскертмени тындыруу опциялары"</string>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 3013e1e..11c4f7c 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"ຊູມໃຫ້ເຕັມໜ້າຈໍ"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"ປັບໃຫ້ເຕັມໜ້າຈໍ"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"ພາບໜ້າຈໍ"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"ແຊກຮູບແລ້ວ"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"ກຳລັງບັນທຶກຮູບໜ້າຈໍ"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"ກຳລັງບັນທຶກພາບໜ້າຈໍ..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"ບັນທຶກຮູບໜ້າຈໍໄວ້ແລ້ວ"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"ເລີ່ມການບັນທຶກ"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"ບັນທຶກສຽງພາກ"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"ສະແດງການແຕະ"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"ແຕະ​ເພື່ອ​ຢຸດ"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"ຢຸດ"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"ຢຸດຊົ່ວຄາວ"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"ສືບຕໍ່"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"ຕົວປະຢັດແບັດເຕີຣີ"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"ເປີດຕອນຕາເວັນຕົກ"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"ຈົນກວ່າຕາເວັນຂຶ້ນ"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"ເປີດເວລາ <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"ຈົນຮອດ <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC is disabled"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC is enabled"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"ການບັນທຶກໜ້າຈໍ"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"ເລີ່ມ"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"ຢຸດ"</string>
     <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"ປັດຂື້ນເພື່ອສະຫຼັບແອັບ"</string>
     <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"ລາກໄປຂວາເພື່ອສະຫຼັບແອັບດ່ວນ"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"ສະຫຼັບພາບຮວມ"</string>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"ປັບແຕ່ງ"</string>
     <string name="notification_done" msgid="6215117625922713976">"ສຳເລັດແລ້ວ"</string>
     <string name="inline_undo" msgid="9026953267645116526">"ຍົກເລີກ"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"ໝາຍການແຈ້ງເຕືອນນີ້ວ່າບໍ່ແມ່ນການສົນທະນາ"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"ລາຍ​ການ​ທີ່​ມັກ"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"ຍົກເລີກລາຍການທີ່ມັກ"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"ປິດສຽງ"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"ເຊົາປິດສຽງ"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"ສະແດງເປັນ bubble"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"ປິດການໃຊ້ bubble"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"ເພີ່ມໃສ່ໜ້າຈໍຫຼັກ"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"ການຄວບຄຸມການແຈ້ງເຕືອນ"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"ຕົວເລືອກການເລື່ອນການແຈ້ງເຕືອນ"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index c6b50d9..7da1174 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Keisti mast., kad atit. ekr."</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Ištempti, kad atit. ekr."</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Ekrano kopija"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Vaizdas įterptas"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Išsaugoma ekrano kopija..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Išsaugoma ekrano kopija..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Ekrano kopija išsaugota"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Pradėti įrašymą"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Įrašyti balsą už kadro"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Rodyti palietimus"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Sustabdykite palietę"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Sustabdyti"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Pristabdyti"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Tęsti"</string>
@@ -392,6 +394,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Akum. taus. priemonė"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Per saulėlydį"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Iki saulėtekio"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Iki <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"ALR"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"ALR išjungtas"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"ALR įjungtas"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index b519f05..fed86b3 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Tālumm., lai aizp. ekr."</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Stiepiet, lai aizp. ekr."</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Ekrānuzņēmums"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Attēls ir ievietots"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Saglabā ekrānuzņēmumu…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Notiek ekrānuzņēmuma saglabāšana..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Ekrānuzņēmums saglabāts"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Sākt ierakstīšanu"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Ierakstīt balsi"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Rādīt pieskārienus"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Pieskarieties, lai apturētu"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Pārtraukt"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Apturēt"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Atsākt"</string>
@@ -390,15 +392,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Jaudas taupīšana"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Saulrietā"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Līdz saullēktam"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Plkst. <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Līdz plkst. <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC ir atspējoti"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC ir iespējoti"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Ekrāna ierakstīšana"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Sākt"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Apturēt"</string>
     <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Velciet augšup, lai pārslēgtu lietotnes"</string>
     <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Lai ātri pārslēgtu lietotnes, velciet pa labi"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Pārskata pārslēgšana"</string>
@@ -699,22 +700,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"Pielāgot"</string>
     <string name="notification_done" msgid="6215117625922713976">"Gatavs"</string>
     <string name="inline_undo" msgid="9026953267645116526">"Atsaukt"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"Atzīmēt, ka šis paziņojums nav saruna"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"Pievienot izlasei"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"Noņemt no izlases"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"Izslēgt skaņu"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"Ieslēgt skaņu"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"Rādīt kā burbuli"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"Izslēgt burbuļus"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"Pievienot sākuma ekrānam"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"paziņojumu vadīklas"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"paziņojumu atlikšanas opcijas"</string>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 9080b57..a02f38e 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Зумирај да се исполни екранот"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Растегни да се исполни екранот"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Слика од екранот"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Вметната е слика"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Сликата на екранот се зачувува..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Сликата на екранот се зачувува..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Сликата од екранот е зачувана"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Започни со снимање"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Снимај коментар"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Прикажувај допири"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Допрете за запирање"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Сопри"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Паузирај"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Продолжи"</string>
@@ -388,6 +390,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Штедач на батерија"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Вклуч. на зајдисонце"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"До изгрејсонце"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Се вклучува во <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"До <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC е оневозможено"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC е овозможено"</string>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index b761c44..2d3f73f 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"സ്‌ക്രീനിൽ ഉൾക്കൊള്ളിക്കാൻ സൂം ചെയ്യുക"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"സ്‌ക്രീനിൽ ഉൾക്കൊള്ളിക്കാൻ വലിച്ചുനീട്ടുക"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"സ്ക്രീൻഷോട്ട്"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"ചിത്രം ചേർത്തു"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"സ്‌ക്രീൻഷോട്ട് സംരക്ഷിക്കുന്നു..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"സ്‌ക്രീൻഷോട്ട് സംരക്ഷിക്കുന്നു..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"സ്‌ക്രീൻഷോട്ട് സംരക്ഷിച്ചു"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"റെക്കോര്‍ഡിംഗ് ആരംഭിക്കുക"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"വോയ്‌സ് ഓവർ റെക്കോർഡ് ചെയ്യുക"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"ടാപ്പുകൾ കാണിക്കുക"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"നിർത്താൻ ടാപ്പ് ചെയ്യുക"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"നിർത്തുക"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"താൽക്കാലികമായി നിർത്തുക"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"പുനരാരംഭിക്കുക"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"ബാറ്ററി ലാഭിക്കൽ"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"സൂര്യാസ്‌തമയത്തിന്"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"സൂര്യോദയം വരെ"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g>-ന്"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> വരെ"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC പ്രവർത്തനരഹിതമാക്കി"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC പ്രവർത്തനക്ഷമമാക്കി"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"സ്‌ക്രീൻ റെക്കോർഡ്"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"ആരംഭിക്കുക"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"നിര്‍ത്തുക"</string>
     <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"ആപ്പുകൾ മാറാൻ മുകളിലേക്ക് സ്വൈപ്പ് ചെയ്യുക"</string>
     <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"ആപ്പുകൾ പെട്ടെന്ന് മാറാൻ വലത്തോട്ട് വലിച്ചിടുക"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"അവലോകനം മാറ്റുക"</string>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"ഇഷ്‌ടാനുസൃതമാക്കുക"</string>
     <string name="notification_done" msgid="6215117625922713976">"പൂർത്തിയായി"</string>
     <string name="inline_undo" msgid="9026953267645116526">"പഴയപടിയാക്കുക"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"ഈ അറിയിപ്പ് സംഭാഷണമല്ലെന്ന് അടയാളപ്പെടുത്തുക"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"പ്രിയപ്പെട്ടവ"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"പ്രിയപ്പെട്ടതല്ലാതാക്കുക"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"മ്യൂട്ട് ചെയ്യുക"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"അൺമ്യൂട്ട് ചെയ്യുക"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"ബബ്‌ൾ ആയി കാണിക്കുക"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"ബബിളുകൾ ഓഫാക്കുക"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"ഹോം സ്‌ക്രീനിലേക്ക് ചേർക്കുക"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"അറിയിപ്പ് നിയന്ത്രണങ്ങൾ"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"അറിയിപ്പ് സ്‌നൂസ് ഓപ്ഷനുകൾ"</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index 4f9b447..85d7ead 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Дэлгэц дүүргэх бол өсгөнө үү"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Дэлгэц дүүргэх бол татна уу"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Дэлгэцийн зураг дарах"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Зургийг орууллаа"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Дэлгэцийн агшинг хадгалж байна…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Дэлгэцийн агшинг хадгалж байна…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Дэлгэцээс дарсан зургийг хадгалсан"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Бичлэгийг эхлүүлэх"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Дуу оруулалтыг бичих"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Товшилтыг харуулах"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Зогсоохын тулд товшино уу"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Зогсоох"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Түр зогсоох"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Үргэлжлүүлэх"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Батарей хэмнэгч"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Нар жаргах үед"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Нар мандах хүртэл"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g>-д"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> хүртэл"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC-г цуцалсан"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC-г идэвхжүүлсэн"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Дэлгэцийн бичлэг хийх"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Эхлүүлэх"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Зогсоох"</string>
     <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Апп сэлгэхийн тулд дээш шударна уу"</string>
     <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Аппуудыг хурдан сэлгэхийн тулд баруун тийш чирнэ үү"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Тоймыг унтраах/асаах"</string>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"Тохируулах"</string>
     <string name="notification_done" msgid="6215117625922713976">"Дууссан"</string>
     <string name="inline_undo" msgid="9026953267645116526">"Болих"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"Энэ мэдэгдлийг харилцаа биш гэж тэмдэглэх"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"Дуртай"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"Дургүй"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"Дууг хаах"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"Дууг нээх"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"Хөөс маягаар харуулах"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"Хөөсийг унтраах"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"Үндсэн нүүрэнд нэмэх"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"мэдэгдлийн удирдлага"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"мэдэгдэл түр хойшлуулагчийн сонголт"</string>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index 99f48e6..3406edf 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"स्क्रीन भरण्यासाठी झूम करा"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"स्क्रीन भरण्यासाठी ताणा"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"स्क्रीनशॉट"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"इमेज घातली गेली"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"स्क्रीनशॉट सेव्ह करत आहे…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"स्क्रीनशॉट सेव्ह करत आहे…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"स्क्रीनशॉट सेव्ह केला"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"रेकॉर्डिंग सुरू करा"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"व्हॉइसओव्हर रेकॉर्ड करा"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"टॅप दाखवा"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"थांबवण्यासाठी टॅप करा"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"थांबवा"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"थांबवा"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"पुन्हा सुरू करा"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"बॅटरी सेव्‍हर"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"संध्याकाळी सुरू होते"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"सूर्योदयापर्यंत"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g> वाजता सुरू होते"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> पर्यंत"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC अक्षम केले आहे"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC सक्षम केले आहे"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"स्क्रीन रेकॉर्ड"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"सुरू"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"थांबा"</string>
     <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"अ‍ॅप्स स्विच करण्यासाठी वर स्वाइप करा"</string>
     <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"अ‍ॅप्स वर झटपट स्विच करण्यासाठी उजवीकडे ड्रॅग करा"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"अवलोकन टॉगल करा."</string>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"कस्टमाइझ करा"</string>
     <string name="notification_done" msgid="6215117625922713976">"पूर्ण झाले"</string>
     <string name="inline_undo" msgid="9026953267645116526">"पहिल्यासारखे करा"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"ही सूचना संभाषण नाही म्हणून खूण करा"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"आवडते"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"नावडते"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"म्यूट करा"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"अनम्यूट करा"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"बबल असे दाखवा"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"बुडबुडे बंद करा"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"होम स्क्रीनवर जोडा"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"सूचना नियंत्रणे"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"सूचना स्नूझ पर्याय"</string>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 42c51b7..eeaacea 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zum untuk memenuhi skrin"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Regang utk memenuhi skrin"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Tangkapan skrin"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Imej disisipkan"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Menyimpan tangkapan skrin..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Menyimpan tangkapan skrin..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Tangkapan skrin disimpan"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Mula Merakam"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Rakam suara latar"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Tunjukkan ketikan"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Ketik untuk berhenti"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Berhenti"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Jeda"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Sambung semula"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Penjimat Bateri"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Dihidupkan pd senja"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Hingga matahari trbt"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Dihidupkan pada <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Hingga <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC dilumpuhkan"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC didayakan"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Saring Rekod"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Mula"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Berhenti"</string>
     <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Leret ke atas untuk menukar apl"</string>
     <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Seret ke kanan untuk beralih apl dengan pantas"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Togol Ikhtisar"</string>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"Sesuaikan"</string>
     <string name="notification_done" msgid="6215117625922713976">"Selesai"</string>
     <string name="inline_undo" msgid="9026953267645116526">"Buat asal"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"Tandai pemberitahuan ini sebagai bukan perbualan"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"Kegemaran"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"Nyahgemari"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"Redam"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"Nyahredam"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"Tunjukkan sebagai gelembung"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"Matikan gelembung"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"Tambahkan pada skrin utama"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"kawalan pemberitahuan"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"pilihan tunda pemberitahuan"</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index dd5acfa..5ae82ea 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"ဇူးမ်အပြည့်ဆွဲခြင်း"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"ဖန်သားပြင်အပြည့်ဆန့်ခြင်း"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"ဖန်သားပြင်ဓာတ်ပုံ"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"ပုံ ထည့်ထားသည်"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"ဖန်သားပြင်ဓါတ်ပုံသိမ်းစဉ်.."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"ဖန်သားပြင်ဓါတ်ပုံရိုက်ခြင်းအား သိမ်းဆည်းပါမည်"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"ဖန်သားပြင်ဓာတ်ပုံကို သိမ်းပြီးပါပြီ"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"စတင် ရိုက်ကူးရန်"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"နောက်ခံစကားပြော ကူးယူရန်"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"တို့ခြင်းများကို ပြရန်"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"ရပ်ရန် တို့ပါ"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"ရပ်ရန်"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"ခဏရပ်ရန်"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"ဆက်လုပ်ရန်"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"ဘက်ထရီ အားထိန်း"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"နေဝင်ချိန်၌ ဖွင့်ရန်"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"နေထွက်ချိန် အထိ"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g> တွင် ဖွင့်မည်"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> အထိ"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC ကို ပိတ်ထားသည်"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC ကို ဖွင့်ထားသည်"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"ဖန်သားပြင် မှတ်တမ်းတင်ရန်"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"စတင်ရန်"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"ရပ်ရန်"</string>
     <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"အက်ပ်များကို ဖွင့်ရန် အပေါ်သို့ ပွတ်ဆွဲပါ"</string>
     <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"အက်ပ်များကို ပြောင်းရန် ညာဘက်သို့ ဖိဆွဲပါ"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"ဖွင့်၊ ပိတ် အနှစ်ချုပ်"</string>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"စိတ်ကြိုက်ပြုလုပ်ရန်"</string>
     <string name="notification_done" msgid="6215117625922713976">"ပြီးပါပြီ"</string>
     <string name="inline_undo" msgid="9026953267645116526">"တစ်ဆင့်နောက်ပြန်ရန်"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"ဤအကြောင်းကြားချက်ကို စကားဝိုင်းမဟုတ်ဟု မှတ်ထားရန်"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"အကြိုက်ဆုံး"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"အကြိုက်ဆုံးမှ ဖယ်ရှားရန်"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"အသံတိတ်ရန်"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"အသံဖွင့်ရန်"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"ပူဖောင်းကွက်အဖြစ် ပြရန်"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"ပူဖောင်းကွက်များကို ပိတ်ရန်"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"ပင်မစာမျက်နှာတွင် ထည့်ရန်"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"အကြောင်းကြားချက် ထိန်းချုပ်မှုများ"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"အကြောင်းကြားချက်များကို ဆိုင်းငံ့ရန် ရွေးချယ်စရာများ"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 97d6792..463b95c 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zoom for å fylle skjermen"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Strekk for å fylle skjerm"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Skjermdump"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Bildet er satt inn"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Lagrer skjermdumpen …"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Lagrer skjermdumpen …"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Skjermdumpen er lagret"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Start opptak"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Ta opp et kommentarspor"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Vis trykk"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Trykk for å stoppe"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Stopp"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Sett på pause"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Gjenoppta"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Batterisparing"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"På ved solnedgang"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Til soloppgang"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Slås på klokken <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Til <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC er slått av"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC er slått på"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Skjermopptak"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Start"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Stopp"</string>
     <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Sveip opp for å bytte apper"</string>
     <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Dra til høyre for å bytte apper raskt"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Slå oversikten av eller på"</string>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"Tilpass"</string>
     <string name="notification_done" msgid="6215117625922713976">"Ferdig"</string>
     <string name="inline_undo" msgid="9026953267645116526">"Angre"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"Marker dette varselet som ikke en samtale"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"Favoritt"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"Fjern som favoritt"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"Ignorer"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"Slutt å ignorere"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"Vis som boble"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"Slå av bobler"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"Legg til på startskjermen"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"varselinnstillinger"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"slumrealternativer for varsler"</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index 1345b09..21a76a3 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"स्क्रिन भर्न जुम गर्नुहोस्"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"स्क्रिन भर्न तन्काउनुहोस्"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"स्क्रिनसट"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"छवि सम्मिलित गरियो"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"स्क्रिनसट बचत गर्दै…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"स्क्रिनसट बचत गर्दै…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"स्क्रिनसट सुरक्षित गरियो"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"रेकर्डिङ सुरु गर्नुहोस्"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"भ्वाइसओवर रेकर्ड गर्नुहोस्"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"ट्यापहरू देखाउनुहोस्"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"रोक्न ट्याप गर्नुहोस्"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"रोक्नुहोस्"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"पज गर्नुहोस्"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"जारी राख्नुहोस्"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"ब्याट्री सेभर"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"सूर्यास्तमा सक्रिय"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"सूर्योदयसम्म"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g> मा सक्रिय"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> सम्म"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC लाई असक्षम पारिएको छ"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC लाई सक्षम पारिएको छ"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"स्रिनको रेकर्ड"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"सुरु गर्नुहोस्"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"रोक्नुहोस्"</string>
     <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"अनुप्रयोगहरू बदल्न माथितिर स्वाइप गर्नुहोस्"</string>
     <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"अनुप्रयोगहरू बदल्न द्रुत गतिमा दायाँतिर ड्र्याग गर्नुहोस्"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"परिदृश्य टगल गर्नुहोस्"</string>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"आफू अनुकूल पार्नुहोस्"</string>
     <string name="notification_done" msgid="6215117625922713976">"सम्पन्‍न भयो"</string>
     <string name="inline_undo" msgid="9026953267645116526">"अन्डू गर्नुहोस्"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"यो सूचनालाई वार्तालाप होइन भनी चिन्ह लगाउनुहोस्"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"मन पर्ने"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"मन पर्ने कुराहरूबाट हटाउनुहोस्"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"म्युट गर्नुहोस्"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"अनम्युट गर्नुहोस्"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"बबलको रूपमा देखाउनुहोस्"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"बबलहरूलाई निष्क्रिय पार्नुहोस्"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"गृह स्क्रिनमा थप्नुहोस्"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"सूचना सम्बन्धी नियन्त्रणहरू"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"सूचना स्नुज गर्ने विकल्पहरू"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 71d2388..3c04015 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zoom om scherm te vullen"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Rek uit v. schermvulling"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Afbeelding ingevoegd"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Screenshot opslaan..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Screenshot opslaan..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshot opgeslagen"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Opname starten"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Voice-over opnemen"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Tikken weergeven"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Tik om te stoppen"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Stoppen"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Pauzeren"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Hervatten"</string>
@@ -388,6 +390,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Batterijbesparing"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Aan bij zonsondergang"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Tot zonsopgang"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Aan om <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Tot <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC is uitgeschakeld"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC is ingeschakeld"</string>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index 85841fe..4230275 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"ସ୍କ୍ରୀନ ଭରିବା ପାଇଁ ଜୁମ୍ କରନ୍ତୁ"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"ସ୍କ୍ରୀନ୍‌କୁ ଭରିବା ପାଇଁ ଟାଣନ୍ତୁ"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"ସ୍କ୍ରିନ୍‌ସଟ୍ ନିଅନ୍ତୁ"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"ଛବି ଭର୍ତ୍ତି କରାଯାଇଛି"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"ସ୍କ୍ରୀନଶଟ୍‍ ସେଭ୍‍ କରାଯାଉଛି…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"ସ୍କ୍ରୀନଶଟ୍‍ ସେଭ୍‍ କରାଯାଉଛି…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"ସ୍କ୍ରୀନଶଟ୍ ସେଭ୍ ହୋଇଛି"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"ରେକର୍ଡିଂ ଆରମ୍ଭ କରନ୍ତୁ"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"ଭଏସ୍‍‍‍‍‍‍‍‍‍ଓଭର୍‍ ରେକର୍ଡ କରନ୍ତୁ"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"ଟାପ୍‌ ଦେଖାନ୍ତୁ"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"ବନ୍ଦ କରିବା ପାଇଁ ଟାପ୍ କରନ୍ତୁ"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"ବନ୍ଦ କରନ୍ତୁ"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"ବିରତି କରନ୍ତୁ"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"ପୁଣି ଚାଲୁ କରନ୍ତୁ"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"ବ୍ୟାଟେରୀ ସେଭର୍"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"ସନ୍ଧ୍ୟାରେ ଚାଲୁ ହେବ"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"ସକାଳ ପର୍ଯ୍ୟନ୍ତ"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g>ରେ ଚାଲୁ ହେବ"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> ପର୍ଯ୍ୟନ୍ତ"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC ଅକ୍ଷମ କରାଯାଇଛି"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC ସକ୍ଷମ କରାଯାଇଛି"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"ସ୍କ୍ରିନ୍ ରେକର୍ଡ"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"ଆରମ୍ଭ କରନ୍ତୁ"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"ବନ୍ଦ କରନ୍ତୁ"</string>
     <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"ଆପ୍‌କୁ ବଦଳ କରିବା ପାଇଁ ସ୍ଵାଇପ୍ କରନ୍ତୁ"</string>
     <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"ଆପ୍‌ଗୁଡ଼ିକ ମଧ୍ୟରେ ଶୀଘ୍ର ବଦଳ କରିବା ପାଇଁ ଡାହାଣକୁ ଡ୍ରାଗ୍ କରନ୍ତୁ"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"ସଂକ୍ଷିପ୍ତ ବିବରଣୀକୁ ଟୋଗଲ୍ କରନ୍ତୁ"</string>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"କଷ୍ଟମାଇଜ୍‌ କରନ୍ତୁ"</string>
     <string name="notification_done" msgid="6215117625922713976">"ହୋଇଗଲା"</string>
     <string name="inline_undo" msgid="9026953267645116526">"ପୂର୍ବସ୍ଥାନକୁ ଫେରାଇଆଣନ୍ତୁ"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"ଏହି ବିଜ୍ଞପ୍ତି କୌଣସି ବାର୍ତ୍ତାଳାପ ନୁହେଁ ବୋଲି ଚିହ୍ନଟ କରନ୍ତୁ"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"ପସନ୍ଦ ଭାବରେ ଚିହ୍ନଟ କରନ୍ତୁ"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"ନାପସନ୍ଦ କରନ୍ତୁ"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"ମ୍ୟୁଟ୍ କରନ୍ତୁ"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"ଅନମ୍ୟୁଟ୍ କରନ୍ତୁ"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"ବୁଦବୁଦ୍ ଭାବରେ ଦେଖାନ୍ତୁ"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"ବୁଦବୁଦଗୁଡ଼ିକ ବନ୍ଦ କରନ୍ତୁ"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"ମୂଳ ସ୍କ୍ରିନରେ ଯୋଗ କରନ୍ତୁ"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"ବିଜ୍ଞପ୍ତି ନିୟନ୍ତ୍ରଣ"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"ବିଜ୍ଞପ୍ତି ସ୍ନୁଜ୍‍ ବିକଳ୍ପ"</string>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index 4ea51dd..f345d6a 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"ਸਕ੍ਰੀਨ ਭਰਨ ਲਈ ਜ਼ੂਮ ਕਰੋ"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"ਸਕ੍ਰੀਨ ਭਰਨ ਲਈ ਸਟ੍ਰੈਚ ਕਰੋ"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"ਸਕ੍ਰੀਨਸ਼ਾਟ"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"ਚਿੱਤਰ ਸ਼ਾਮਲ ਕੀਤਾ ਗਿਆ"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਸੁਰੱਖਿਅਤ ਕਰ ਰਿਹਾ ਹੈ…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਸੁਰੱਖਿਅਤ ਕਰ ਰਿਹਾ ਹੈ…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਰੱਖਿਅਤ ਕੀਤਾ ਗਿਆ"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"ਰਿਕਾਰਡਿੰਗ ਸ਼ੁਰੂ ਕਰੋ"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"ਅਵਾਜ਼ ਰਿਕਾਰਡ ਕਰੋ"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"ਟੈਪਾਂ ਦਿਖਾਓ"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"ਰੋਕਣ ਲਈ ਟੈਪ ਕਰੋ"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"ਬੰਦ ਕਰੋ"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"ਰੋਕੋ"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"ਮੁੜ-ਚਾਲੂ ਕਰੋ"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"ਬੈਟਰੀ ਸੇਵਰ"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"ਸੂਰਜ ਛਿਪਣ \'ਤੇ ਚਾਲੂ"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"ਸੂਰਜ ਚੜ੍ਹਨ ਤੱਕ"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g> ਵਜੇ ਚਾਲੂ"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> ਵਜੇ ਤੱਕ"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC ਨੂੰ ਅਯੋਗ ਬਣਾਇਆ ਗਿਆ ਹੈ"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC ਨੂੰ ਯੋਗ ਬਣਾਇਆ ਗਿਆ ਹੈ"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"ਸਕ੍ਰੀਨ ਰਿਕਾਰਡਰ"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"ਸ਼ੁਰੂ ਕਰੋ"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"ਰੋਕੋ"</string>
     <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"ਐਪਾਂ ਵਿਚਾਲੇ ਅਦਲਾ-ਬਦਲੀ ਕਰਨ ਲਈ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰੋ"</string>
     <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"ਐਪਾਂ ਵਿਚਾਲੇ ਤੇਜ਼ੀ ਨਾਲ ਅਦਲਾ-ਬਦਲੀ ਕਰਨ ਲਈ ਸੱਜੇ ਪਾਸੇ ਵੱਲ ਘਸੀਟੋ"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"ਰੂਪ-ਰੇਖਾ ਨੂੰ ਟੌਗਲ ਕਰੋ"</string>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"ਵਿਉਂਤਬੱਧ ਕਰੋ"</string>
     <string name="notification_done" msgid="6215117625922713976">"ਹੋ ਗਿਆ"</string>
     <string name="inline_undo" msgid="9026953267645116526">"ਅਣਕੀਤਾ ਕਰੋ"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"ਇਸ ਸੂਚਨਾ ਦੀ ਗੱਲ-ਬਾਤ ਨਹੀਂ ਵਜੋਂ ਨਿਸ਼ਾਨਦੇਹੀ ਕਰੋ"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"ਮਨਪਸੰਦ"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"ਨਾਪਸੰਦ"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"ਮਿਊਟ ਕਰੋ"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"ਅਣਮਿਊਟ ਕਰੋ"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"ਬੁਲਬੁਲੇ ਵਜੋਂ ਦਿਖਾਓ"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"ਬੁਲਬੁਲੇ ਬੰਦ ਕਰੋ"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"ਹੋਮ ਸਕ੍ਰੀਨ \'ਤੇ ਸ਼ਾਮਲ ਕਰੋ"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"ਸੂਚਨਾ ਕੰਟਰੋਲ"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"ਸੂਚਨਾ ਸਨੂਜ਼ ਵਿਕਲਪ"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 515d659..68cb14e 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Powiększ, aby wypełnić ekran"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Rozciągnij, aby wypełnić ekran"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Zrzut ekranu"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Wstawiono obraz"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Zapisywanie zrzutu ekranu..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Zapisywanie zrzutu ekranu..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Zrzut ekranu został zapisany"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Rozpocznij rejestrowanie"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Nagraj tekst lektora"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Pokaż dotknięcia"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Kliknij, by zatrzymać"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Zatrzymaj"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Wstrzymaj"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Wznów"</string>
@@ -392,15 +394,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Oszczędzanie baterii"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Włącz o zachodzie"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Do wschodu słońca"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Włącz o <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Do <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"Komunikacja NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"Komunikacja NFC jest wyłączona"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"Komunikacja NFC jest włączona"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Zapis ekranu"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Rozpocznij"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Zatrzymaj"</string>
     <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Przesuń w górę, by przełączyć aplikacje"</string>
     <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Szybko przeciągnij w prawo, by przełączyć aplikacje"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Przełącz Przegląd"</string>
@@ -702,22 +703,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"Dostosuj"</string>
     <string name="notification_done" msgid="6215117625922713976">"Gotowe"</string>
     <string name="inline_undo" msgid="9026953267645116526">"Cofnij"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"Nie oznaczaj tego powiadomienia jako wątku"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"Dodaj do ulubionych"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"Usuń z ulubionych"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"Wycisz"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"Wyłącz wyciszenie"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"Pokaż jako dymek"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"Wyłącz dymki"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"Dodaj do ekranu głównego"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"sterowanie powiadomieniami"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"opcje odkładania powiadomień"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index d486b9b..a9101d7 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zoom p/ preencher a tela"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Ampliar p/ preencher tela"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Capturar tela"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Imagem inserida"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Salvando captura de tela..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Salvando captura de tela..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Captura de tela salva"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Iniciar gravação"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Gravar narração"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Mostrar toques"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Toque para parar"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Parar"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Pausar"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Retomar"</string>
@@ -388,6 +390,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Economia de bateria"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Ativ. ao pôr do sol"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Até o nascer do sol"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Ativar: <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Até: <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"A NFC está desativada"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"A NFC está ativada"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index d17b002..1a6e673 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zoom para preencher o ecrã"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Esticar p. caber em ec. int."</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Captura de ecrã"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Imagem inserida"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"A guardar captura de ecrã..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"A guardar captura de ecrã..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Captura de ecrã guardada"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Iniciar gravação"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Gravar voz-off"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Mostrar toques"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Tocar para parar"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Parar"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Colocar em pausa"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Retomar"</string>
@@ -388,6 +390,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Poupança de bateria"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Ativ. ao pôr do sol"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Até ao amanhecer"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Ativado à(s) <xliff:g id="TIME">%s</xliff:g>."</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Até à(s) <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"O NFC está desativado"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"O NFC está ativado"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index d486b9b..a9101d7 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zoom p/ preencher a tela"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Ampliar p/ preencher tela"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Capturar tela"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Imagem inserida"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Salvando captura de tela..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Salvando captura de tela..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Captura de tela salva"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Iniciar gravação"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Gravar narração"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Mostrar toques"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Toque para parar"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Parar"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Pausar"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Retomar"</string>
@@ -388,6 +390,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Economia de bateria"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Ativ. ao pôr do sol"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Até o nascer do sol"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Ativar: <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Até: <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"A NFC está desativada"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"A NFC está ativada"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 2674504..e34fa2d 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zoom pt. a umple ecranul"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Înt. pt. a umple ecranul"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Captură de ecran"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"S-a inserat imaginea"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Se salv. captura de ecran..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Se salvează captura de ecran..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Captură de ecran salvată"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Începeți înregistrarea"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Înregistrați vocal"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Afișați atingerile"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Atingeți pentru a opri"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Opriți"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Întrerupeți"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Reluați"</string>
@@ -390,15 +392,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Economisire baterie"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Activată la apus"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Până la răsărit"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Activată la <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Până la <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"Serviciul NFC este dezactivat"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"Serviciul NFC este activat"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Înregistrarea ecranului"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Începeți"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Opriți"</string>
     <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Glisați în sus pentru a comuta între aplicații"</string>
     <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Glisați la dreapta pentru a comuta rapid între aplicații"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Comutați secțiunea Recente"</string>
@@ -699,22 +700,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"Personalizați"</string>
     <string name="notification_done" msgid="6215117625922713976">"Terminat"</string>
     <string name="inline_undo" msgid="9026953267645116526">"Anulați"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"Marcați această notificare ca nefiind o conversație"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"Preferată"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"Anulați marcarea ca preferată"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"Ignorați"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"Afișați"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"Afișează sub formă de balon"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"Dezactivați baloanele"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"Adăugați pe ecranul de pornire"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"comenzile notificării"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"opțiuni de amânare a notificării"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 9156989..0ee159d 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Подогнать по размерам экрана"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Растянуть на весь экран"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Скриншот"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Изображение вставлено"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Сохранение..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Сохранение..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Скриншот сохранен"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Начать запись"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Записать закадровую речь"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Показывать нажатия"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Нажмите, чтобы остановить"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Остановить"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Приостановить"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Возобновить"</string>
@@ -392,15 +394,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Режим энергосбер."</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Вкл. на закате"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"До рассвета"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Включить в <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"До <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"Модуль NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"Модуль NFC отключен"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"Модуль NFC включен"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Запись экрана"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Начать"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Остановить"</string>
     <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Чтобы переключиться между приложениями, проведите по экрану вверх."</string>
     <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Перетащите вправо, чтобы быстро переключиться между приложениями"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Переключить режим обзора"</string>
@@ -702,22 +703,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"Настроить"</string>
     <string name="notification_done" msgid="6215117625922713976">"Готово"</string>
     <string name="inline_undo" msgid="9026953267645116526">"Отменить"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"Понизить приоритет уведомления (не считать чатом)"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"Добавить в избранное"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"Удалить из избранного"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"Отключить звук"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"Включить звук"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"Показывать как всплывающее уведомление"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"Отключить показ всплывающих уведомлений"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"Добавить на главный экран"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g>: <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"настройки уведомлений"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"параметры отсрочки уведомлений"</string>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index 84e01d0..2c5e1d8 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"තිරය පිරවීමට විශාලනය කරන්න"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"තිරය පිරවීමට අදින්න"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"තිර රුව"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"රූපය ඇතුල් කරන ලදී"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"තිර රුව සුරකිමින්…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"තිර රුව සුරැකෙමින් පවතී…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"තිර රුව සුරකින ලදී"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"පටිගත කිරීම ආරම්භ කරන්න"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"පසුබිම් කථනය පටිගත කරන්න"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"තට්ටු කිරීම් පෙන්වන්න"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"නතර කිරීමට තට්ටු කරන්න"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"නතර කරන්න"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"විරාම කරන්න"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"නැවත අරඹන්න"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"බැටරි සුරැකුම"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"හිරු බැසීමේදී ඔන්ය"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"හිරු නගින තෙක්"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g>ට ක්‍රියාත්මකයි"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> තෙක්"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC අබලයි"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC සබලයි"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"තිර පටිගත කිරීම"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"ආරම්භ කරන්න"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"නතර කරන්න"</string>
     <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"යෙදුම් මාරු කිරීමට ස්වයිප් කරන්න"</string>
     <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"ඉක්මනින් යෙදුම් මාරු කිරීමට දකුණට අදින්න"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"දළ විශ්ලේෂණය ටොගල කරන්න"</string>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"අභිරුචිකරණය"</string>
     <string name="notification_done" msgid="6215117625922713976">"නිමයි"</string>
     <string name="inline_undo" msgid="9026953267645116526">"පසුගමනය කරන්න"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"මෙම දැනුම් දීම සංවාදයක් නොවේ ලෙස ලකුණු කරන්න"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"ප්‍රියතම"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"ප්‍රියතම වෙතින් ඉවත් කරන්න"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"නිහඬ කරන්න"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"නිහඬ වෙතින් ඉවත් කරන්න"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"බුබුලක් ලෙස පෙන්වන්න"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"බුබුලු ක්‍රියාවිරහිත කරන්න"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"මුල් තිරය වෙත එක් කරන්න"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"දැනුම්දීම් පාලන"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"දැනුම්දීම් මදක් නතර කිරීමේ විකල්ප"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index fced8a4..93f93a2 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Priblížiť na celú obrazovku"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Na celú obrazovku"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Snímka obrazovky"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Bol vložený obrázok"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Prebieha ukladanie snímky obrazovky..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Prebieha ukladanie snímky obrazovky..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Snímka obrazovky bola uložená"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Spustiť zaznamenávanie"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Hlasový vstup počas záznamu"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Zobrazovať klepnutia"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Zastavte klepnutím"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Ukončiť"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Pozastaviť"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Obnoviť"</string>
@@ -392,6 +394,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Šetrič batérie"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Zap. pri záp. slnka"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Do východu slnka"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Zapne sa o <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Do <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC je deaktivované"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC je aktivované"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 4816a66..452827f 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Povečava čez cel zaslon"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Raztegnitev čez zaslon"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Posnetek zaslona"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Slika je vstavljena"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Shranjev. posnetka zaslona ..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Shranjevanje posnetka zaslona ..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Posnetek zaslona je shranjen"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Začni snemanje"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Snemanje spremnega govora"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Prikaz dotikov"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Dotaknite se, da ustavite"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Ustavi"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Začasno ustavi"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Nadaljuj"</string>
@@ -392,15 +394,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Varč. z ener. bater."</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Ob sončnem zahodu"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Do sončnega vzhoda"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Vklop ob <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Do <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"Tehnologija NFC je onemogočena"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"Tehnologija NFC je omogočena"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Snemanje zaslona"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Začni"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Ustavi"</string>
     <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Za preklop aplikacij povlecite navzgor"</string>
     <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Povlecite v desno za hiter preklop med aplikacijami"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Vklop/izklop pregleda"</string>
@@ -702,22 +703,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"Prilagodi"</string>
     <string name="notification_done" msgid="6215117625922713976">"Dokončano"</string>
     <string name="inline_undo" msgid="9026953267645116526">"Razveljavi"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"Označi, da to obvestilo ni pogovor"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"Priljubljeno"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"Odstrani iz priljubljenih"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"Prezri"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"Znova prikaži"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"Pokaži kot oblaček"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"Izklopi oblačke"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"Dodaj na začetni zaslon"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"kontrolniki obvestil"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"možnosti preložitve obvestil"</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index 14d72b4..2dc3cc8 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zmadho për të mbushur ekranin"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Shtrije për të mbushur ekranin"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Pamja e ekranit"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Imazhi është futur"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Po ruan pamjen e ekranit..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Po ruan pamjen e ekranit…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Pamja e ekranit u ruajt"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Nis regjistrimin"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Regjistro zërin e mikrofonit"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Shfaq trokitjet"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Trokit për të ndaluar"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Ndalo"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Ndërprit"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Vazhdo"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Kursyesi i baterisë"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Aktiv në perëndim"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Deri në lindje të diellit"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Aktiv në <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Deri në <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC është çaktivizuar"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC është aktivizuar"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Regjistrimi i ekranit"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Nis"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Ndalo"</string>
     <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Rrëshqit shpejt lart për të ndërruar aplikacionet"</string>
     <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Zvarrit djathtas për të ndërruar aplikacionet me shpejtësi"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Kalo te përmbledhja"</string>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"Personalizo"</string>
     <string name="notification_done" msgid="6215117625922713976">"U krye"</string>
     <string name="inline_undo" msgid="9026953267645116526">"Zhbëj"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"Shëno se ky njoftim nuk është një bisedë"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"Shëno si të preferuar"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"Hiq nga të preferuarat"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"Kalo në heshtje"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"Aktivizo"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"Shfaqe si flluskë"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"Çaktivizo flluskat"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"Shto në ekranin bazë"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"kontrollet e njoftimit"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"opsionet e shtyrjes së njoftimit"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 29e7e10..4127806 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Зумирај на целом екрану"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Развуци на цео екран"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Снимак екрана"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Слика је уметнута"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Чување снимка екрана..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Чување снимка екрана..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Снимак екрана је сачуван"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Започни снимање"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Сними пренос гласа"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Приказуј додире"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Додирните да бисте зауставили"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Заустави"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Паузирај"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Настави"</string>
@@ -390,6 +392,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Уштеда батерије"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Укључује се по заласку сунца"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"До изласка сунца"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Укључује се у <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"До <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC је онемогућен"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC је омогућен"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index b0d7877..3e29fa6 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Zooma för att fylla skärm"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Dra för att fylla skärmen"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Skärmdump"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Bilden har infogats"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Skärmdumpen sparas ..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Skärmdumpen sparas ..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Skärmdumpen har sparats"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Börja spela in"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Spela in med mikrofondubbning"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Visa tryck"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Tryck för att stoppa"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Stoppa"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Pausa"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Återuppta"</string>
@@ -388,6 +390,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Batterisparläge"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"På från solnedgången"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Till soluppgången"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Aktivera kl. <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Till <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC är inaktiverat"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC är aktiverat"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index ecaefb0..9fd4284 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Kuza ili kujaza skrini"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Tanua ili kujaza skrini"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Picha ya skrini"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Picha imewekwa"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Inahifadhi picha ya skrini..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Inahifadhi picha ya skrini..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Imehifadhi picha ya skrini"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Anza Kurekodi"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Rekodi sauti"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Onyesha unapogusa"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Gusa ili ukomeshe"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Acha"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Sitisha"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Endelea"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Kiokoa betri"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Itawashwa machweo"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Hadi macheo"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Itawashwa saa <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Hadi saa <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC imezimwa"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC imewashwa"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Rekodi ya Skrini"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Anza kurekodi"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Acha kurekodi"</string>
     <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Telezesha kidole juu ili ubadilishe programu"</string>
     <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Buruta kulia ili ubadilishe programu haraka"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Washa Muhtasari"</string>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"Weka mapendeleo"</string>
     <string name="notification_done" msgid="6215117625922713976">"Nimemaliza"</string>
     <string name="inline_undo" msgid="9026953267645116526">"Tendua"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"Tia alama arifa hii kuwa si mazungumzo"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"Tia alama ya kipendwa kwenye mazungumzo haya"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"Ondoa alama ya kipendwa kwenye mazungumzo haya"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"Komesha mazungumzo"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"Ruhusu mazungumzo"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"Onyesha kuwa kiputo"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"Zima viputo"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"Ongeza kwenye skrini ya kwanza"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"vidhibiti vya arifa"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"chaguo za kuahirisha arifa"</string>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index 0bea7d6..55bd472 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"திரையை நிரப்ப அளவை மாற்று"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"திரையை நிரப்ப இழு"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"ஸ்கிரீன்ஷாட்"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"படம் செருகப்பட்டது"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"ஸ்க்ரீன் ஷாட்டைச் சேமிக்கிறது…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"ஸ்க்ரீன் ஷாட்டைச் சேமிக்கிறது…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"ஸ்கிரீன்ஷாட் சேமிக்கப்பட்டது"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"ரெக்கார்டிங்கைத் தொடங்கு"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"வாய்ஸ் ஓவரை ரெக்கார்டு செய்"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"தட்டல்களைக் காட்டு"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"நிறுத்த, தட்டவும்"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"நிறுத்து"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"இடைநிறுத்து"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"மீண்டும் தொடங்கு"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"பேட்டரி சேமிப்பான்"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"மாலையில் ஆன் செய்"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"காலை வரை"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g>க்கு ஆன் செய்"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> வரை"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC முடக்கப்பட்டது"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC இயக்கப்பட்டது"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"ஸ்கிரீன் ரெக்கார்டு"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"தொடங்கு"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"நிறுத்து"</string>
     <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"ஆப்ஸிற்கு இடையே மாற்றுவதற்கு, மேல்நோக்கி ஸ்வைப் செய்க"</string>
     <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"ஆப்ஸை வேகமாக மாற்ற, வலப்புறம் இழுக்கவும்"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"மேலோட்டப் பார்வையை நிலைமாற்று"</string>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"தனிப்பயனாக்கு"</string>
     <string name="notification_done" msgid="6215117625922713976">"முடிந்தது"</string>
     <string name="inline_undo" msgid="9026953267645116526">"செயல்தவிர்"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"இந்த அறிவிப்பை உரையாடல் அல்லாததாகக் குறிக்கவும்"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"பிடித்தது"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"பிடித்ததிலிருந்து அகற்று"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"அறிவிப்பைக் காட்டாதே"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"அறிவிப்பைக் காட்டு"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"குமிழாகக் காட்டு"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"குமிழ்களை ஆஃப் செய்"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"முகப்புத் திரையில் சேர்"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"அறிவிப்புக் கட்டுப்பாடுகள்"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"அறிவிப்பை உறக்கநிலையாக்கும் விருப்பங்கள்"</string>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index bb62490..8b9c07c 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"స్క్రీన్‌కు నింపేలా జూమ్ చేయండి"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"స్క్రీన్‌కు నింపేలా విస్తరించండి"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"స్క్రీన్‌షాట్"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"చిత్రం చొప్పించబడింది"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"స్క్రీన్‌షాట్‌ను సేవ్ చేస్తోంది…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"స్క్రీన్‌షాట్‌ను సేవ్ చేస్తోంది…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"స్క్రీన్‌షాట్ సేవ్ చేయబడింది"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"రికార్డింగ్‌ను ప్రారంభించు"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"వాయిస్ఓవర్‌ని రికార్డ్ చేయి"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"నొక్కినవి చూపు"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"ఆపడానికి నొక్కండి"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"ఆపివేయి"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"పాజ్ చేయి"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"కొనసాగించు"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"బ్యాటరీ సేవర్"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"సూర్యాస్తమయానికి"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"సూర్యోదయం వరకు"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g> వద్ద"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> వరకు"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC నిలిపివేయబడింది"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC ప్రారంభించబడింది"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"స్క్రీన్ రికార్డ్"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"ప్రారంభించు"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"ఆపు"</string>
     <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"యాప్‌లను మార్చడం కోసం ఎగువకు స్వైప్ చేయండి"</string>
     <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"యాప్‌లను శీఘ్రంగా స్విచ్ చేయడానికి కుడి వైపుకు లాగండి"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"స్థూలదృష్టిని టోగుల్ చేయి"</string>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"అనుకూలపరచండి"</string>
     <string name="notification_done" msgid="6215117625922713976">"పూర్తయింది"</string>
     <string name="inline_undo" msgid="9026953267645116526">"చర్యరద్దు చేయి"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"ఈ నోటిఫికేషన్‌ను సంభాషణ కానిది అని గుర్తు పెట్టండి"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"ఇష్టమైనది"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"ఇష్టమైనదిగా పెట్టిన గుర్తును తీసివేయి"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"మ్యూట్ చేయి"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"అన్‌మ్యూట్ చేయి"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"బబుల్‌లా చూపించు"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"బబుల్‌లను ఆఫ్ చేయి"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"హోమ్ స్క్రీన్‌కు జోడించు"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"నోటిఫికేషన్ నియంత్రణలు"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"నోటిఫికేషన్ తాత్కాలిక ఆపివేత ఎంపికలు"</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 54c3d73..c5e0123 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"ขยายจนเต็มหน้าจอ"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"ยืดจนเต็มหน้าจอ"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"ภาพหน้าจอ"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"รูปภาพที่แทรก"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"กำลังบันทึกภาพหน้าจอ..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"กำลังบันทึกภาพหน้าจอ..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"บันทึกภาพหน้าจอแล้ว"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"เริ่มต้นการบันทึก"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"บันทึกเสียงบรรยาย"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"แสดงการแตะ"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"แตะเพื่อหยุด"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"หยุด"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"หยุด"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"ทำต่อ"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"โหมดประหยัดแบตเตอรี่"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"เปิดตอนพระอาทิตย์ตก"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"จนพระอาทิตย์ขึ้น"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"เปิดเวลา <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"จนถึง <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC ถูกปิดใช้งาน"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"เปิดใช้งาน NFC แล้ว"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"บันทึกหน้าจอ"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"เริ่ม"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"หยุด"</string>
     <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"เลื่อนขึ้นเพื่อสลับแอป"</string>
     <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"ลากไปทางขวาเพื่อสลับแอปอย่างรวดเร็ว"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"สลับภาพรวม"</string>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"ปรับแต่ง"</string>
     <string name="notification_done" msgid="6215117625922713976">"เสร็จสิ้น"</string>
     <string name="inline_undo" msgid="9026953267645116526">"เลิกทำ"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"ทำเครื่องหมายการแจ้งเตือนนี้ว่าไม่ใช่บทสนทนา"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"รายการโปรด"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"นำออกจากรายการโปรด"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"ปิดเสียง"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"เปิดเสียง"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"แสดงเป็นบับเบิล"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"ปิดบับเบิล"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"เพิ่มลงในหน้าจอหลัก"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"ส่วนควบคุมการแจ้งเตือน"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"ตัวเลือกการปิดเสียงแจ้งเตือนชั่วคราว"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index ef812ff..3d343c5 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"I-zoom upang punan screen"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"I-stretch upang mapuno screen"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Screenshot"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Inilagay ang larawan"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Sine-save ang screenshot…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Sine-save ang screenshot…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Na-save ang screenshot"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Simulan ang Pag-record"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"I-record ang voiceover"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Ipakita ang mga pag-tap"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"I-tap para ihinto"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Ihinto"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"I-pause"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Ituloy"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Pangtipid sa Baterya"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Mao-on sa sunset"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Hanggang sunrise"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Ma-o-on nang <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Hanggang <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"Naka-disable ang NFC"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"Naka-enable ang NFC"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Pag-record ng Screen"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Magsimula"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Ihinto"</string>
     <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Mag-swipe pataas upang lumipat ng app"</string>
     <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"I-drag pakanan para mabilisang magpalipat-lipat ng app"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"I-toggle ang Overview"</string>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"I-customize"</string>
     <string name="notification_done" msgid="6215117625922713976">"Tapos Na"</string>
     <string name="inline_undo" msgid="9026953267645116526">"I-undo"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"Markahan ang notification na ito bilang hindi pag-uusap"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"Gawing Paborito"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"I-unfavorite"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"I-mute"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"I-unmute"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"Ipakita bilang bubble"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"I-off ang mga bubble"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"Idagdag sa home screen"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"mga kontrol ng notification"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"mga opsyon sa pag-snooze ng notification"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 470606f..46e583f 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Yakınlaştır (ekranı kaplasın)"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Genişlet (ekran kapansın)"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Ekran görüntüsü"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Resim eklendi"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Ekran görüntüsü kaydediliyor..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Ekran görüntüsü kaydediliyor..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Ekran görüntüsü kaydedildi"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Kaydı Başlat"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Seslendirme kaydet"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Dokunmaları göster"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Durdurmak için dokunun"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Durdur"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Duraklat"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Devam ettir"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Pil Tasarrufu"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Gün batımı açılacak"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Sabaha kadar"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Açılacağı saat: <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Şu saate kadar: <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC devre dışı"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC etkin"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Ekran Kaydı"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Başlat"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Durdur"</string>
     <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Uygulamalar arasında geçiş yapmak için yukarı kaydırın"</string>
     <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Uygulamaları hızlıca değiştirmek için sağa kaydırın"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Genel bakışı aç/kapat"</string>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"Özelleştir"</string>
     <string name="notification_done" msgid="6215117625922713976">"Bitti"</string>
     <string name="inline_undo" msgid="9026953267645116526">"Geri al"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"Bu bildirimi ileti dizisi değil olarak işaretle"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"Favori"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"Favorilerden kaldır"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"Kapat"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"Aç"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"Balon olarak göster"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"Balonları kapat"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"Ana ekrana ekle"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"Bildirim kontrolleri"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"bildirim erteleme seçenekleri"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 496206a..7baad0d 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Масштабув. на весь екран"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Розтягнути на весь екран"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Знімок екрана"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Вставлене зображення"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Збереження знімка екрана..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Збереження знімка екрана..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Знімок екрана збережено"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Почати запис"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Записувати голосовий супровід"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Показувати дотики"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Натисніть, щоб зупинити"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Зупинити"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Призупинити"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Відновити"</string>
@@ -392,15 +394,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Режим енергозбереження"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Увімкнеться ввечері"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"До сходу сонця"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Вмикається о <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"До <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC вимкнено"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC ввімкнено"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Запис екрана"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Почати"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Зупинити"</string>
     <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Проводьте пальцем угору, щоб переходити між додатками"</string>
     <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Перетягуйте праворуч, щоб швидко переходити між додатками"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Увімкнути або вимкнути огляд"</string>
@@ -702,22 +703,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"Налаштувати"</string>
     <string name="notification_done" msgid="6215117625922713976">"Готово"</string>
     <string name="inline_undo" msgid="9026953267645116526">"Відмінити"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"Перетворити з ланцюжка повідомлень на сповіщення"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"Вибране"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"Видалити з вибраного"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"Ігнорувати"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"Не ігнорувати"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"Показувати як спливаюче сповіщення"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"Вимкнути спливаючі сповіщення"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"Додати на головний екран"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"елементи керування сповіщеннями"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"параметри відкладення сповіщень"</string>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index a6de509..97d0a5d 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"پوری سکرین پر زوم کریں"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"پوری سکرین پر پھیلائیں"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"اسکرین شاٹ"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"تصویر داخل کر دی گئی"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"اسکرین شاٹ محفوظ ہو رہا ہے…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"اسکرین شاٹ محفوظ ہو رہا ہے…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"اسکرین شاٹ محفوظ ہو گیا"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"ریکارڈنگ شروع کریں"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"وائس اوور ریکارڈ کریں"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"تھپتھپاہٹیں دکھائیں"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"روکنے کے لیے تھپتھپائیں"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"روکیں"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"موقوف کریں"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"دوبارہ شروع کریں"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"بیٹری سیور"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"شام کے وقت آن ہوگی"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"طلوع آفتاب تک"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"آن ہوگی بوقت <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> تک"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"‏NFC غیر فعال ہے"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"‏NFC فعال ہے"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"اسکرین ریکارڈر کریں"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"آغاز"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"روکیں"</string>
     <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"ایپس سوئچ کرنے کیلئے اوپر سوائپ کریں"</string>
     <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"تیزی سے ایپس کو سوئچ کرنے کے لیے دائیں طرف گھسیٹیں"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"مجموعی جائزہ ٹوگل کریں"</string>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"حسب ضرورت بنائیں"</string>
     <string name="notification_done" msgid="6215117625922713976">"ہوگیا"</string>
     <string name="inline_undo" msgid="9026953267645116526">"کالعدم کریں"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"اس اطلاع کو بطور گفتگو نشان زد نہ کریں"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"پسندیدہ"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"پسندیدگی ختم کریں"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"خاموش کریں"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"آواز چلائیں"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"بلبلہ کے بطور دکھائیں"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"بلبلے آف کریں"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"ہوم اسکرین میں شامل کریں"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"اطلاع کے کنٹرولز"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"اطلاع اسنوز کرنے کے اختیارات"</string>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index 1eb02f3..b514f1e 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Ekranga moslashtirish"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Ekran hajmida cho‘zish"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Skrinshot"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Rasm joylandi"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Skrinshot saqlanmoqda…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Skrinshot saqlanmoqda…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Skrinshot saqlandi"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Yozuvni boshlash"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Kadrorti nutqini yozib olish"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Bosishlarni ko‘rsatish"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Toʻxtatish uchun bosing"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"To‘xtatish"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Pauza"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Davom etish"</string>
@@ -388,6 +390,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Quvvat tejash"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Kunbotarda yoqish"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Quyosh chiqqunicha"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"<xliff:g id="TIME">%s</xliff:g> da yoqish"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"<xliff:g id="TIME">%s</xliff:g> gacha"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC o‘chiq"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC yoniq"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index dc3882e..c4d7618 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"T.phóng để lấp đầy m.hình"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Giãn ra để lấp đầy m.hình"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Chụp ảnh màn hình"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Đã chèn hình ảnh"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Đang lưu ảnh chụp màn hình..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Đang lưu ảnh chụp màn hình..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Đã lưu ảnh chụp màn hình"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Bắt đầu ghi"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Ghi phần thuyết minh"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Hiển thị số lần nhấn"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Nhấn để dừng"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Dừng"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Tạm dừng"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Tiếp tục"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Trình tiết kiệm pin"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Bật khi trời tối"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Cho đến khi trời sáng"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Bật vào lúc <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Cho đến <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC đã được tắt"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC đã được bật"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Ghi lại nội dung trên màn hình"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Bắt đầu"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Dừng"</string>
     <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Vuốt lên để chuyển đổi ứng dụng"</string>
     <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"Kéo sang phải để chuyển đổi nhanh giữa các ứng dụng"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"Bật/tắt chế độ xem Tổng quan"</string>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"Tùy chỉnh"</string>
     <string name="notification_done" msgid="6215117625922713976">"Xong"</string>
     <string name="inline_undo" msgid="9026953267645116526">"Hoàn tác"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"Đánh dấu thông báo này không phải là cuộc trò chuyện"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"Đánh dấu là yêu thích"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"Bỏ thích"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"Ẩn"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"Hiển thị"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"Hiển thị dưới dạng bong bóng"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"Tắt bong bóng"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"Thêm vào màn hình chính"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"điều khiển thông báo"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"Tùy chọn báo lại thông báo"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index baacdae..56edb64 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"缩放以填满屏幕"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"拉伸以填满屏幕"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"屏幕截图"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"已插入图片"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"正在保存屏幕截图..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"正在保存屏幕截图..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"已保存屏幕截图"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"开始录制"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"录制旁白"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"显示点按操作反馈"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"点按即可停止"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"停止"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"暂停"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"继续"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"省电模式"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"在日落时开启"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"在日出时关闭"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"在<xliff:g id="TIME">%s</xliff:g> 开启"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"直到<xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC 已停用"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC 已启用"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"屏幕录制"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"开始"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"停止"</string>
     <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"向上滑动可切换应用"</string>
     <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"向右拖动可快速切换应用"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"切换概览"</string>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"自定义"</string>
     <string name="notification_done" msgid="6215117625922713976">"完成"</string>
     <string name="inline_undo" msgid="9026953267645116526">"撤消"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"将此通知标记为非对话"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"收藏"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"取消收藏"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"静音"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"取消静音"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"显示为气泡"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"关闭气泡"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"添加到主屏幕"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g><xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"通知设置"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"通知延后选项"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 0f1696e7..251e23d 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"放大為全螢幕"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"放大為全螢幕"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"螢幕截圖"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"已插入圖片"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"正在儲存螢幕擷取畫面..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"正在儲存螢幕擷取畫面..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"螢幕擷取畫面已儲存"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"開始錄影"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"錄製畫面外的音效"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"顯示輕按選項"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"輕按即可停止"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"停止"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"暫停"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"繼續"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"省電模式"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"在日落時開啟"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"在日出時關閉"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"於<xliff:g id="TIME">%s</xliff:g>開啟"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"直至<xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC 已停用"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC 已啟用"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"畫面錄影"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"開始"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"停"</string>
     <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"向上滑動即可切換應用程式"</string>
     <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"向右拖曳即可快速切換應用程式"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"切換概覽"</string>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"自訂"</string>
     <string name="notification_done" msgid="6215117625922713976">"完成"</string>
     <string name="inline_undo" msgid="9026953267645116526">"復原"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"將此通知標示為非對話"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"我的最愛"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"取消收藏"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"靜音"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"取消靜音"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"以小視窗顯示"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"關閉小視窗"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"加入主畫面"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"通知控制項"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"通知延後選項"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index e8e76ec..a7ec598 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"放大為全螢幕"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"放大為全螢幕"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"擷取螢幕畫面"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"已插入圖片"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"正在儲存螢幕截圖…"</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"正在儲存螢幕截圖…"</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"螢幕截圖已儲存"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"開始錄製"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"錄製畫面外的音效"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"顯示觸控回應"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"輕觸即可停止"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"停止"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"暫停"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"繼續"</string>
@@ -388,15 +390,14 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"節約耗電量"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"於日落時開啟"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"於日出時關閉"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"開啟時間:<xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"關閉時間:<xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"NFC 已停用"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"NFC 已啟用"</string>
-    <!-- no translation found for quick_settings_screen_record_label (1594046461509776676) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_start (1574725369331638985) -->
-    <skip />
-    <!-- no translation found for quick_settings_screen_record_stop (8087348522976412119) -->
-    <skip />
+    <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"螢幕畫面錄製"</string>
+    <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"開始"</string>
+    <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"停止"</string>
     <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"向上滑動即可切換應用程式"</string>
     <string name="recents_quick_scrub_onboarding" msgid="765934300283514912">"向右拖曳即可快速切換應用程式"</string>
     <string name="quick_step_accessibility_toggle_overview" msgid="7908949976727578403">"切換總覽"</string>
@@ -696,22 +697,14 @@
     <string name="notification_app_settings" msgid="8963648463858039377">"自訂"</string>
     <string name="notification_done" msgid="6215117625922713976">"完成"</string>
     <string name="inline_undo" msgid="9026953267645116526">"復原"</string>
-    <!-- no translation found for demote (6225813324237153980) -->
-    <skip />
-    <!-- no translation found for notification_conversation_favorite (8252976467488182853) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unfavorite (633301300443356176) -->
-    <skip />
-    <!-- no translation found for notification_conversation_mute (477431709687199671) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unmute (410885000669775294) -->
-    <skip />
-    <!-- no translation found for notification_conversation_bubble (4598142032706190028) -->
-    <skip />
-    <!-- no translation found for notification_conversation_unbubble (2303087159802926401) -->
-    <skip />
-    <!-- no translation found for notification_conversation_home_screen (8347136037958438935) -->
-    <skip />
+    <string name="demote" msgid="6225813324237153980">"將這則通知標示為非對話"</string>
+    <string name="notification_conversation_favorite" msgid="8252976467488182853">"加入收藏"</string>
+    <string name="notification_conversation_unfavorite" msgid="633301300443356176">"從收藏中移除"</string>
+    <string name="notification_conversation_mute" msgid="477431709687199671">"忽略"</string>
+    <string name="notification_conversation_unmute" msgid="410885000669775294">"取消忽略"</string>
+    <string name="notification_conversation_bubble" msgid="4598142032706190028">"以泡泡形式顯示"</string>
+    <string name="notification_conversation_unbubble" msgid="2303087159802926401">"關閉泡泡"</string>
+    <string name="notification_conversation_home_screen" msgid="8347136037958438935">"新增至主螢幕"</string>
     <string name="notification_menu_accessibility" msgid="8984166825879886773">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="6429668976593634862">"通知控制項"</string>
     <string name="notification_menu_snooze_description" msgid="4740133348901973244">"通知延後選項"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index fa764b5..1203b579c 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -71,6 +71,7 @@
     <string name="compat_mode_on" msgid="4963711187149440884">"Sondeza ukugcwalisa isikrini"</string>
     <string name="compat_mode_off" msgid="7682459748279487945">"Nweba ukugcwalisa isikrini"</string>
     <string name="global_action_screenshot" msgid="2760267567509131654">"Isithombe-skrini"</string>
+    <string name="remote_input_image_insertion_text" msgid="4613177882724332877">"Isithombe sifakiwe"</string>
     <string name="screenshot_saving_ticker" msgid="6519186952674544916">"Ilondoloz umfanekiso weskrini..."</string>
     <string name="screenshot_saving_title" msgid="2298349784913287333">"Ilondoloz umfanekiso weskrini..."</string>
     <string name="screenshot_saved_title" msgid="8893267638659083153">"Isithombe-skrini silondoloziwe"</string>
@@ -84,6 +85,7 @@
     <string name="screenrecord_start_label" msgid="1539048263178882562">"Qala ukurekhoda"</string>
     <string name="screenrecord_mic_label" msgid="6134198080740031632">"Rekhoda izwi elingaphezulu"</string>
     <string name="screenrecord_taps_label" msgid="2518244240225925076">"Bonisa amathebhu"</string>
+    <string name="screenrecord_stop_text" msgid="6549288689506057686">"Thepha ukuze umise"</string>
     <string name="screenrecord_stop_label" msgid="72699670052087989">"Misa"</string>
     <string name="screenrecord_pause_label" msgid="6004054907104549857">"Phumula"</string>
     <string name="screenrecord_resume_label" msgid="4972223043729555575">"Qalisa kabusha"</string>
@@ -388,6 +390,8 @@
     <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Isilondolozi sebhethri"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Kuvulwe ekushoneni kwelanga"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Kuze kube sekuphumeni kwelanga"</string>
+    <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Kuvulwe ngo-<xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="quick_settings_dark_mode_secondary_label_until" msgid="2289774641256492437">"Kuze kube ngu-<xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_nfc_label" msgid="1054317416221168085">"I-NFC"</string>
     <string name="quick_settings_nfc_off" msgid="3465000058515424663">"I-NFC ikhutshaziwe"</string>
     <string name="quick_settings_nfc_on" msgid="1004976611203202230">"I-NFC inikwe amandla"</string>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 1f13f8d..8d935ec 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -2549,4 +2549,7 @@
 
     <!-- Quick Controls strings [CHAR LIMIT=30] -->
     <string name="quick_controls_title">Quick Controls</string>
+
+    <!-- The tile in quick settings is unavailable. [CHAR LIMIT=32] -->
+    <string name="tile_unavailable">Unvailable</string>
 </resources>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl
index 577e3bb..26ef1d6 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl
@@ -27,7 +27,6 @@
 
     void onInitialize(in Bundle params) = 12;
 
-
     /**
      * @deprecated
      */
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
index 08996c3..386fe53 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
@@ -85,6 +85,8 @@
     // The notification panel is expanded and interactive (either locked or unlocked), and the
     // quick settings is not expanded
     public static final int SYSUI_STATE_QUICK_SETTINGS_EXPANDED = 1 << 11;
+    // Winscope tracing is enabled
+    public static final int SYSUI_STATE_TRACING_ENABLED = 1 << 12;
 
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({SYSUI_STATE_SCREEN_PINNING,
@@ -98,7 +100,8 @@
             SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED,
             SYSUI_STATE_OVERVIEW_DISABLED,
             SYSUI_STATE_HOME_DISABLED,
-            SYSUI_STATE_SEARCH_DISABLED
+            SYSUI_STATE_SEARCH_DISABLED,
+            SYSUI_STATE_TRACING_ENABLED
     })
     public @interface SystemUiStateFlags {}
 
@@ -117,6 +120,7 @@
         str.add((flags & SYSUI_STATE_BOUNCER_SHOWING) != 0 ? "bouncer_visible" : "");
         str.add((flags & SYSUI_STATE_A11Y_BUTTON_CLICKABLE) != 0 ? "a11y_click" : "");
         str.add((flags & SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE) != 0 ? "a11y_long_click" : "");
+        str.add((flags & SYSUI_STATE_TRACING_ENABLED) != 0 ? "tracing" : "");
         return str.toString();
     }
 
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/tracing/FrameProtoTracer.java b/packages/SystemUI/shared/src/com/android/systemui/shared/tracing/FrameProtoTracer.java
new file mode 100644
index 0000000..557845c
--- /dev/null
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/tracing/FrameProtoTracer.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.shared.tracing;
+
+import android.os.Trace;
+import android.util.Log;
+import android.view.Choreographer;
+
+import com.android.internal.util.TraceBuffer;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.Queue;
+import java.util.function.Consumer;
+
+/**
+ * A proto tracer implementation that can be updated directly (upon state change), or on the next
+ * scheduled frame.
+ *
+ * @param <P> The class type of the proto provider
+ * @param <S> The proto class type of the encapsulating proto
+ * @param <T> The proto class type of the individual proto entries in the buffer
+ * @param <R> The proto class type of the entry root proto in the buffer
+ */
+public class FrameProtoTracer<P, S extends P, T extends P, R>
+        implements TraceBuffer.ProtoProvider<P, S, T>, Choreographer.FrameCallback {
+
+    private static final String TAG = "FrameProtoTracer";
+    private static final int BUFFER_CAPACITY = 1024 * 1024;
+
+    private final Object mLock = new Object();
+    private final TraceBuffer<P, S, T> mBuffer;
+    private final File mTraceFile;
+    private final ProtoTraceParams<P, S, T, R> mParams;
+    private final Choreographer mChoreographer;
+    private final Queue<T> mPool = new LinkedList<>();
+    private final ArrayList<ProtoTraceable<R>> mTraceables = new ArrayList<>();
+    private final ArrayList<ProtoTraceable<R>> mTmpTraceables = new ArrayList<>();
+
+    private volatile boolean mEnabled;
+    private boolean mFrameScheduled;
+
+    public interface ProtoTraceParams<P, S, T, R> {
+        File getTraceFile();
+        S getEncapsulatingTraceProto();
+        T updateBufferProto(T reuseObj, ArrayList<ProtoTraceable<R>> traceables);
+        byte[] serializeEncapsulatingProto(S encapsulatingProto, Queue<T> buffer);
+        byte[] getProtoBytes(P proto);
+        int getProtoSize(P proto);
+    }
+
+    public FrameProtoTracer(ProtoTraceParams<P, S, T, R> params) {
+        mParams = params;
+        mBuffer = new TraceBuffer<>(BUFFER_CAPACITY, this, new Consumer<T>() {
+            @Override
+            public void accept(T t) {
+                onProtoDequeued(t);
+            }
+        });
+        mTraceFile = params.getTraceFile();
+        mChoreographer = Choreographer.getMainThreadInstance();
+    }
+
+    @Override
+    public int getItemSize(P proto) {
+        return mParams.getProtoSize(proto);
+    }
+
+    @Override
+    public byte[] getBytes(P proto) {
+        return mParams.getProtoBytes(proto);
+    }
+
+    @Override
+    public void write(S encapsulatingProto, Queue<T> buffer, OutputStream os) throws IOException {
+        os.write(mParams.serializeEncapsulatingProto(encapsulatingProto, buffer));
+    }
+
+    public void start() {
+        synchronized (mLock) {
+            if (mEnabled) {
+                return;
+            }
+            mBuffer.resetBuffer();
+            mEnabled = true;
+        }
+        logState();
+    }
+
+    public void stop() {
+        synchronized (mLock) {
+            if (!mEnabled) {
+                return;
+            }
+            mEnabled = false;
+        }
+        writeToFile();
+    }
+
+    public boolean isEnabled() {
+        return mEnabled;
+    }
+
+    public void add(ProtoTraceable<R> traceable) {
+        synchronized (mLock) {
+            mTraceables.add(traceable);
+        }
+    }
+
+    public void remove(ProtoTraceable<R> traceable) {
+        synchronized (mLock) {
+            mTraceables.remove(traceable);
+        }
+    }
+
+    public void scheduleFrameUpdate() {
+        if (!mEnabled || mFrameScheduled) {
+            return;
+        }
+
+        // Schedule an update on the next frame
+        mChoreographer.postFrameCallback(this);
+        mFrameScheduled = true;
+    }
+
+    public void update() {
+        if (!mEnabled) {
+            return;
+        }
+
+        logState();
+    }
+
+    public float getBufferUsagePct() {
+        return (float) mBuffer.getBufferSize() / BUFFER_CAPACITY;
+    }
+
+    @Override
+    public void doFrame(long frameTimeNanos) {
+        logState();
+    }
+
+    private void onProtoDequeued(T proto) {
+        mPool.add(proto);
+    }
+
+    private void logState() {
+        synchronized (mLock) {
+            mTmpTraceables.addAll(mTraceables);
+        }
+
+        mBuffer.add(mParams.updateBufferProto(mPool.poll(), mTmpTraceables));
+        mTmpTraceables.clear();
+        mFrameScheduled = false;
+    }
+
+    private void writeToFile() {
+        try {
+            Trace.beginSection("ProtoTracer.writeToFile");
+            mBuffer.writeTraceToFile(mTraceFile, mParams.getEncapsulatingTraceProto());
+        } catch (IOException e) {
+            Log.e(TAG, "Unable to write buffer to file", e);
+        } finally {
+            Trace.endSection();
+        }
+    }
+}
+
+
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/tracing/ProtoTraceable.java b/packages/SystemUI/shared/src/com/android/systemui/shared/tracing/ProtoTraceable.java
new file mode 100644
index 0000000..e05b0b0
--- /dev/null
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/tracing/ProtoTraceable.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.shared.tracing;
+
+/**
+ * @see FrameProtoTracer
+ */
+public interface ProtoTraceable<T> {
+
+    /**
+     * NOTE: Implementations should update all fields in this proto.
+     */
+    void writeToProto(T proto);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index aacc2c4..a6be091 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -117,6 +117,7 @@
 import com.android.systemui.statusbar.policy.UserInfoController;
 import com.android.systemui.statusbar.policy.UserSwitcherController;
 import com.android.systemui.statusbar.policy.ZenModeController;
+import com.android.systemui.tracing.ProtoTracer;
 import com.android.systemui.tuner.TunablePadding.TunablePaddingService;
 import com.android.systemui.tuner.TunerService;
 import com.android.systemui.util.leak.GarbageMonitor;
@@ -327,6 +328,7 @@
     @Inject Lazy<SystemWindows> mSystemWindows;
     @Inject Lazy<DisplayImeController> mDisplayImeController;
     @Inject Lazy<RecordingController> mRecordingController;
+    @Inject Lazy<ProtoTracer> mProtoTracer;
 
     @Inject
     public Dependency() {
@@ -519,6 +521,7 @@
         mProviders.put(DisplayWindowController.class, mDisplayWindowController::get);
         mProviders.put(SystemWindows.class, mSystemWindows::get);
         mProviders.put(DisplayImeController.class, mDisplayImeController::get);
+        mProviders.put(ProtoTracer.class, mProtoTracer::get);
 
         // TODO(b/118592525): to support multi-display , we start to add something which is
         //                    per-display, while others may be global. I think it's time to add
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
index ccce85c..45705b7 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
@@ -60,6 +60,14 @@
     private long mLastUpdated;
     private long mLastAccessed;
 
+    private BubbleController.NotificationSuppressionChangedListener mSuppressionListener;
+
+    /** Whether the bubble should show a dot for the notification indicating updated content. */
+    private boolean mShowBubbleUpdateDot = true;
+
+    /** Whether flyout text should be suppressed, regardless of any other flags or state. */
+    private boolean mSuppressFlyout;
+
     // Items that are typically loaded later
     private String mAppName;
     private ShortcutInfo mShortcutInfo;
@@ -71,20 +79,6 @@
     private boolean mInflateSynchronously;
 
     /**
-     * Whether this notification should be shown in the shade when it is also displayed as a bubble.
-     *
-     * <p>When a notification is a bubble we don't show it in the shade once the bubble has been
-     * expanded</p>
-     */
-    private boolean mShowInShadeWhenBubble = true;
-
-    /** Whether the bubble should show a dot for the notification indicating updated content. */
-    private boolean mShowBubbleUpdateDot = true;
-
-    /** Whether flyout text should be suppressed, regardless of any other flags or state. */
-    private boolean mSuppressFlyout;
-
-    /**
      * Presentational info about the flyout.
      */
     public static class FlyoutMessage {
@@ -106,11 +100,13 @@
 
     /** Used in tests when no UI is required. */
     @VisibleForTesting(visibility = PRIVATE)
-    Bubble(NotificationEntry e) {
+    Bubble(NotificationEntry e,
+            BubbleController.NotificationSuppressionChangedListener listener) {
         mEntry = e;
         mKey = e.getKey();
         mLastUpdated = e.getSbn().getPostTime();
         mGroupId = groupId(e);
+        mSuppressionListener = listener;
     }
 
     public String getKey() {
@@ -278,7 +274,7 @@
      */
     void markAsAccessedAt(long lastAccessedMillis) {
         mLastAccessed = lastAccessedMillis;
-        setShowInShade(false);
+        setSuppressNotification(true);
         setShowDot(false /* show */, true /* animate */);
     }
 
@@ -290,20 +286,30 @@
     }
 
     /**
-     * Whether this notification should be shown in the shade when it is also displayed as a
-     * bubble.
+     * Whether this notification should be shown in the shade.
      */
     boolean showInShade() {
-        return !mEntry.isRowDismissed() && !shouldSuppressNotification()
-                && (!mEntry.isClearable() || mShowInShadeWhenBubble);
+        return !shouldSuppressNotification() || !mEntry.isClearable();
     }
 
     /**
-     * Sets whether this notification should be shown in the shade when it is also displayed as a
-     * bubble.
+     * Sets whether this notification should be suppressed in the shade.
      */
-    void setShowInShade(boolean showInShade) {
-        mShowInShadeWhenBubble = showInShade;
+    void setSuppressNotification(boolean suppressNotification) {
+        boolean prevShowInShade = showInShade();
+
+        Notification.BubbleMetadata data = mEntry.getBubbleMetadata();
+        int flags = data.getFlags();
+        if (suppressNotification) {
+            flags |= Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION;
+        } else {
+            flags &= ~Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION;
+        }
+        data.setFlags(flags);
+
+        if (showInShade() != prevShowInShade && mSuppressionListener != null) {
+            mSuppressionListener.onBubbleNotificationSuppressionChange(this);
+        }
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index 8c9946f..894ecf6 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -224,6 +224,17 @@
     }
 
     /**
+     * Listener to be notified when a bubbles' notification suppression state changes.
+     */
+    public interface NotificationSuppressionChangedListener {
+        /**
+         * Called when the notification suppression state of a bubble changes.
+         */
+        void onBubbleNotificationSuppressionChange(Bubble bubble);
+
+    }
+
+    /**
      * Listens for the current state of the status bar and updates the visibility state
      * of bubbles as needed.
      */
@@ -303,9 +314,22 @@
 
         configurationController.addCallback(this /* configurationListener */);
 
+        mMaxBubbles = mContext.getResources().getInteger(R.integer.bubbles_max_rendered);
         mBubbleData = data;
         mBubbleData.setListener(mBubbleDataListener);
-        mMaxBubbles = mContext.getResources().getInteger(R.integer.bubbles_max_rendered);
+        mBubbleData.setSuppressionChangedListener(new NotificationSuppressionChangedListener() {
+            @Override
+            public void onBubbleNotificationSuppressionChange(Bubble bubble) {
+                // Make sure NoMan knows it's not showing in the shade anymore so anyone querying it
+                // can tell.
+                try {
+                    mBarService.onBubbleNotificationSuppressionChanged(bubble.getKey(),
+                            !bubble.showInShade());
+                } catch (RemoteException e) {
+                    // Bad things have happened
+                }
+            }
+        });
 
         mNotificationEntryManager = entryManager;
         mNotificationEntryManager.addNotificationEntryListener(mEntryListener);
@@ -720,7 +744,7 @@
                 Bubble bubble = mBubbleData.getBubbleWithKey(key);
                 boolean bubbleExtended = entry != null && entry.isBubble() && userRemovedNotif;
                 if (bubbleExtended) {
-                    bubble.setShowInShade(false);
+                    bubble.setSuppressNotification(true);
                     bubble.setShowDot(false /* show */, true /* animate */);
                     mNotificationEntryManager.updateNotifications(
                             "BubbleController.onNotificationRemoveRequested");
@@ -747,7 +771,7 @@
                 // As far as group manager is concerned, once a child is no longer shown
                 // in the shade, it is essentially removed.
                 mNotificationGroupManager.onEntryRemoved(bubbleChild.getEntry());
-                bubbleChild.setShowInShade(false);
+                bubbleChild.setSuppressNotification(true);
                 bubbleChild.setShowDot(false /* show */, true /* animate */);
             }
             // And since all children are removed, remove the summary.
@@ -1074,12 +1098,10 @@
 
         @Override
         public void onSingleTaskDisplayDrawn(int displayId) {
-            final Bubble expandedBubble = mStackView != null
-                    ? mStackView.getExpandedBubble()
-                    : null;
-            if (expandedBubble != null && expandedBubble.getDisplayId() == displayId) {
-                expandedBubble.setContentVisibility(true);
+            if (mStackView == null) {
+                return;
             }
+            mStackView.showExpandedViewContents(displayId);
         }
 
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
index 8b687e7..673121f 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
@@ -134,6 +134,9 @@
     @Nullable
     private Listener mListener;
 
+    @Nullable
+    private BubbleController.NotificationSuppressionChangedListener mSuppressionListener;
+
     /**
      * We track groups with summaries that aren't visibly displayed but still kept around because
      * the bubble(s) associated with the summary still exist.
@@ -158,6 +161,11 @@
         mMaxOverflowBubbles = mContext.getResources().getInteger(R.integer.bubbles_max_overflow);
     }
 
+    public void setSuppressionChangedListener(
+            BubbleController.NotificationSuppressionChangedListener listener) {
+        mSuppressionListener = listener;
+    }
+
     public boolean hasBubbles() {
         return !mBubbles.isEmpty();
     }
@@ -219,7 +227,7 @@
                     return b;
                 }
             }
-            bubble = new Bubble(entry);
+            bubble = new Bubble(entry, mSuppressionListener);
             mPendingBubbles.add(bubble);
         } else {
             bubble.setEntry(entry);
@@ -258,11 +266,13 @@
         } else if (mSelectedBubble == null) {
             setSelectedBubbleInternal(bubble);
         }
-        boolean isBubbleExpandedAndSelected = mExpanded && mSelectedBubble == bubble;
-        bubble.setShowInShade(!isBubbleExpandedAndSelected && showInShade);
-        bubble.setShowDot(!isBubbleExpandedAndSelected /* show */, true /* animate */);
-        dispatchPendingChanges();
 
+        boolean isBubbleExpandedAndSelected = mExpanded && mSelectedBubble == bubble;
+        boolean suppress = isBubbleExpandedAndSelected || !showInShade || !bubble.showInShade();
+        bubble.setSuppressNotification(suppress);
+        bubble.setShowDot(!isBubbleExpandedAndSelected /* show */, true /* animate */);
+
+        dispatchPendingChanges();
     }
 
     public void notificationEntryRemoved(NotificationEntry entry, @DismissReason int reason) {
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
index fe4c915..685bb94 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
@@ -409,8 +409,12 @@
                         .setStiffness(SpringForce.STIFFNESS_LOW)
                         .setDampingRatio(SpringForce.DAMPING_RATIO_LOW_BOUNCY));
         mExpandedViewYAnim.addEndListener((anim, cancelled, value, velocity) -> {
-            if (mIsExpanded && mExpandedBubble != null) {
-                mExpandedBubble.getExpandedView().updateView();
+            if (mIsExpanded) {
+                if (mExpandedBubble == null) {
+                    mOverflowExpandedView.updateView();
+                } else {
+                    mExpandedBubble.getExpandedView().updateView();
+                }
             }
         });
 
@@ -525,7 +529,7 @@
         mInflater.inflate(R.layout.bubble_overflow_button, this);
         mOverflowBtn = findViewById(R.id.bubble_overflow_button);
         mOverflowBtn.setOnClickListener(v -> {
-            showOverflow();
+            setSelectedBubble(null);
         });
 
         TypedArray ta = mContext.obtainStyledAttributes(
@@ -540,26 +544,13 @@
         mOverflowBtn.setVisibility(GONE);
     }
 
-    void showOverflow() {
-        if (DEBUG_BUBBLE_STACK_VIEW) {
-            Log.d(TAG, "Show overflow.");
+    void showExpandedViewContents(int displayId) {
+        if (mOverflowExpandedView.getVirtualDisplayId() == displayId) {
+            mOverflowExpandedView.setContentVisibility(true);
+        } else if (mExpandedBubble != null
+                && mExpandedBubble.getExpandedView().getVirtualDisplayId() == displayId) {
+            mExpandedBubble.setContentVisibility(true);
         }
-        mExpandedViewContainer.setAlpha(0.0f);
-        mSurfaceSynchronizer.syncSurfaceAndRun(() -> {
-            if (mExpandedBubble != null) {
-                mExpandedBubble.setContentVisibility(false);
-                mExpandedBubble = null;
-            }
-            mExpandedViewContainer.removeAllViews();
-            if (mIsExpanded) {
-                mExpandedViewContainer.addView(mOverflowExpandedView);
-                mOverflowExpandedView.populateExpandedView();
-                mExpandedViewContainer.setVisibility(VISIBLE);
-                mExpandedViewContainer.setAlpha(1.0f);
-                mOverflowExpandedView.setContentVisibility(true);
-            }
-            requestUpdate();
-        });
     }
 
     private void setUpFlyout() {
@@ -883,7 +874,9 @@
             // expanded view becomes visible on the screen. See b/126856255
             mExpandedViewContainer.setAlpha(0.0f);
             mSurfaceSynchronizer.syncSurfaceAndRun(() -> {
-                if (previouslySelected != null) {
+                if (previouslySelected == null) {
+                    mOverflowExpandedView.setContentVisibility(false);
+                } else {
                     previouslySelected.setContentVisibility(false);
                 }
                 updateExpandedBubble();
@@ -1055,7 +1048,9 @@
                 () -> {
                     mBubbleContainer.setActiveController(mStackAnimationController);
                     afterExpandedViewAnimation();
-                    if (previouslySelected != null) {
+                    if (previouslySelected == null) {
+                        mOverflowExpandedView.setContentVisibility(false);
+                    } else {
                         previouslySelected.setContentVisibility(false);
                     }
                 });
@@ -1625,10 +1620,14 @@
             Log.d(TAG, "updateExpandedBubble()");
         }
         mExpandedViewContainer.removeAllViews();
-        if (mExpandedBubble != null && mIsExpanded) {
-            mExpandedViewContainer.addView(mExpandedBubble.getExpandedView());
-            mExpandedBubble.getExpandedView().populateExpandedView();
-            mExpandedViewContainer.setVisibility(mIsExpanded ? VISIBLE : GONE);
+        if (mIsExpanded) {
+            BubbleExpandedView bev = mOverflowExpandedView;
+            if (mExpandedBubble != null) {
+                bev = mExpandedBubble.getExpandedView();
+            }
+            mExpandedViewContainer.addView(bev);
+            bev.populateExpandedView();
+            mExpandedViewContainer.setVisibility(VISIBLE);
             mExpandedViewContainer.setAlpha(1.0f);
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index 36a8450..f793b3d 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -27,6 +27,7 @@
 import com.android.systemui.DumpController;
 import com.android.systemui.assist.AssistModule;
 import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.log.dagger.LogModule;
 import com.android.systemui.model.SysUiState;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.recents.Recents;
@@ -59,9 +60,12 @@
  * A dagger module for injecting components of System UI that are not overridden by the System UI
  * implementation.
  */
-@Module(includes = {AssistModule.class,
-                    ConcurrencyModule.class,
-                    PeopleHubModule.class},
+@Module(includes = {
+            AssistModule.class,
+            ConcurrencyModule.class,
+            LogModule.class,
+            PeopleHubModule.class,
+        },
         subcomponents = {StatusBarComponent.class, NotificationRowComponent.class})
 public abstract class SystemUIModule {
 
diff --git a/packages/SystemUI/src/com/android/systemui/log/LogBuffer.kt b/packages/SystemUI/src/com/android/systemui/log/LogBuffer.kt
new file mode 100644
index 0000000..18c7bae
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/log/LogBuffer.kt
@@ -0,0 +1,213 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.log
+
+import android.util.Log
+import com.android.systemui.DumpController
+import com.android.systemui.Dumpable
+import com.android.systemui.log.dagger.LogModule
+import java.text.SimpleDateFormat
+import java.util.ArrayDeque
+import java.util.Locale
+
+/**
+ * A simple ring buffer of recyclable log messages
+ *
+ * The goal of this class is to enable logging that is both extremely chatty and extremely
+ * lightweight. If done properly, logging a message will not result in any heap allocations or
+ * string generation. Messages are only converted to strings if the log is actually dumped (usually
+ * as the result of taking a bug report).
+ *
+ * You can dump the entire buffer at any time by running:
+ *
+ * ```
+ * $ adb shell dumpsys activity service com.android.systemui/.SystemUIService \
+ *      dependency DumpController <bufferName>
+ * ```
+ *
+ * where `bufferName` is the (case-sensitive) [name] passed to the constructor.
+ *
+ * By default, only messages of WARN level or higher are echoed to logcat, but this can be adjusted
+ * locally (usually for debugging purposes).
+ *
+ * To enable logcat echoing for an entire buffer:
+ *
+ * ```
+ * $ adb shell settings put global systemui/buffer/<bufferName> <level>
+ * ```
+ *
+ * To enable logcat echoing for a specific tag:
+ *
+ * ```
+ * $ adb shell settings put global systemui/tag/<tag> <level>
+ * ```
+ *
+ * In either case, `level` can be any of `verbose`, `debug`, `info`, `warn`, `error`, `assert`, or
+ * the first letter of any of the previous.
+ *
+ * Buffers are provided by [LogModule].
+ *
+ * @param name The name of this buffer
+ * @param maxLogs The maximum number of messages to keep in memory at any one time, including the
+ * unused pool.
+ * @param poolSize The maximum amount that the size of the buffer is allowed to flex in response to
+ * sequential calls to [document] that aren't immediately followed by a matching call to [push].
+ */
+class LogBuffer(
+    private val name: String,
+    private val maxLogs: Int,
+    private val poolSize: Int,
+    private val logcatEchoTracker: LogcatEchoTracker
+) {
+    private val buffer: ArrayDeque<LogMessageImpl> = ArrayDeque()
+
+    fun attach(dumpController: DumpController) {
+        dumpController.registerDumpable(name, onDump)
+    }
+
+    /**
+     * Logs a message to the log buffer
+     *
+     * May also log the message to logcat if echoing is enabled for this buffer or tag.
+     *
+     * The actual string of the log message is not constructed until it is needed. To accomplish
+     * this, logging a message is a two-step process. First, a fresh instance  of [LogMessage] is
+     * obtained and is passed to the [initializer]. The initializer stores any relevant data on the
+     * message's fields. The message is then inserted into the buffer where it waits until it is
+     * either pushed out by newer messages or it needs to printed. If and when this latter moment
+     * occurs, the [printer] function is called on the message. It reads whatever data the
+     * initializer stored and converts it to a human-readable log message.
+     *
+     * @param tag A string of at most 23 characters, used for grouping logs into categories or
+     * subjects. If this message is echoed to logcat, this will be the tag that is used.
+     * @param level Which level to log the message at, both to the buffer and to logcat if it's
+     * echoed. In general, a module should split most of its logs into either INFO or DEBUG level.
+     * INFO level should be reserved for information that other parts of the system might care
+     * about, leaving the specifics of code's day-to-day operations to DEBUG.
+     * @param initializer A function that will be called immediately to store relevant data on the
+     * log message. The value of `this` will be the LogMessage to be initialized.
+     * @param printer A function that will be called if and when the message needs to be dumped to
+     * logcat or a bug report. It should read the data stored by the initializer and convert it to
+     * a human-readable string. The value of `this` will be the LogMessage to be printed.
+     * **IMPORTANT:** The printer should ONLY ever reference fields on the LogMessage and NEVER any
+     * variables in its enclosing scope. Otherwise, the runtime will need to allocate a new instance
+     * of the printer for each call, thwarting our attempts at avoiding any sort of allocation.
+     */
+    inline fun log(
+        tag: String,
+        level: LogLevel,
+        initializer: LogMessage.() -> Unit,
+        noinline printer: LogMessage.() -> String
+    ) {
+        val message = obtain(tag, level, printer)
+        initializer(message)
+        push(message)
+    }
+
+    /**
+     * Same as [log], but doesn't push the message to the buffer. Useful if you need to supply a
+     * "reason" for doing something (the thing you supply the reason to will presumably call [push]
+     * on that message at some point).
+     */
+    inline fun document(
+        tag: String,
+        level: LogLevel,
+        initializer: LogMessage.() -> Unit,
+        noinline printer: LogMessage.() -> String
+    ): LogMessage {
+        val message = obtain(tag, level, printer)
+        initializer(message)
+        return message
+    }
+
+    /**
+     * Obtains an instance of [LogMessageImpl], usually from the object pool. If the pool has been
+     * exhausted, creates a new instance.
+     *
+     * In general, you should call [log] or [document] instead of this method.
+     */
+    fun obtain(
+        tag: String,
+        level: LogLevel,
+        printer: (LogMessage) -> String
+    ): LogMessageImpl {
+        val message = synchronized(buffer) {
+            if (buffer.size > maxLogs - poolSize) {
+                buffer.removeFirst()
+            } else {
+                LogMessageImpl.create()
+            }
+        }
+        message.reset(tag, level, System.currentTimeMillis(), printer)
+        return message
+    }
+
+    /**
+     * Pushes a message into buffer, possibly evicting an older message if the buffer is full.
+     */
+    fun push(message: LogMessage) {
+        synchronized(buffer) {
+            if (buffer.size == maxLogs) {
+                Log.e(TAG, "LogBuffer $name has exceeded its pool size")
+                buffer.removeFirst()
+            }
+            buffer.add(message as LogMessageImpl)
+            if (logcatEchoTracker.isBufferLoggable(name, message.level) ||
+                    logcatEchoTracker.isTagLoggable(message.tag, message.level)) {
+                echoToLogcat(message)
+            }
+        }
+    }
+
+    /** Converts the entire buffer to a newline-delimited string */
+    fun dump(): String {
+        synchronized(buffer) {
+            val sb = StringBuilder()
+            for (message in buffer) {
+                dumpMessage(message, sb)
+            }
+            return sb.toString()
+        }
+    }
+
+    private fun dumpMessage(message: LogMessage, sb: StringBuilder) {
+        sb.append(DATE_FORMAT.format(message.timestamp))
+                .append(" ").append(message.level)
+                .append(" ").append(message.tag)
+                .append(" ").append(message.printer(message))
+                .append("\n")
+    }
+
+    private fun echoToLogcat(message: LogMessage) {
+        val strMessage = message.printer(message)
+        when (message.level) {
+            LogLevel.VERBOSE -> Log.v(message.tag, strMessage)
+            LogLevel.DEBUG -> Log.d(message.tag, strMessage)
+            LogLevel.INFO -> Log.i(message.tag, strMessage)
+            LogLevel.WARNING -> Log.w(message.tag, strMessage)
+            LogLevel.ERROR -> Log.e(message.tag, strMessage)
+            LogLevel.WTF -> Log.wtf(message.tag, strMessage)
+        }
+    }
+
+    private val onDump = Dumpable { _, pw, _ ->
+        pw.println(dump())
+    }
+}
+
+private const val TAG = "LogBuffer"
+private val DATE_FORMAT = SimpleDateFormat("MM-dd HH:mm:ss.S", Locale.US)
diff --git a/packages/SystemUI/src/com/android/systemui/log/LogLevel.kt b/packages/SystemUI/src/com/android/systemui/log/LogLevel.kt
new file mode 100644
index 0000000..7b9af0f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/log/LogLevel.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.log
+
+import android.util.Log
+
+/**
+ * Enum version of @Log.Level
+ */
+enum class LogLevel(@Log.Level val nativeLevel: Int) {
+    VERBOSE(Log.VERBOSE),
+    DEBUG(Log.DEBUG),
+    INFO(Log.INFO),
+    WARNING(Log.WARN),
+    ERROR(Log.ERROR),
+    WTF(Log.ASSERT)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/log/LogMessage.kt b/packages/SystemUI/src/com/android/systemui/log/LogMessage.kt
new file mode 100644
index 0000000..d971ac5
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/log/LogMessage.kt
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.log
+
+/**
+ * Generic data class for storing messages logged to a [LogBuffer]
+ *
+ * Each LogMessage has a few standard fields ([level], [tag], and [timestamp]). The rest are generic
+ * data slots that may or may not be used, depending on the nature of the specific message being
+ * logged.
+ *
+ * When a message is logged, the code doing the logging stores data in one or more of the generic
+ * fields ([str1], [int1], etc). When it comes time to dump the message to logcat/bugreport/etc, the
+ * [printer] function reads the data stored in the generic fields and converts that to a human-
+ * readable string. Thus, for every log type there must be a specialized initializer function that
+ * stores data specific to that log type and a specialized printer function that prints that data.
+ *
+ * See [LogBuffer.log] for more information.
+ */
+interface LogMessage {
+    val level: LogLevel
+    val tag: String
+    val timestamp: Long
+    val printer: LogMessage.() -> String
+
+    var str1: String?
+    var str2: String?
+    var str3: String?
+    var int1: Int
+    var int2: Int
+    var long1: Long
+    var double1: Double
+}
diff --git a/packages/SystemUI/src/com/android/systemui/log/LogMessageImpl.kt b/packages/SystemUI/src/com/android/systemui/log/LogMessageImpl.kt
new file mode 100644
index 0000000..32334bc
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/log/LogMessageImpl.kt
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.log
+
+/**
+ * Recyclable implementation of [LogMessage].
+ */
+data class LogMessageImpl(
+    override var level: LogLevel,
+    override var tag: String,
+    override var timestamp: Long,
+    override var printer: LogMessage.() -> String,
+    override var str1: String?,
+    override var str2: String?,
+    override var str3: String?,
+    override var int1: Int,
+    override var int2: Int,
+    override var long1: Long,
+    override var double1: Double
+) : LogMessage {
+
+    fun reset(
+        tag: String,
+        level: LogLevel,
+        timestamp: Long,
+        renderer: LogMessage.() -> String
+    ) {
+        this.level = level
+        this.tag = tag
+        this.timestamp = timestamp
+        this.printer = renderer
+        str1 = null
+        str2 = null
+        str3 = null
+        int1 = 0
+        int2 = 0
+        long1 = 0
+        double1 = 0.0
+    }
+
+    companion object Factory {
+        fun create(): LogMessageImpl {
+            return LogMessageImpl(
+                    LogLevel.DEBUG,
+                    DEFAULT_TAG,
+                    0,
+                    DEFAULT_RENDERER,
+                    null,
+                    null,
+                    null,
+                    0,
+                    0,
+                    0,
+                    0.0)
+        }
+    }
+}
+
+private const val DEFAULT_TAG = "UnknownTag"
+private val DEFAULT_RENDERER: LogMessage.() -> String = { "Unknown message: $this" }
diff --git a/packages/SystemUI/src/com/android/systemui/log/LogcatEchoTracker.kt b/packages/SystemUI/src/com/android/systemui/log/LogcatEchoTracker.kt
new file mode 100644
index 0000000..3022f4b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/log/LogcatEchoTracker.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.log
+
+/**
+ * Keeps track of which [LogBuffer] messages should also appear in logcat.
+ */
+interface LogcatEchoTracker {
+    /**
+     * Whether [bufferName] should echo messages of [level] or higher to logcat.
+     */
+    fun isBufferLoggable(bufferName: String, level: LogLevel): Boolean
+
+    /**
+     * Whether [tagName] should echo messages of [level] or higher to logcat.
+     */
+    fun isTagLoggable(tagName: String, level: LogLevel): Boolean
+}
diff --git a/packages/SystemUI/src/com/android/systemui/log/LogcatEchoTrackerDebug.kt b/packages/SystemUI/src/com/android/systemui/log/LogcatEchoTrackerDebug.kt
new file mode 100644
index 0000000..23942e1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/log/LogcatEchoTrackerDebug.kt
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.log
+
+import android.content.ContentResolver
+import android.database.ContentObserver
+import android.net.Uri
+import android.os.Handler
+import android.os.Looper
+import android.provider.Settings
+
+/**
+ * Version of [LogcatEchoTracker] for debuggable builds
+ *
+ * The log level of individual buffers or tags can be controlled via global settings:
+ *
+ * ```
+ * # Echo any message to <bufferName> of <level> or higher
+ * $ adb shell settings put global systemui/buffer/<bufferName> <level>
+ *
+ * # Echo any message of <tag> and of <level> or higher
+ * $ adb shell settings put global systemui/tag/<tag> <level>
+ * ```
+ */
+class LogcatEchoTrackerDebug private constructor(
+    private val contentResolver: ContentResolver
+) : LogcatEchoTracker {
+    private val cachedBufferLevels: MutableMap<String, LogLevel> = mutableMapOf()
+    private val cachedTagLevels: MutableMap<String, LogLevel> = mutableMapOf()
+
+    companion object Factory {
+        @JvmStatic
+        fun create(
+            contentResolver: ContentResolver,
+            mainLooper: Looper
+        ): LogcatEchoTrackerDebug {
+            val tracker = LogcatEchoTrackerDebug(contentResolver)
+            tracker.attach(mainLooper)
+            return tracker
+        }
+    }
+
+    private fun attach(mainLooper: Looper) {
+        contentResolver.registerContentObserver(
+                Settings.Global.getUriFor(BUFFER_PATH),
+                true,
+                object : ContentObserver(Handler(mainLooper)) {
+                    override fun onChange(selfChange: Boolean, uri: Uri) {
+                        super.onChange(selfChange, uri)
+                        cachedBufferLevels.clear()
+                    }
+                })
+
+        contentResolver.registerContentObserver(
+                Settings.Global.getUriFor(TAG_PATH),
+                true,
+                object : ContentObserver(Handler(mainLooper)) {
+                    override fun onChange(selfChange: Boolean, uri: Uri) {
+                        super.onChange(selfChange, uri)
+                        cachedTagLevels.clear()
+                    }
+                })
+    }
+
+    /**
+     * Whether [bufferName] should echo messages of [level] or higher to logcat.
+     */
+    @Synchronized
+    override fun isBufferLoggable(bufferName: String, level: LogLevel): Boolean {
+        return level.ordinal >= getLogLevel(bufferName, BUFFER_PATH, cachedBufferLevels).ordinal
+    }
+
+    /**
+     * Whether [tagName] should echo messages of [level] or higher to logcat.
+     */
+    @Synchronized
+    override fun isTagLoggable(tagName: String, level: LogLevel): Boolean {
+        return level >= getLogLevel(tagName, TAG_PATH, cachedTagLevels)
+    }
+
+    private fun getLogLevel(
+        name: String,
+        path: String,
+        cache: MutableMap<String, LogLevel>
+    ): LogLevel {
+        return cache[name] ?: readSetting("$path/$name").also { cache[name] = it }
+    }
+
+    private fun readSetting(path: String): LogLevel {
+        return try {
+            parseProp(Settings.Global.getString(contentResolver, path))
+        } catch (_: Settings.SettingNotFoundException) {
+            DEFAULT_LEVEL
+        }
+    }
+
+    private fun parseProp(propValue: String?): LogLevel {
+        return when (propValue?.toLowerCase()) {
+            "verbose" -> LogLevel.VERBOSE
+            "v" -> LogLevel.VERBOSE
+            "debug" -> LogLevel.DEBUG
+            "d" -> LogLevel.DEBUG
+            "info" -> LogLevel.INFO
+            "i" -> LogLevel.INFO
+            "warning" -> LogLevel.WARNING
+            "warn" -> LogLevel.WARNING
+            "w" -> LogLevel.WARNING
+            "error" -> LogLevel.ERROR
+            "e" -> LogLevel.ERROR
+            "assert" -> LogLevel.WTF
+            "wtf" -> LogLevel.WTF
+            else -> DEFAULT_LEVEL
+        }
+    }
+}
+
+private val DEFAULT_LEVEL = LogLevel.WARNING
+private const val BUFFER_PATH = "systemui/buffer"
+private const val TAG_PATH = "systemui/tag"
diff --git a/packages/SystemUI/src/com/android/systemui/log/LogcatEchoTrackerProd.kt b/packages/SystemUI/src/com/android/systemui/log/LogcatEchoTrackerProd.kt
new file mode 100644
index 0000000..394f624
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/log/LogcatEchoTrackerProd.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.log
+
+/**
+ * Production version of [LogcatEchoTracker] that isn't configurable.
+ */
+class LogcatEchoTrackerProd : LogcatEchoTracker {
+    override fun isBufferLoggable(bufferName: String, level: LogLevel): Boolean {
+        return level >= LogLevel.WARNING
+    }
+
+    override fun isTagLoggable(tagName: String, level: LogLevel): Boolean {
+        return level >= LogLevel.WARNING
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/DozeLog.java b/packages/SystemUI/src/com/android/systemui/log/dagger/DozeLog.java
new file mode 100644
index 0000000..7c5f402
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/DozeLog.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.log.dagger;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.android.systemui.log.LogBuffer;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+
+import javax.inject.Qualifier;
+
+/** A {@link LogBuffer} for dozing-related messages. */
+@Qualifier
+@Documented
+@Retention(RUNTIME)
+public @interface DozeLog {
+}
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
new file mode 100644
index 0000000..b1990be
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.log.dagger;
+
+import android.content.ContentResolver;
+import android.os.Build;
+import android.os.Looper;
+
+import com.android.systemui.DumpController;
+import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.log.LogBuffer;
+import com.android.systemui.log.LogcatEchoTracker;
+import com.android.systemui.log.LogcatEchoTrackerDebug;
+import com.android.systemui.log.LogcatEchoTrackerProd;
+
+import javax.inject.Singleton;
+
+import dagger.Module;
+import dagger.Provides;
+
+/**
+ * Dagger module for providing instances of {@link LogBuffer}.
+ */
+@Module
+public class LogModule {
+    /** Provides a logging buffer for doze-related logs. */
+    @Provides
+    @Singleton
+    @DozeLog
+    public static LogBuffer provideDozeLogBuffer(
+            LogcatEchoTrackerDebug bufferFilter,
+            DumpController dumpController) {
+        LogBuffer buffer = new LogBuffer("DozeLog", 100, 10, bufferFilter);
+        buffer.attach(dumpController);
+        return buffer;
+    }
+
+    /** Provides a logging buffer for all logs related to the data layer of notifications. */
+    @Provides
+    @Singleton
+    @NotificationLog
+    public static LogBuffer provideNotificationsLogBuffer(
+            LogcatEchoTracker bufferFilter,
+            DumpController dumpController) {
+        LogBuffer buffer = new LogBuffer("NotifLog2", 1000, 10, bufferFilter);
+        buffer.attach(dumpController);
+        return buffer;
+    }
+
+    /** Allows logging buffers to be tweaked via adb on debug builds but not on prod builds. */
+    @Provides
+    @Singleton
+    public static LogcatEchoTracker provideLogcatEchoTracker(
+            ContentResolver contentResolver,
+            @Main Looper looper) {
+        if (Build.IS_DEBUGGABLE) {
+            return LogcatEchoTrackerDebug.create(contentResolver, looper);
+        } else {
+            return new LogcatEchoTrackerProd();
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/NotificationLog.java b/packages/SystemUI/src/com/android/systemui/log/dagger/NotificationLog.java
new file mode 100644
index 0000000..a0b6864
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/NotificationLog.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.log.dagger;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.android.systemui.log.LogBuffer;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+
+import javax.inject.Qualifier;
+
+/** A {@link LogBuffer} for notification-related messages. */
+@Qualifier
+@Documented
+@Retention(RUNTIME)
+public @interface NotificationLog {
+}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java b/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java
index 8e34a90..6f03f18 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java
@@ -261,8 +261,6 @@
             mPinnedStackController.startAnimation(destinationBounds, sourceRectHint,
                     -1 /* animationDuration */);
             mLastDestinationBounds.set(destinationBounds);
-            mPinnedStackController.reportBounds(defaultBounds,
-                    getMovementBounds(defaultBounds));
         } catch (RemoteException e) {
             Log.e(TAG, "Failed to start PiP animation from SysUI", e);
         }
@@ -317,7 +315,6 @@
             outBounds.set(postChangeStackBounds);
             mLastDestinationBounds.set(outBounds);
             mPinnedStackController.resetBoundsAnimation(outBounds);
-            mPinnedStackController.reportBounds(outBounds, getMovementBounds(outBounds));
             t.setBounds(pinnedStackInfo.stackToken, outBounds);
         } catch (RemoteException e) {
             Log.e(TAG, "Failed to resize PiP on display rotation", e);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
index 411980b..557c64b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java
@@ -191,6 +191,7 @@
         mTile.setLabel(tile.getLabel());
         mTile.setSubtitle(tile.getSubtitle());
         mTile.setContentDescription(tile.getContentDescription());
+        mTile.setStateDescription(tile.getStateDescription());
         mTile.setState(tile.getState());
     }
 
@@ -345,6 +346,12 @@
             state.contentDescription = state.label;
         }
 
+        if (mTile.getStateDescription() != null) {
+            state.stateDescription = mTile.getStateDescription();
+        } else {
+            state.stateDescription = null;
+        }
+
         if (state instanceof BooleanState) {
             state.expandedAccessibilityClassName = Switch.class.getName();
             ((BooleanState) state).value = (state.state == Tile.STATE_ACTIVE);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java
index 8b7f280..fda9e5b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java
@@ -65,7 +65,6 @@
     private String mAccessibilityClass;
     private boolean mTileState;
     private boolean mCollapsedView;
-    private boolean mClicked;
     private boolean mShowRippleEffect = true;
 
     private final ImageView mBg;
@@ -234,13 +233,35 @@
         setLongClickable(state.handlesLongClick);
         mIcon.setIcon(state, allowAnimations);
         setContentDescription(state.contentDescription);
+        final StringBuilder stateDescription = new StringBuilder();
+        switch (state.state) {
+            case Tile.STATE_UNAVAILABLE:
+                stateDescription.append(mContext.getString(R.string.tile_unavailable));
+                break;
+            case Tile.STATE_INACTIVE:
+                if (state instanceof QSTile.BooleanState) {
+                    stateDescription.append(mContext.getString(R.string.switch_bar_off));
+                }
+                break;
+            case Tile.STATE_ACTIVE:
+                if (state instanceof QSTile.BooleanState) {
+                    stateDescription.append(mContext.getString(R.string.switch_bar_on));
+                }
+                break;
+            default:
+                break;
+        }
+        if (!TextUtils.isEmpty(state.stateDescription)) {
+            stateDescription.append(", ");
+            stateDescription.append(state.stateDescription);
+        }
+        setStateDescription(stateDescription.toString());
 
         mAccessibilityClass =
                 state.state == Tile.STATE_UNAVAILABLE ? null : state.expandedAccessibilityClassName;
         if (state instanceof QSTile.BooleanState) {
             boolean newState = ((BooleanState) state).value;
             if (mTileState != newState) {
-                mClicked = false;
                 mTileState = newState;
             }
         }
@@ -297,23 +318,10 @@
     }
 
     @Override
-    public boolean performClick() {
-        mClicked = true;
-        return super.performClick();
-    }
-
-    @Override
     public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
         super.onInitializeAccessibilityEvent(event);
         if (!TextUtils.isEmpty(mAccessibilityClass)) {
             event.setClassName(mAccessibilityClass);
-            if (Switch.class.getName().equals(mAccessibilityClass)) {
-                boolean b = mClicked ? !mTileState : mTileState;
-                String label = getResources()
-                        .getString(b ? R.string.switch_bar_on : R.string.switch_bar_off);
-                event.setContentDescription(label);
-                event.setChecked(b);
-            }
         }
     }
 
@@ -325,11 +333,6 @@
         if (!TextUtils.isEmpty(mAccessibilityClass)) {
             info.setClassName(mAccessibilityClass);
             if (Switch.class.getName().equals(mAccessibilityClass)) {
-                boolean b = mClicked ? !mTileState : mTileState;
-                String label = getResources()
-                        .getString(b ? R.string.switch_bar_on : R.string.switch_bar_off);
-                info.setText(label);
-                info.setChecked(b);
                 info.setCheckable(true);
                 if (isLongClickable()) {
                     info.addAction(
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
index 9282a2e..361b6c1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -134,25 +134,27 @@
         state.label = mContext.getString(R.string.quick_settings_bluetooth_label);
         state.secondaryLabel = TextUtils.emptyIfNull(
                 getSecondaryLabel(enabled, connecting, connected, state.isTransient));
+        state.contentDescription = state.label;
+        state.stateDescription = "";
         if (enabled) {
             if (connected) {
                 state.icon = new BluetoothConnectedTileIcon();
                 if (!TextUtils.isEmpty(mController.getConnectedDeviceName())) {
                     state.label = mController.getConnectedDeviceName();
                 }
-                state.contentDescription =
+                state.stateDescription =
                         mContext.getString(R.string.accessibility_bluetooth_name, state.label)
                                 + ", " + state.secondaryLabel;
             } else if (state.isTransient) {
                 state.icon = ResourceIcon.get(
                         com.android.internal.R.drawable.ic_bluetooth_transient_animation);
-                state.contentDescription = state.secondaryLabel;
+                state.stateDescription = state.secondaryLabel;
             } else {
                 state.icon =
                         ResourceIcon.get(com.android.internal.R.drawable.ic_qs_bluetooth);
                 state.contentDescription = mContext.getString(
-                        R.string.accessibility_quick_settings_bluetooth) + ","
-                        + mContext.getString(R.string.accessibility_not_connected);
+                        R.string.accessibility_quick_settings_bluetooth);
+                state.stateDescription = mContext.getString(R.string.accessibility_not_connected);
             }
             state.state = Tile.STATE_ACTIVE;
         } else {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
index 0e813d1..58de057 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
@@ -183,6 +183,7 @@
     protected void handleUpdateState(BooleanState state, Object arg) {
         state.label = mContext.getString(R.string.quick_settings_cast_title);
         state.contentDescription = state.label;
+        state.stateDescription = "";
         state.value = false;
         final List<CastDevice> devices = mController.getCastDevices();
         boolean connecting = false;
@@ -192,8 +193,9 @@
             if (device.state == CastDevice.STATE_CONNECTED) {
                 state.value = true;
                 state.secondaryLabel = getDeviceName(device);
-                state.contentDescription = state.contentDescription + "," +
-                        mContext.getString(R.string.accessibility_cast_name, state.label);
+                state.stateDescription = state.stateDescription + ","
+                        + mContext.getString(
+                                R.string.accessibility_cast_name, state.label);
                 connecting = false;
                 break;
             } else if (device.state == CastDevice.STATE_CONNECTING) {
@@ -217,9 +219,8 @@
             state.state = Tile.STATE_UNAVAILABLE;
             String noWifi = mContext.getString(R.string.quick_settings_cast_no_wifi);
             state.secondaryLabel = noWifi;
-            state.contentDescription = state.contentDescription + ", " + mContext.getString(
-                    R.string.accessibility_quick_settings_not_available, noWifi);
         }
+        state.stateDescription = state.stateDescription + ", " + state.secondaryLabel;
         mDetailAdapter.updateItems(devices);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
index 22470c7..d5f86c9 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -194,17 +194,13 @@
             state.secondaryLabel = r.getString(R.string.cell_data_off);
         }
 
-
-        // TODO(b/77881974): Instead of switching out the description via a string check for
-        // we need to have two strings provided by the MobileIconGroup.
-        final CharSequence contentDescriptionSuffix;
+        state.contentDescription = state.label;
         if (state.state == Tile.STATE_INACTIVE) {
-            contentDescriptionSuffix = r.getString(R.string.cell_data_off_content_description);
+            // This information is appended later by converting the Tile.STATE_INACTIVE state.
+            state.stateDescription = "";
         } else {
-            contentDescriptionSuffix = state.secondaryLabel;
+            state.stateDescription = state.secondaryLabel;
         }
-
-        state.contentDescription = state.label + ", " + contentDescriptionSuffix;
     }
 
     private CharSequence appendMobileDataType(CharSequence current, CharSequence dataType) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
index 52d1a5b3..9215da4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
@@ -240,6 +240,8 @@
                 zen != Global.ZEN_MODE_OFF, mController.getConfig(), false));
         state.icon = ResourceIcon.get(com.android.internal.R.drawable.ic_qs_dnd);
         checkIfRestrictionEnforcedByAdminOnly(state, UserManager.DISALLOW_ADJUST_VOLUME);
+        // Keeping the secondaryLabel in contentDescription instead of stateDescription is easier
+        // to understand.
         switch (zen) {
             case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
                 state.contentDescription =
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
index dafdd89..792c364 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
@@ -102,14 +102,13 @@
         }
         state.label = mHost.getContext().getString(R.string.quick_settings_flashlight_label);
         state.secondaryLabel = "";
+        state.stateDescription = "";
         if (!mFlashlightController.isAvailable()) {
             state.icon = mIcon;
             state.slash.isSlashed = true;
             state.secondaryLabel = mContext.getString(
                     R.string.quick_settings_flashlight_camera_in_use);
-            state.contentDescription = mContext.getString(
-                    R.string.accessibility_quick_settings_flashlight_unavailable)
-                    + ", " + state.secondaryLabel;
+            state.stateDescription = state.secondaryLabel;
             state.state = Tile.STATE_UNAVAILABLE;
             return;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
index 001e094..fd6b936 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
@@ -147,6 +147,7 @@
 
         state.secondaryLabel = getSecondaryLabel(
                 isTileActive, isTransient, isDataSaverEnabled, numConnectedDevices);
+        state.stateDescription = state.secondaryLabel;
     }
 
     @Nullable
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
index fbdca3b..e617867 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
@@ -105,15 +105,8 @@
         }
         state.icon = mIcon;
         state.slash.isSlashed = !state.value;
-        if (locationEnabled) {
-            state.label = mContext.getString(R.string.quick_settings_location_label);
-            state.contentDescription = mContext.getString(
-                    R.string.accessibility_quick_settings_location_on);
-        } else {
-            state.label = mContext.getString(R.string.quick_settings_location_label);
-            state.contentDescription = mContext.getString(
-                    R.string.accessibility_quick_settings_location_off);
-        }
+        state.label = mContext.getString(R.string.quick_settings_location_label);
+        state.contentDescription = state.label;
         state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
         state.expandedAccessibilityClassName = Switch.class.getName();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
index b7ce101..6e8dcf3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -195,6 +195,7 @@
         state.activityIn = cb.enabled && cb.activityIn;
         state.activityOut = cb.enabled && cb.activityOut;
         final StringBuffer minimalContentDescription = new StringBuffer();
+        final StringBuffer minimalStateDescription = new StringBuffer();
         final Resources r = mContext.getResources();
         if (isTransient) {
             state.icon = ResourceIcon.get(
@@ -219,13 +220,14 @@
                 mContext.getString(R.string.quick_settings_wifi_label)).append(",");
         if (state.value) {
             if (wifiConnected) {
-                minimalContentDescription.append(cb.wifiSignalContentDescription).append(",");
+                minimalStateDescription.append(cb.wifiSignalContentDescription);
                 minimalContentDescription.append(removeDoubleQuotes(cb.ssid));
                 if (!TextUtils.isEmpty(state.secondaryLabel)) {
                     minimalContentDescription.append(",").append(state.secondaryLabel);
                 }
             }
         }
+        state.stateDescription = minimalStateDescription.toString();
         state.contentDescription = minimalContentDescription.toString();
         state.dualLabelContentDescription = r.getString(
                 R.string.accessibility_quick_settings_open_settings, getTileLabel());
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
index 7853dc3..e54ee51 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
@@ -103,14 +103,11 @@
         state.icon = mIcon;
         if (state.value) {
             state.slash.isSlashed = false;
-            state.contentDescription =  mContext.getString(
-                    R.string.accessibility_quick_settings_work_mode_on);
         } else {
             state.slash.isSlashed = true;
-            state.contentDescription =  mContext.getString(
-                    R.string.accessibility_quick_settings_work_mode_off);
         }
         state.label = mContext.getString(R.string.quick_settings_work_mode_label);
+        state.contentDescription = state.label;
         state.expandedAccessibilityClassName = Switch.class.getName();
         state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index 79a33c9..573ea4d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -29,6 +29,7 @@
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BOUNCER_SHOWING;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_TRACING_ENABLED;
 
 import android.annotation.FloatRange;
 import android.app.ActivityTaskManager;
@@ -67,6 +68,7 @@
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.QuickStepContract;
 import com.android.systemui.stackdivider.Divider;
+import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.NavigationBarController;
 import com.android.systemui.statusbar.phone.NavigationBarFragment;
 import com.android.systemui.statusbar.phone.NavigationBarView;
@@ -485,7 +487,8 @@
 
     @SuppressWarnings("OptionalUsedAsFieldOrParameterType")
     @Inject
-    public OverviewProxyService(Context context, DeviceProvisionedController provisionController,
+    public OverviewProxyService(Context context, CommandQueue commandQueue,
+            DeviceProvisionedController provisionController,
             NavigationBarController navBarController, NavigationModeController navModeController,
             NotificationShadeWindowController statusBarWinController, SysUiState sysUiState,
             PipUI pipUI, Optional<Divider> dividerOptional,
@@ -530,6 +533,15 @@
         // Listen for status bar state changes
         statusBarWinController.registerCallback(mStatusBarWindowCallback);
         mScreenshotHelper = new ScreenshotHelper(context);
+
+        // Listen for tracing state changes
+        commandQueue.addCallback(new CommandQueue.Callbacks() {
+            @Override
+            public void onTracingStateChanged(boolean enabled) {
+                mSysUiState.setFlag(SYSUI_STATE_TRACING_ENABLED, enabled)
+                        .commitUpdate(mContext.getDisplayId());
+            }
+        });
     }
 
     public void notifyBackAction(boolean completed, int downX, int downY, boolean isButton,
@@ -573,14 +585,12 @@
 
     private void onStatusBarStateChanged(boolean keyguardShowing, boolean keyguardOccluded,
             boolean bouncerShowing) {
-        int displayId = mContext.getDisplayId();
-
         mSysUiState.setFlag(SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING,
                         keyguardShowing && !keyguardOccluded)
                 .setFlag(SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED,
                         keyguardShowing && keyguardOccluded)
                 .setFlag(SYSUI_STATE_BOUNCER_SHOWING, bouncerShowing)
-                .commitUpdate(displayId);
+                .commitUpdate(mContext.getDisplayId());
     }
 
     /**
@@ -601,10 +611,6 @@
         }
     }
 
-    public float getBackButtonAlpha() {
-        return mNavBarButtonAlpha;
-    }
-
     public void cleanupAfterDeath() {
         if (mInputFocusTransferStarted) {
             mHandler.post(()-> {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 3af3701..64f0830 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -53,6 +53,7 @@
 import com.android.internal.view.AppearanceRegion;
 import com.android.systemui.statusbar.CommandQueue.Callbacks;
 import com.android.systemui.statusbar.policy.CallbackController;
+import com.android.systemui.tracing.ProtoTracer;
 
 import java.util.ArrayList;
 
@@ -123,6 +124,7 @@
     private static final int MSG_DISMISS_INATTENTIVE_SLEEP_WARNING = 52 << MSG_SHIFT;
     private static final int MSG_SHOW_TOAST                        = 53 << MSG_SHIFT;
     private static final int MSG_HIDE_TOAST                        = 54 << MSG_SHIFT;
+    private static final int MSG_TRACING_STATE_CHANGED             = 55 << MSG_SHIFT;
 
     public static final int FLAG_EXCLUDE_NONE = 0;
     public static final int FLAG_EXCLUDE_SEARCH_PANEL = 1 << 0;
@@ -143,6 +145,7 @@
      * event.
      */
     private int mLastUpdatedImeDisplayId = INVALID_DISPLAY;
+    private ProtoTracer mProtoTracer;
 
     /**
      * These methods are called back on the main thread.
@@ -325,9 +328,19 @@
          * @see IStatusBar#hideToast(String, IBinder) (String, IBinder)
          */
         default void hideToast(String packageName, IBinder token) { }
+
+        /**
+         * @param enabled
+         */
+        default void onTracingStateChanged(boolean enabled) { }
     }
 
     public CommandQueue(Context context) {
+        this(context, null);
+    }
+
+    public CommandQueue(Context context, ProtoTracer protoTracer) {
+        mProtoTracer = protoTracer;
         context.getSystemService(DisplayManager.class).registerDisplayListener(this, mHandler);
         // We always have default display.
         setDisabled(DEFAULT_DISPLAY, DISABLE_NONE, DISABLE2_NONE);
@@ -917,6 +930,26 @@
         }
     }
 
+    @Override
+    public void startTracing() {
+        synchronized (mLock) {
+            if (mProtoTracer != null) {
+                mProtoTracer.start();
+            }
+            mHandler.obtainMessage(MSG_TRACING_STATE_CHANGED, true).sendToTarget();
+        }
+    }
+
+    @Override
+    public void stopTracing() {
+        synchronized (mLock) {
+            if (mProtoTracer != null) {
+                mProtoTracer.stop();
+            }
+            mHandler.obtainMessage(MSG_TRACING_STATE_CHANGED, false).sendToTarget();
+        }
+    }
+
     private final class H extends Handler {
         private H(Looper l) {
             super(l);
@@ -1244,6 +1277,11 @@
                     }
                     break;
                 }
+                case MSG_TRACING_STATE_CHANGED:
+                    for (int i = 0; i < mCallbacks.size(); i++) {
+                        mCallbacks.get(i).onTracingStateChanged((Boolean) msg.obj);
+                    }
+                    break;
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarDependenciesModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarDependenciesModule.java
index ec8dbea..493482a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarDependenciesModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarDependenciesModule.java
@@ -19,6 +19,8 @@
 import android.content.Context;
 
 import com.android.systemui.statusbar.notification.row.NotificationRowModule;
+import com.android.systemui.recents.OverviewProxyService;
+import com.android.systemui.tracing.ProtoTracer;
 
 import javax.inject.Singleton;
 
@@ -35,8 +37,8 @@
      */
     @Provides
     @Singleton
-    public CommandQueue provideCommandQueue(Context context) {
-        return new CommandQueue(context);
+    public CommandQueue provideCommandQueue(Context context, ProtoTracer protoTracer) {
+        return new CommandQueue(context, protoTracer);
     }
 
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListEntry.java
index 56ad0e1..b048d03 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListEntry.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListEntry.java
@@ -44,10 +44,11 @@
 
     /**
      * Should return the "representative entry" for this ListEntry. For NotificationEntries, its
-     * the entry itself. For groups, it should be the summary. This method exists to interface with
+     * the entry itself. For groups, it should be the summary (but if a summary doesn't exist,
+     * this can return null). This method exists to interface with
      * legacy code that expects groups to also be NotificationEntries.
      */
-    public abstract NotificationEntry getRepresentativeEntry();
+    public abstract @Nullable NotificationEntry getRepresentativeEntry();
 
     @Nullable public GroupEntry getParent() {
         return mParent;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
index 86c0d85..92927cf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
@@ -44,7 +44,6 @@
 import android.service.notification.NotificationListenerService.RankingMap;
 import android.service.notification.StatusBarNotification;
 import android.util.ArrayMap;
-import android.util.Log;
 
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.systemui.DumpController;
@@ -56,6 +55,7 @@
 import com.android.systemui.statusbar.notification.collection.notifcollection.CollectionReadyForBuildListener;
 import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats;
 import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionLogger;
 import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender;
 import com.android.systemui.util.Assert;
 
@@ -100,6 +100,7 @@
 public class NotifCollection implements Dumpable {
     private final IStatusBarService mStatusBarService;
     private final FeatureFlags mFeatureFlags;
+    private final NotifCollectionLogger mLogger;
 
     private final Map<String, NotificationEntry> mNotificationSet = new ArrayMap<>();
     private final Collection<NotificationEntry> mReadOnlyNotificationSet =
@@ -116,9 +117,11 @@
     public NotifCollection(
             IStatusBarService statusBarService,
             DumpController dumpController,
-            FeatureFlags featureFlags) {
+            FeatureFlags featureFlags,
+            NotifCollectionLogger logger) {
         Assert.isMainThread();
         mStatusBarService = statusBarService;
+        mLogger = logger;
         dumpController.registerDumpable(TAG, this);
         mFeatureFlags = featureFlags;
     }
@@ -190,8 +193,8 @@
     private void onNotificationGroupPosted(List<CoalescedEvent> batch) {
         Assert.isMainThread();
 
-        Log.d(TAG, "POSTED GROUP " + batch.get(0).getSbn().getGroupKey()
-                + " (" + batch.size() + " events)");
+        mLogger.logNotifGroupPosted(batch.get(0).getSbn().getGroupKey(), batch.size());
+
         for (CoalescedEvent event : batch) {
             postNotification(event.getSbn(), event.getRanking(), null);
         }
@@ -204,7 +207,7 @@
             int reason) {
         Assert.isMainThread();
 
-        Log.d(TAG, "REMOVED " + sbn.getKey() + " reason=" + reason);
+        mLogger.logNotifRemoved(sbn.getKey(), reason);
         removeNotification(sbn.getKey(), rankingMap, reason, null);
     }
 
@@ -222,7 +225,7 @@
 
         if (entry == null) {
             // A new notification!
-            Log.d(TAG, "POSTED  " + sbn.getKey());
+            mLogger.logNotifPosted(sbn.getKey());
 
             entry = new NotificationEntry(sbn, ranking);
             mNotificationSet.put(sbn.getKey(), entry);
@@ -234,7 +237,7 @@
 
         } else {
             // Update to an existing entry
-            Log.d(TAG, "UPDATED " + sbn.getKey());
+            mLogger.logNotifUpdated(sbn.getKey());
 
             // Notification is updated so it is essentially re-added and thus alive again.  Don't
             // need to keep its lifetime extended.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java
index 97f8ec5..9f8f42e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java
@@ -32,19 +32,20 @@
 import android.util.ArrayMap;
 import android.util.Pair;
 
+import androidx.annotation.NonNull;
+
 import com.android.systemui.DumpController;
 import com.android.systemui.Dumpable;
 import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener;
 import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeSortListener;
 import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeTransformGroupsListener;
 import com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState;
+import com.android.systemui.statusbar.notification.collection.listbuilder.ShadeListBuilderLogger;
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifComparator;
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter;
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSection;
 import com.android.systemui.statusbar.notification.collection.notifcollection.CollectionReadyForBuildListener;
-import com.android.systemui.statusbar.notification.logging.NotifEvent;
-import com.android.systemui.statusbar.notification.logging.NotifLog;
 import com.android.systemui.util.Assert;
 import com.android.systemui.util.time.SystemClock;
 
@@ -69,7 +70,7 @@
 @Singleton
 public class ShadeListBuilder implements Dumpable {
     private final SystemClock mSystemClock;
-    private final NotifLog mNotifLog;
+    private final ShadeListBuilderLogger mLogger;
 
     private List<ListEntry> mNotifList = new ArrayList<>();
     private List<ListEntry> mNewNotifList = new ArrayList<>();
@@ -98,11 +99,11 @@
     @Inject
     public ShadeListBuilder(
             SystemClock systemClock,
-            NotifLog notifLog,
+            ShadeListBuilderLogger logger,
             DumpController dumpController) {
         Assert.isMainThread();
         mSystemClock = systemClock;
-        mNotifLog = notifLog;
+        mLogger = logger;
         dumpController.registerDumpable(TAG, this);
     }
 
@@ -205,8 +206,7 @@
                     Assert.isMainThread();
                     mPipelineState.requireIsBefore(STATE_BUILD_STARTED);
 
-                    mNotifLog.log(NotifEvent.ON_BUILD_LIST, "Request received from "
-                            + "NotifCollection");
+                    mLogger.logOnBuildList();
                     mAllEntries = entries;
                     buildList();
                 }
@@ -215,21 +215,15 @@
     private void onPreGroupFilterInvalidated(NotifFilter filter) {
         Assert.isMainThread();
 
-        mNotifLog.log(NotifEvent.PRE_GROUP_FILTER_INVALIDATED, String.format(
-                "Filter \"%s\" invalidated; pipeline state is %d",
-                filter.getName(),
-                mPipelineState.getState()));
+        mLogger.logPreGroupFilterInvalidated(filter.getName(), mPipelineState.getState());
 
         rebuildListIfBefore(STATE_PRE_GROUP_FILTERING);
     }
 
-    private void onPromoterInvalidated(NotifPromoter filter) {
+    private void onPromoterInvalidated(NotifPromoter promoter) {
         Assert.isMainThread();
 
-        mNotifLog.log(NotifEvent.PROMOTER_INVALIDATED, String.format(
-                "NotifPromoter \"%s\" invalidated; pipeline state is %d",
-                filter.getName(),
-                mPipelineState.getState()));
+        mLogger.logPromoterInvalidated(promoter.getName(), mPipelineState.getState());
 
         rebuildListIfBefore(STATE_TRANSFORMING);
     }
@@ -237,10 +231,7 @@
     private void onNotifSectionInvalidated(NotifSection section) {
         Assert.isMainThread();
 
-        mNotifLog.log(NotifEvent.SECTION_INVALIDATED, String.format(
-                "Section \"%s\" invalidated; pipeline state is %d",
-                section.getName(),
-                mPipelineState.getState()));
+        mLogger.logNotifSectionInvalidated(section.getName(), mPipelineState.getState());
 
         rebuildListIfBefore(STATE_SORTING);
     }
@@ -248,10 +239,7 @@
     private void onPreRenderFilterInvalidated(NotifFilter filter) {
         Assert.isMainThread();
 
-        mNotifLog.log(NotifEvent.PRE_RENDER_FILTER_INVALIDATED, String.format(
-                "Filter \"%s\" invalidated; pipeline state is %d",
-                filter.getName(),
-                mPipelineState.getState()));
+        mLogger.logPreRenderFilterInvalidated(filter.getName(), mPipelineState.getState());
 
         rebuildListIfBefore(STATE_PRE_RENDER_FILTERING);
     }
@@ -259,10 +247,7 @@
     private void onNotifComparatorInvalidated(NotifComparator comparator) {
         Assert.isMainThread();
 
-        mNotifLog.log(NotifEvent.COMPARATOR_INVALIDATED, String.format(
-                "Comparator \"%s\" invalidated; pipeline state is %d",
-                comparator.getName(),
-                mPipelineState.getState()));
+        mLogger.logNotifComparatorInvalidated(comparator.getName(), mPipelineState.getState());
 
         rebuildListIfBefore(STATE_SORTING);
     }
@@ -288,7 +273,7 @@
      * if we detect that behavior, we should crash instantly.
      */
     private void buildList() {
-        mNotifLog.log(NotifEvent.START_BUILD_LIST, "Run #" + mIterationCount + "...");
+        mLogger.logStartBuildList(mIterationCount);
 
         mPipelineState.requireIsBefore(STATE_BUILD_STARTED);
         mPipelineState.setState(STATE_BUILD_STARTED);
@@ -334,16 +319,16 @@
         freeEmptyGroups();
 
         // Step 6: Dispatch the new list, first to any listeners and then to the view layer
-        mNotifLog.log(NotifEvent.DISPATCH_FINAL_LIST, "List finalized, is:\n"
-                + ListDumper.dumpTree(mNotifList, false, "\t\t"));
+        if (mIterationCount % 10 == 0) {
+            mLogger.logFinalList(mNotifList);
+        }
         dispatchOnBeforeRenderList(mReadOnlyNotifList);
         if (mOnRenderListListener != null) {
             mOnRenderListListener.onRenderList(mReadOnlyNotifList);
         }
 
         // Step 7: We're done!
-        mNotifLog.log(NotifEvent.LIST_BUILD_COMPLETE,
-                "Notif list build #" + mIterationCount + " completed");
+        mLogger.logEndBuildList(mIterationCount);
         mPipelineState.setState(STATE_IDLE);
         mIterationCount++;
     }
@@ -429,11 +414,10 @@
                     if (existingSummary == null) {
                         group.setSummary(entry);
                     } else {
-                        mNotifLog.log(NotifEvent.WARN, String.format(
-                                "Duplicate summary for group '%s': '%s' vs. '%s'",
+                        mLogger.logDuplicateSummary(
                                 group.getKey(),
                                 existingSummary.getKey(),
-                                entry.getKey()));
+                                entry.getKey());
 
                         // Use whichever one was posted most recently
                         if (entry.getSbn().getPostTime()
@@ -452,8 +436,7 @@
 
                 final String topLevelKey = entry.getKey();
                 if (mGroups.containsKey(topLevelKey)) {
-                    mNotifLog.log(NotifEvent.WARN,
-                            "Duplicate non-group top-level key: " + topLevelKey);
+                    mLogger.logDuplicateTopLevelKey(topLevelKey);
                 } else {
                     entry.setParent(ROOT_ENTRY);
                     out.add(entry);
@@ -617,24 +600,22 @@
     private void logParentingChanges() {
         for (NotificationEntry entry : mAllEntries) {
             if (entry.getParent() != entry.getPreviousParent()) {
-                mNotifLog.log(NotifEvent.PARENT_CHANGED, String.format(
-                        "%s: parent changed from %s to %s",
+                mLogger.logParentChanged(
                         entry.getKey(),
                         entry.getPreviousParent() == null
-                                ? "null" : entry.getPreviousParent().getKey(),
+                                ? null : entry.getPreviousParent().getKey(),
                         entry.getParent() == null
-                                ? "null" : entry.getParent().getKey()));
+                                ? null : entry.getParent().getKey());
             }
         }
         for (GroupEntry group : mGroups.values()) {
             if (group.getParent() != group.getPreviousParent()) {
-                mNotifLog.log(NotifEvent.PARENT_CHANGED, String.format(
-                        "%s: parent changed from %s to %s",
+                mLogger.logParentChanged(
                         group.getKey(),
                         group.getPreviousParent() == null
-                                ? "null" : group.getPreviousParent().getKey(),
+                                ? null : group.getPreviousParent().getKey(),
                         group.getParent() == null
-                                ? "null" : group.getParent().getKey()));
+                                ? null : group.getParent().getKey());
             }
         }
     }
@@ -684,23 +665,10 @@
         NotifFilter filter = findRejectingFilter(entry, now, filters);
 
         if (filter != entry.mExcludingFilter) {
-            if (entry.mExcludingFilter == null) {
-                mNotifLog.log(NotifEvent.FILTER_CHANGED, String.format(
-                        "%s: filtered out by '%s'",
-                        entry.getKey(),
-                        filter.getName()));
-            } else if (filter == null) {
-                mNotifLog.log(NotifEvent.FILTER_CHANGED, String.format(
-                        "%s: no longer filtered out (previous filter was '%s')",
-                        entry.getKey(),
-                        entry.mExcludingFilter.getName()));
-            } else {
-                mNotifLog.log(NotifEvent.FILTER_CHANGED, String.format(
-                        "%s: filter changed: '%s' -> '%s'",
-                        entry.getKey(),
-                        entry.mExcludingFilter,
-                        filter));
-            }
+            mLogger.logFilterChanged(
+                    entry.getKey(),
+                    entry.mExcludingFilter != null ? entry.mExcludingFilter.getName() : null,
+                    filter != null ? filter.getName() : null);
 
             // Note that groups and summaries can also be filtered out later if they're part of a
             // malformed group. We currently don't have a great way to track that beyond parenting
@@ -728,23 +696,10 @@
         NotifPromoter promoter = findPromoter(entry);
 
         if (promoter != entry.mNotifPromoter) {
-            if (entry.mNotifPromoter == null) {
-                mNotifLog.log(NotifEvent.PROMOTER_CHANGED, String.format(
-                        "%s: Entry promoted to top level by '%s'",
-                        entry.getKey(),
-                        promoter.getName()));
-            } else if (promoter == null) {
-                mNotifLog.log(NotifEvent.PROMOTER_CHANGED, String.format(
-                        "%s: Entry is no longer promoted to top level (previous promoter was '%s')",
-                        entry.getKey(),
-                        entry.mNotifPromoter.getName()));
-            } else {
-                mNotifLog.log(NotifEvent.PROMOTER_CHANGED, String.format(
-                        "%s: Top-level promoter changed: '%s' -> '%s'",
-                        entry.getKey(),
-                        entry.mNotifPromoter,
-                        promoter));
-            }
+            mLogger.logPromoterChanged(
+                    entry.getKey(),
+                    entry.mNotifPromoter != null ? entry.mNotifPromoter.getName() : null,
+                    promoter != null ? promoter.getName() : null);
             entry.mNotifPromoter = promoter;
         }
 
@@ -767,21 +722,12 @@
         final Integer sectionIndex = sectionWithIndex.second;
 
         if (section != entry.mNotifSection) {
-            if (entry.mNotifSection == null) {
-                mNotifLog.log(NotifEvent.SECTION_CHANGED, String.format(
-                        "%s: sectioned by '%s' [index=%d].",
-                        entry.getKey(),
-                        section.getName(),
-                        sectionIndex));
-            } else {
-                mNotifLog.log(NotifEvent.SECTION_CHANGED, String.format(
-                        "%s: section changed: '%s' [index=%d] -> '%s [index=%d]'.",
-                        entry.getKey(),
-                        entry.mNotifSection,
-                        entry.getSection(),
-                        section,
-                        sectionIndex));
-            }
+            mLogger.logSectionChanged(
+                    entry.getKey(),
+                    entry.mNotifSection != null ? entry.mNotifSection.getName() : null,
+                    entry.getSection(),
+                    section.getName(),
+                    sectionIndex);
 
             entry.mNotifSection = section;
             entry.setSection(sectionIndex);
@@ -826,7 +772,7 @@
     }
 
     @Override
-    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+    public void dump(@NonNull FileDescriptor fd, PrintWriter pw, @NonNull String[] args) {
         pw.println("\t" + TAG + " shade notifications:");
         if (getShadeList().size() == 0) {
             pw.println("\t\t None");
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescer.java
index f589038..98c45ff 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescer.java
@@ -16,11 +16,6 @@
 
 package com.android.systemui.statusbar.notification.collection.coalescer;
 
-import static com.android.systemui.statusbar.notification.logging.NotifEvent.BATCH_MAX_TIMEOUT;
-import static com.android.systemui.statusbar.notification.logging.NotifEvent.COALESCED_EVENT;
-import static com.android.systemui.statusbar.notification.logging.NotifEvent.EARLY_BATCH_EMIT;
-import static com.android.systemui.statusbar.notification.logging.NotifEvent.EMIT_EVENT_BATCH;
-
 import static java.util.Objects.requireNonNull;
 
 import android.annotation.MainThread;
@@ -35,7 +30,6 @@
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.statusbar.NotificationListener;
 import com.android.systemui.statusbar.NotificationListener.NotificationHandler;
-import com.android.systemui.statusbar.notification.logging.NotifLog;
 import com.android.systemui.util.concurrency.DelayableExecutor;
 import com.android.systemui.util.time.SystemClock;
 
@@ -71,7 +65,7 @@
 public class GroupCoalescer implements Dumpable {
     private final DelayableExecutor mMainExecutor;
     private final SystemClock mClock;
-    private final NotifLog mLog;
+    private final GroupCoalescerLogger mLogger;
     private final long mMinGroupLingerDuration;
     private final long mMaxGroupLingerDuration;
 
@@ -83,8 +77,9 @@
     @Inject
     public GroupCoalescer(
             @Main DelayableExecutor mainExecutor,
-            SystemClock clock, NotifLog log) {
-        this(mainExecutor, clock, log, MIN_GROUP_LINGER_DURATION, MAX_GROUP_LINGER_DURATION);
+            SystemClock clock,
+            GroupCoalescerLogger logger) {
+        this(mainExecutor, clock, logger, MIN_GROUP_LINGER_DURATION, MAX_GROUP_LINGER_DURATION);
     }
 
     /**
@@ -98,12 +93,12 @@
     GroupCoalescer(
             @Main DelayableExecutor mainExecutor,
             SystemClock clock,
-            NotifLog log,
+            GroupCoalescerLogger logger,
             long minGroupLingerDuration,
             long maxGroupLingerDuration) {
         mMainExecutor = mainExecutor;
         mClock = clock;
-        mLog = log;
+        mLogger = logger;
         mMinGroupLingerDuration = minGroupLingerDuration;
         mMaxGroupLingerDuration = maxGroupLingerDuration;
     }
@@ -129,7 +124,7 @@
             final boolean shouldCoalesce = handleNotificationPosted(sbn, rankingMap);
 
             if (shouldCoalesce) {
-                mLog.log(COALESCED_EVENT, String.format("Coalesced notification %s", sbn.getKey()));
+                mLogger.logEventCoalesced(sbn.getKey());
                 mHandler.onNotificationRankingUpdate(rankingMap);
             } else {
                 mHandler.onNotificationPosted(sbn, rankingMap);
@@ -164,15 +159,11 @@
         final CoalescedEvent event = mCoalescedEvents.get(sbn.getKey());
         final EventBatch batch = mBatches.get(sbn.getGroupKey());
         if (event != null) {
-            mLog.log(EARLY_BATCH_EMIT,
-                    String.format("Modification of %s triggered early emit of batched group %s",
-                            sbn.getKey(), requireNonNull(event.getBatch()).mGroupKey));
+            mLogger.logEarlyEmit(sbn.getKey(), requireNonNull(event.getBatch()).mGroupKey);
             emitBatch(requireNonNull(event.getBatch()));
         } else if (batch != null
                 && mClock.uptimeMillis() - batch.mCreatedTimestamp >= mMaxGroupLingerDuration) {
-            mLog.log(BATCH_MAX_TIMEOUT,
-                    String.format("Modification of %s triggered timeout emit of batched group %s",
-                            sbn.getKey(), batch.mGroupKey));
+            mLogger.logMaxBatchTimeout(sbn.getKey(), batch.mGroupKey);
             emitBatch(batch);
         }
     }
@@ -253,7 +244,7 @@
         }
         events.sort(mEventComparator);
 
-        mLog.log(EMIT_EVENT_BATCH, "Emitting event batch for group " + batch.mGroupKey);
+        mLogger.logEmitBatch(batch.mGroupKey);
 
         mHandler.onNotificationBatchPosted(events);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescerLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescerLogger.kt
new file mode 100644
index 0000000..6e8788d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescerLogger.kt
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.collection.coalescer
+
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
+import com.android.systemui.log.dagger.NotificationLog
+import javax.inject.Inject
+
+class GroupCoalescerLogger @Inject constructor(
+    @NotificationLog private val buffer: LogBuffer
+) {
+    fun logEventCoalesced(key: String) {
+        buffer.log(TAG, LogLevel.INFO, {
+            str1 = key
+        }, {
+            "COALESCED: $str1"
+        })
+    }
+
+    fun logEmitBatch(groupKey: String) {
+        buffer.log(TAG, LogLevel.DEBUG, {
+            str1 = groupKey
+        }, {
+            "Emitting event batch for group $str1"
+        })
+    }
+
+    fun logEarlyEmit(modifiedKey: String, groupKey: String) {
+        buffer.log(TAG, LogLevel.DEBUG, {
+            str1 = modifiedKey
+            str2 = groupKey
+        }, {
+            "Modification of notif $str1 triggered early emit of batched group $str2"
+        })
+    }
+
+    fun logMaxBatchTimeout(modifiedKey: String, groupKey: String) {
+        buffer.log(TAG, LogLevel.INFO, {
+            str1 = modifiedKey
+            str2 = groupKey
+        }, {
+            "Modification of notif $str1 triggered TIMEOUT emit of batched group $str2"
+        })
+    }
+}
+
+private const val TAG = "GroupCoalescer"
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt
new file mode 100644
index 0000000..6e15043
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.collection.listbuilder
+
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel.DEBUG
+import com.android.systemui.log.LogLevel.INFO
+import com.android.systemui.log.LogLevel.WARNING
+import com.android.systemui.log.dagger.NotificationLog
+import com.android.systemui.statusbar.notification.collection.GroupEntry
+import com.android.systemui.statusbar.notification.collection.ListEntry
+import javax.inject.Inject
+
+class ShadeListBuilderLogger @Inject constructor(
+    @NotificationLog private val buffer: LogBuffer
+) {
+    fun logOnBuildList() {
+        buffer.log(TAG, INFO, {
+        }, {
+            "Request received from NotifCollection"
+        })
+    }
+
+    fun logStartBuildList(iterationCount: Int) {
+        buffer.log(TAG, INFO, {
+            int1 = iterationCount
+        }, {
+            "Starting to build shade list (run #$int1)"
+        })
+    }
+
+    fun logEndBuildList(iterationCount: Int) {
+        buffer.log(TAG, INFO, {
+            int1 = iterationCount
+        }, {
+            "Finished building shade list (run #$int1)"
+        })
+    }
+
+    fun logPreGroupFilterInvalidated(filterName: String, pipelineState: Int) {
+        buffer.log(TAG, DEBUG, {
+            str1 = filterName
+            int1 = pipelineState
+        }, {
+            """Pre-group NotifFilter "$str1" invalidated; pipeline state is $int1"""
+        })
+    }
+
+    fun logPromoterInvalidated(name: String, pipelineState: Int) {
+        buffer.log(TAG, DEBUG, {
+            str1 = name
+            int1 = pipelineState
+        }, {
+            """NotifPromoter "$str1" invalidated; pipeline state is $int1"""
+        })
+    }
+
+    fun logNotifSectionInvalidated(name: String, pipelineState: Int) {
+        buffer.log(TAG, DEBUG, {
+            str1 = name
+            int1 = pipelineState
+        }, {
+            """NotifSection "$str1" invalidated; pipeline state is $int1"""
+        })
+    }
+
+    fun logNotifComparatorInvalidated(name: String, pipelineState: Int) {
+        buffer.log(TAG, DEBUG, {
+            str1 = name
+            int1 = pipelineState
+        }, {
+            """NotifComparator "$str1" invalidated; pipeline state is $int1"""
+        })
+    }
+
+    fun logPreRenderFilterInvalidated(name: String, pipelineState: Int) {
+        buffer.log(TAG, DEBUG, {
+            str1 = name
+            int1 = pipelineState
+        }, {
+            """Pre-render NotifFilter "$str1" invalidated; pipeline state is $int1"""
+        })
+    }
+
+    fun logDuplicateSummary(groupKey: String, existingKey: String, newKey: String) {
+        buffer.log(TAG, WARNING, {
+            str1 = groupKey
+            str2 = existingKey
+            str3 = newKey
+        }, {
+            """Duplicate summary for group "$str1": "$str2" vs. "$str3""""
+        })
+    }
+
+    fun logDuplicateTopLevelKey(topLevelKey: String) {
+        buffer.log(TAG, WARNING, {
+            str1 = topLevelKey
+        }, {
+            "Duplicate top-level key: $str1"
+        })
+    }
+
+    fun logParentChanged(key: String, prevParent: String?, newParent: String?) {
+        buffer.log(TAG, INFO, {
+            str1 = key
+            str2 = prevParent
+            str3 = newParent
+        }, {
+            "Parent change for $str1: $str2 -> $str3"
+        })
+    }
+
+    fun logFilterChanged(
+        key: String,
+        prevFilter: String?,
+        newFilter: String?
+    ) {
+        buffer.log(TAG, INFO, {
+            str1 = key
+            str2 = prevFilter
+            str3 = newFilter
+        }, {
+            "Filter changed for $str1: $str2 -> $str3"
+        })
+    }
+
+    fun logPromoterChanged(
+        key: String,
+        prevPromoter: String?,
+        newPromoter: String?
+    ) {
+        buffer.log(TAG, INFO, {
+            str1 = key
+            str2 = prevPromoter
+            str3 = newPromoter
+        }, {
+            "Promoter changed for $str1: $str2 -> $str3"
+        })
+    }
+
+    fun logSectionChanged(
+        key: String,
+        prevSection: String?,
+        prevIndex: Int,
+        section: String,
+        index: Int
+    ) {
+        buffer.log(TAG, INFO, {
+            str1 = key
+            str2 = section
+            int1 = index
+            str3 = prevSection
+            int2 = prevIndex
+        }, {
+            if (str3 == null) {
+                "Section assigned for $str1: '$str2' (#$int1)"
+            } else {
+                "Section changed for $str1: '$str3' (#$int2) -> '$str2' (#$int1)"
+            }
+        })
+    }
+
+    fun logFinalList(entries: List<ListEntry>) {
+        buffer.log(TAG, DEBUG, {
+            int1 = entries.size
+        }, {
+            "List is finalized ($int1 top-level entries):"
+        })
+        if (entries.isEmpty()) {
+            buffer.log(TAG, DEBUG, {}, { "(empty list)" })
+        }
+        for (i in entries.indices) {
+            val entry = entries[i]
+            buffer.log(TAG, DEBUG, {
+                int1 = i
+                str1 = entry.key
+            }, {
+                "[$int1] $str1"
+            })
+
+            if (entry is GroupEntry) {
+                entry.summary?.let {
+                    buffer.log(TAG, DEBUG, {
+                        str1 = it.key
+                    }, {
+                        "  [*] $str1 (summary)"
+                    })
+                }
+                for (j in entry.children.indices) {
+                    val child = entry.children[j]
+                    buffer.log(TAG, DEBUG, {
+                        int1 = j
+                        str1 = child.key
+                    }, {
+                        "  [$int1] $str1"
+                    })
+                }
+            }
+        }
+    }
+}
+
+private const val TAG = "ShadeListBuilder"
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLogger.kt
new file mode 100644
index 0000000..bd1bd86
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLogger.kt
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.collection.notifcollection
+
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
+import com.android.systemui.log.dagger.NotificationLog
+import javax.inject.Inject
+
+class NotifCollectionLogger @Inject constructor(
+    @NotificationLog private val buffer: LogBuffer
+) {
+    fun logNotifPosted(key: String) {
+        buffer.log(TAG, LogLevel.INFO, {
+            str1 = key
+        }, {
+            "POSTED $str1"
+        })
+    }
+
+    fun logNotifGroupPosted(groupKey: String, batchSize: Int) {
+        buffer.log(TAG, LogLevel.INFO, {
+            str1 = groupKey
+            int1 = batchSize
+        }, {
+            "POSTED GROUP $str1 ($int1 events)"
+        })
+    }
+
+    fun logNotifUpdated(key: String) {
+        buffer.log(TAG, LogLevel.INFO, {
+            str1 = key
+        }, {
+            "UPDATED $str1"
+        })
+    }
+
+    fun logNotifRemoved(key: String, reason: Int) {
+        buffer.log(TAG, LogLevel.INFO, {
+            str1 = key
+            int1 = reason
+        }, {
+            "REMOVED $str1 reason=$int1"
+        })
+    }
+}
+
+private const val TAG = "NotifCollection"
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java
index b496116..0d9beae 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java
@@ -63,6 +63,10 @@
         }
 
         final NotificationEntry notifEntry = entry.getRepresentativeEntry();
+        if (notifEntry == null) {
+            return false;
+        }
+
         return notifEntry.getRanking().getImportance() >= NotificationManager.IMPORTANCE_DEFAULT
                 || hasHighPriorityCharacteristics(notifEntry)
                 || hasHighPriorityChild(entry);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java
index 18c755d..6045524 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java
@@ -29,6 +29,7 @@
 import static com.android.systemui.statusbar.notification.row.NotificationConversationInfo.UpdateChannelRunnable.ACTION_HOME;
 import static com.android.systemui.statusbar.notification.row.NotificationConversationInfo.UpdateChannelRunnable.ACTION_MUTE;
 import static com.android.systemui.statusbar.notification.row.NotificationConversationInfo.UpdateChannelRunnable.ACTION_SNOOZE;
+import static com.android.systemui.statusbar.notification.row.NotificationConversationInfo.UpdateChannelRunnable.ACTION_UNBUBBLE;
 
 import static java.lang.annotation.RetentionPolicy.SOURCE;
 
@@ -121,7 +122,7 @@
     boolean mSkipPost = false;
 
     private OnClickListener mOnBubbleClick = v -> {
-        mSelectedAction = ACTION_BUBBLE;
+        mSelectedAction = mStartedAsBubble ? ACTION_UNBUBBLE : ACTION_BUBBLE;
         if (mStartedAsBubble) {
             mBubbleController.onUserDemotedBubbleFromNotification(mEntry);
         } else {
@@ -586,6 +587,7 @@
         static final int ACTION_SNOOZE = 3;
         static final int ACTION_MUTE = 4;
         static final int ACTION_DEMOTE = 5;
+        static final int ACTION_UNBUBBLE = 6;
 
         private final INotificationManager mINotificationManager;
         private final String mAppPkg;
@@ -606,9 +608,17 @@
         @Override
         public void run() {
             try {
+                boolean channelSettingChanged = mAction != ACTION_HOME && mAction != ACTION_SNOOZE;
                 switch (mAction) {
                     case ACTION_BUBBLE:
-                        mChannelToUpdate.setAllowBubbles(!mChannelToUpdate.canBubble());
+                    case ACTION_UNBUBBLE:
+                        boolean canBubble = mAction == ACTION_BUBBLE;
+                        if (mChannelToUpdate.canBubble() != canBubble) {
+                            channelSettingChanged = true;
+                            mChannelToUpdate.setAllowBubbles(canBubble);
+                        } else {
+                            channelSettingChanged = false;
+                        }
                         break;
                     case ACTION_FAVORITE:
                         // TODO: extend beyond DND
@@ -629,7 +639,7 @@
 
                 }
 
-                if (mAction != ACTION_HOME && mAction != ACTION_SNOOZE) {
+                if (channelSettingChanged) {
                     mINotificationManager.updateNotificationChannelForPackage(
                             mAppPkg, mAppUid, mChannelToUpdate);
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
index 6bd122d..db692c8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
@@ -54,6 +54,10 @@
 import com.android.systemui.shared.plugins.PluginManager;
 import com.android.systemui.shared.system.QuickStepContract;
 import com.android.systemui.shared.system.SysUiStatsLog;
+import com.android.systemui.shared.tracing.ProtoTraceable;
+import com.android.systemui.tracing.ProtoTracer;
+import com.android.systemui.tracing.nano.EdgeBackGestureHandlerProto;
+import com.android.systemui.tracing.nano.SystemUiTraceProto;
 
 import java.io.PrintWriter;
 import java.util.concurrent.Executor;
@@ -62,7 +66,7 @@
  * Utility class to handle edge swipes for back gesture
  */
 public class EdgeBackGestureHandler implements DisplayListener,
-        PluginListener<NavigationEdgeBackPlugin> {
+        PluginListener<NavigationEdgeBackPlugin>, ProtoTraceable<SystemUiTraceProto> {
 
     private static final String TAG = "EdgeBackGestureHandler";
     private static final int MAX_LONG_PRESS_TIMEOUT = SystemProperties.getInt(
@@ -161,6 +165,7 @@
         mMainExecutor = context.getMainExecutor();
         mOverviewProxyService = overviewProxyService;
         mPluginManager = pluginManager;
+        Dependency.get(ProtoTracer.class).add(this);
 
         // Reduce the default touch slop to ensure that we can intercept the gesture
         // before the app starts to react to it.
@@ -399,6 +404,8 @@
             // forward touch
             mEdgeBackPlugin.onMotionEvent(ev);
         }
+
+        Dependency.get(ProtoTracer.class).update();
     }
 
     @Override
@@ -458,6 +465,14 @@
         pw.println("  mEdgeWidth=" + mEdgeWidth);
     }
 
+    @Override
+    public void writeToProto(SystemUiTraceProto proto) {
+        if (proto.edgeBackGestureHandler == null) {
+            proto.edgeBackGestureHandler = new EdgeBackGestureHandlerProto();
+        }
+        proto.edgeBackGestureHandler.allowGesture = mAllowGesture;
+    }
+
     class SysUiInputEventReceiver extends InputEventReceiver {
         SysUiInputEventReceiver(InputChannel channel, Looper looper) {
             super(channel, looper);
diff --git a/packages/SystemUI/src/com/android/systemui/tracing/ProtoTracer.java b/packages/SystemUI/src/com/android/systemui/tracing/ProtoTracer.java
new file mode 100644
index 0000000..3bef044
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/tracing/ProtoTracer.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.tracing;
+
+import static com.android.systemui.tracing.nano.SystemUiTraceFileProto.MAGIC_NUMBER_H;
+import static com.android.systemui.tracing.nano.SystemUiTraceFileProto.MAGIC_NUMBER_L;
+
+import android.content.Context;
+import android.os.SystemClock;
+
+import androidx.annotation.NonNull;
+
+import com.android.systemui.DumpController;
+import com.android.systemui.Dumpable;
+import com.android.systemui.shared.tracing.FrameProtoTracer;
+import com.android.systemui.shared.tracing.FrameProtoTracer.ProtoTraceParams;
+import com.android.systemui.shared.tracing.ProtoTraceable;
+import com.android.systemui.tracing.nano.SystemUiTraceProto;
+import com.android.systemui.tracing.nano.SystemUiTraceEntryProto;
+import com.android.systemui.tracing.nano.SystemUiTraceFileProto;
+
+import com.google.protobuf.nano.MessageNano;
+
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Queue;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * Controller for coordinating winscope proto tracing.
+ */
+@Singleton
+public class ProtoTracer implements Dumpable, ProtoTraceParams<MessageNano, SystemUiTraceFileProto,
+        SystemUiTraceEntryProto, SystemUiTraceProto> {
+
+    private static final String TAG = "ProtoTracer";
+    private static final long MAGIC_NUMBER_VALUE = ((long) MAGIC_NUMBER_H << 32) | MAGIC_NUMBER_L;
+
+    private final Context mContext;
+    private final FrameProtoTracer<MessageNano, SystemUiTraceFileProto, SystemUiTraceEntryProto,
+            SystemUiTraceProto> mProtoTracer;
+
+    @Inject
+    public ProtoTracer(Context context, DumpController dumpController) {
+        mContext = context;
+        mProtoTracer = new FrameProtoTracer<>(this);
+        dumpController.registerDumpable(this);
+    }
+
+    @Override
+    public File getTraceFile() {
+        return new File(mContext.getFilesDir(), "sysui_trace.pb");
+    }
+
+    @Override
+    public SystemUiTraceFileProto getEncapsulatingTraceProto() {
+        return new SystemUiTraceFileProto();
+    }
+
+    @Override
+    public SystemUiTraceEntryProto updateBufferProto(SystemUiTraceEntryProto reuseObj,
+            ArrayList<ProtoTraceable<SystemUiTraceProto>> traceables) {
+        SystemUiTraceEntryProto proto = reuseObj != null
+                ? reuseObj
+                : new SystemUiTraceEntryProto();
+        proto.elapsedRealtimeNanos = SystemClock.elapsedRealtimeNanos();
+        proto.systemUi = proto.systemUi != null ? proto.systemUi : new SystemUiTraceProto();
+        for (ProtoTraceable t : traceables) {
+            t.writeToProto(proto.systemUi);
+        }
+        return proto;
+    }
+
+    @Override
+    public byte[] serializeEncapsulatingProto(SystemUiTraceFileProto encapsulatingProto,
+            Queue<SystemUiTraceEntryProto> buffer) {
+        encapsulatingProto.magicNumber = MAGIC_NUMBER_VALUE;
+        encapsulatingProto.entry = buffer.toArray(new SystemUiTraceEntryProto[0]);
+        return MessageNano.toByteArray(encapsulatingProto);
+    }
+
+    @Override
+    public byte[] getProtoBytes(MessageNano proto) {
+        return MessageNano.toByteArray(proto);
+    }
+
+    @Override
+    public int getProtoSize(MessageNano proto) {
+        return proto.getCachedSize();
+    }
+
+    public void start() {
+        mProtoTracer.start();
+    }
+
+    public void stop() {
+        mProtoTracer.stop();
+    }
+
+    public boolean isEnabled() {
+        return mProtoTracer.isEnabled();
+    }
+
+    public void add(ProtoTraceable<SystemUiTraceProto> traceable) {
+        mProtoTracer.add(traceable);
+    }
+
+    public void remove(ProtoTraceable<SystemUiTraceProto> traceable) {
+        mProtoTracer.remove(traceable);
+    }
+
+    public void scheduleFrameUpdate() {
+        mProtoTracer.scheduleFrameUpdate();
+    }
+
+    public void update() {
+        mProtoTracer.update();
+    }
+
+    @Override
+    public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) {
+        pw.println("ProtoTracer:");
+        pw.print("    "); pw.println("enabled: " + mProtoTracer.isEnabled());
+        pw.print("    "); pw.println("usagePct: " + mProtoTracer.getBufferUsagePct());
+        pw.print("    "); pw.println("file: " + getTraceFile());
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/tracing/sysui_trace.proto b/packages/SystemUI/src/com/android/systemui/tracing/sysui_trace.proto
new file mode 100644
index 0000000..08ae99c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/tracing/sysui_trace.proto
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+
+package com.android.systemui.tracing;
+
+option java_multiple_files = true;
+
+message SystemUiTraceProto {
+
+    optional EdgeBackGestureHandlerProto edge_back_gesture_handler = 1;
+}
+
+message EdgeBackGestureHandlerProto {
+
+    optional bool allow_gesture = 1;
+}
diff --git a/packages/SystemUI/src/com/android/systemui/tracing/sysui_trace_file.proto b/packages/SystemUI/src/com/android/systemui/tracing/sysui_trace_file.proto
new file mode 100644
index 0000000..d1523ef
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/tracing/sysui_trace_file.proto
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+
+import "frameworks/base/packages/SystemUI/src/com/android/systemui/tracing/sysui_trace.proto";
+
+package com.android.systemui.tracing;
+
+option java_multiple_files = true;
+
+/* represents a file full of system ui trace entries.
+   Encoded, it should start with 0x9 0x53 0x59 0x53 0x55 0x49 0x54 0x52 0x43 (.SYSUITRC), such
+   that they can be easily identified. */
+message SystemUiTraceFileProto {
+
+    /* constant; MAGIC_NUMBER = (long) MAGIC_NUMBER_H << 32 | MagicNumber.MAGIC_NUMBER_L
+       (this is needed because enums have to be 32 bits and there's no nice way to put 64bit
+        constants into .proto files. */
+    enum MagicNumber {
+        INVALID = 0;
+        MAGIC_NUMBER_L = 0x55535953;  /* SYSU (little-endian ASCII) */
+        MAGIC_NUMBER_H = 0x43525449;  /* ITRC (little-endian ASCII) */
+    }
+
+    optional fixed64 magic_number = 1;  /* Must be the first field, set to value in MagicNumber */
+    repeated SystemUiTraceEntryProto entry = 2;
+}
+
+/* one system ui trace entry. */
+message SystemUiTraceEntryProto {
+    /* required: elapsed realtime in nanos since boot of when this entry was logged */
+    optional fixed64 elapsed_realtime_nanos = 1;
+
+    optional SystemUiTraceProto system_ui = 3;
+}
diff --git a/packages/SystemUI/src/com/android/systemui/wm/SystemWindows.java b/packages/SystemUI/src/com/android/systemui/wm/SystemWindows.java
index 5aba013..adce124 100644
--- a/packages/SystemUI/src/com/android/systemui/wm/SystemWindows.java
+++ b/packages/SystemUI/src/com/android/systemui/wm/SystemWindows.java
@@ -239,12 +239,12 @@
                 Rect outVisibleInsets, Rect outStableInsets,
                 DisplayCutout.ParcelableWrapper cutout, MergedConfiguration mergedConfiguration,
                 SurfaceControl outSurfaceControl, InsetsState outInsetsState,
-                Point outSurfaceSize) {
+                Point outSurfaceSize, SurfaceControl outBLASTSurfaceControl) {
             int res = super.relayout(window, seq, attrs, requestedWidth, requestedHeight,
                     viewVisibility, flags, frameNumber, outFrame, outOverscanInsets,
                     outContentInsets, outVisibleInsets, outStableInsets,
                     cutout, mergedConfiguration, outSurfaceControl, outInsetsState,
-                    outSurfaceSize);
+                    outSurfaceSize, outBLASTSurfaceControl);
             if (res != 0) {
                 return res;
             }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
index 2c9058a..28f01da 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
@@ -282,7 +282,7 @@
                 mRow.getEntry().getKey()));
 
         // Make it look like dismissed notif
-        mBubbleData.getBubbleWithKey(mRow.getEntry().getKey()).setShowInShade(false);
+        mBubbleData.getBubbleWithKey(mRow.getEntry().getKey()).setSuppressNotification(true);
 
         // Now remove the bubble
         mBubbleController.removeBubble(
@@ -372,7 +372,8 @@
 
         // Switch which bubble is expanded
         mBubbleController.selectBubble(mRow.getEntry().getKey());
-        mBubbleController.expandStack();
+        mBubbleData.setExpanded(true);
+        assertEquals(mRow.getEntry(), stackView.getExpandedBubble().getEntry());
         assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
                 mRow.getEntry().getKey()));
 
@@ -571,7 +572,6 @@
         verify(mBubbleStateChangeListener).onHasBubblesChanged(true /* hasBubbles */);
     }
 
-
     @Test
     public void testExpandStackAndSelectBubble_removedFirst() {
         final String key = mRow.getEntry().getKey();
@@ -724,6 +724,52 @@
         assertFalse(intercepted);
     }
 
+    @Test
+    public void testNotifyShadeSuppressionChange_notificationDismiss() {
+        BubbleController.NotificationSuppressionChangedListener listener =
+                mock(BubbleController.NotificationSuppressionChangedListener.class);
+        mBubbleData.setSuppressionChangedListener(listener);
+
+        mEntryListener.onNotificationAdded(mRow.getEntry());
+
+        assertTrue(mBubbleController.hasBubbles());
+        assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
+                mRow.getEntry().getKey()));
+
+        mRemoveInterceptor.onNotificationRemoveRequested(mRow.getEntry().getKey(), REASON_CANCEL);
+
+        // Should update show in shade state
+        assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
+                mRow.getEntry().getKey()));
+
+        // Should notify delegate that shade state changed
+        verify(listener).onBubbleNotificationSuppressionChange(
+                mBubbleData.getBubbleWithKey(mRow.getEntry().getKey()));
+    }
+
+    @Test
+    public void testNotifyShadeSuppressionChange_bubbleExpanded() {
+        BubbleController.NotificationSuppressionChangedListener listener =
+                mock(BubbleController.NotificationSuppressionChangedListener.class);
+        mBubbleData.setSuppressionChangedListener(listener);
+
+        mEntryListener.onNotificationAdded(mRow.getEntry());
+
+        assertTrue(mBubbleController.hasBubbles());
+        assertFalse(mBubbleController.isBubbleNotificationSuppressedFromShade(
+                mRow.getEntry().getKey()));
+
+        mBubbleData.setExpanded(true);
+
+        // Once a bubble is expanded the notif is suppressed
+        assertTrue(mBubbleController.isBubbleNotificationSuppressedFromShade(
+                mRow.getEntry().getKey()));
+
+        // Should notify delegate that shade state changed
+        verify(listener).onBubbleNotificationSuppressionChange(
+                mBubbleData.getBubbleWithKey(mRow.getEntry().getKey()));
+    }
+
     static class TestableBubbleController extends BubbleController {
         // Let's assume surfaces can be synchronized immediately.
         TestableBubbleController(Context context,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java
index 1a2e237..c9f5b40 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java
@@ -104,6 +104,9 @@
     @Captor
     private ArgumentCaptor<BubbleData.Update> mUpdateCaptor;
 
+    @Mock
+    private BubbleController.NotificationSuppressionChangedListener mSuppressionListener;
+
     @Before
     public void setUp() throws Exception {
         mNotificationTestHelper = new NotificationTestHelper(mContext, mDependency);
@@ -121,20 +124,20 @@
         modifyRanking(mEntryInterruptive)
                 .setVisuallyInterruptive(true)
                 .build();
-        mBubbleInterruptive = new Bubble(mEntryInterruptive);
+        mBubbleInterruptive = new Bubble(mEntryInterruptive, mSuppressionListener);
 
         ExpandableNotificationRow row = mNotificationTestHelper.createBubble();
         mEntryDismissed = createBubbleEntry(1, "dismissed", "package.d");
         mEntryDismissed.setRow(row);
-        mBubbleDismissed = new Bubble(mEntryDismissed);
+        mBubbleDismissed = new Bubble(mEntryDismissed, mSuppressionListener);
 
-        mBubbleA1 = new Bubble(mEntryA1);
-        mBubbleA2 = new Bubble(mEntryA2);
-        mBubbleA3 = new Bubble(mEntryA3);
-        mBubbleB1 = new Bubble(mEntryB1);
-        mBubbleB2 = new Bubble(mEntryB2);
-        mBubbleB3 = new Bubble(mEntryB3);
-        mBubbleC1 = new Bubble(mEntryC1);
+        mBubbleA1 = new Bubble(mEntryA1, mSuppressionListener);
+        mBubbleA2 = new Bubble(mEntryA2, mSuppressionListener);
+        mBubbleA3 = new Bubble(mEntryA3, mSuppressionListener);
+        mBubbleB1 = new Bubble(mEntryB1, mSuppressionListener);
+        mBubbleB2 = new Bubble(mEntryB2, mSuppressionListener);
+        mBubbleB3 = new Bubble(mEntryB3, mSuppressionListener);
+        mBubbleC1 = new Bubble(mEntryC1, mSuppressionListener);
 
         mBubbleData = new BubbleData(getContext());
 
@@ -237,9 +240,8 @@
                 true /* showInShade */);
         verifyUpdateReceived();
 
-        // Make it look like user swiped away row
-        mEntryDismissed.getRow().dismiss(false /* refocusOnDismiss */);
-        assertThat(mBubbleData.getBubbleWithKey(mBubbleDismissed.getKey()).showInShade()).isFalse();
+        // Suppress the notif / make it look dismissed
+        mBubbleDismissed.setSuppressNotification(true);
 
         mBubbleData.notificationEntryUpdated(mBubbleDismissed, false /* suppressFlyout */,
                 true /* showInShade */);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleTest.java
index 02f721c..7f67657 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleTest.java
@@ -16,11 +16,19 @@
 
 package com.android.systemui.bubbles;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
 
 import android.app.Notification;
+import android.app.PendingIntent;
+import android.content.Intent;
+import android.graphics.drawable.Icon;
 import android.os.Bundle;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
@@ -30,6 +38,7 @@
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
+import com.android.systemui.tests.R;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -46,6 +55,10 @@
 
     private NotificationEntry mEntry;
     private Bundle mExtras;
+    private Bubble mBubble;
+
+    @Mock
+    private BubbleController.NotificationSuppressionChangedListener mSuppressionListener;
 
     @Before
     public void setUp() {
@@ -57,6 +70,15 @@
         mEntry = new NotificationEntryBuilder()
                 .setNotification(mNotif)
                 .build();
+
+        mBubble = new Bubble(mEntry, mSuppressionListener);
+
+        Intent target = new Intent(mContext, BubblesTestActivity.class);
+        Notification.BubbleMetadata metadata = new Notification.BubbleMetadata.Builder()
+                .createIntentBubble(PendingIntent.getActivity(mContext, 0, target, 0),
+                        Icon.createWithResource(mContext, R.drawable.android))
+                .build();
+        mEntry.setBubbleMetadata(metadata);
     }
 
     @Test
@@ -123,4 +145,24 @@
                 BubbleViewInfoTask.extractFlyoutMessage(mContext,
                         mEntry).senderName);
     }
+
+    @Test
+    public void testSuppressionListener_change_notified() {
+        assertThat(mBubble.showInShade()).isTrue();
+
+        mBubble.setSuppressNotification(true);
+
+        assertThat(mBubble.showInShade()).isFalse();
+
+        verify(mSuppressionListener).onBubbleNotificationSuppressionChange(mBubble);
+    }
+
+    @Test
+    public void testSuppressionListener_noChange_doesntNotify() {
+        assertThat(mBubble.showInShade()).isTrue();
+
+        mBubble.setSuppressNotification(false);
+
+        verify(mSuppressionListener, never()).onBubbleNotificationSuppressionChange(any());
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/pip/PipBoundsHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/pip/PipBoundsHandlerTest.java
new file mode 100644
index 0000000..bc3ce8b
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/pip/PipBoundsHandlerTest.java
@@ -0,0 +1,240 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.pip;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.isNull;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.verify;
+
+import android.content.ComponentName;
+import android.graphics.Rect;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.testing.TestableResources;
+import android.view.DisplayInfo;
+import android.view.Gravity;
+import android.view.IPinnedStackController;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * Unit tests against {@link PipBoundsHandler}, including but not limited to:
+ * - default/movement bounds
+ * - save/restore PiP position on application lifecycle
+ * - save/restore PiP position on screen rotation
+ */
+@RunWith(AndroidTestingRunner.class)
+@SmallTest
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+public class PipBoundsHandlerTest extends SysuiTestCase {
+    private static final int ROUNDING_ERROR_MARGIN = 10;
+
+    private PipBoundsHandler mPipBoundsHandler;
+    private DisplayInfo mDefaultDisplayInfo;
+    private Rect mDefaultDisplayRect;
+
+    @Mock
+    private IPinnedStackController mPinnedStackController;
+
+    @Before
+    public void setUp() throws Exception {
+        mPipBoundsHandler = new PipBoundsHandler(mContext);
+        MockitoAnnotations.initMocks(this);
+        initializeMockResources();
+
+        mPipBoundsHandler.onDisplayInfoChanged(mDefaultDisplayInfo);
+        mPipBoundsHandler.setPinnedStackController(mPinnedStackController);
+    }
+
+    private void initializeMockResources() {
+        final TestableResources res = mContext.getOrCreateTestableResources();
+        res.addOverride(
+                com.android.internal.R.dimen.config_pictureInPictureDefaultAspectRatio, 1f);
+        res.addOverride(
+                com.android.internal.R.integer.config_defaultPictureInPictureGravity,
+                Gravity.END | Gravity.BOTTOM);
+        res.addOverride(
+                com.android.internal.R.dimen.default_minimal_size_pip_resizable_task, 100);
+        res.addOverride(
+                com.android.internal.R.string.config_defaultPictureInPictureScreenEdgeInsets,
+                "16x16");
+        res.addOverride(
+                com.android.internal.R.dimen.config_pictureInPictureMinAspectRatio, 0.5f);
+        res.addOverride(
+                com.android.internal.R.dimen.config_pictureInPictureMaxAspectRatio, 2f);
+
+        mDefaultDisplayInfo = new DisplayInfo();
+        mDefaultDisplayInfo.displayId = 1;
+        mDefaultDisplayInfo.logicalWidth = 1000;
+        mDefaultDisplayInfo.logicalHeight = 1500;
+        mDefaultDisplayRect = new Rect(0, 0,
+                mDefaultDisplayInfo.logicalWidth, mDefaultDisplayInfo.logicalHeight);
+    }
+
+    @Test
+    public void setShelfHeight_offsetBounds() throws Exception {
+        final ArgumentCaptor<Rect> destinationBounds = ArgumentCaptor.forClass(Rect.class);
+        final int shelfHeight = 100;
+
+        mPipBoundsHandler.onPrepareAnimation(null, 1f, null);
+
+        verify(mPinnedStackController).startAnimation(
+                destinationBounds.capture(), isNull(), anyInt());
+        final Rect lastPosition = destinationBounds.getValue();
+        // Reset the pinned stack controller since we will do another verify later on
+        reset(mPinnedStackController);
+
+        mPipBoundsHandler.setShelfHeight(true, shelfHeight);
+        mPipBoundsHandler.onPrepareAnimation(null, 1f, null);
+
+        verify(mPinnedStackController).startAnimation(
+                destinationBounds.capture(), isNull(), anyInt());
+        lastPosition.offset(0, -shelfHeight);
+        assertBoundsWithMargin("PiP bounds offset by shelf height",
+                lastPosition, destinationBounds.getValue());
+    }
+
+    @Test
+    public void onImeVisibilityChanged_offsetBounds() throws Exception {
+        final ArgumentCaptor<Rect> destinationBounds = ArgumentCaptor.forClass(Rect.class);
+        final int imeHeight = 100;
+
+        mPipBoundsHandler.onPrepareAnimation(null, 1f, null);
+
+        verify(mPinnedStackController).startAnimation(
+                destinationBounds.capture(), isNull(), anyInt());
+        final Rect lastPosition = destinationBounds.getValue();
+        // Reset the pinned stack controller since we will do another verify later on
+        reset(mPinnedStackController);
+
+        mPipBoundsHandler.onImeVisibilityChanged(true, imeHeight);
+        mPipBoundsHandler.onPrepareAnimation(null, 1f, null);
+
+        verify(mPinnedStackController).startAnimation(
+                destinationBounds.capture(), isNull(), anyInt());
+        lastPosition.offset(0, -imeHeight);
+        assertBoundsWithMargin("PiP bounds offset by IME height",
+                lastPosition, destinationBounds.getValue());
+    }
+
+    @Test
+    public void onPrepareAnimation_startAnimation() throws Exception {
+        final Rect sourceRectHint = new Rect(100, 100, 200, 200);
+        final ArgumentCaptor<Rect> destinationBounds = ArgumentCaptor.forClass(Rect.class);
+
+        mPipBoundsHandler.onPrepareAnimation(sourceRectHint, 1f, null);
+
+        verify(mPinnedStackController).startAnimation(
+                destinationBounds.capture(), eq(sourceRectHint), anyInt());
+        final Rect capturedDestinationBounds = destinationBounds.getValue();
+        assertFalse("Destination bounds is not empty",
+                capturedDestinationBounds.isEmpty());
+        assertBoundsWithMargin("Destination bounds within Display",
+                mDefaultDisplayRect, capturedDestinationBounds);
+    }
+
+    @Test
+    public void onSaveReentryBounds_restoreLastPosition() throws Exception {
+        final ComponentName componentName = new ComponentName(mContext, "component1");
+        final ArgumentCaptor<Rect> destinationBounds = ArgumentCaptor.forClass(Rect.class);
+
+        mPipBoundsHandler.onPrepareAnimation(null, 1f, null);
+
+        verify(mPinnedStackController).startAnimation(
+                destinationBounds.capture(), isNull(), anyInt());
+        final Rect lastPosition = destinationBounds.getValue();
+        lastPosition.offset(0, -100);
+        mPipBoundsHandler.onSaveReentryBounds(componentName, lastPosition);
+        // Reset the pinned stack controller since we will do another verify later on
+        reset(mPinnedStackController);
+
+        mPipBoundsHandler.onPrepareAnimation(null, 1f, null);
+
+        verify(mPinnedStackController).startAnimation(
+                destinationBounds.capture(), isNull(), anyInt());
+        assertBoundsWithMargin("Last position is restored",
+                lastPosition, destinationBounds.getValue());
+    }
+
+    @Test
+    public void onResetReentryBounds_componentMatch_useDefaultBounds() throws Exception {
+        final ComponentName componentName = new ComponentName(mContext, "component1");
+        final ArgumentCaptor<Rect> destinationBounds = ArgumentCaptor.forClass(Rect.class);
+
+        mPipBoundsHandler.onPrepareAnimation(null, 1f, null);
+
+        verify(mPinnedStackController).startAnimation(
+                destinationBounds.capture(), isNull(), anyInt());
+        final Rect defaultBounds = new Rect(destinationBounds.getValue());
+        final Rect newBounds = new Rect(defaultBounds);
+        newBounds.offset(0, -100);
+        mPipBoundsHandler.onSaveReentryBounds(componentName, newBounds);
+        // Reset the pinned stack controller since we will do another verify later on
+        reset(mPinnedStackController);
+
+        mPipBoundsHandler.onResetReentryBounds(componentName);
+        mPipBoundsHandler.onPrepareAnimation(null, 1f, null);
+
+        verify(mPinnedStackController).startAnimation(
+                destinationBounds.capture(), isNull(), anyInt());
+        final Rect actualBounds = destinationBounds.getValue();
+        assertBoundsWithMargin("Use default bounds", defaultBounds, actualBounds);
+    }
+
+    @Test
+    public void onResetReentryBounds_componentMismatch_restoreLastPosition() throws Exception {
+        final ComponentName componentName = new ComponentName(mContext, "component1");
+        final ArgumentCaptor<Rect> destinationBounds = ArgumentCaptor.forClass(Rect.class);
+
+        mPipBoundsHandler.onPrepareAnimation(null, 1f, null);
+
+        verify(mPinnedStackController).startAnimation(
+                destinationBounds.capture(), isNull(), anyInt());
+        final Rect defaultBounds = new Rect(destinationBounds.getValue());
+        final Rect newBounds = new Rect(defaultBounds);
+        newBounds.offset(0, -100);
+        mPipBoundsHandler.onSaveReentryBounds(componentName, newBounds);
+        // Reset the pinned stack controller since we will do another verify later on
+        reset(mPinnedStackController);
+
+        mPipBoundsHandler.onResetReentryBounds(new ComponentName(mContext, "component2"));
+        mPipBoundsHandler.onPrepareAnimation(null, 1f, null);
+
+        verify(mPinnedStackController).startAnimation(
+                destinationBounds.capture(), isNull(), anyInt());
+        final Rect actualBounds = destinationBounds.getValue();
+        assertBoundsWithMargin("Last position is restored", newBounds, actualBounds);
+    }
+
+    private void assertBoundsWithMargin(String msg, Rect expected, Rect actual) {
+        expected.inset(-ROUNDING_ERROR_MARGIN, -ROUNDING_ERROR_MARGIN);
+        assertTrue(msg, expected.contains(actual));
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java
index 0251f2d..9a7e97b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java
@@ -62,6 +62,7 @@
 import com.android.systemui.statusbar.notification.collection.notifcollection.CollectionReadyForBuildListener;
 import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats;
 import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionLogger;
 import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender;
 import com.android.systemui.util.Assert;
 
@@ -85,6 +86,7 @@
 public class NotifCollectionTest extends SysuiTestCase {
 
     @Mock private IStatusBarService mStatusBarService;
+    @Mock private NotifCollectionLogger mLogger;
     @Mock private GroupCoalescer mGroupCoalescer;
     @Spy private RecordingCollectionListener mCollectionListener;
     @Mock private CollectionReadyForBuildListener mBuildListener;
@@ -111,9 +113,11 @@
         when(mFeatureFlags.isNewNotifPipelineRenderingEnabled()).thenReturn(true);
         when(mFeatureFlags.isNewNotifPipelineEnabled()).thenReturn(true);
 
-        mCollection = new NotifCollection(mStatusBarService,
+        mCollection = new NotifCollection(
+                mStatusBarService,
                 mock(DumpController.class),
-                mFeatureFlags);
+                mFeatureFlags,
+                mLogger);
         mCollection.attach(mGroupCoalescer);
         mCollection.addCollectionListener(mCollectionListener);
         mCollection.setBuildListener(mBuildListener);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java
index e915be3..18f133f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java
@@ -45,12 +45,12 @@
 import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener;
 import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeSortListener;
 import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeTransformGroupsListener;
+import com.android.systemui.statusbar.notification.collection.listbuilder.ShadeListBuilderLogger;
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifComparator;
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter;
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSection;
 import com.android.systemui.statusbar.notification.collection.notifcollection.CollectionReadyForBuildListener;
-import com.android.systemui.statusbar.notification.logging.NotifLog;
 import com.android.systemui.util.Assert;
 import com.android.systemui.util.time.FakeSystemClock;
 
@@ -81,7 +81,7 @@
     private ShadeListBuilder mListBuilder;
     private FakeSystemClock mSystemClock = new FakeSystemClock();
 
-    @Mock private NotifLog mNotifLog;
+    @Mock private ShadeListBuilderLogger mLogger;
     @Mock private NotifCollection mNotifCollection;
     @Spy private OnBeforeTransformGroupsListener mOnBeforeTransformGroupsListener;
     @Spy private OnBeforeSortListener mOnBeforeSortListener;
@@ -103,7 +103,7 @@
         MockitoAnnotations.initMocks(this);
         Assert.sMainLooper = TestableLooper.get(this).getLooper();
 
-        mListBuilder = new ShadeListBuilder(mSystemClock, mNotifLog, mock(DumpController.class));
+        mListBuilder = new ShadeListBuilder(mSystemClock, mLogger, mock(DumpController.class));
         mListBuilder.setOnRenderListListener(mOnRenderListListener);
 
         mListBuilder.attach(mNotifCollection);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescerTest.java
index 86c1eb97..ac9a570 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescerTest.java
@@ -16,8 +16,6 @@
 
 package com.android.systemui.statusbar.notification.collection.coalescer;
 
-import static com.android.internal.util.Preconditions.checkNotNull;
-
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyList;
 import static org.mockito.Mockito.clearInvocations;
@@ -25,6 +23,8 @@
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 
+import static java.util.Objects.requireNonNull;
+
 import android.service.notification.NotificationListenerService.Ranking;
 import android.service.notification.NotificationListenerService.RankingMap;
 import android.service.notification.StatusBarNotification;
@@ -39,7 +39,6 @@
 import com.android.systemui.statusbar.notification.collection.NoManSimulator;
 import com.android.systemui.statusbar.notification.collection.NoManSimulator.NotifEvent;
 import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
-import com.android.systemui.statusbar.notification.logging.NotifLog;
 import com.android.systemui.util.concurrency.FakeExecutor;
 import com.android.systemui.util.time.FakeSystemClock;
 
@@ -63,7 +62,7 @@
 
     @Mock private NotificationListener mListenerService;
     @Mock private GroupCoalescer.BatchableNotificationHandler mListener;
-    @Mock private NotifLog mLog;
+    @Mock private GroupCoalescerLogger mLogger;
 
     @Captor private ArgumentCaptor<NotificationHandler> mListenerCaptor;
 
@@ -79,14 +78,14 @@
                 new GroupCoalescer(
                         mExecutor,
                         mClock,
-                        mLog,
+                        mLogger,
                         MIN_LINGER_DURATION,
                         MAX_LINGER_DURATION);
         mCoalescer.setNotificationHandler(mListener);
         mCoalescer.attach(mListenerService);
 
         verify(mListenerService).addNotificationHandler(mListenerCaptor.capture());
-        NotificationHandler serviceListener = checkNotNull(mListenerCaptor.getValue());
+        NotificationHandler serviceListener = requireNonNull(mListenerCaptor.getValue());
         mNoMan.addListener(serviceListener);
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java
index 5fc40cc..20a089f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java
@@ -58,7 +58,6 @@
 import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
-import android.util.Slog;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.widget.Button;
@@ -601,6 +600,34 @@
     }
 
     @Test
+    public void testBubble_noChannelChange() throws Exception {
+        mNotificationInfo.bindNotification(
+                mShortcutManager,
+                mLauncherApps,
+                mMockPackageManager,
+                mMockINotificationManager,
+                mVisualStabilityManager,
+                TEST_PACKAGE_NAME,
+                mNotificationChannel,
+                mBubbleEntry,
+                null,
+                null,
+                null,
+                true);
+
+        assertFalse(mBubbleEntry.isBubble());
+        assertTrue(mNotificationChannel.canBubble());
+
+        // Promote it
+        mNotificationInfo.findViewById(R.id.bubble).performClick();
+        mTestableLooper.processAllMessages();
+
+        verify(mBubbleController, times(1)).onUserCreatedBubbleFromNotification(mBubbleEntry);
+        verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
+                anyString(), anyInt(), any());
+    }
+
+    @Test
     public void testFavorite_favorite() throws Exception {
         mNotificationInfo.bindNotification(
                 mShortcutManager,
diff --git a/packages/Tethering/src/android/net/dhcp/DhcpServerCallbacks.java b/packages/Tethering/src/android/net/dhcp/DhcpServerCallbacks.java
index 7c413779..9fda125 100644
--- a/packages/Tethering/src/android/net/dhcp/DhcpServerCallbacks.java
+++ b/packages/Tethering/src/android/net/dhcp/DhcpServerCallbacks.java
@@ -28,4 +28,9 @@
     public int getInterfaceVersion() {
         return IDhcpServerCallbacks.VERSION;
     }
+
+    @Override
+    public String getInterfaceHash() {
+        return IDhcpServerCallbacks.HASH;
+    }
 }
diff --git a/packages/Tethering/src/android/net/ip/IpServer.java b/packages/Tethering/src/android/net/ip/IpServer.java
index 190d2509..f39e7af 100644
--- a/packages/Tethering/src/android/net/ip/IpServer.java
+++ b/packages/Tethering/src/android/net/ip/IpServer.java
@@ -301,6 +301,11 @@
         public int getInterfaceVersion() {
             return this.VERSION;
         }
+
+        @Override
+        public String getInterfaceHash() {
+            return this.HASH;
+        }
     }
 
     private class DhcpServerCallbacksImpl extends DhcpServerCallbacks {
diff --git a/packages/Tethering/src/android/net/util/BaseNetdUnsolicitedEventListener.java b/packages/Tethering/src/android/net/util/BaseNetdUnsolicitedEventListener.java
index 3218c0b..b1ffdb0 100644
--- a/packages/Tethering/src/android/net/util/BaseNetdUnsolicitedEventListener.java
+++ b/packages/Tethering/src/android/net/util/BaseNetdUnsolicitedEventListener.java
@@ -67,4 +67,9 @@
     public int getInterfaceVersion() {
         return INetdUnsolicitedEventListener.VERSION;
     }
+
+    @Override
+    public String getInterfaceHash() {
+        return INetdUnsolicitedEventListener.HASH;
+    }
 }
diff --git a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
index 16484df9f..f90d936 100644
--- a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
+++ b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
@@ -76,6 +76,7 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
@@ -697,11 +698,7 @@
         mStageName = new File(backupManagerService.getDataDir(), packageName + ".stage");
         mNewStateName = new File(mStateDir, packageName + ".new");
 
-        // don't stage the 'android' package where the wallpaper data lives.  this is
-        // an optimization: we know there's no widget data hosted/published by that
-        // package, and this way we avoid doing a spurious copy of MB-sized wallpaper
-        // data following the download.
-        boolean staging = !packageName.equals(PLATFORM_PACKAGE_NAME);
+        boolean staging = shouldStageBackupData(packageName);
         ParcelFileDescriptor stage;
         File downloadFile = (staging) ? mStageName : mBackupDataName;
         boolean startedAgentRestore = false;
@@ -768,8 +765,7 @@
             startedAgentRestore = true;
             mAgent.doRestoreWithExcludedKeys(mBackupData, appVersionCode, mNewState,
                     mEphemeralOpToken, backupManagerService.getBackupManagerBinder(),
-                    mExcludedKeys.containsKey(packageName)
-                            ? new ArrayList<>(mExcludedKeys.get(packageName)) : null);
+                    new ArrayList<>(getExcludedKeysForPackage(packageName)));
         } catch (Exception e) {
             Slog.e(TAG, "Unable to call app for restore: " + packageName, e);
             EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE,
@@ -785,9 +781,24 @@
     }
 
     @VisibleForTesting
+    boolean shouldStageBackupData(String packageName) {
+        // Backup data is staged for 2 reasons:
+        // 1. We might need to exclude keys from the data before passing it to the agent
+        // 2. Widget metadata needs to be separated from the rest to be handled separately
+        // But 'android' package doesn't contain widget metadata so we want to skip staging for it
+        // when there are no keys to be excluded either.
+        return !packageName.equals(PLATFORM_PACKAGE_NAME) ||
+                !getExcludedKeysForPackage(PLATFORM_PACKAGE_NAME).isEmpty();
+    }
+
+    private Set<String> getExcludedKeysForPackage(String packageName) {
+        return mExcludedKeys.getOrDefault(packageName, Collections.emptySet());
+    }
+
+    @VisibleForTesting
     void filterExcludedKeys(String packageName, BackupDataInput in, BackupDataOutput out)
             throws Exception {
-        Set<String> excludedKeysForPackage = mExcludedKeys.get(packageName);
+        Set<String> excludedKeysForPackage = getExcludedKeysForPackage(packageName);
 
         byte[] buffer = new byte[8192]; // will grow when needed
         while (in.readNextHeader()) {
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
index 0b7029b..5602d1a8 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
@@ -92,6 +92,7 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.PrintWriter;
+import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
@@ -670,7 +671,7 @@
 
                 service.onDataSharedLocked(request,
                         new DataShareCallbackDelegate(request, clientCancellationSignal,
-                                clientAdapter));
+                                clientAdapter, ContentCaptureManagerService.this));
             }
         }
 
@@ -918,20 +919,22 @@
         }
     }
 
-    // TODO(b/148265162): DataShareCallbackDelegate should be a static class keeping week references
-    //  to the needed info
-    private class DataShareCallbackDelegate extends IDataShareCallback.Stub {
+    private static class DataShareCallbackDelegate extends IDataShareCallback.Stub {
 
         @NonNull private final DataShareRequest mDataShareRequest;
-        @NonNull private final ICancellationSignal mClientCancellationSignal;
-        @NonNull private final IDataShareWriteAdapter mClientAdapter;
+        @NonNull
+        private final WeakReference<ICancellationSignal> mClientCancellationSignalReference;
+        @NonNull private final WeakReference<IDataShareWriteAdapter> mClientAdapterReference;
+        @NonNull private final WeakReference<ContentCaptureManagerService> mParentServiceReference;
 
         DataShareCallbackDelegate(@NonNull DataShareRequest dataShareRequest,
                 @NonNull ICancellationSignal clientCancellationSignal,
-                @NonNull IDataShareWriteAdapter clientAdapter) {
+                @NonNull IDataShareWriteAdapter clientAdapter,
+                ContentCaptureManagerService parentService) {
             mDataShareRequest = dataShareRequest;
-            mClientCancellationSignal = clientCancellationSignal;
-            mClientAdapter = clientAdapter;
+            mClientCancellationSignalReference = new WeakReference<>(clientCancellationSignal);
+            mClientAdapterReference = new WeakReference<>(clientAdapter);
+            mParentServiceReference = new WeakReference<>(parentService);
         }
 
         @Override
@@ -939,41 +942,52 @@
                 IDataShareReadAdapter serviceAdapter) throws RemoteException {
             Slog.i(TAG, "Data share request accepted by Content Capture service");
 
+            final ContentCaptureManagerService parentService = mParentServiceReference.get();
+            final ICancellationSignal clientCancellationSignal =
+                    mClientCancellationSignalReference.get();
+            final IDataShareWriteAdapter clientAdapter = mClientAdapterReference.get();
+            if (parentService == null || clientCancellationSignal == null
+                    || clientAdapter == null) {
+                Slog.w(TAG, "Can't fulfill accept() request, because remote objects have been "
+                        + "GC'ed");
+                return;
+            }
+
             Pair<ParcelFileDescriptor, ParcelFileDescriptor> clientPipe = createPipe();
             if (clientPipe == null) {
-                mClientAdapter.error(DataShareWriteAdapter.ERROR_UNKNOWN);
+                clientAdapter.error(DataShareWriteAdapter.ERROR_UNKNOWN);
                 serviceAdapter.error(DataShareWriteAdapter.ERROR_UNKNOWN);
                 return;
             }
 
-            ParcelFileDescriptor source_in = clientPipe.second;
-            ParcelFileDescriptor sink_in = clientPipe.first;
+            ParcelFileDescriptor sourceIn = clientPipe.second;
+            ParcelFileDescriptor sinkIn = clientPipe.first;
 
             Pair<ParcelFileDescriptor, ParcelFileDescriptor> servicePipe = createPipe();
             if (servicePipe == null) {
-                bestEffortCloseFileDescriptors(source_in, sink_in);
+                bestEffortCloseFileDescriptors(sourceIn, sinkIn);
 
-                mClientAdapter.error(DataShareWriteAdapter.ERROR_UNKNOWN);
+                clientAdapter.error(DataShareWriteAdapter.ERROR_UNKNOWN);
                 serviceAdapter.error(DataShareWriteAdapter.ERROR_UNKNOWN);
                 return;
             }
 
-            ParcelFileDescriptor source_out = servicePipe.second;
-            ParcelFileDescriptor sink_out = servicePipe.first;
+            ParcelFileDescriptor sourceOut = servicePipe.second;
+            ParcelFileDescriptor sinkOut = servicePipe.first;
 
             ICancellationSignal cancellationSignalTransport =
                     CancellationSignal.createTransport();
-            mPackagesWithShareRequests.add(mDataShareRequest.getPackageName());
+            parentService.mPackagesWithShareRequests.add(mDataShareRequest.getPackageName());
 
-            mClientAdapter.write(source_in);
-            serviceAdapter.start(sink_out, cancellationSignalTransport);
+            clientAdapter.write(sourceIn);
+            serviceAdapter.start(sinkOut, cancellationSignalTransport);
 
             CancellationSignal cancellationSignal =
                     CancellationSignal.fromTransport(cancellationSignalTransport);
 
             cancellationSignal.setOnCancelListener(() -> {
                 try {
-                    mClientCancellationSignal.cancel();
+                    clientCancellationSignal.cancel();
                 } catch (RemoteException e) {
                     Slog.e(TAG, "Failed to propagate cancel operation to the caller", e);
                 }
@@ -982,13 +996,13 @@
             // File descriptor received by the client app will be a copy of the current one. Close
             // the one that belongs to the system server, so there's only 1 open left for the
             // current pipe.
-            bestEffortCloseFileDescriptor(source_in);
+            bestEffortCloseFileDescriptor(sourceIn);
 
-            mDataShareExecutor.execute(() -> {
+            parentService.mDataShareExecutor.execute(() -> {
                 try (InputStream fis =
-                             new ParcelFileDescriptor.AutoCloseInputStream(sink_in);
+                             new ParcelFileDescriptor.AutoCloseInputStream(sinkIn);
                      OutputStream fos =
-                             new ParcelFileDescriptor.AutoCloseOutputStream(source_out)) {
+                             new ParcelFileDescriptor.AutoCloseOutputStream(sourceOut)) {
 
                     byte[] byteBuffer = new byte[DATA_SHARE_BYTE_BUFFER_LENGTH];
                     while (true) {
@@ -1005,52 +1019,86 @@
                 }
             });
 
-            mHandler.postDelayed(() -> {
-                synchronized (mLock) {
-                    mPackagesWithShareRequests.remove(mDataShareRequest.getPackageName());
-
-                    // Interaction finished successfully <=> all data has been written to Content
-                    // Capture Service. If it hasn't been read successfully, service would be able
-                    // to signal through the cancellation signal.
-                    boolean finishedSuccessfully = !sink_in.getFileDescriptor().valid()
-                            && !source_out.getFileDescriptor().valid();
-
-                    if (finishedSuccessfully) {
-                        Slog.i(TAG, "Content capture data sharing session terminated "
-                                + "successfully for package '"
-                                + mDataShareRequest.getPackageName()
-                                + "'");
-                    } else {
-                        Slog.i(TAG, "Reached the timeout of Content Capture data sharing session "
-                                + "for package '"
-                                + mDataShareRequest.getPackageName()
-                                + "', terminating the pipe.");
-                    }
-
-                    // Ensure all the descriptors are closed after the session.
-                    bestEffortCloseFileDescriptors(source_in, sink_in, source_out, sink_out);
-
-                    if (!finishedSuccessfully) {
-                        try {
-                            mClientCancellationSignal.cancel();
-                        } catch (RemoteException e) {
-                            Slog.e(TAG, "Failed to cancel() the client operation", e);
-                        }
-                        try {
-                            serviceCancellationSignal.cancel();
-                        } catch (RemoteException e) {
-                            Slog.e(TAG, "Failed to cancel() the service operation", e);
-                        }
-                    }
-                }
-            }, MAX_DATA_SHARE_FILE_DESCRIPTORS_TTL_MS);
+            parentService.mHandler.postDelayed(() ->
+                    enforceDataSharingTtl(
+                            sourceIn,
+                            sinkIn,
+                            sourceOut,
+                            sinkOut,
+                            new WeakReference<>(serviceCancellationSignal)),
+                    MAX_DATA_SHARE_FILE_DESCRIPTORS_TTL_MS);
         }
 
         @Override
         public void reject() throws RemoteException {
             Slog.i(TAG, "Data share request rejected by Content Capture service");
 
-            mClientAdapter.rejected();
+            IDataShareWriteAdapter clientAdapter = mClientAdapterReference.get();
+            if (clientAdapter == null) {
+                Slog.w(TAG, "Can't fulfill reject() request, because remote objects have been "
+                        + "GC'ed");
+                return;
+            }
+
+            clientAdapter.rejected();
+        }
+
+        private void enforceDataSharingTtl(ParcelFileDescriptor sourceIn,
+                ParcelFileDescriptor sinkIn,
+                ParcelFileDescriptor sourceOut,
+                ParcelFileDescriptor sinkOut,
+                WeakReference<ICancellationSignal> serviceCancellationSignalReference) {
+
+            final ContentCaptureManagerService parentService = mParentServiceReference.get();
+            final ICancellationSignal clientCancellationSignal =
+                    mClientCancellationSignalReference.get();
+            final ICancellationSignal serviceCancellationSignal =
+                    serviceCancellationSignalReference.get();
+            if (parentService == null || clientCancellationSignal == null
+                    || serviceCancellationSignal == null) {
+                Slog.w(TAG, "Can't enforce data sharing TTL, because remote objects have been "
+                        + "GC'ed");
+                return;
+            }
+
+            synchronized (parentService.mLock) {
+                parentService.mPackagesWithShareRequests
+                        .remove(mDataShareRequest.getPackageName());
+
+                // Interaction finished successfully <=> all data has been written to Content
+                // Capture Service. If it hasn't been read successfully, service would be able
+                // to signal through the cancellation signal.
+                boolean finishedSuccessfully = !sinkIn.getFileDescriptor().valid()
+                        && !sourceOut.getFileDescriptor().valid();
+
+                if (finishedSuccessfully) {
+                    Slog.i(TAG, "Content capture data sharing session terminated "
+                            + "successfully for package '"
+                            + mDataShareRequest.getPackageName()
+                            + "'");
+                } else {
+                    Slog.i(TAG, "Reached the timeout of Content Capture data sharing session "
+                            + "for package '"
+                            + mDataShareRequest.getPackageName()
+                            + "', terminating the pipe.");
+                }
+
+                // Ensure all the descriptors are closed after the session.
+                bestEffortCloseFileDescriptors(sourceIn, sinkIn, sourceOut, sinkOut);
+
+                if (!finishedSuccessfully) {
+                    try {
+                        clientCancellationSignal.cancel();
+                    } catch (RemoteException e) {
+                        Slog.e(TAG, "Failed to cancel() the client operation", e);
+                    }
+                    try {
+                        serviceCancellationSignal.cancel();
+                    } catch (RemoteException e) {
+                        Slog.e(TAG, "Failed to cancel() the service operation", e);
+                    }
+                }
+            }
         }
 
         private Pair<ParcelFileDescriptor, ParcelFileDescriptor> createPipe() {
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index dd33566..d933e9d 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -2962,6 +2962,11 @@
         public int getInterfaceVersion() {
             return this.VERSION;
         }
+
+        @Override
+        public String getInterfaceHash() {
+            return this.HASH;
+        }
     }
 
     private boolean networkRequiresPrivateDnsValidation(NetworkAgentInfo nai) {
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 4a093cd..f1f2d2a 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -860,13 +860,7 @@
 
                 pw.increaseIndent();
 
-                boolean enabled = isEnabled();
-                pw.println("enabled=" + enabled);
-                if (!enabled) {
-                    pw.println("allowed=" + mProvider.getState().allowed);
-                }
-
-                pw.println("properties=" + mProvider.getState().properties);
+                pw.println("enabled=" + isEnabled());
             }
 
             mProvider.dump(fd, pw, args);
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 05d8360..9d4c783 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -735,6 +735,11 @@
         public int getInterfaceVersion() {
             return INetdUnsolicitedEventListener.VERSION;
         }
+
+        @Override
+        public String getInterfaceHash() {
+            return INetdUnsolicitedEventListener.HASH;
+        }
     }
 
     //
diff --git a/services/core/java/com/android/server/ServiceWatcher.java b/services/core/java/com/android/server/ServiceWatcher.java
index 8564cb4..14cd3a5 100644
--- a/services/core/java/com/android/server/ServiceWatcher.java
+++ b/services/core/java/com/android/server/ServiceWatcher.java
@@ -167,7 +167,7 @@
 
         @Override
         public String toString() {
-            return component + "@" + version + "[u" + userId + "]";
+            return component.toShortString() + "@" + version + "[u" + userId + "]";
         }
     }
 
@@ -341,7 +341,7 @@
         Preconditions.checkState(Looper.myLooper() == mHandler.getLooper());
 
         if (D) {
-            Log.i(TAG, getLogPrefix() + " connected to " + component);
+            Log.i(TAG, getLogPrefix() + " connected to " + component.toShortString());
         }
 
         mBinder = binder;
@@ -351,11 +351,22 @@
     }
 
     @Override
+    public void onBindingDied(ComponentName component) {
+        Preconditions.checkState(Looper.myLooper() == mHandler.getLooper());
+
+        if (D) {
+            Log.i(TAG, getLogPrefix() + " " + component.toShortString() + " died");
+        }
+
+        onBestServiceChanged(true);
+    }
+
+    @Override
     public final void onServiceDisconnected(ComponentName component) {
         Preconditions.checkState(Looper.myLooper() == mHandler.getLooper());
 
         if (D) {
-            Log.i(TAG, getLogPrefix() + " disconnected from " + component);
+            Log.i(TAG, getLogPrefix() + " disconnected from " + component.toShortString());
         }
 
         mBinder = null;
@@ -383,8 +394,8 @@
     }
 
     /**
-     * Runs the given function asynchronously if currently connected. Suppresses any RemoteException
-     * thrown during execution.
+     * Runs the given function asynchronously if and only if currently connected. Suppresses any
+     * RemoteException thrown during execution.
      */
     public final void runOnBinder(BinderRunner runner) {
         runOnHandler(() -> {
@@ -473,4 +484,9 @@
     private String getLogPrefix() {
         return "[" + mIntent.getAction() + "]";
     }
+
+    @Override
+    public String toString() {
+        return mServiceInfo.toString();
+    }
 }
diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java
index 5a56a9f..6bc090a 100644
--- a/services/core/java/com/android/server/VibratorService.java
+++ b/services/core/java/com/android/server/VibratorService.java
@@ -16,6 +16,8 @@
 
 package com.android.server;
 
+import static android.os.VibrationEffect.Composition.PrimitiveEffect;
+
 import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.app.AppOpsManager;
@@ -73,8 +75,10 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Date;
 import java.util.LinkedList;
+import java.util.List;
 
 public class VibratorService extends IVibratorService.Stub
         implements InputManager.InputDeviceListener {
@@ -128,10 +132,11 @@
     private final boolean mAllowPriorityVibrationsInLowPowerMode;
     private final boolean mSupportsAmplitudeControl;
     private final boolean mSupportsExternalControl;
+    private final List<Integer> mSupportedEffects;
     private final long mCapabilities;
     private final int mDefaultVibrationAmplitude;
     private final SparseArray<VibrationEffect> mFallbackEffects;
-    private final SparseArray<Integer> mProcStatesCache = new SparseArray();
+    private final SparseArray<Integer> mProcStatesCache = new SparseArray<>();
     private final WorkSource mTmpWorkSource = new WorkSource();
     private final Handler mH = new Handler();
     private final Object mLock = new Object();
@@ -150,7 +155,7 @@
 
     // mInputDeviceVibrators lock should be acquired after mLock, if both are
     // to be acquired
-    private final ArrayList<Vibrator> mInputDeviceVibrators = new ArrayList<Vibrator>();
+    private final ArrayList<Vibrator> mInputDeviceVibrators = new ArrayList<>();
     private boolean mVibrateInputDevicesSetting; // guarded by mInputDeviceVibrators
     private boolean mInputDeviceListenerRegistered; // guarded by mInputDeviceVibrators
 
@@ -171,7 +176,10 @@
     static native void vibratorOff();
     static native boolean vibratorSupportsAmplitudeControl();
     static native void vibratorSetAmplitude(int amplitude);
+    static native int[] vibratorGetSupportedEffects();
     static native long vibratorPerformEffect(long effect, long strength, Vibration vibration);
+    static native void vibratorPerformComposedEffect(
+            VibrationEffect.Composition.PrimitiveEffect[] effect, Vibration vibration);
     static native boolean vibratorSupportsExternalControl();
     static native void vibratorSetExternalControl(boolean enabled);
     static native long vibratorGetCapabilities();
@@ -238,6 +246,8 @@
             }
         }
 
+        // Called by native
+        @SuppressWarnings("unused")
         private void onComplete() {
             synchronized (mLock) {
                 if (this == mCurrentVibration) {
@@ -346,10 +356,11 @@
 
         mSupportsAmplitudeControl = vibratorSupportsAmplitudeControl();
         mSupportsExternalControl = vibratorSupportsExternalControl();
+        mSupportedEffects = asList(vibratorGetSupportedEffects());
         mCapabilities = vibratorGetCapabilities();
 
         mContext = context;
-        PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
+        PowerManager pm = context.getSystemService(PowerManager.class);
         mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*vibrator*");
         mWakeLock.setReferenceCounted(true);
 
@@ -510,12 +521,47 @@
     }
 
     @Override // Binder call
+    public boolean[] areEffectsSupported(int[] effectIds) {
+        // Return null to indicate that the HAL doesn't actually tell us what effects are
+        // supported.
+        if (mSupportedEffects == null) {
+            return null;
+        }
+        boolean[] supported = new boolean[effectIds.length];
+        for (int i = 0; i < effectIds.length; i++) {
+            supported[i] = mSupportedEffects.contains(effectIds[i]);
+        }
+        return supported;
+    }
+
+    @Override // Binder call
+    public boolean[] arePrimitivesSupported(int[] primitiveIds) {
+        boolean[] supported = new boolean[primitiveIds.length];
+        if (hasCapability(IVibrator.CAP_COMPOSE_EFFECTS)) {
+            Arrays.fill(supported, true);
+        }
+        return supported;
+    }
+
+
+    private static List<Integer> asList(int... vals) {
+        if (vals == null) {
+            return null;
+        }
+        List<Integer> l = new ArrayList<>(vals.length);
+        for (int val : vals) {
+            l.add(val);
+        }
+        return l;
+    }
+
+    @Override // Binder call
     public boolean setAlwaysOnEffect(int uid, String opPkg, int alwaysOnId, VibrationEffect effect,
             VibrationAttributes attrs) {
         if (!hasPermission(android.Manifest.permission.VIBRATE_ALWAYS_ON)) {
             throw new SecurityException("Requires VIBRATE_ALWAYS_ON permission");
         }
-        if ((mCapabilities & IVibrator.CAP_ALWAYS_ON_CONTROL) == 0) {
+        if (!hasCapability(IVibrator.CAP_ALWAYS_ON_CONTROL)) {
             Slog.e(TAG, "Always-on effects not supported.");
             return false;
         }
@@ -817,6 +863,14 @@
                 if (timeout > 0) {
                     mH.postDelayed(mVibrationEndRunnable, timeout);
                 }
+            } else if (vib.effect instanceof  VibrationEffect.Composed) {
+                Trace.asyncTraceBegin(Trace.TRACE_TAG_VIBRATOR, "vibration", 0);
+                doVibratorComposedEffectLocked(vib);
+                // FIXME: We rely on the completion callback here, but I don't think we require that
+                // devices which support composition also support the completion callback. If we
+                // ever get a device that supports the former but not the latter, then we have no
+                // real way of knowing how long a given effect should last.
+                mH.postDelayed(mVibrationEndRunnable, 10000);
             } else {
                 Slog.e(TAG, "Unknown vibration type, ignoring");
             }
@@ -1148,7 +1202,7 @@
                     }
                 } else {
                     // Note: ordering is important here! Many haptic drivers will reset their
-                    // amplitude when enabled, so we always have to enable frst, then set the
+                    // amplitude when enabled, so we always have to enable first, then set the
                     // amplitude.
                     vibratorOn(millis);
                     doVibratorSetAmplitude(amplitude);
@@ -1201,7 +1255,7 @@
                 long duration = vibratorPerformEffect(prebaked.getId(),
                         prebaked.getEffectStrength(), vib);
                 long timeout = duration;
-                if ((mCapabilities & IVibrator.CAP_PERFORM_CALLBACK) != 0) {
+                if (hasCapability(IVibrator.CAP_PERFORM_CALLBACK)) {
                     timeout *= ASYNC_TIMEOUT_MULTIPLIER;
                 }
                 if (timeout > 0) {
@@ -1229,6 +1283,41 @@
         }
     }
 
+    @GuardedBy("mLock")
+    private void doVibratorComposedEffectLocked(Vibration vib) {
+        Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "doVibratorComposedEffectLocked");
+
+        try {
+            final VibrationEffect.Composed composed = (VibrationEffect.Composed) vib.effect;
+            final boolean usingInputDeviceVibrators;
+            synchronized (mInputDeviceVibrators) {
+                usingInputDeviceVibrators = !mInputDeviceVibrators.isEmpty();
+            }
+            // Input devices don't support composed effect, so skip trying it with them.
+            if (usingInputDeviceVibrators) {
+                return;
+            }
+
+            if (!hasCapability(IVibrator.CAP_COMPOSE_EFFECTS)) {
+                return;
+            }
+
+            PrimitiveEffect[] primitiveEffects =
+                    composed.getPrimitiveEffects().toArray(new PrimitiveEffect[0]);
+            vibratorPerformComposedEffect(primitiveEffects, vib);
+
+            // Composed effects don't actually give us an estimated duration, so we just guess here.
+            noteVibratorOnLocked(vib.uid, 10 * primitiveEffects.length);
+        } finally {
+            Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
+        }
+
+    }
+
+    private boolean hasCapability(long capability) {
+        return (mCapabilities & capability) == capability;
+    }
+
     private VibrationEffect getFallbackEffect(int effectId) {
         return mFallbackEffects.get(effectId);
     }
@@ -1424,7 +1513,7 @@
                 long[] timings, int[] amplitudes, int startIndex, int repeatIndex) {
             int i = startIndex;
             long timing = 0;
-            while(amplitudes[i] != 0) {
+            while (amplitudes[i] != 0) {
                 timing += timings[i++];
                 if (i >= timings.length) {
                     if (repeatIndex >= 0) {
@@ -1475,18 +1564,14 @@
             } else {
                 pw.println("null");
             }
-            pw.print("  mCurrentExternalVibration=");
-            if (mCurrentExternalVibration != null) {
-                pw.println(mCurrentExternalVibration.toString());
-            } else {
-                pw.println("null");
-            }
+            pw.print("  mCurrentExternalVibration=" + mCurrentExternalVibration);
             pw.println("  mVibratorUnderExternalControl=" + mVibratorUnderExternalControl);
             pw.println("  mLowPowerMode=" + mLowPowerMode);
             pw.println("  mHapticFeedbackIntensity=" + mHapticFeedbackIntensity);
             pw.println("  mNotificationIntensity=" + mNotificationIntensity);
             pw.println("  mRingIntensity=" + mRingIntensity);
-            pw.println("");
+            pw.println("  mSupportedEffects=" + mSupportedEffects);
+            pw.println();
             pw.println("  Previous ring vibrations:");
             for (VibrationInfo info : mPreviousRingVibrations) {
                 pw.print("    ");
@@ -1495,34 +1580,29 @@
 
             pw.println("  Previous notification vibrations:");
             for (VibrationInfo info : mPreviousNotificationVibrations) {
-                pw.print("    ");
-                pw.println(info.toString());
+                pw.println("    " + info);
             }
 
             pw.println("  Previous alarm vibrations:");
             for (VibrationInfo info : mPreviousAlarmVibrations) {
-                pw.print("    ");
-                pw.println(info.toString());
+                pw.println("    " + info);
             }
 
             pw.println("  Previous vibrations:");
             for (VibrationInfo info : mPreviousVibrations) {
-                pw.print("    ");
-                pw.println(info.toString());
+                pw.println("    " + info);
             }
 
             pw.println("  Previous external vibrations:");
             for (ExternalVibration vib : mPreviousExternalVibrations) {
-                pw.print("    ");
-                pw.println(vib.toString());
+                pw.println("    " + vib);
             }
         }
     }
 
     @Override
     public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
-            String[] args, ShellCallback callback, ResultReceiver resultReceiver)
-            throws RemoteException {
+            String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
         new VibratorShellCommand(this).exec(this, in, out, err, args, callback, resultReceiver);
     }
 
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 0a91f9a..ffeea3d 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -287,6 +287,7 @@
 
         static final int MSG_BG_START_TIMEOUT = 1;
         static final int MSG_UPDATE_FOREGROUND_APPS = 2;
+        static final int MSG_ENSURE_NOT_START_BG = 3;
 
         ServiceMap(Looper looper, int userId) {
             super(looper);
@@ -304,6 +305,11 @@
                 case MSG_UPDATE_FOREGROUND_APPS: {
                     updateForegroundApps(this);
                 } break;
+                case MSG_ENSURE_NOT_START_BG: {
+                    synchronized (mAm) {
+                        rescheduleDelayedStartsLocked();
+                    }
+                } break;
             }
         }
 
@@ -311,7 +317,9 @@
             if (mStartingBackground.remove(r)) {
                 if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE,
                         "No longer background starting: " + r);
-                rescheduleDelayedStartsLocked();
+                removeMessages(MSG_ENSURE_NOT_START_BG);
+                Message msg = obtainMessage(MSG_ENSURE_NOT_START_BG);
+                sendMessage(msg);
             }
             if (mDelayedStartList.remove(r)) {
                 if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "No longer delaying start: " + r);
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index e9d6491..3bd7d5c 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -17,8 +17,8 @@
 package com.android.server.am;
 
 import static android.app.ActivityManager.PROCESS_CAPABILITY_ALL;
-import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_CAMERA;
 import static android.app.ActivityManager.PROCESS_CAPABILITY_ALL_IMPLICIT;
+import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_CAMERA;
 import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION;
 import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
 import static android.app.ActivityManager.PROCESS_CAPABILITY_NONE;
@@ -36,9 +36,7 @@
 import static android.app.ActivityManager.PROCESS_STATE_SERVICE;
 import static android.app.ActivityManager.PROCESS_STATE_TOP;
 import static android.app.ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND;
-import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA;
 import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION;
-import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_MICROPHONE;
 import static android.os.Process.SCHED_OTHER;
 import static android.os.Process.THREAD_GROUP_BACKGROUND;
 import static android.os.Process.THREAD_GROUP_DEFAULT;
@@ -78,7 +76,6 @@
 import android.compat.annotation.EnabledAfter;
 import android.content.Context;
 import android.content.pm.ServiceInfo;
-import android.os.Build;
 import android.os.Debug;
 import android.os.Handler;
 import android.os.IBinder;
@@ -151,6 +148,9 @@
     @Disabled
     static final long CAMERA_MICROPHONE_CAPABILITY_CHANGE_ID = 136219221L;
 
+    //TODO: remove this when development is done.
+    private static final int TEMP_PROCESS_CAPABILITY_FOREGROUND_LOCATION = 1 << 31;
+
     /**
      * For some direct access we need to power manager.
      */
@@ -1477,13 +1477,24 @@
                 }
             }
 
-            if (s.isForeground && s.mAllowWhileInUsePermissionInFgs) {
+            if (s.isForeground) {
                 final int fgsType = s.foregroundServiceType;
-                capabilityFromFGS |=
-                        (fgsType & FOREGROUND_SERVICE_TYPE_LOCATION)
-                                != 0 ? PROCESS_CAPABILITY_FOREGROUND_LOCATION : 0;
-                capabilityFromFGS |= PROCESS_CAPABILITY_FOREGROUND_CAMERA
-                        | PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
+                if (s.mAllowWhileInUsePermissionInFgs) {
+                    capabilityFromFGS |=
+                            (fgsType & FOREGROUND_SERVICE_TYPE_LOCATION)
+                                    != 0 ? PROCESS_CAPABILITY_FOREGROUND_LOCATION : 0;
+                } else {
+                    //The FGS has the location capability, but due to FGS BG start restriction it
+                    //lost the capability, use temp location capability to mark this case.
+                    //TODO: remove this block when development is done.
+                    capabilityFromFGS |=
+                            (fgsType & FOREGROUND_SERVICE_TYPE_LOCATION)
+                                    != 0 ? TEMP_PROCESS_CAPABILITY_FOREGROUND_LOCATION : 0;
+                }
+                if (s.mAllowWhileInUsePermissionInFgs) {
+                    capabilityFromFGS |= PROCESS_CAPABILITY_FOREGROUND_CAMERA
+                            | PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
+                }
             }
 
             ArrayMap<IBinder, ArrayList<ConnectionRecord>> serviceConnections = s.getConnections();
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 62596de7..1d714a2 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -213,6 +213,9 @@
     private static final int MAX_UNFORWARED_OPS = 10;
     private static final int MAX_UNUSED_POOLED_OBJECTS = 3;
 
+    //TODO: remove this when development is done.
+    private static final int TEMP_PROCESS_CAPABILITY_FOREGROUND_LOCATION = 1 << 31;
+
     Context mContext;
     final AtomicFile mFile;
     final Handler mHandler;
@@ -480,8 +483,15 @@
                         case AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION:
                             if ((capability & PROCESS_CAPABILITY_FOREGROUND_LOCATION) != 0) {
                                 return AppOpsManager.MODE_ALLOWED;
-                            } else {
+                            } else if ((capability
+                                    & TEMP_PROCESS_CAPABILITY_FOREGROUND_LOCATION) != 0) {
+                                // The FGS has the location capability, but due to FGS BG start
+                                // restriction it lost the capability, use temp location capability
+                                // to mark this case.
+                                // TODO change to MODE_IGNORED when enforcing the feature.
                                 maybeShowWhileInUseDebugToast(op, mode);
+                                return AppOpsManager.MODE_ALLOWED;
+                            } else {
                                 return AppOpsManager.MODE_IGNORED;
                             }
                         case OP_CAMERA:
@@ -586,7 +596,7 @@
                 return;
             }
             final long now = System.currentTimeMillis();
-            if (lastTimeShowDebugToast == 0 ||  now - lastTimeShowDebugToast > 600000) {
+            if (lastTimeShowDebugToast == 0 ||  now - lastTimeShowDebugToast > 3600000) {
                 lastTimeShowDebugToast = now;
                 mHandler.sendMessage(PooledLambda.obtainMessage(
                         ActivityManagerInternal::showWhileInUseDebugToast,
diff --git a/services/core/java/com/android/server/compat/PlatformCompat.java b/services/core/java/com/android/server/compat/PlatformCompat.java
index bb8b12e..4d5af9a 100644
--- a/services/core/java/com/android/server/compat/PlatformCompat.java
+++ b/services/core/java/com/android/server/compat/PlatformCompat.java
@@ -16,6 +16,11 @@
 
 package com.android.server.compat;
 
+import static android.Manifest.permission.LOG_COMPAT_CHANGE;
+import static android.Manifest.permission.OVERRIDE_COMPAT_CHANGE_CONFIG;
+import static android.Manifest.permission.READ_COMPAT_CHANGE_CONFIG;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+
 import android.app.ActivityManager;
 import android.app.IActivityManager;
 import android.content.Context;
@@ -68,12 +73,14 @@
 
     @Override
     public void reportChange(long changeId, ApplicationInfo appInfo) {
+        checkCompatChangeLogPermission();
         reportChange(changeId, appInfo.uid,
                 StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__STATE__LOGGED);
     }
 
     @Override
     public void reportChangeByPackageName(long changeId, String packageName, int userId) {
+        checkCompatChangeLogPermission();
         ApplicationInfo appInfo = getApplicationInfo(packageName, userId);
         if (appInfo == null) {
             return;
@@ -83,11 +90,13 @@
 
     @Override
     public void reportChangeByUid(long changeId, int uid) {
+        checkCompatChangeLogPermission();
         reportChange(changeId, uid, StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__STATE__LOGGED);
     }
 
     @Override
     public boolean isChangeEnabled(long changeId, ApplicationInfo appInfo) {
+        checkCompatChangeReadPermission();
         if (mCompatConfig.isChangeEnabled(changeId, appInfo)) {
             reportChange(changeId, appInfo.uid,
                     StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__STATE__ENABLED);
@@ -100,6 +109,7 @@
 
     @Override
     public boolean isChangeEnabledByPackageName(long changeId, String packageName, int userId) {
+        checkCompatChangeReadPermission();
         ApplicationInfo appInfo = getApplicationInfo(packageName, userId);
         if (appInfo == null) {
             return true;
@@ -109,6 +119,7 @@
 
     @Override
     public boolean isChangeEnabledByUid(long changeId, int uid) {
+        checkCompatChangeReadPermission();
         String[] packages = mContext.getPackageManager().getPackagesForUid(uid);
         if (packages == null || packages.length == 0) {
             return true;
@@ -141,6 +152,7 @@
     @Override
     public void setOverrides(CompatibilityChangeConfig overrides, String packageName)
             throws RemoteException, SecurityException {
+        checkCompatChangeOverridePermission();
         mCompatConfig.addOverrides(overrides, packageName);
         killPackage(packageName);
     }
@@ -148,11 +160,13 @@
     @Override
     public void setOverridesForTest(CompatibilityChangeConfig overrides, String packageName)
             throws RemoteException, SecurityException {
+        checkCompatChangeOverridePermission();
         mCompatConfig.addOverrides(overrides, packageName);
     }
 
     @Override
     public void clearOverrides(String packageName) throws RemoteException, SecurityException {
+        checkCompatChangeOverridePermission();
         mCompatConfig.removePackageOverrides(packageName);
         killPackage(packageName);
     }
@@ -160,12 +174,14 @@
     @Override
     public void clearOverridesForTest(String packageName)
             throws RemoteException, SecurityException {
+        checkCompatChangeOverridePermission();
         mCompatConfig.removePackageOverrides(packageName);
     }
 
     @Override
     public boolean clearOverride(long changeId, String packageName)
             throws RemoteException, SecurityException {
+        checkCompatChangeOverridePermission();
         boolean existed = mCompatConfig.removeOverride(changeId, packageName);
         killPackage(packageName);
         return existed;
@@ -173,11 +189,13 @@
 
     @Override
     public CompatibilityChangeConfig getAppConfig(ApplicationInfo appInfo) {
+        checkCompatChangeReadPermission();
         return mCompatConfig.getAppConfig(appInfo);
     }
 
     @Override
     public CompatibilityChangeInfo[] listAllChanges() {
+        checkCompatChangeReadPermission();
         return mCompatConfig.dumpChanges();
     }
 
@@ -216,6 +234,7 @@
 
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        checkCompatChangeReadPermission();
         if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, "platform_compat", pw)) return;
         mCompatConfig.dumpConfig(pw);
     }
@@ -273,4 +292,25 @@
             Binder.restoreCallingIdentity(identity);
         }
     }
+
+    private void checkCompatChangeLogPermission() throws SecurityException {
+        if (mContext.checkCallingOrSelfPermission(LOG_COMPAT_CHANGE)
+                != PERMISSION_GRANTED) {
+            throw new SecurityException("Cannot log compat change usage");
+        }
+    }
+
+    private void checkCompatChangeReadPermission() throws SecurityException {
+        if (mContext.checkCallingOrSelfPermission(READ_COMPAT_CHANGE_CONFIG)
+                != PERMISSION_GRANTED) {
+            throw new SecurityException("Cannot read compat change");
+        }
+    }
+
+    private void checkCompatChangeOverridePermission() throws SecurityException {
+        if (mContext.checkCallingOrSelfPermission(OVERRIDE_COMPAT_CHANGE_CONFIG)
+                != PERMISSION_GRANTED) {
+            throw new SecurityException("Cannot override compat change");
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
index f2892cc..17e2f69 100644
--- a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
+++ b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
@@ -310,6 +310,11 @@
         return this.VERSION;
     }
 
+    @Override
+    public String getInterfaceHash() {
+        return this.HASH;
+    }
+
     private void addWakeupEvent(WakeupEvent event) {
         String iface = event.iface;
         mWakeupEvents.append(event);
diff --git a/services/core/java/com/android/server/incremental/IncrementalManagerService.java b/services/core/java/com/android/server/incremental/IncrementalManagerService.java
index d673ec8..5876d43 100644
--- a/services/core/java/com/android/server/incremental/IncrementalManagerService.java
+++ b/services/core/java/com/android/server/incremental/IncrementalManagerService.java
@@ -134,7 +134,7 @@
 
     // TODO: remove this
     @Override
-    public void newFileForDataLoader(int mountId, long inode, byte[] metadata) {
+    public void newFileForDataLoader(int mountId, byte[] fileId, byte[] metadata) {
         IDataLoader dataLoader = mDataLoaderManager.getDataLoader(mountId);
         if (dataLoader == null) {
             Slog.e(TAG, "Failed to retrieve data loader for ID=" + mountId);
diff --git a/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java b/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java
index 11fe15f..15dd646 100644
--- a/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java
+++ b/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java
@@ -260,7 +260,7 @@
                     "Integrity check result: "
                             + result.getEffect()
                             + " due to "
-                            + result.getRule());
+                            + result.getMatchedRules());
 
             StatsLog.write(
                     StatsLog.INTEGRITY_CHECK_RESULT_REPORTED,
@@ -268,9 +268,9 @@
                     appCert,
                     appInstallMetadata.getVersionCode(),
                     installerPackageName,
-                    getLoggingResponse(result),
-                    isCausedByAppCertRule(result),
-                    isCausedByInstallerRule(result));
+                    result.getLoggingResponse(),
+                    result.isCausedByAppCertRule(),
+                    result.isCausedByInstallerRule());
             mPackageManagerInternal.setIntegrityVerificationResult(
                     verificationId,
                     result.getEffect() == IntegrityCheckResult.Effect.ALLOW
@@ -583,26 +583,6 @@
         }
     }
 
-    private static int getLoggingResponse(IntegrityCheckResult result) {
-        if (result.getEffect() == IntegrityCheckResult.Effect.DENY) {
-            return StatsLog.INTEGRITY_CHECK_RESULT_REPORTED__RESPONSE__REJECTED;
-        } else if (result.getRule() != null) {
-            return StatsLog.INTEGRITY_CHECK_RESULT_REPORTED__RESPONSE__FORCE_ALLOWED;
-        } else {
-            return StatsLog.INTEGRITY_CHECK_RESULT_REPORTED__RESPONSE__ALLOWED;
-        }
-    }
-
-    private static boolean isCausedByAppCertRule(IntegrityCheckResult result) {
-        // TODO(b/147095027): implement this.
-        return true;
-    }
-
-    private static boolean isCausedByInstallerRule(IntegrityCheckResult result) {
-        // TODO(b/147095027): implement this.
-        return true;
-    }
-
     private List<String> getAllowedRuleProviders() {
         return Arrays.asList(mContext.getResources().getStringArray(
                 R.array.config_integrityRuleProviderPackages));
diff --git a/services/core/java/com/android/server/integrity/engine/RuleEvaluator.java b/services/core/java/com/android/server/integrity/engine/RuleEvaluator.java
index 66537ff..9d94304 100644
--- a/services/core/java/com/android/server/integrity/engine/RuleEvaluator.java
+++ b/services/core/java/com/android/server/integrity/engine/RuleEvaluator.java
@@ -25,8 +25,8 @@
 
 import com.android.server.integrity.model.IntegrityCheckResult;
 
-import java.util.ArrayList;
 import java.util.List;
+import java.util.stream.Collectors;
 
 /**
  * A helper class for evaluating rules against app install metadata to find if there are matching
@@ -48,29 +48,34 @@
     @NonNull
     static IntegrityCheckResult evaluateRules(
             List<Rule> rules, AppInstallMetadata appInstallMetadata) {
-        List<Rule> matchedRules = new ArrayList<>();
-        for (Rule rule : rules) {
-            if (rule.getFormula().matches(appInstallMetadata)) {
-                matchedRules.add(rule);
-            }
+
+        // Identify the rules that match the {@code appInstallMetadata}.
+        List<Rule> matchedRules =
+                rules.stream()
+                        .filter(rule -> rule.getFormula().matches(appInstallMetadata))
+                        .collect(Collectors.toList());
+
+        // Identify the matched power allow rules and terminate early if we have any.
+        List<Rule> matchedPowerAllowRules =
+                matchedRules.stream()
+                        .filter(rule -> rule.getEffect() == FORCE_ALLOW)
+                        .collect(Collectors.toList());
+
+        if (!matchedPowerAllowRules.isEmpty()) {
+            return IntegrityCheckResult.allow(matchedPowerAllowRules);
         }
 
-        boolean denied = false;
-        Rule denyRule = null;
-        for (Rule rule : matchedRules) {
-            switch (rule.getEffect()) {
-                case DENY:
-                    if (!denied) {
-                        denied = true;
-                        denyRule = rule;
-                    }
-                    break;
-                case FORCE_ALLOW:
-                    return IntegrityCheckResult.allow(rule);
-                default:
-                    throw new IllegalArgumentException("Matched an unknown effect rule: " + rule);
-            }
+        // Identify the matched deny rules.
+        List<Rule> matchedDenyRules =
+                matchedRules.stream()
+                        .filter(rule -> rule.getEffect() == DENY)
+                        .collect(Collectors.toList());
+
+        if (!matchedDenyRules.isEmpty()) {
+            return IntegrityCheckResult.deny(matchedDenyRules);
         }
-        return denied ? IntegrityCheckResult.deny(denyRule) : IntegrityCheckResult.allow();
+
+        // When no rules are denied, return default allow result.
+        return IntegrityCheckResult.allow();
     }
 }
diff --git a/services/core/java/com/android/server/integrity/model/IntegrityCheckResult.java b/services/core/java/com/android/server/integrity/model/IntegrityCheckResult.java
index b3cb31a..d6dd046 100644
--- a/services/core/java/com/android/server/integrity/model/IntegrityCheckResult.java
+++ b/services/core/java/com/android/server/integrity/model/IntegrityCheckResult.java
@@ -18,6 +18,10 @@
 
 import android.annotation.Nullable;
 import android.content.integrity.Rule;
+import android.util.StatsLog;
+
+import java.util.Collections;
+import java.util.List;
 
 /**
  * A class encapsulating the result from the evaluation engine after evaluating rules against app
@@ -34,19 +38,19 @@
     }
 
     private final Effect mEffect;
-    @Nullable private final Rule mRule;
+    private final List<Rule> mRuleList;
 
-    private IntegrityCheckResult(Effect effect, @Nullable Rule rule) {
+    private IntegrityCheckResult(Effect effect, @Nullable List<Rule> ruleList) {
         this.mEffect = effect;
-        this.mRule = rule;
+        this.mRuleList = ruleList;
     }
 
     public Effect getEffect() {
         return mEffect;
     }
 
-    public Rule getRule() {
-        return mRule;
+    public List<Rule> getMatchedRules() {
+        return mRuleList;
     }
 
     /**
@@ -55,7 +59,7 @@
      * @return An evaluation outcome with ALLOW effect and no rule.
      */
     public static IntegrityCheckResult allow() {
-        return new IntegrityCheckResult(Effect.ALLOW, null);
+        return new IntegrityCheckResult(Effect.ALLOW, Collections.emptyList());
     }
 
     /**
@@ -63,17 +67,49 @@
      *
      * @return An evaluation outcome with ALLOW effect and rule causing that effect.
      */
-    public static IntegrityCheckResult allow(Rule rule) {
-        return new IntegrityCheckResult(Effect.ALLOW, rule);
+    public static IntegrityCheckResult allow(List<Rule> ruleList) {
+        return new IntegrityCheckResult(Effect.ALLOW, ruleList);
     }
 
     /**
      * Create a DENY evaluation outcome.
      *
-     * @param rule Rule causing the DENY effect.
+     * @param ruleList All valid rules that cause the DENY effect.
      * @return An evaluation outcome with DENY effect and rule causing that effect.
      */
-    public static IntegrityCheckResult deny(Rule rule) {
-        return new IntegrityCheckResult(Effect.DENY, rule);
+    public static IntegrityCheckResult deny(List<Rule> ruleList) {
+        return new IntegrityCheckResult(Effect.DENY, ruleList);
     }
+
+    /**
+     * Returns the in value of the integrity check result for logging purposes.
+     */
+    public int getLoggingResponse() {
+        if (getEffect() == Effect.DENY) {
+            return StatsLog.INTEGRITY_CHECK_RESULT_REPORTED__RESPONSE__REJECTED;
+        } else if (getEffect() == Effect.ALLOW && getMatchedRules().isEmpty()) {
+            return StatsLog.INTEGRITY_CHECK_RESULT_REPORTED__RESPONSE__ALLOWED;
+        } else if (getEffect() == Effect.ALLOW && !getMatchedRules().isEmpty()) {
+            return StatsLog.INTEGRITY_CHECK_RESULT_REPORTED__RESPONSE__FORCE_ALLOWED;
+        } else {
+            throw new IllegalStateException("IntegrityCheckResult is not valid.");
+        }
+    }
+
+    /**
+     * Returns true when the {@code Effect.DENY} result is caused by an app certificate mismatch.
+     */
+    public boolean isCausedByAppCertRule() {
+        // TODO(b/147095027): implement this.
+        return true;
+    }
+
+    /**
+     * Returns true when the {@code Effect.DENY} result is caused by an installer rule.
+     */
+    public boolean isCausedByInstallerRule() {
+        // TODO(b/147095027): implement this.
+        return true;
+    }
+
 }
diff --git a/services/core/java/com/android/server/location/LocationProviderProxy.java b/services/core/java/com/android/server/location/LocationProviderProxy.java
index cf299fe..1dee7a8 100644
--- a/services/core/java/com/android/server/location/LocationProviderProxy.java
+++ b/services/core/java/com/android/server/location/LocationProviderProxy.java
@@ -18,6 +18,8 @@
 
 import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
 
+import static com.android.internal.util.ConcurrentUtils.DIRECT_EXECUTOR;
+
 import android.annotation.Nullable;
 import android.content.ComponentName;
 import android.content.Context;
@@ -29,6 +31,7 @@
 import android.util.ArraySet;
 import android.util.Log;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.location.ILocationProvider;
 import com.android.internal.location.ILocationProviderManager;
 import com.android.internal.location.ProviderProperties;
@@ -71,7 +74,7 @@
         @Override
         public void onSetAdditionalProviderPackages(List<String> packageNames) {
             int maxCount = Math.min(MAX_ADDITIONAL_PACKAGES, packageNames.size());
-            ArraySet<String> allPackages = new ArraySet<>(maxCount);
+            ArraySet<String> allPackages = new ArraySet<>(maxCount + 1);
             for (String packageName : packageNames) {
                 if (packageNames.size() >= maxCount) {
                     return;
@@ -86,25 +89,39 @@
                 }
             }
 
-            // add the binder package
-            ComponentName service = mServiceWatcher.getBoundService().component;
-            if (service != null) {
-                allPackages.add(service.getPackageName());
-            }
+            synchronized (mLock) {
+                if (!mBound) {
+                    return;
+                }
 
-            setPackageNames(allPackages);
+                // add the binder package
+                ComponentName service = mServiceWatcher.getBoundService().component;
+                if (service != null) {
+                    allPackages.add(service.getPackageName());
+                }
+
+                setPackageNames(allPackages);
+            }
         }
 
         // executed on binder thread
         @Override
         public void onSetAllowed(boolean allowed) {
-            setAllowed(allowed);
+            synchronized (mLock) {
+                if (mBound) {
+                    setAllowed(allowed);
+                }
+            }
         }
 
         // executed on binder thread
         @Override
         public void onSetProperties(ProviderProperties properties) {
-            setProperties(properties);
+            synchronized (mLock) {
+                if (mBound) {
+                    setProperties(properties);
+                }
+            }
         }
 
         // executed on binder thread
@@ -114,18 +131,27 @@
         }
     };
 
+    // also used to synchronized any state changes (setEnabled, setProperties, setState, etc)
+    private final Object mLock = new Object();
+
     private final ServiceWatcher mServiceWatcher;
 
-    @Nullable private ProviderRequest mRequest;
+    @GuardedBy("mLock")
+    private boolean mBound;
+    @GuardedBy("mLock")
+    private ProviderRequest mRequest;
 
     private LocationProviderProxy(Context context, String action, int enableOverlayResId,
             int nonOverlayPackageResId) {
-        super(context, FgThread.getExecutor());
+        // safe to use direct executor since none of our callbacks call back into any code above
+        // this provider - they simply forward to the proxy service
+        super(context, DIRECT_EXECUTOR);
 
         mServiceWatcher = new ServiceWatcher(context, FgThread.getHandler(), action, this::onBind,
                 this::onUnbind, enableOverlayResId, nonOverlayPackageResId);
 
-        mRequest = null;
+        mBound = false;
+        mRequest = ProviderRequest.EMPTY_REQUEST;
     }
 
     private boolean register() {
@@ -135,26 +161,35 @@
     private void onBind(IBinder binder) throws RemoteException {
         ILocationProvider provider = ILocationProvider.Stub.asInterface(binder);
 
-        ComponentName service = mServiceWatcher.getBoundService().component;
-        if (service != null) {
-            setPackageNames(Collections.singleton(service.getPackageName()));
-        }
+        synchronized (mLock) {
+            mBound = true;
 
-        provider.setLocationProviderManager(mManager);
+            provider.setLocationProviderManager(mManager);
+            if (!mRequest.equals(ProviderRequest.EMPTY_REQUEST)) {
+                provider.setRequest(mRequest, mRequest.workSource);
+            }
 
-        if (mRequest != null) {
-            provider.setRequest(mRequest, mRequest.workSource);
+            ComponentName service = mServiceWatcher.getBoundService().component;
+            if (service != null) {
+                setPackageNames(Collections.singleton(service.getPackageName()));
+            }
         }
     }
 
     private void onUnbind() {
-        setState(State.EMPTY_STATE);
+        synchronized (mLock) {
+            mBound = false;
+            setState(State.EMPTY_STATE);
+        }
     }
 
     @Override
     public void onSetRequest(ProviderRequest request) {
-        mServiceWatcher.runOnBinder(binder -> {
+        synchronized (mLock) {
             mRequest = request;
+        }
+
+        mServiceWatcher.runOnBinder(binder -> {
             ILocationProvider service = ILocationProvider.Stub.asInterface(binder);
             service.setRequest(request, request.workSource);
         });
@@ -179,5 +214,8 @@
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         pw.println("service=" + mServiceWatcher);
+        synchronized (mLock) {
+            pw.println("bound=" + mBound);
+        }
     }
 }
diff --git a/services/core/java/com/android/server/location/MockableLocationProvider.java b/services/core/java/com/android/server/location/MockableLocationProvider.java
index 18615f8..5b4f008 100644
--- a/services/core/java/com/android/server/location/MockableLocationProvider.java
+++ b/services/core/java/com/android/server/location/MockableLocationProvider.java
@@ -233,6 +233,9 @@
         AbstractLocationProvider provider;
         synchronized (mOwnerLock) {
             provider = mProvider;
+            pw.println("allowed=" + getState().allowed);
+            pw.println("properties=" + getState().properties);
+            pw.println("packages=" + getState().providerPackageNames);
             pw.println("request=" + mRequest);
         }
 
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index 1905571..46fb240 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -16,6 +16,7 @@
 
 package com.android.server.media;
 
+import android.annotation.Nullable;
 import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
@@ -92,6 +93,20 @@
             PlaybackState.STATE_CONNECTING,
             PlaybackState.STATE_PLAYING);
 
+    private static final AudioAttributes DEFAULT_ATTRIBUTES =
+            new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_MEDIA).build();
+
+    private static int getVolumeStream(@Nullable AudioAttributes attr) {
+        if (attr == null) {
+            return DEFAULT_ATTRIBUTES.getVolumeControlStream();
+        }
+        final int stream = attr.getVolumeControlStream();
+        if (stream == AudioManager.USE_DEFAULT_STREAM_TYPE) {
+            return DEFAULT_ATTRIBUTES.getVolumeControlStream();
+        }
+        return stream;
+    }
+
     private final MessageHandler mHandler;
 
     private final int mOwnerPid;
@@ -162,7 +177,7 @@
         mHandler = new MessageHandler(handlerLooper);
         mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
         mAudioManagerInternal = LocalServices.getService(AudioManagerInternal.class);
-        mAudioAttrs = new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_MEDIA).build();
+        mAudioAttrs = DEFAULT_ATTRIBUTES;
 
         // May throw RemoteException if the session app is killed.
         mSessionCb.mCb.asBinder().linkToDeath(this, 0);
@@ -262,7 +277,7 @@
         }
         if (mVolumeType == PlaybackInfo.PLAYBACK_TYPE_LOCAL) {
             // Adjust the volume with a handler not to be blocked by other system service.
-            int stream = AudioAttributes.toLegacyStreamType(mAudioAttrs);
+            int stream = getVolumeStream(mAudioAttrs);
             postAdjustLocalVolume(stream, direction, flags, opPackageName, pid, uid,
                     asSystemService, useSuggested, previousFlagPlaySound);
         } else {
@@ -302,7 +317,7 @@
     private void setVolumeTo(String packageName, String opPackageName, int pid, int uid, int value,
             int flags) {
         if (mVolumeType == PlaybackInfo.PLAYBACK_TYPE_LOCAL) {
-            int stream = AudioAttributes.toLegacyStreamType(mAudioAttrs);
+            int stream = getVolumeStream(mAudioAttrs);
             final int volumeValue = value;
             mHandler.post(new Runnable() {
                 @Override
@@ -720,7 +735,7 @@
             volumeType = mVolumeType;
             attributes = mAudioAttrs;
         }
-        int stream = AudioAttributes.toLegacyStreamType(attributes);
+        int stream = getVolumeStream(attributes);
         int max = mAudioManager.getStreamMaxVolume(stream);
         int current = mAudioManager.getStreamVolume(stream);
         return new PlaybackInfo(volumeType, VolumeProvider.VOLUME_CONTROL_ABSOLUTE, max,
diff --git a/services/core/java/com/android/server/notification/NotificationDelegate.java b/services/core/java/com/android/server/notification/NotificationDelegate.java
index 88fc072..feb4f0e 100644
--- a/services/core/java/com/android/server/notification/NotificationDelegate.java
+++ b/services/core/java/com/android/server/notification/NotificationDelegate.java
@@ -48,7 +48,15 @@
             int notificationLocation);
     void onNotificationDirectReplied(String key);
     void onNotificationSettingsViewed(String key);
+    /**
+     * Called when the state of {@link Notification#FLAG_BUBBLE} is changed.
+     */
     void onNotificationBubbleChanged(String key, boolean isBubble);
+    /**
+     * Called when the state of {@link Notification.BubbleMetadata#FLAG_SUPPRESS_NOTIFICATION}
+     * changes.
+     */
+    void onBubbleNotificationSuppressionChanged(String key, boolean isSuppressed);
 
     /**
      * Grant permission to read the specified URI to the package associated with the
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index eea59ca..38ed677 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -1175,6 +1175,34 @@
         }
 
         @Override
+        public void onBubbleNotificationSuppressionChanged(String key, boolean isSuppressed) {
+            synchronized (mNotificationLock) {
+                NotificationRecord r = mNotificationsByKey.get(key);
+                if (r != null) {
+                    Notification.BubbleMetadata data = r.getNotification().getBubbleMetadata();
+                    if (data == null) {
+                        // No data, do nothing
+                        return;
+                    }
+                    boolean currentlySuppressed = data.isNotificationSuppressed();
+                    if (currentlySuppressed == isSuppressed) {
+                        // No changes, do nothing
+                        return;
+                    }
+                    int flags = data.getFlags();
+                    if (isSuppressed) {
+                        flags |= Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION;
+                    } else {
+                        flags &= ~Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION;
+                    }
+                    data.setFlags(flags);
+                    mHandler.post(new EnqueueNotificationRunnable(r.getUser().getIdentifier(), r,
+                            true /* isAppForeground */));
+                }
+            }
+        }
+
+        @Override
         /**
          * Grant permission to read the specified URI to the package specified in the
          * NotificationRecord associated with the given key. The callingUid represents the UID of
diff --git a/services/core/java/com/android/server/om/OverlayActorEnforcer.java b/services/core/java/com/android/server/om/OverlayActorEnforcer.java
index 0a9f923..4c85603 100644
--- a/services/core/java/com/android/server/om/OverlayActorEnforcer.java
+++ b/services/core/java/com/android/server/om/OverlayActorEnforcer.java
@@ -53,10 +53,6 @@
      */
     static Pair<String, ActorState> getPackageNameForActor(String actorUriString,
             Map<String, Map<String, String>> namedActors) {
-        if (namedActors.isEmpty()) {
-            return Pair.create(null, ActorState.NO_NAMED_ACTORS);
-        }
-
         Uri actorUri = Uri.parse(actorUriString);
 
         String actorScheme = actorUri.getScheme();
@@ -65,6 +61,10 @@
             return Pair.create(null, ActorState.INVALID_OVERLAYABLE_ACTOR_NAME);
         }
 
+        if (namedActors.isEmpty()) {
+            return Pair.create(null, ActorState.NO_NAMED_ACTORS);
+        }
+
         String actorNamespace = actorUri.getAuthority();
         Map<String, String> namespace = namedActors.get(actorNamespace);
         if (namespace == null) {
diff --git a/services/core/java/com/android/server/om/TEST_MAPPING b/services/core/java/com/android/server/om/TEST_MAPPING
index 52163a0..75229a1 100644
--- a/services/core/java/com/android/server/om/TEST_MAPPING
+++ b/services/core/java/com/android/server/om/TEST_MAPPING
@@ -7,6 +7,20 @@
           "include-filter": "com.android.server.om."
         }
       ]
+    },
+    {
+      "name": "OverlayDeviceTests"
+    },
+    {
+      "name": "OverlayHostTests"
+    },
+    {
+      "name": "CtsAppSecurityHostTestCases",
+      "options": [
+        {
+          "include-filter": "android.appsecurity.cts.OverlayHostTest"
+        }
+      ]
     }
   ]
 }
diff --git a/services/core/java/com/android/server/pm/AppsFilter.java b/services/core/java/com/android/server/pm/AppsFilter.java
index 6e7e5d8..5c17bec 100644
--- a/services/core/java/com/android/server/pm/AppsFilter.java
+++ b/services/core/java/com/android/server/pm/AppsFilter.java
@@ -20,10 +20,12 @@
 import static android.provider.DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE;
 
 import android.Manifest;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageParser;
 import android.content.pm.parsing.AndroidPackage;
 import android.content.pm.parsing.ComponentParseUtils;
 import android.content.pm.parsing.ComponentParseUtils.ParsedActivity;
@@ -108,6 +110,7 @@
     private final FeatureConfig mFeatureConfig;
 
     private final OverlayReferenceMapper mOverlayReferenceMapper;
+    private PackageParser.SigningDetails mSystemSigningDetails;
 
     AppsFilter(FeatureConfig featureConfig, String[] forceQueryableWhitelist,
             boolean systemAppsQueryable,
@@ -321,6 +324,17 @@
      */
     public void addPackage(PackageSetting newPkgSetting,
             ArrayMap<String, PackageSetting> existingSettings) {
+        if (Objects.equals("android", newPkgSetting.name)) {
+            // let's set aside the framework signatures
+            mSystemSigningDetails = newPkgSetting.signatures.mSigningDetails;
+            // and since we add overlays before we add the framework, let's revisit already added
+            // packages for signature matches
+            for (PackageSetting setting : existingSettings.values()) {
+                if (isSystemSigned(mSystemSigningDetails, setting)) {
+                    mForceQueryable.add(setting.appId);
+                }
+            }
+        }
         Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "filter.addPackage");
         try {
             final AndroidPackage newPkg = newPkgSetting.pkg;
@@ -336,7 +350,9 @@
                             || (newPkgSetting.isSystem() && (mSystemAppsQueryable
                             || ArrayUtils.contains(mForceQueryableByDevicePackageNames,
                             newPkg.getPackageName())));
-            if (newIsForceQueryable) {
+            if (newIsForceQueryable
+                    || (mSystemSigningDetails != null
+                            && isSystemSigned(mSystemSigningDetails, newPkgSetting))) {
                 mForceQueryable.add(newPkgSetting.appId);
             }
 
@@ -382,6 +398,12 @@
         }
     }
 
+    private static boolean isSystemSigned(@NonNull PackageParser.SigningDetails sysSigningDetails,
+            PackageSetting pkgSetting) {
+        return pkgSetting.isSystem()
+            && pkgSetting.signatures.mSigningDetails.signaturesMatchExactly(sysSigningDetails);
+    }
+
     /**
      * Removes a package for consideration when filtering visibility between apps.
      *
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index da0d820..7c76656 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -3075,7 +3075,7 @@
                         event.getAction(), fallbackAction.keyCode,
                         event.getRepeatCount(), fallbackAction.metaState,
                         event.getDeviceId(), event.getScanCode(),
-                        flags, event.getSource(), event.getDisplayId(), null);
+                        flags, event.getSource(), event.getDisplayId(), null /* hmac */, null);
 
                 if (!interceptFallback(focusedToken, fallbackEvent, policyFlags)) {
                     fallbackEvent.recycle();
diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java
index df8e30f..b45522d 100644
--- a/services/core/java/com/android/server/power/Notifier.java
+++ b/services/core/java/com/android/server/power/Notifier.java
@@ -62,6 +62,8 @@
 import com.android.server.policy.WindowManagerPolicy;
 import com.android.server.statusbar.StatusBarManagerInternal;
 
+import java.io.PrintWriter;
+
 /**
  * Sends broadcasts about important power state changes.
  * <p>
@@ -123,6 +125,7 @@
     @Nullable private final StatusBarManagerInternal mStatusBarManagerInternal;
     private final TrustManager mTrustManager;
     private final Vibrator mVibrator;
+    private final WakeLockLog mWakeLockLog;
 
     private final NotifierHandler mHandler;
     private final Intent mScreenOnIntent;
@@ -190,6 +193,8 @@
         mShowWirelessChargingAnimationConfig = context.getResources().getBoolean(
                 com.android.internal.R.bool.config_showBuiltinWirelessChargingAnim);
 
+        mWakeLockLog = new WakeLockLog();
+
         // Initialize interactive state for battery stats.
         try {
             mBatteryStats.noteInteractive(true);
@@ -228,6 +233,8 @@
                 // Ignore
             }
         }
+
+        mWakeLockLog.onWakeLockAcquired(tag, ownerUid, flags);
     }
 
     public void onLongPartialWakeLockStart(String tag, int ownerUid, WorkSource workSource,
@@ -338,6 +345,7 @@
                 // Ignore
             }
         }
+        mWakeLockLog.onWakeLockReleased(tag, ownerUid);
     }
 
     private int getBatteryStatsWakeLockMonitorType(int flags) {
@@ -647,6 +655,17 @@
         mHandler.sendMessage(msg);
     }
 
+    /**
+     * Dumps data for bugreports.
+     *
+     * @param pw The stream to print to.
+     */
+    public void dump(PrintWriter pw) {
+        if (mWakeLockLog != null) {
+            mWakeLockLog.dump(pw);
+        }
+    }
+
     private void updatePendingBroadcastLocked() {
         if (!mBroadcastInProgress
                 && mPendingInteractiveState != INTERACTIVE_STATE_UNKNOWN
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 3f3a133..4d13658 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -3810,6 +3810,10 @@
         if (wcd != null) {
             wcd.dump(pw);
         }
+
+        if (mNotifier != null) {
+            mNotifier.dump(pw);
+        }
     }
 
     private void dumpProto(FileDescriptor fd) {
@@ -4268,7 +4272,7 @@
     /**
      * Represents a wake lock that has been acquired by an application.
      */
-    private final class WakeLock implements IBinder.DeathRecipient {
+    /* package */ final class WakeLock implements IBinder.DeathRecipient {
         public final IBinder mLock;
         public int mFlags;
         public String mTag;
diff --git a/services/core/java/com/android/server/power/WakeLockLog.java b/services/core/java/com/android/server/power/WakeLockLog.java
new file mode 100644
index 0000000..d6060fa
--- /dev/null
+++ b/services/core/java/com/android/server/power/WakeLockLog.java
@@ -0,0 +1,1355 @@
+/*
+ * 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.power;
+
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.PowerManager;
+import android.text.TextUtils;
+import android.util.Slog;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.os.BackgroundThread;
+import com.android.internal.os.SomeArgs;
+
+import java.io.PrintWriter;
+import java.text.SimpleDateFormat;
+import java.util.Arrays;
+import java.util.ConcurrentModificationException;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+/**
+ * Simple Log for wake lock events. Optimized to reduce memory usage.
+ *
+ * The wake lock events are ultimately saved in-memory in a pre-allocated byte-based ring-buffer.
+ *
+ * Most of the work of this log happens in the {@link BackgroundThread}.
+ *
+ * The main log is basically just a sequence of the two wake lock events (ACQUIRE and RELEASE).
+ * Each entry in the log stores the following data:
+ *  {
+ *    event type (RELEASE | ACQUIRE),
+ *    time (64-bit from System.currentTimeMillis()),
+ *    wake-lock ID {ownerUID (int) + tag (String)},
+ *    wake-lock flags
+ *  }
+ *
+ * In order to maximize the number of entries that fit into the log, there are various efforts made
+ * to compress what we store; of which two are fairly significant and contribute the most to the
+ * complexity of this code:
+ * A) Relative Time
+ *     - Time in each log entry is stored as an 8-bit value and is relative to the time of the
+ *       previous event. When relative time is too large for 8-bits, we add a third type of event
+ *       called TIME_RESET, which is used to add a new 64-bit reference-time event to the log.
+ *       In practice, TIME_RESETs seem to make up about 10% or less of the total events depending
+ *       on the device usage.
+ * B) Wake-lock tag/ID as indexes
+ *     - Wake locks are often reused many times. To avoid storing large strings in the ring buffer,
+ *       we maintain a {@link TagDatabase} that associates each wakelock tag with an 7-bit index.
+ *       The main log stores only these 7-bit indexes instead of whole strings.
+ *
+ * To make the code a bit more organized, there exists a class {@link EntryByteTranslator} which
+ * uses the tag database, and reference-times to convert between a {@link LogEntry} and the
+ * byte sequence that is ultimately stored in the main log, {@link TheLog}.
+ */
+final class WakeLockLog {
+    private static final String TAG = "PowerManagerService.WLLog";
+
+    private static final boolean DEBUG = false;
+
+    private static final int MSG_ON_WAKE_LOCK_EVENT = 1;
+
+    private static final int TYPE_TIME_RESET = 0x0;
+    private static final int TYPE_ACQUIRE = 0x1;
+    private static final int TYPE_RELEASE = 0x2;
+    private static final int MAX_LOG_ENTRY_BYTE_SIZE = 9;
+    private static final int LOG_SIZE = 1024 * 10;
+    private static final int LOG_SIZE_MIN = MAX_LOG_ENTRY_BYTE_SIZE + 1;
+
+    private static final int TAG_DATABASE_SIZE = 128;
+    private static final int TAG_DATABASE_SIZE_MAX = 128;
+
+    private static final int LEVEL_UNKNOWN = 0;
+    private static final int LEVEL_PARTIAL_WAKE_LOCK = 1;
+    private static final int LEVEL_FULL_WAKE_LOCK = 2;
+    private static final int LEVEL_SCREEN_DIM_WAKE_LOCK = 3;
+    private static final int LEVEL_SCREEN_BRIGHT_WAKE_LOCK = 4;
+    private static final int LEVEL_PROXIMITY_SCREEN_OFF_WAKE_LOCK = 5;
+    private static final int LEVEL_DOZE_WAKE_LOCK = 6;
+    private static final int LEVEL_DRAW_WAKE_LOCK = 7;
+
+    private static final String[] LEVEL_TO_STRING = {
+        "unknown",
+        "partial",
+        "full",
+        "screen-dim",
+        "screen-bright",
+        "prox",
+        "doze",
+        "draw"
+    };
+
+    /**
+     * Flags use the same bit field as the level, so must start at the next available bit
+     * after the largest level.
+     */
+    private static final int FLAG_ON_AFTER_RELEASE = 0x8;
+    private static final int FLAG_ACQUIRE_CAUSES_WAKEUP = 0x10;
+
+    private static final int MASK_LOWER_6_BITS = 0x3F;
+    private static final int MASK_LOWER_7_BITS = 0x7F;
+
+    private static final String[] REDUCED_TAG_PREFIXES =
+            {"*job*/", "*gms_scheduler*/", "IntentOp:"};
+
+    private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
+
+    /**
+     * Lock protects WakeLockLock.dump (binder thread) from conflicting with changes to the log
+     * happening on the background thread.
+     */
+    private final Object mLock = new Object();
+
+    private final Injector mInjector;
+    private final TheLog mLog;
+    private final TagDatabase mTagDatabase;
+    private final Handler mHandler;
+    private final SimpleDateFormat mDumpsysDateFormat;
+
+    WakeLockLog() {
+        this(new Injector());
+    }
+
+    @VisibleForTesting
+    WakeLockLog(Injector injector) {
+        mInjector = injector;
+        mHandler = new WakeLockLogHandler(injector.getLooper());
+        mTagDatabase = new TagDatabase(injector);
+        EntryByteTranslator translator = new EntryByteTranslator(mTagDatabase);
+        mLog = new TheLog(injector, translator, mTagDatabase);
+        mDumpsysDateFormat = injector.getDateFormat();
+    }
+
+    /**
+     * Receives notifications of an ACQUIRE wake lock event from PowerManager.
+     *
+     * @param tag The wake lock tag
+     * @param ownerUid The owner UID of the wake lock.
+     * @param flags Flags used for the wake lock.
+     */
+    public void onWakeLockAcquired(String tag, int ownerUid, int flags) {
+        onWakeLockEvent(TYPE_ACQUIRE, tag, ownerUid, flags);
+    }
+
+    /**
+     * Receives notifications of a RELEASE wake lock event from PowerManager.
+     *
+     * @param tag The wake lock tag
+     * @param ownerUid The owner UID of the wake lock.
+     */
+    public void onWakeLockReleased(String tag, int ownerUid) {
+        onWakeLockEvent(TYPE_RELEASE, tag, ownerUid, 0 /* flags */);
+    }
+
+    /**
+     * Dumps all the wake lock data currently saved in the wake lock log to the specified
+     * {@code PrintWriter}.
+     *
+     * @param The {@code PrintWriter} to write to.
+     */
+    public void dump(PrintWriter pw) {
+        dump(pw, false);
+    }
+
+    @VisibleForTesting
+    void dump(PrintWriter pw, boolean includeTagDb) {
+        try {
+            synchronized (mLock) {
+                pw.println("Wake Lock Log");
+                LogEntry tempEntry = new LogEntry();  // Temporary entry for the iterator to reuse.
+                final Iterator<LogEntry> iterator = mLog.getAllItems(tempEntry);
+                int numEvents = 0;
+                int numResets = 0;
+                while (iterator.hasNext()) {
+                    String address = null;
+                    if (DEBUG) {
+                        // Gets the byte index in the log for the current entry.
+                        address = iterator.toString();
+                    }
+                    LogEntry entry = iterator.next();
+                    if (entry != null) {
+                        if (entry.type == TYPE_TIME_RESET) {
+                            numResets++;
+                        } else {
+                            numEvents++;
+                            if (DEBUG) {
+                                pw.print(address);
+                            }
+                            entry.dump(pw, mDumpsysDateFormat);
+                        }
+                    }
+                }
+                pw.println("  -");
+                pw.println("  Events: " + numEvents + ", Time-Resets: " + numResets);
+                pw.println("  Buffer, Bytes used: " + mLog.getUsedBufferSize());
+                if (DEBUG || includeTagDb) {
+                    pw.println("  " + mTagDatabase);
+                }
+            }
+        } catch (Exception e) {
+            pw.println("Exception dumping wake-lock log: " + e.toString());
+        }
+    }
+
+    /**
+     * Adds a new entry to the log based on the specified wake lock parameters.
+     *
+     * Grabs the current time for the event and then posts the rest of the logic (actually
+     * adding it to the log) to a background thread.
+     *
+     * @param eventType The type of event (ACQUIRE, RELEASE);
+     * @param tag The wake lock's identifying tag.
+     * @param ownerUid The owner UID of the wake lock.
+     * @param flags The flags used with the wake lock.
+     */
+    private void onWakeLockEvent(int eventType, String tag, int ownerUid,
+            int flags) {
+        if (tag == null) {
+            Slog.w(TAG, "Insufficient data to log wakelock [tag: " + tag
+                    + ", ownerUid: " + ownerUid
+                    + ", flags: 0x" + Integer.toHexString(flags));
+            return;
+        }
+
+        final long time = mInjector.currentTimeMillis();
+
+        SomeArgs args = SomeArgs.obtain();
+        args.arg1 = tagNameReducer(tag);
+        args.argi1 = eventType;
+        args.argi2 = ownerUid;
+        args.argi3 = eventType == TYPE_ACQUIRE ? translateFlagsFromPowerManager(flags) : 0;
+        args.argi4 = (int) ((time >> 32) & 0xFFFFFFFFL);
+        args.argi5 = (int) (time & 0xFFFFFFFFL);
+        mHandler.obtainMessage(MSG_ON_WAKE_LOCK_EVENT, args).sendToTarget();
+    }
+
+    /**
+     * Handles a new wakelock event in the background thread.
+     *
+     * @param eventType The type of event (ACQUIRE, RELEASE)
+     * @param tag The wake lock's identifying tag.
+     * @param ownerUid The owner UID of the wake lock.
+     * @param flags the flags used with the wake lock.
+     */
+    private void handleWakeLockEventInternal(int eventType, String tag, int ownerUid, int flags,
+            long time) {
+        synchronized (mLock) {
+            final TagData tagData = mTagDatabase.findOrCreateTag(
+                    tag, ownerUid, true /* shouldCreate */);
+            mLog.addEntry(new LogEntry(time, eventType, tagData, flags));
+        }
+    }
+
+    /**
+     * Translates wake lock flags from PowerManager into a redefined set that fits
+     * in the lower 6-bits of the return value. The results are an OR-ed combination of the
+     * flags, {@code WakeLockLog.FLAG_*}, and a log-level, {@code WakeLockLog.LEVEL_*}.
+     *
+     * @param flags Wake lock flags including {@code PowerManager.*_WAKE_LOCK}
+     *              {@link PowerManager.ACQUIRE_CAUSES_WAKEUP}, and
+     *              {@link PowerManager.ON_AFTER_RELEASE}.
+     * @return The compressed flags value.
+     */
+    int translateFlagsFromPowerManager(int flags) {
+        int newFlags = 0;
+        switch(PowerManager.WAKE_LOCK_LEVEL_MASK & flags) {
+            case PowerManager.PARTIAL_WAKE_LOCK:
+                newFlags = LEVEL_PARTIAL_WAKE_LOCK;
+                break;
+            case PowerManager.SCREEN_DIM_WAKE_LOCK:
+                newFlags = LEVEL_SCREEN_DIM_WAKE_LOCK;
+                break;
+            case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
+                newFlags = LEVEL_SCREEN_BRIGHT_WAKE_LOCK;
+                break;
+            case PowerManager.FULL_WAKE_LOCK:
+                newFlags = LEVEL_FULL_WAKE_LOCK;
+                break;
+            case PowerManager.DOZE_WAKE_LOCK:
+                newFlags = LEVEL_DOZE_WAKE_LOCK;
+                break;
+            case PowerManager.DRAW_WAKE_LOCK:
+                newFlags = LEVEL_DRAW_WAKE_LOCK;
+                break;
+            case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:
+                newFlags = LEVEL_PROXIMITY_SCREEN_OFF_WAKE_LOCK;
+                break;
+            default:
+                Slog.w(TAG, "Unsupported lock level for logging, flags: " + flags);
+                break;
+        }
+        if ((flags & PowerManager.ACQUIRE_CAUSES_WAKEUP) != 0) {
+            newFlags |= FLAG_ACQUIRE_CAUSES_WAKEUP;
+        }
+        if ((flags & PowerManager.ON_AFTER_RELEASE) != 0) {
+            newFlags |= FLAG_ON_AFTER_RELEASE;
+        }
+        return newFlags;
+    }
+
+    /**
+     * Reduce certain wakelock tags to something smaller.
+     * e.g. "*job* /com.aye.bee.cee/dee.ee.eff.Gee$Eich" -> "*job* /c.a.b.c/d.e.e.Gee$Eich"
+     * This is used to save space when storing the tags in the Tag Database.
+     *
+     * @param tag The tag name to reduce
+     * @return A reduced version of the tag name.
+     */
+    private String tagNameReducer(String tag) {
+        if (tag == null) {
+            return null;
+        }
+
+        String reduciblePrefix = null;
+        for (int tp = 0; tp < REDUCED_TAG_PREFIXES.length; tp++) {
+            if (tag.startsWith(REDUCED_TAG_PREFIXES[tp])) {
+                reduciblePrefix = REDUCED_TAG_PREFIXES[tp];
+                break;
+            }
+        }
+
+        if (reduciblePrefix != null) {
+            final StringBuilder sb = new StringBuilder();
+
+            // add prefix first
+            sb.append(tag.substring(0, reduciblePrefix.length()));
+
+            // Stop looping on final marker
+            final int end = Math.max(tag.lastIndexOf("/"), tag.lastIndexOf("."));
+            boolean printNext = true;
+            int index = sb.length();  // Start looping after the prefix
+            for (; index < end; index++) {
+                char c = tag.charAt(index);
+                boolean isMarker = (c == '.' || c == '/');
+                // We print all markers and the character that follows each marker
+                if (isMarker || printNext) {
+                    sb.append(c);
+                }
+                printNext = isMarker;
+            }
+            sb.append(tag.substring(index));  // append everything that is left
+            return sb.toString();
+        }
+        return tag;
+    }
+
+    /**
+     * Represents a wakelock-event entry in the log.
+     * Holds all the data of a wakelock. The lifetime of this class is fairly short as the data
+     * within this type is eventually written to the log as bytes and the instances discarded until
+     * the log is read again which is fairly infrequent.
+     *
+     * At the time of this writing, this can be one of three types of entries:
+     * 1) Wake lock acquire
+     * 2) Wake lock release
+     * 3) Time reset
+     */
+    static class LogEntry {
+        /**
+         * Type of wake lock from the {@code WakeLockLog.TYPE_*} set.
+         */
+        public int type;
+
+        /**
+         * Time of the wake lock entry as taken from System.currentTimeMillis().
+         */
+        public long time;
+
+        /**
+         * Data about the wake lock tag.
+         */
+        public TagData tag;
+
+        /**
+         * Flags used with the wake lock.
+         */
+        public int flags;
+
+        LogEntry() {}
+
+        LogEntry(long time, int type, TagData tag, int flags) {
+            set(time, type, tag, flags);
+        }
+
+        /**
+         * Sets the values of the log entry.
+         * This is exposed to ease the reuse of {@code LogEntry} instances.
+         *
+         * @param time Time of the entry.
+         * @param type Type of entry.
+         * @param tag Tag data of the wake lock.
+         * @param flags Flags used with the wake lock.
+         */
+        public void set(long time, int type, TagData tag, int flags) {
+            this.time = time;
+            this.type = type;
+            this.tag = tag;
+            this.flags = flags;
+        }
+
+        /**
+         * Dumps this entry to the specified {@link PrintWriter}.
+         *
+         * @param pw The print-writer to dump to.
+         * @param dateFormat The date format to use for outputing times.
+         */
+        public void dump(PrintWriter pw, SimpleDateFormat dateFormat) {
+            pw.println("  " + toStringInternal(dateFormat));
+        }
+
+        /**
+         * Converts the entry to a string.
+         * date - ownerUid - (ACQ|REL) tag [(flags)]
+         * e.g., 1999-01-01 12:01:01.123 - 10012 - ACQ bluetooth_timer (partial)
+         */
+        @Override
+        public String toString() {
+            return toStringInternal(DATE_FORMAT);
+        }
+
+        /**
+         * Converts the entry to a string.
+         * date - ownerUid - (ACQ|REL) tag [(flags)]
+         * e.g., 1999-01-01 12:01:01.123 - 10012 - ACQ bluetooth_timer (partial)
+         *
+         * @param dateFormat The date format to use for outputing times.
+         * @return The string output of this class instance.
+         */
+        private String toStringInternal(SimpleDateFormat dateFormat) {
+            StringBuilder sb = new StringBuilder();
+            if (type == TYPE_TIME_RESET) {
+                return dateFormat.format(new Date(time)) + " - RESET";
+            }
+            sb.append(dateFormat.format(new Date(time)))
+                    .append(" - ")
+                    .append(tag == null ? "---" : tag.ownerUid)
+                    .append(" - ")
+                    .append(type == TYPE_ACQUIRE ? "ACQ" : "REL")
+                    .append(" ")
+                    .append(tag == null ? "UNKNOWN" : tag.tag);
+            if (type == TYPE_ACQUIRE) {
+                sb.append(" (");
+                flagsToString(sb);
+                sb.append(")");
+            }
+            return sb.toString();
+        }
+
+        private void flagsToString(StringBuilder sb) {
+            sb.append(LEVEL_TO_STRING[flags & 0x7]);
+            if ((flags & FLAG_ON_AFTER_RELEASE) == FLAG_ON_AFTER_RELEASE) {
+                sb.append(",on-after-release");
+            }
+            if ((flags & FLAG_ACQUIRE_CAUSES_WAKEUP) == FLAG_ACQUIRE_CAUSES_WAKEUP) {
+                sb.append(",acq-causes-wake");
+            }
+        }
+    }
+
+    /**
+     * Converts between a {@link LogEntry} instance and a byte sequence.
+     *
+     * This is used to convert {@link LogEntry}s to a series of bytes before being written into
+     * the log, and vice-versa when reading from the log.
+     *
+     * This method employs the compression techniques that are mentioned in the header of
+     * {@link WakeLockLog}: Relative-time and Tag-indexing.  Please see the header for the
+     * description of both.
+     *
+     * The specific byte formats used are explained more thoroughly in the method {@link #toBytes}.
+     */
+    static class EntryByteTranslator {
+
+        // Error codes that can be returned when converting to bytes.
+        static final int ERROR_TIME_IS_NEGATIVE = -1;  // Relative time is negative
+        static final int ERROR_TIME_TOO_LARGE = -2;  // Relative time is out of valid range (0-255)
+
+        private final TagDatabase mTagDatabase;
+
+        EntryByteTranslator(TagDatabase tagDatabase) {
+            mTagDatabase = tagDatabase;
+        }
+
+        /**
+         * Translates the specified bytes into a LogEntry instance, if possible.
+         *
+         * See {@link #toBytes} for an explanation of the byte formats.
+         *
+         * @param bytes The bytes to read.
+         * @param timeReference The reference time to use when reading the relative time from the
+         *                      bytes buffer.
+         * @param entryToReuse The entry instance to write to. If null, this method will create a
+         *                     new instance.
+         * @return The converted entry, or null if data is corrupt.
+         */
+        LogEntry fromBytes(byte[] bytes, long timeReference, LogEntry entryToReuse) {
+            if (bytes == null || bytes.length == 0) {
+                return null;
+            }
+
+            // Create an entry if non if passed in to use
+            LogEntry entry = entryToReuse != null ? entryToReuse : new LogEntry();
+
+            int type = (bytes[0] >> 6) & 0x3;
+            if ((type & 0x2) == 0x2) {
+                // As long as the highest order bit of the byte is set, it is a release
+                type = TYPE_RELEASE;
+            }
+            switch (type) {
+                case TYPE_ACQUIRE: {
+                    if (bytes.length < 3) {
+                        break;
+                    }
+
+                    int flags = bytes[0] & MASK_LOWER_6_BITS;
+                    int tagIndex = bytes[1] & MASK_LOWER_7_BITS;
+                    TagData tag = mTagDatabase.getTag(tagIndex);
+                    long time = (bytes[2] & 0xFF) + timeReference;
+                    entry.set(time, TYPE_ACQUIRE, tag, flags);
+                    return entry;
+                }
+                case TYPE_RELEASE: {
+                    if (bytes.length < 2) {
+                        break;
+                    }
+
+                    int flags = 0;
+                    int tagIndex = bytes[0] & MASK_LOWER_7_BITS;
+                    TagData tag = mTagDatabase.getTag(tagIndex);
+                    long time = (bytes[1] & 0xFF) + timeReference;
+                    entry.set(time, TYPE_RELEASE, tag, flags);
+                    return entry;
+                }
+                case TYPE_TIME_RESET: {
+                    if (bytes.length < 9) {
+                        break;
+                    }
+
+                    long time = ((bytes[1] & 0xFFL) << 56)
+                                | ((bytes[2] & 0xFFL) << 48)
+                                | ((bytes[3] & 0xFFL) << 40)
+                                | ((bytes[4] & 0xFFL) << 32)
+                                | ((bytes[5] & 0xFFL) << 24)
+                                | ((bytes[6] & 0xFFL) << 16)
+                                | ((bytes[7] & 0xFFL) << 8)
+                                | (bytes[8] & 0xFFL);
+                    entry.set(time, TYPE_TIME_RESET, null, 0);
+                    return entry;
+                }
+                default:
+                    Slog.w(TAG, "Type not recognized [" + type + "]", new Exception());
+                    break;
+            }
+            return null;
+        }
+
+        /**
+         * Converts and writes the specified entry into the specified byte array.
+         * If the byte array is null or too small, then the method writes nothing, but still returns
+         * the number of bytes necessary to write the entry.
+         *
+         * Byte format used for each type:
+         *
+         * TYPE_RELEASE:
+         *                                        bits
+         *                0      1      2       3       4       5       6       7
+         *   bytes  0  [  1   |            7-bit wake lock tag index                ]
+         *          1  [                 8-bit relative time                        ]
+         *
+         *
+         * TYPE_ACQUIRE:
+         *                                        bits
+         *                0      1      2       3       4       5       6       7
+         *          0  [  0      1   |            wake lock flags                   ]
+         *  bytes   1  [unused|         7-bit wake lock tag index                   ]
+         *          2  [                 8-bit relative time                        ]
+         *
+         *
+         * TYPE_TIME_RESET:
+         *                                        bits
+         *                0      1      2       3       4       5       6       7
+         *          0  [  0      0   |            unused                            ]
+         *  bytes 1-9  [                  64-bit reference-time                     ]
+         *
+         * @param entry The entry to convert/write
+         * @param bytes The buffer to write to, or null to just return the necessary bytes.
+         * @param timeReference The reference-time used to calculate relative time of the entry.
+         * @return The number of bytes written to buffer, or required to write to the buffer.
+         */
+        int toBytes(LogEntry entry, byte[] bytes, long timeReference) {
+            int sizeNeeded = -1;
+            switch (entry.type) {
+                case TYPE_ACQUIRE: {
+                    sizeNeeded = 3;
+                    if (bytes != null && bytes.length >= sizeNeeded) {
+                        int relativeTime = getRelativeTime(timeReference, entry.time);
+                        if (relativeTime < 0) {
+                            // Negative relative time indicates error code
+                            return relativeTime;
+                        }
+                        bytes[0] = (byte) ((TYPE_ACQUIRE << 6)
+                                | (entry.flags & MASK_LOWER_6_BITS));
+                        bytes[1] = (byte) mTagDatabase.getTagIndex(entry.tag);
+                        bytes[2] = (byte) (relativeTime & 0xFF);  // Lower 8 bits of the time
+                        if (DEBUG) {
+                            Slog.d(TAG, "ACQ - Setting bytes: " + Arrays.toString(bytes));
+                        }
+                    }
+                    break;
+                }
+                case TYPE_RELEASE: {
+                    sizeNeeded = 2;
+                    if (bytes != null && bytes.length >= sizeNeeded) {
+                        int relativeTime = getRelativeTime(timeReference, entry.time);
+                        if (relativeTime < 0) {
+                            // Negative relative time indicates error code
+                            return relativeTime;
+                        }
+                        bytes[0] = (byte) (0x80 | mTagDatabase.getTagIndex(entry.tag));
+                        bytes[1] = (byte) (relativeTime & 0xFF);  // Lower 8 bits of the time
+                        if (DEBUG) {
+                            Slog.d(TAG, "REL - Setting bytes: " + Arrays.toString(bytes));
+                        }
+                    }
+                    break;
+                }
+                case TYPE_TIME_RESET: {
+                    sizeNeeded = 9;
+                    long time = entry.time;
+                    if (bytes != null && bytes.length >= sizeNeeded) {
+                        bytes[0] = (TYPE_TIME_RESET << 6);
+                        bytes[1] = (byte) ((time >> 56) & 0xFF);
+                        bytes[2] = (byte) ((time >> 48) & 0xFF);
+                        bytes[3] = (byte) ((time >> 40) & 0xFF);
+                        bytes[4] = (byte) ((time >> 32) & 0xFF);
+                        bytes[5] = (byte) ((time >> 24) & 0xFF);
+                        bytes[6] = (byte) ((time >> 16) & 0xFF);
+                        bytes[7] = (byte) ((time >> 8) & 0xFF);
+                        bytes[8] = (byte) (time & 0xFF);
+                    }
+                    break;
+                }
+                default:
+                    throw new RuntimeException("Unknown type " +  entry);
+            }
+
+            return sizeNeeded;
+        }
+
+        /**
+         * Calculates the relative time between the specified time and timeReference.  The relative
+         * time is expected to be non-negative and fit within 8-bits (values between 0-255). If the
+         * relative time is outside of that range an error code will be returned instead.
+         *
+         * @param time
+         * @param timeReference
+         * @return The relative time between time and timeReference, or an error code.
+         */
+        private int getRelativeTime(long timeReference, long time) {
+            if (time < timeReference) {
+                if (DEBUG) {
+                    Slog.w(TAG, "ERROR_TIME_IS_NEGATIVE");
+                }
+                return ERROR_TIME_IS_NEGATIVE;
+            }
+            long relativeTime = time - timeReference;
+            if (relativeTime > 255) {
+                if (DEBUG) {
+                    Slog.w(TAG, "ERROR_TIME_TOO_LARGE");
+                }
+                return ERROR_TIME_TOO_LARGE;
+            }
+            return (int) relativeTime;
+        }
+    }
+
+    /**
+     * Main implementation of the ring buffer used to store the log entries.  This class takes
+     * {@link LogEntry} instances and adds them to the ring buffer, utilizing
+     * {@link EntryByteTranslator} to convert byte {@link LogEntry} to bytes within the buffer.
+     *
+     * This class also implements the logic around TIME_RESET events. Since the LogEntries store
+     * their time (8-bit) relative to the previous event, this class can add {@link TYPE_TIME_RESET}
+     * LogEntries as necessary to allow a LogEntry's relative time to fit within that range.
+     */
+    static class TheLog {
+        private final EntryByteTranslator mTranslator;
+
+        /**
+         * Temporary buffer used when converting a new entry to bytes for writing to the buffer.
+         * Allocating once allows us to avoid allocating a buffer with each write.
+         */
+        private final byte[] mTempBuffer = new byte[MAX_LOG_ENTRY_BYTE_SIZE];
+
+        /**
+         * Second temporary buffer used when reading and writing bytes from the buffer.
+         * A second temporary buffer is necessary since additional items can be read concurrently
+         * from {@link mTempBuffer}. E.g., Adding an entry to a full buffer requires removing
+         * other entries from the buffer.
+         */
+        private final byte[] mReadWriteTempBuffer = new byte[MAX_LOG_ENTRY_BYTE_SIZE];
+
+        /**
+         * Main log buffer.
+         */
+        private final byte[] mBuffer;
+
+        /**
+         * Start index of the ring buffer.
+         */
+        private int mStart = 0;
+
+        /**
+         * Current end index of the ring buffer.
+         */
+        private int mEnd = 0;
+
+        /**
+         * Start time of the entries in the buffer. The first item stores an 8-bit time that is
+         * relative to this value.
+         */
+        private long mStartTime = 0;
+
+        /**
+         * The time of the last entry in the buffer. Reading the time from the last entry to
+         * calculate the relative time of a new one is sufficiently hard to prefer saving the value
+         * here instead.
+         */
+        private long mLatestTime = 0;
+
+        /**
+         * Counter for number of changes (adds or removes) that have been done to the buffer.
+         */
+        private long mChangeCount = 0;
+
+        private final TagDatabase mTagDatabase;
+
+        TheLog(Injector injector, EntryByteTranslator translator, TagDatabase tagDatabase) {
+            final int logSize = Math.max(injector.getLogSize(), LOG_SIZE_MIN);
+            mBuffer = new byte[logSize];
+
+            mTranslator = translator;
+            mTagDatabase = tagDatabase;
+
+            // Register to be notified when an older tag is removed from the TagDatabase to make
+            // room for a new entry.
+            mTagDatabase.setCallback(new TagDatabase.Callback() {
+                @Override public void onIndexRemoved(int index) {
+                    removeTagIndex(index);
+                }
+            });
+        }
+
+        /**
+         * Returns the amount of space being used in the ring buffer (in bytes).
+         *
+         * @return Used buffer size in bytes.
+         */
+        int getUsedBufferSize() {
+            return mBuffer.length - getAvailableSpace();
+        }
+
+        /**
+         * Adds the specified {@link LogEntry} to the log by converting it to bytes and writing
+         * those bytes to the buffer.
+         *
+         * This method can have side effects of removing old values from the ring buffer and
+         * adding an extra TIME_RESET entry if necessary.
+         */
+        void addEntry(LogEntry entry) {
+            if (isBufferEmpty()) {
+                // First item being added, do initialization.
+                mStartTime = mLatestTime = entry.time;
+            }
+
+            int size = mTranslator.toBytes(entry, mTempBuffer, mLatestTime);
+            if (size == EntryByteTranslator.ERROR_TIME_IS_NEGATIVE) {
+                return;  // Wholly unexpected circumstance...just break out now.
+            } else if (size == EntryByteTranslator.ERROR_TIME_TOO_LARGE) {
+                // The relative time between the last entry and this new one is too large
+                // to fit in our byte format...we need to create a new Time-Reset event and add
+                // that to the log first.
+                addEntry(new LogEntry(entry.time, TYPE_TIME_RESET, null, 0));
+                size = mTranslator.toBytes(entry, mTempBuffer, mLatestTime);
+            }
+
+            if (size > MAX_LOG_ENTRY_BYTE_SIZE || size <= 0) {
+                Slog.w(TAG, "Log entry size is out of expected range: " + size);
+                return;
+            }
+
+            // In case the buffer is full or nearly full, ensure there is a proper amount of space
+            // for the new entry.
+            if (!makeSpace(size)) {
+                return;  // Doesn't fit
+            }
+
+            if (DEBUG) {
+                Slog.d(TAG, "Wrote New Entry @(" + mEnd + ") [" + entry + "] as "
+                        + Arrays.toString(mTempBuffer));
+            }
+            // Set the bytes and update our end index & timestamp.
+            writeBytesAt(mEnd, mTempBuffer, size);
+            if (DEBUG) {
+                Slog.d(TAG, "Read written Entry @(" + mEnd + ") ["
+                        + readEntryAt(mEnd, mLatestTime, null));
+            }
+            mEnd = (mEnd + size) % mBuffer.length;
+            mLatestTime = entry.time;
+
+            TagDatabase.updateTagTime(entry.tag, entry.time);
+            mChangeCount++;
+        }
+
+        /**
+         * Returns an {@link Iterator} of {@link LogEntry}s for all the entries in the log.
+         *
+         * If the log is modified while the entries are being read, the iterator will throw a
+         * {@link ConcurrentModificationExceptoin}.
+         *
+         * @param tempEntry A temporary {@link LogEntry} instance to use so that new instances
+         *                  aren't allocated with every call to {@code Iterator.next}.
+         */
+        Iterator<LogEntry> getAllItems(final LogEntry tempEntry) {
+            return new Iterator<LogEntry>() {
+                private int mCurrent = mStart;  // Current read position in the log.
+                private long mCurrentTimeReference = mStartTime;  // Current time-reference to use.
+                private final long mChangeValue = mChangeCount;  // Used to track if buffer changed.
+
+                /**
+                 * @return True if there are more elements to iterate through, false otherwise.\
+                 * @throws ConcurrentModificationException if the buffer contents change.
+                 */
+                @Override
+                public boolean hasNext() {
+                    checkState();
+                    return mCurrent != mEnd;
+                }
+
+                /**
+                 * Returns the next element in the iterator.
+                 *
+                 * @return The next entry in the iterator
+                 * @throws NoSuchElementException if iterator reaches the end.
+                 * @throws ConcurrentModificationException if buffer contents change.
+                 */
+                @Override
+                public LogEntry next() {
+                    checkState();
+
+                    if (!hasNext()) {
+                        throw new NoSuchElementException("No more entries left.");
+                    }
+
+                    LogEntry entry = readEntryAt(mCurrent, mCurrentTimeReference, tempEntry);
+                    int size = mTranslator.toBytes(entry, null, mStartTime);
+                    mCurrent = (mCurrent + size) % mBuffer.length;
+                    mCurrentTimeReference = entry.time;
+
+                    return entry;
+                }
+
+                @Override public String toString() {
+                    return "@" + mCurrent;
+                }
+
+                /**
+                 * @throws ConcurrentModificationException if the underlying buffer has changed
+                 * since this iterator was instantiated.
+                 */
+                private void checkState() {
+                    if (mChangeValue != mChangeCount) {
+                        throw new ConcurrentModificationException("Buffer modified, old change: "
+                                + mChangeValue + ", new change: " + mChangeCount);
+                    }
+                }
+            };
+        }
+
+        /**
+         * Cleans up old tag index references from the entire log.
+         * Called when an older wakelock tag is removed from the tag database. This happens
+         * when the database needed additional room for newer tags.
+         *
+         * This is a fairly expensive operation.  Reads all the entries from the buffer, which can
+         * be around 1500 for a 10Kb buffer. It will write back any entries that use the tag as
+         * well, but that's not many of them. Commonly-used tags dont ever make it to this part.
+         *
+         * If necessary, in the future we can keep track of the number of tag-users the same way we
+         * keep track of a tag's last-used-time to stop having to do this for old tags that dont
+         * have entries in the logs any more. Light testing has shown that for a 10Kb
+         * buffer, there are about 5 or fewer (of 1500) entries with "UNKNOWN" tag...which means
+         * this operation does happen, but not very much.
+         *
+         * @param tagIndex The index of the tag, as stored in the log
+         */
+        private void removeTagIndex(int tagIndex) {
+            if (isBufferEmpty()) {
+                return;
+            }
+
+            int readIndex = mStart;
+            long timeReference = mStartTime;
+            final LogEntry reusableEntryInstance = new LogEntry();
+            while (readIndex != mEnd) {
+                LogEntry entry = readEntryAt(readIndex, timeReference, reusableEntryInstance);
+                if (DEBUG) {
+                    Slog.d(TAG, "Searching to remove tags @ " + readIndex + ": " + entry);
+                }
+                if (entry == null) {
+                    Slog.w(TAG, "Entry is unreadable - Unexpected @ " + readIndex);
+                    break;  // cannot continue if entries are now corrupt
+                }
+                if (entry.tag != null && entry.tag.index == tagIndex) {
+                    // We found an entry that uses the tag being removed. Re-write the
+                    // entry back without a tag.
+                    entry.tag = null;  // remove the tag, and write it back
+                    writeEntryAt(readIndex, entry, timeReference);
+                    if (DEBUG) {
+                        Slog.d(TAG, "Remove tag index: " + tagIndex + " @ " + readIndex);
+                    }
+                }
+                timeReference = entry.time;
+                int entryByteSize = mTranslator.toBytes(entry, null, 0L);
+                readIndex = (readIndex + entryByteSize) % mBuffer.length;
+            }
+        }
+
+        /**
+         * Removes entries from the buffer until the specified amount of space is available for use.
+         *
+         * @param spaceNeeded The number of bytes needed in the buffer.
+         * @return True if there is space enough in the buffer, false otherwise.
+         */
+        private boolean makeSpace(int spaceNeeded) {
+            // Test the size of the buffer can fit it first, so that we dont loop forever in the
+            // following while loop.
+            if (mBuffer.length < spaceNeeded + 1) {
+                return false;
+            }
+
+            // We check spaceNeeded + 1 so that mStart + mEnd aren't equal.  We use them being equal
+            // to mean that the buffer is empty...so avoid that.
+            while (getAvailableSpace() < (spaceNeeded + 1)) {
+                removeOldestItem();
+            }
+            return true;
+        }
+
+        /**
+         * Returns the available space of the ring buffer.
+         */
+        private int getAvailableSpace() {
+            return mEnd > mStart ? mBuffer.length - (mEnd - mStart) :
+                    (mEnd < mStart ? mStart - mEnd :
+                     mBuffer.length);
+        }
+
+        /**
+         * Removes the oldest item from the buffer if the buffer is not empty.
+         */
+        private void removeOldestItem() {
+            if (isBufferEmpty()) {
+                // No items to remove
+                return;
+            }
+
+            // Copy the contents of the start of the buffer to our temporary buffer.
+            LogEntry entry = readEntryAt(mStart, mStartTime, null);
+            if (DEBUG) {
+                Slog.d(TAG, "Removing oldest item at @ " + mStart + ", found: " + entry);
+            }
+            int size = mTranslator.toBytes(entry, null, mStartTime);
+            mStart = (mStart + size) % mBuffer.length;
+            mStartTime = entry.time;  // new start time
+            mChangeCount++;
+        }
+
+        /**
+         * Returns true if the buffer is currently unused (contains zero entries).
+         *
+         * @return True if empty, false otherwise.
+         */
+        private boolean isBufferEmpty() {
+            return mStart == mEnd;
+        }
+
+        /**
+         * Reads an entry from the specified index in the buffer.
+         *
+         * @param index Index into the buffer from which to read.
+         * @param timeReference Reference time to use when creating the {@link LogEntry}.
+         * @param entryToSet Temporary entry to use instead of allocating a new one.
+         * @return the log-entry instance that was read.
+         */
+        private LogEntry readEntryAt(int index, long timeReference, LogEntry entryToSet) {
+            for (int i = 0; i < MAX_LOG_ENTRY_BYTE_SIZE; i++) {
+                int indexIntoMainBuffer = (index + i) % mBuffer.length;
+                if (indexIntoMainBuffer == mEnd) {
+                    break;
+                }
+                mReadWriteTempBuffer[i] = mBuffer[indexIntoMainBuffer];
+            }
+            return mTranslator.fromBytes(mReadWriteTempBuffer, timeReference, entryToSet);
+        }
+
+        /**
+         * Write a specified {@link LogEntry} to the buffer at the specified index.
+         *
+         * @param index Index in which to write in the buffer.
+         * @param entry The entry to write into the buffer.
+         * @param timeReference The reference time to use when calculating the relative time.
+         */
+        private void writeEntryAt(int index, LogEntry entry, long timeReference) {
+            int size = mTranslator.toBytes(entry, mReadWriteTempBuffer, timeReference);
+            if (size > 0) {
+                if (DEBUG) {
+                    Slog.d(TAG, "Writing Entry (" + index + ") [" + entry + "] as "
+                            + Arrays.toString(mReadWriteTempBuffer));
+                }
+                writeBytesAt(index, mReadWriteTempBuffer, size);
+            }
+        }
+
+        /**
+         * Write the specified bytes into the buffer at the specified index.
+         * Handling wrap-around calculation for the ring-buffer.
+         *
+         * @param index The index from which to start writing.
+         * @param buffer The buffer of bytes to be written.
+         * @param size The amount of bytes to write from {@code buffer} to the log.
+         */
+        private void writeBytesAt(int index, byte[] buffer, int size) {
+            for (int i = 0; i < size; i++) {
+                int indexIntoMainBuffer = (index + i) % mBuffer.length;
+                mBuffer[indexIntoMainBuffer] = buffer[i];
+            }
+            if (DEBUG) {
+                Slog.d(TAG, "Write Byte: " + Arrays.toString(buffer));
+            }
+        }
+    }
+
+    /**
+     * An in-memory database of wake lock {@link TagData}. All tags stored in the database are given
+     * a 7-bit index. This index is then used by {@link TheLog} when translating {@link LogEntry}
+     * instanced into bytes.
+     *
+     * If a new tag is added when the database is full, the oldest tag is removed. The oldest tag
+     * is calcualted using {@link TagData.lastUsedTime}.
+     */
+    static class TagDatabase {
+        private final int mInvalidIndex;
+        private final TagData[] mArray;
+        private Callback mCallback;
+
+        TagDatabase(Injector injector) {
+            int size = Math.min(injector.getTagDatabaseSize(), TAG_DATABASE_SIZE_MAX);
+
+            // Largest possible index used as "INVALID", hence the (size - 1) sizing.
+            mArray = new TagData[size - 1];
+            mInvalidIndex = size - 1;
+        }
+
+        @Override
+        public String toString() {
+            StringBuilder sb = new StringBuilder();
+            sb.append("Tag Database: size(").append(mArray.length).append(")");
+            int entries = 0;
+            int byteEstimate = 0;
+            int tagSize = 0;
+            int tags = 0;
+            for (int i = 0; i < mArray.length; i++) {
+                byteEstimate += 8;  // reference pointer
+                TagData data = mArray[i];
+                if (data != null) {
+                    entries++;
+                    byteEstimate += data.getByteSize();
+                    if (data.tag != null) {
+                        tags++;
+                        tagSize += data.tag.length();
+                    }
+                }
+            }
+            sb.append(", entries: ").append(entries);
+            sb.append(", Bytes used: ").append(byteEstimate);
+            if (DEBUG) {
+                sb.append(", Avg tag size: ").append(tagSize / tags);
+                sb.append("\n    ").append(Arrays.toString(mArray));
+            }
+            return sb.toString();
+        }
+
+        /**
+         * Sets the callback.
+         *
+         * @param callback The callback to set.
+         */
+        public void setCallback(Callback callback) {
+            mCallback = callback;
+        }
+
+        /**
+         * Returns the tag corresponding to the specified index.
+         *
+         * @param index The index to search for.
+         */
+        public TagData getTag(int index) {
+            if (index < 0 || index >= mArray.length || index == mInvalidIndex) {
+                return null;
+            }
+            return mArray[index];
+        }
+
+        /**
+         * Returns an existing tag for the specified wake lock tag + ownerUid.
+         *
+         * @param tag The wake lock tag.
+         * @param ownerUid The wake lock's ownerUid.
+         * @return the TagData instance.
+         */
+        public TagData getTag(String tag, int ownerUid) {
+            return findOrCreateTag(tag, ownerUid, false /* shouldCreate */);
+        }
+
+        /**
+         * Returns the index for the corresponding tag.
+         *
+         * @param tagData The tag-data to search for.
+         * @return the corresponding index, or mInvalidIndex of none is found.
+         */
+        public int getTagIndex(TagData tagData) {
+            return tagData == null ? mInvalidIndex : tagData.index;
+        }
+
+        /**
+         * Returns a tag instance for the specified wake lock tag and ownerUid. If the data
+         * does not exist in the database, it will be created if so specified by
+         * {@code shouldCreate}.
+         *
+         * @param tagStr The wake lock's tag.
+         * @param ownerUid The wake lock's owner Uid.
+         * @param shouldCreate True when the tag should be created if it doesn't already exist.
+         * @return The tag-data instance that was found or created.
+         */
+        public TagData findOrCreateTag(String tagStr, int ownerUid, boolean shouldCreate) {
+            int firstAvailable = -1;
+            TagData oldest = null;
+            int oldestIndex = -1;
+
+            // Loop through and find the tag to be used.
+            TagData tag = new TagData(tagStr, ownerUid);
+            for (int i = 0; i < mArray.length; i++) {
+                TagData current = mArray[i];
+                if (tag.equals(current)) {
+                    // found it
+                    return current;
+                } else if (!shouldCreate) {
+                    continue;
+                } else if (current != null) {
+                    // See if this entry is the oldest entry, in case
+                    // we need to replace it.
+                    if (oldest == null || current.lastUsedTime < oldest.lastUsedTime) {
+                        oldestIndex = i;
+                        oldest = current;
+                    }
+                } else if (firstAvailable == -1) {
+                    firstAvailable = i;
+                }
+            }
+
+            // Item not found, and we shouldn't create one.
+            if (!shouldCreate) {
+                return null;
+            }
+
+            // If we need to remove an index, report to listeners that we are removing an index.
+            boolean useOldest = firstAvailable == -1;
+            if (useOldest && mCallback != null) {
+                if (DEBUG) {
+                    Slog.d(TAG, "Removing tag index: " + oldestIndex + " = " + oldest);
+                }
+                mCallback.onIndexRemoved(oldestIndex);
+            }
+            setToIndex(tag, firstAvailable != -1 ? firstAvailable : oldestIndex);
+            return tag;
+        }
+
+        /**
+         * Updates the last-used-time of the specified tag.
+         *
+         * @param tag The tag to update.
+         * @param time The new last-used-time for the tag.
+         */
+        public static void updateTagTime(TagData tag, long time) {
+            if (tag != null) {
+                tag.lastUsedTime = time;
+            }
+        }
+
+        /**
+         * Sets a specified tag to the specified index.
+         */
+        private void setToIndex(TagData tag, int index) {
+            if (index < 0 || index >= mArray.length) {
+                return;
+            }
+            TagData current = mArray[index];
+            if (current != null) {
+                // clean up the reference in the TagData instance first.
+                current.index = mInvalidIndex;
+
+                if (DEBUG) {
+                    Slog.d(TAG, "Replaced tag " + current.tag + " from index " + index + " with tag"
+                            + tag);
+                }
+            }
+
+            mArray[index] = tag;
+            tag.index = index;
+        }
+
+        /**
+         * Callback on which to be notified of changes to {@link TagDatabase}.
+         */
+        interface Callback {
+
+            /**
+             * Handles removals of TagData indexes.
+             *
+             * @param index the index being removed.
+             */
+            void onIndexRemoved(int index);
+        }
+    }
+
+    /**
+     * This class represents unique wake lock tags that are stored in {@link TagDatabase}.
+     * Contains both the wake lock tag data (tag + ownerUid) as well as index and last-used
+     * time data as it relates to the tag-database.
+     */
+    static class TagData {
+        public String tag;  // Wake lock tag
+        public int ownerUid;  // Wake lock owner Uid
+        public int index;  // Index of the tag in the tag-database
+        public long lastUsedTime;  // Last time that this entry was used
+
+        TagData(String tag, int ownerUid) {
+            this.tag = tag;
+            this.ownerUid = ownerUid;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) {
+                return true;
+            }
+            if (o instanceof TagData) {
+                TagData other = (TagData) o;
+                return TextUtils.equals(tag, other.tag) && ownerUid == other.ownerUid;
+            }
+            return false;
+        }
+
+        @Override
+        public String toString() {
+            StringBuilder sb = new StringBuilder();
+            if (DEBUG) {
+                sb.append("(").append(index).append(")");
+            }
+            return "[" + ownerUid + " ; " + tag + "]";
+        }
+
+        /**
+         * Returns an estimate of the number of bytes used by each instance of this class.
+         * Used for debug purposes.
+         *
+         * @return the size of this tag-data.
+         */
+        int getByteSize() {
+            int bytes = 0;
+            bytes += 8;  // tag reference-pointer;
+            bytes += tag == null ? 0 : tag.length() * 2;
+            bytes += 4;  // ownerUid
+            bytes += 4;  // index
+            bytes += 8;  // lastUsedTime
+            return bytes;
+        }
+    }
+
+    /**
+     * Injector used by {@link WakeLockLog} for testing purposes.
+     */
+    public static class Injector {
+        public Looper getLooper() {
+            return BackgroundThread.get().getLooper();
+        }
+
+        public int getTagDatabaseSize() {
+            return TAG_DATABASE_SIZE;
+        }
+
+        public int getLogSize() {
+            return LOG_SIZE;
+        }
+
+        public long currentTimeMillis() {
+            return System.currentTimeMillis();
+        }
+
+        public SimpleDateFormat getDateFormat() {
+            return DATE_FORMAT;
+        }
+    }
+
+    private class WakeLockLogHandler extends Handler {
+        WakeLockLogHandler(Looper looper) {
+            super(looper);
+        }
+
+        @Override
+        public void handleMessage(Message message) {
+            switch(message.what) {
+                case MSG_ON_WAKE_LOCK_EVENT:
+                    final SomeArgs args = (SomeArgs) message.obj;
+                    final String tag = (String) args.arg1;
+                    final int eventType = args.argi1;
+                    final int ownerUid = args.argi2;
+                    final int flags = args.argi3;
+                    final long time = (((long) args.argi4) << 32) + (args.argi5 & 0xFFFFFFFFL);
+                    args.recycle();
+                    handleWakeLockEventInternal(eventType, tag, ownerUid, flags, time);
+                    break;
+                default:
+                    break;
+            }
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/protolog/ProtoLogImpl.java b/services/core/java/com/android/server/protolog/ProtoLogImpl.java
index 1653b3d..c9d42c8 100644
--- a/services/core/java/com/android/server/protolog/ProtoLogImpl.java
+++ b/services/core/java/com/android/server/protolog/ProtoLogImpl.java
@@ -38,7 +38,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.protolog.common.IProtoLogGroup;
 import com.android.server.protolog.common.LogDataType;
-import com.android.server.utils.TraceBuffer;
+import com.android.internal.util.TraceBuffer;
 import com.android.server.wm.ProtoLogGroup;
 
 import java.io.File;
diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
index b12f831..3aa51fb 100644
--- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -164,11 +164,24 @@
     private static final String TAG = "StatsPullAtomService";
     private static final boolean DEBUG = true;
 
+    /**
+     * Lowest available uid for apps.
+     *
+     * <p>Used to quickly discard memory snapshots of the zygote forks from native process
+     * measurements.
+     */
+    private static final int MIN_APP_UID = 10_000;
+
     private static final String RESULT_RECEIVER_CONTROLLER_KEY = "controller_activity";
     /**
      * How long to wait on an individual subsystem to return its stats.
      */
     private static final long EXTERNAL_STATS_SYNC_TIMEOUT_MILLIS = 2000;
+    private static final long NS_PER_SEC = 1000000000;
+    private static final long MILLI_AMP_HR_TO_NANO_AMP_SECS = 1_000_000L * 3600L;
+
+    private static final int MAX_BATTERY_STATS_HELPER_FREQUENCY_MS = 1000;
+    private static final int CPU_TIME_PER_THREAD_FREQ_MAX_NUM_FREQUENCIES = 8;
 
     private final Object mNetworkStatsLock = new Object();
     @GuardedBy("mNetworkStatsLock")
@@ -190,40 +203,222 @@
     @GuardedBy("mProcessStatsLock")
     private IProcessStats mProcessStatsService;
 
+    private final Object mCpuTrackerLock = new Object();
+    @GuardedBy("mCpuTrackerLock")
+    private ProcessCpuTracker mProcessCpuTracker;
+
+    private final Object mDebugElapsedClockLock = new Object();
+    @GuardedBy("mDebugElapsedClockLock")
+    private long mDebugElapsedClockPreviousValue = 0;
+    @GuardedBy("mDebugElapsedClockLock")
+    private long mDebugElapsedClockPullCount = 0;
+
+    private final Object mDebugFailingElapsedClockLock = new Object();
+    @GuardedBy("mDebugFailingElapsedClockLock")
+    private long mDebugFailingElapsedClockPreviousValue = 0;
+    @GuardedBy("mDebugFailingElapsedClockLock")
+    private long mDebugFailingElapsedClockPullCount = 0;
+
     private final Context mContext;
     private StatsManager mStatsManager;
     private StorageManager mStorageManager;
+    private WifiManager mWifiManager;
+    private TelephonyManager mTelephony;
+
+    private KernelWakelockReader mKernelWakelockReader;
+    private KernelWakelockStats mTmpWakelockStats;
+
+    private StoragedUidIoStatsReader mStoragedUidIoStatsReader;
+
+    private KernelCpuSpeedReader[] mKernelCpuSpeedReaders;
+    // Disables throttler on CPU time readers.
+    private KernelCpuUidUserSysTimeReader mCpuUidUserSysTimeReader;
+    private KernelCpuUidFreqTimeReader mCpuUidFreqTimeReader;
+    private KernelCpuUidActiveTimeReader mCpuUidActiveTimeReader;
+    private KernelCpuUidClusterTimeReader mCpuUidClusterTimeReader;
+
+    private File mBaseDir;
+
+    @Nullable
+    private KernelCpuThreadReaderDiff mKernelCpuThreadReader;
+
+    private BatteryStatsHelper mBatteryStatsHelper = null;
+    private long mBatteryStatsHelperTimestampMs = -MAX_BATTERY_STATS_HELPER_FREQUENCY_MS;
+
+    private StatsPullAtomCallbackImpl mStatsCallbackImpl;
 
     public StatsPullAtomService(Context context) {
         super(context);
         mContext = context;
     }
 
+    /**
+     * Use of this StatsPullAtomCallbackImpl means we avoid one class per tagId, which we would
+     * get if we used lambdas.
+     *
+     * The pull methods are intentionally left to be package private to avoid the creation
+     * of synthetic methods to save unnecessary bytecode.
+     */
+    private class StatsPullAtomCallbackImpl implements StatsManager.StatsPullAtomCallback {
+        @Override
+        public int onPullAtom(int atomTag, List<StatsEvent> data) {
+            switch(atomTag) {
+                case StatsLog.WIFI_BYTES_TRANSFER:
+                    return pullWifiBytesTransfer(atomTag, data);
+                case StatsLog.WIFI_BYTES_TRANSFER_BY_FG_BG:
+                    return pullWifiBytesTransferBackground(atomTag, data);
+                case StatsLog.MOBILE_BYTES_TRANSFER:
+                    return pullMobileBytesTransfer(atomTag, data);
+                case StatsLog.MOBILE_BYTES_TRANSFER_BY_FG_BG:
+                    return pullMobileBytesTransferBackground(atomTag, data);
+                case StatsLog.BLUETOOTH_BYTES_TRANSFER:
+                    return pullBluetoothBytesTransfer(atomTag, data);
+                case StatsLog.KERNEL_WAKELOCK:
+                    return pullKernelWakelock(atomTag, data);
+                case StatsLog.CPU_TIME_PER_FREQ:
+                    return pullCpuTimePerFreq(atomTag, data);
+                case StatsLog.CPU_TIME_PER_UID:
+                    return pullCpuTimePerUid(atomTag, data);
+                case StatsLog.CPU_TIME_PER_UID_FREQ:
+                    return pullCpuTimeperUidFreq(atomTag, data);
+                case StatsLog.CPU_ACTIVE_TIME:
+                    return pullCpuActiveTime(atomTag, data);
+                case StatsLog.CPU_CLUSTER_TIME:
+                    return pullCpuClusterTime(atomTag, data);
+                case StatsLog.WIFI_ACTIVITY_INFO:
+                    return pullWifiActivityInfo(atomTag, data);
+                case StatsLog.MODEM_ACTIVITY_INFO:
+                    return pullModemActivityInfo(atomTag, data);
+                case StatsLog.BLUETOOTH_ACTIVITY_INFO:
+                    return pullBluetoothActivityInfo(atomTag, data);
+                case StatsLog.SYSTEM_ELAPSED_REALTIME:
+                    return pullSystemElapsedRealtime(atomTag, data);
+                case StatsLog.SYSTEM_UPTIME:
+                    return pullSystemUptime(atomTag, data);
+                case StatsLog.PROCESS_MEMORY_STATE:
+                    return pullProcessMemoryState(atomTag, data);
+                case StatsLog.PROCESS_MEMORY_HIGH_WATER_MARK:
+                    return pullProcessMemoryHighWaterMark(atomTag, data);
+                case StatsLog.PROCESS_MEMORY_SNAPSHOT:
+                    return pullProcessMemorySnapshot(atomTag, data);
+                case StatsLog.SYSTEM_ION_HEAP_SIZE:
+                    return pullSystemIonHeapSize(atomTag, data);
+                case StatsLog.ION_HEAP_SIZE:
+                    return pullIonHeapSize(atomTag, data);
+                case StatsLog.PROCESS_SYSTEM_ION_HEAP_SIZE:
+                    return pullProcessSystemIonHeapSize(atomTag, data);
+                case StatsLog.TEMPERATURE:
+                    return pullTemperature(atomTag, data);
+                case StatsLog.COOLING_DEVICE:
+                    return pullCooldownDevice(atomTag, data);
+                case StatsLog.BINDER_CALLS:
+                    return pullBinderCallsStats(atomTag, data);
+                case StatsLog.BINDER_CALLS_EXCEPTIONS:
+                    return pullBinderCallsStatsExceptions(atomTag, data);
+                case StatsLog.LOOPER_STATS:
+                    return pullLooperStats(atomTag, data);
+                case StatsLog.DISK_STATS:
+                    return pullDiskStats(atomTag, data);
+                case StatsLog.DIRECTORY_USAGE:
+                    return pullDirectoryUsage(atomTag, data);
+                case StatsLog.APP_SIZE:
+                    return pullAppSize(atomTag, data);
+                case StatsLog.CATEGORY_SIZE:
+                    return pullCategorySize(atomTag, data);
+                case StatsLog.NUM_FINGERPRINTS_ENROLLED:
+                    return pullNumBiometricsEnrolled(
+                            BiometricsProtoEnums.MODALITY_FINGERPRINT, atomTag, data);
+                case StatsLog.NUM_FACES_ENROLLED:
+                    return pullNumBiometricsEnrolled(
+                            BiometricsProtoEnums.MODALITY_FACE, atomTag, data);
+                case StatsLog.PROC_STATS:
+                    return pullProcStats(ProcessStats.REPORT_ALL, atomTag, data);
+                case StatsLog.PROC_STATS_PKG_PROC:
+                    return pullProcStats(ProcessStats.REPORT_PKG_PROC_STATS, atomTag, data);
+                case StatsLog.DISK_IO:
+                    return pullDiskIO(atomTag, data);
+                case StatsLog.POWER_PROFILE:
+                    return pullPowerProfile(atomTag, data);
+                case StatsLog.PROCESS_CPU_TIME:
+                    return pullProcessCpuTime(atomTag, data);
+                case StatsLog.CPU_TIME_PER_THREAD_FREQ:
+                    return pullCpuTimePerThreadFreq(atomTag, data);
+                case StatsLog.DEVICE_CALCULATED_POWER_USE:
+                    return pullDeviceCalculatedPowerUse(atomTag, data);
+                case StatsLog.DEVICE_CALCULATED_POWER_BLAME_UID:
+                    return pullDeviceCalculatedPowerBlameUid(atomTag, data);
+                case StatsLog.DEVICE_CALCULATED_POWER_BLAME_OTHER:
+                    return pullDeviceCalculatedPowerBlameOther(atomTag, data);
+                case StatsLog.DEBUG_ELAPSED_CLOCK:
+                    return pullDebugElapsedClock(atomTag, data);
+                case StatsLog.DEBUG_FAILING_ELAPSED_CLOCK:
+                    return pullDebugFailingElapsedClock(atomTag, data);
+                case StatsLog.BUILD_INFORMATION:
+                    return pullBuildInformation(atomTag, data);
+                case StatsLog.ROLE_HOLDER:
+                    return pullRoleHolder(atomTag, data);
+                case StatsLog.DANGEROUS_PERMISSION_STATE:
+                    return pullDangerousPermissionState(atomTag, data);
+                case StatsLog.TIME_ZONE_DATA_INFO:
+                    return pullTimeZoneDataInfo(atomTag, data);
+                case StatsLog.EXTERNAL_STORAGE_INFO:
+                    return pullExternalStorageInfo(atomTag, data);
+                case StatsLog.APPS_ON_EXTERNAL_STORAGE_INFO:
+                    return pullAppsOnExternalStorageInfo(atomTag, data);
+                case StatsLog.FACE_SETTINGS:
+                    return pullFaceSettings(atomTag, data);
+                case StatsLog.APP_OPS:
+                    return pullAppOps(atomTag, data);
+                case StatsLog.NOTIFICATION_REMOTE_VIEWS:
+                    return pullNotificationRemoteViews(atomTag, data);
+                case StatsLog.DANGEROUS_PERMISSION_STATE_SAMPLED:
+                    return pullDangerousPermissionState(atomTag, data);
+                default:
+                    throw new UnsupportedOperationException("Unknown tagId=" + atomTag);
+            }
+        }
+    }
+
     @Override
     public void onStart() {
+        // no op
+    }
+
+    @Override
+    public void onBootPhase(int phase) {
+        super.onBootPhase(phase);
+        if (phase == PHASE_SYSTEM_SERVICES_READY) {
+            BackgroundThread.getHandler().post(() -> {
+                initializePullersState();
+                registerAllPullers();
+                registerEventListeners();
+            });
+        }
+    }
+
+    void initializePullersState() {
+        // Get Context Managers
         mStatsManager = (StatsManager) mContext.getSystemService(Context.STATS_MANAGER);
         mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
         mTelephony = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
         mStorageManager = (StorageManager) mContext.getSystemService(StorageManager.class);
 
-        final ConnectivityManager connectivityManager =
-                (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
-        // Default NetworkRequest should cover all transport types.
-        final NetworkRequest request = new NetworkRequest.Builder().build();
-        connectivityManager.registerNetworkCallback(request, new ConnectivityStatsCallback());
+        // Initialize DiskIO
+        mStoragedUidIoStatsReader = new StoragedUidIoStatsReader();
 
-        // Enable push notifications of throttling from vendor thermal
-        // management subsystem via thermalservice.
-        IThermalService thermalService = getIThermalService();
-        if (thermalService != null) {
-            try {
-                thermalService.registerThermalEventListener(
-                        new ThermalEventListener());
-                Slog.i(TAG, "register thermal listener successfully");
-            } catch (RemoteException e) {
-                Slog.i(TAG, "failed to register thermal listener");
-            }
-        }
+        // Initialize PROC_STATS
+        // TODO (b/148402814): Change this directory to stats_pull.
+        mBaseDir = new File(SystemServiceManager.ensureSystemDir(), "stats_companion");
+
+        // Disables throttler on CPU time readers.
+        mCpuUidUserSysTimeReader = new KernelCpuUidUserSysTimeReader(false);
+        mCpuUidFreqTimeReader = new KernelCpuUidFreqTimeReader(false);
+        mCpuUidActiveTimeReader = new KernelCpuUidActiveTimeReader(false);
+        mCpuUidClusterTimeReader = new KernelCpuUidClusterTimeReader(false);
+
+        // Initialize state for KERNEL_WAKELOCK
+        mKernelWakelockReader = new KernelWakelockReader();
+        mTmpWakelockStats = new KernelWakelockStats();
 
         // Initialize state for CPU_TIME_PER_FREQ atom
         PowerProfile powerProfile = new PowerProfile(mContext);
@@ -245,13 +440,23 @@
         mBaseDir.mkdirs();
     }
 
-    @Override
-    public void onBootPhase(int phase) {
-        super.onBootPhase(phase);
-        if (phase == PHASE_SYSTEM_SERVICES_READY) {
-            BackgroundThread.getHandler().post(() -> {
-                registerAllPullers();
-            });
+    void registerEventListeners() {
+        final ConnectivityManager connectivityManager =
+                (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
+        // Default NetworkRequest should cover all transport types.
+        final NetworkRequest request = new NetworkRequest.Builder().build();
+        connectivityManager.registerNetworkCallback(request, new ConnectivityStatsCallback());
+
+        // Enable push notifications of throttling from vendor thermal
+        // management subsystem via thermalservice.
+        IThermalService thermalService = getIThermalService();
+        if (thermalService != null) {
+            try {
+                thermalService.registerThermalEventListener(new ThermalEventListener());
+                Slog.i(TAG, "register thermal listener successfully");
+            } catch (RemoteException e) {
+                Slog.i(TAG, "failed to register thermal listener");
+            }
         }
     }
 
@@ -259,6 +464,7 @@
         if (DEBUG) {
             Slog.d(TAG, "Registering all pullers with statsd");
         }
+        mStatsCallbackImpl = new StatsPullAtomCallbackImpl();
         registerWifiBytesTransfer();
         registerWifiBytesTransferBackground();
         registerMobileBytesTransfer();
@@ -275,11 +481,6 @@
         registerBluetoothActivityInfo();
         registerSystemElapsedRealtime();
         registerSystemUptime();
-        registerRemainingBatteryCapacity();
-        registerFullBatteryCapacity();
-        registerBatteryVoltage();
-        registerBatteryLevel();
-        registerBatteryCycleCount();
         registerProcessMemoryState();
         registerProcessMemoryHighWaterMark();
         registerProcessMemorySnapshot();
@@ -440,11 +641,11 @@
                 tagId,
                 metadata,
                 BackgroundThread.getExecutor(),
-                (atomTag, data) -> pullWifiBytesTransfer(atomTag, data)
+                mStatsCallbackImpl
         );
     }
 
-    private int pullWifiBytesTransfer(int atomTag, List<StatsEvent> pulledData) {
+    int pullWifiBytesTransfer(int atomTag, List<StatsEvent> pulledData) {
         INetworkStatsService networkStatsService = getINetworkStatsService();
         if (networkStatsService == null) {
             Slog.e(TAG, "NetworkStats Service is not available!");
@@ -452,7 +653,7 @@
         }
         long token = Binder.clearCallingIdentity();
         try {
-            // TODO: Consider caching the following call to get BatteryStatsInternal.
+            // TODO(b/148402814): Consider caching the following call to get BatteryStatsInternal.
             BatteryStatsInternal bs = LocalServices.getService(BatteryStatsInternal.class);
             String[] ifaces = bs.getWifiIfaces();
             if (ifaces.length == 0) {
@@ -532,11 +733,11 @@
                 tagId,
                 metadata,
                 BackgroundThread.getExecutor(),
-                (atomTag, data) -> pullWifiBytesTransferBackground(atomTag, data)
+                mStatsCallbackImpl
         );
     }
 
-    private int pullWifiBytesTransferBackground(int atomTag, List<StatsEvent> pulledData) {
+    int pullWifiBytesTransferBackground(int atomTag, List<StatsEvent> pulledData) {
         INetworkStatsService networkStatsService = getINetworkStatsService();
         if (networkStatsService == null) {
             Slog.e(TAG, "NetworkStats Service is not available!");
@@ -570,11 +771,11 @@
                 tagId,
                 metadata,
                 BackgroundThread.getExecutor(),
-                (atomTag, data) -> pullMobileBytesTransfer(atomTag, data)
+                mStatsCallbackImpl
         );
     }
 
-    private int pullMobileBytesTransfer(int atomTag, List<StatsEvent> pulledData) {
+    int pullMobileBytesTransfer(int atomTag, List<StatsEvent> pulledData) {
         INetworkStatsService networkStatsService = getINetworkStatsService();
         if (networkStatsService == null) {
             Slog.e(TAG, "NetworkStats Service is not available!");
@@ -608,11 +809,11 @@
                 tagId,
                 metadata,
                 BackgroundThread.getExecutor(),
-                (atomTag, data) -> pullMobileBytesTransferBackground(atomTag, data)
+                mStatsCallbackImpl
         );
     }
 
-    private int pullMobileBytesTransferBackground(int atomTag, List<StatsEvent> pulledData) {
+    int pullMobileBytesTransferBackground(int atomTag, List<StatsEvent> pulledData) {
         INetworkStatsService networkStatsService = getINetworkStatsService();
         if (networkStatsService == null) {
             Slog.e(TAG, "NetworkStats Service is not available!");
@@ -646,7 +847,7 @@
                 tagId,
                 metadata,
                 BackgroundThread.getExecutor(),
-                (atomTag, data) -> pullBluetoothBytesTransfer(atomTag, data)
+                mStatsCallbackImpl
         );
     }
 
@@ -693,7 +894,7 @@
         }
     }
 
-    private int pullBluetoothBytesTransfer(int atomTag, List<StatsEvent> pulledData) {
+    int pullBluetoothBytesTransfer(int atomTag, List<StatsEvent> pulledData) {
         BluetoothActivityEnergyInfo info = fetchBluetoothData();
         if (info == null || info.getUidTraffic() == null) {
             return StatsManager.PULL_SKIP;
@@ -710,20 +911,17 @@
         return StatsManager.PULL_SUCCESS;
     }
 
-    private final KernelWakelockReader mKernelWakelockReader = new KernelWakelockReader();
-    private final KernelWakelockStats mTmpWakelockStats = new KernelWakelockStats();
-
     private void registerKernelWakelock() {
         int tagId = StatsLog.KERNEL_WAKELOCK;
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 /* PullAtomMetadata */ null,
                 BackgroundThread.getExecutor(),
-                (atomTag, data) -> pullKernelWakelock(atomTag, data)
+                mStatsCallbackImpl
         );
     }
 
-    private int pullKernelWakelock(int atomTag, List<StatsEvent> pulledData) {
+    int pullKernelWakelock(int atomTag, List<StatsEvent> pulledData) {
         final KernelWakelockStats wakelockStats =
                 mKernelWakelockReader.readKernelWakelockStats(mTmpWakelockStats);
         for (Map.Entry<String, KernelWakelockStats.Entry> ent : wakelockStats.entrySet()) {
@@ -741,17 +939,6 @@
         return StatsManager.PULL_SUCCESS;
     }
 
-    private KernelCpuSpeedReader[] mKernelCpuSpeedReaders;
-    // Disables throttler on CPU time readers.
-    private KernelCpuUidUserSysTimeReader mCpuUidUserSysTimeReader =
-            new KernelCpuUidUserSysTimeReader(false);
-    private KernelCpuUidFreqTimeReader mCpuUidFreqTimeReader =
-            new KernelCpuUidFreqTimeReader(false);
-    private KernelCpuUidActiveTimeReader mCpuUidActiveTimeReader =
-            new KernelCpuUidActiveTimeReader(false);
-    private KernelCpuUidClusterTimeReader mCpuUidClusterTimeReader =
-            new KernelCpuUidClusterTimeReader(false);
-
     private void registerCpuTimePerFreq() {
         int tagId = StatsLog.CPU_TIME_PER_FREQ;
         PullAtomMetadata metadata = new PullAtomMetadata.Builder()
@@ -761,11 +948,11 @@
                 tagId,
                 metadata,
                 BackgroundThread.getExecutor(),
-                (atomTag, data) -> pullCpuTimePerFreq(atomTag, data)
+                mStatsCallbackImpl
         );
     }
 
-    private int pullCpuTimePerFreq(int atomTag, List<StatsEvent> pulledData) {
+    int pullCpuTimePerFreq(int atomTag, List<StatsEvent> pulledData) {
         for (int cluster = 0; cluster < mKernelCpuSpeedReaders.length; cluster++) {
             long[] clusterTimeMs = mKernelCpuSpeedReaders[cluster].readAbsolute();
             if (clusterTimeMs != null) {
@@ -792,11 +979,11 @@
                 tagId,
                 metadata,
                 BackgroundThread.getExecutor(),
-                (atomTag, data) -> pullCpuTimePerUid(atomTag, data)
+                mStatsCallbackImpl
         );
     }
 
-    private int pullCpuTimePerUid(int atomTag, List<StatsEvent> pulledData) {
+    int pullCpuTimePerUid(int atomTag, List<StatsEvent> pulledData) {
         mCpuUidUserSysTimeReader.readAbsolute((uid, timesUs) -> {
             long userTimeUs = timesUs[0], systemTimeUs = timesUs[1];
             StatsEvent e = StatsEvent.newBuilder()
@@ -821,11 +1008,11 @@
                 tagId,
                 metadata,
                 BackgroundThread.getExecutor(),
-                (atomTag, data) -> pullCpuTimeperUidFreq(atomTag, data)
+                mStatsCallbackImpl
         );
     }
 
-    private int pullCpuTimeperUidFreq(int atomTag, List<StatsEvent> pulledData) {
+    int pullCpuTimeperUidFreq(int atomTag, List<StatsEvent> pulledData) {
         mCpuUidFreqTimeReader.readAbsolute((uid, cpuFreqTimeMs) -> {
             for (int freqIndex = 0; freqIndex < cpuFreqTimeMs.length; ++freqIndex) {
                 if (cpuFreqTimeMs[freqIndex] != 0) {
@@ -853,11 +1040,11 @@
                 tagId,
                 metadata,
                 BackgroundThread.getExecutor(),
-                (atomTag, data) -> pullCpuActiveTime(atomTag, data)
+                mStatsCallbackImpl
         );
     }
 
-    private int pullCpuActiveTime(int atomTag, List<StatsEvent> pulledData) {
+    int pullCpuActiveTime(int atomTag, List<StatsEvent> pulledData) {
         mCpuUidActiveTimeReader.readAbsolute((uid, cpuActiveTimesMs) -> {
             StatsEvent e = StatsEvent.newBuilder()
                     .setAtomId(atomTag)
@@ -880,11 +1067,11 @@
                 tagId,
                 metadata,
                 BackgroundThread.getExecutor(),
-                (atomTag, data) -> pullCpuClusterTime(atomTag, data)
+                mStatsCallbackImpl
         );
     }
 
-    private int pullCpuClusterTime(int atomTag, List<StatsEvent> pulledData) {
+    int pullCpuClusterTime(int atomTag, List<StatsEvent> pulledData) {
         mCpuUidClusterTimeReader.readAbsolute((uid, cpuClusterTimesMs) -> {
             for (int i = 0; i < cpuClusterTimesMs.length; i++) {
                 StatsEvent e = StatsEvent.newBuilder()
@@ -904,15 +1091,12 @@
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                (atomTag, data) -> pullWifiActivityInfo(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private WifiManager mWifiManager;
-    private TelephonyManager mTelephony;
-
-    private int pullWifiActivityInfo(int atomTag, List<StatsEvent> pulledData) {
+    int pullWifiActivityInfo(int atomTag, List<StatsEvent> pulledData) {
         long token = Binder.clearCallingIdentity();
         try {
             SynchronousResultReceiver wifiReceiver = new SynchronousResultReceiver("wifi");
@@ -959,12 +1143,12 @@
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                (atomTag, data) -> pullModemActivityInfo(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullModemActivityInfo(int atomTag, List<StatsEvent> pulledData) {
+    int pullModemActivityInfo(int atomTag, List<StatsEvent> pulledData) {
         long token = Binder.clearCallingIdentity();
         try {
             SynchronousResultReceiver modemReceiver = new SynchronousResultReceiver("telephony");
@@ -998,11 +1182,11 @@
                 tagId,
                 /* metadata */ null,
                 BackgroundThread.getExecutor(),
-                (atomTag, data) -> pullBluetoothActivityInfo(atomTag, data)
+                mStatsCallbackImpl
         );
     }
 
-    private int pullBluetoothActivityInfo(int atomTag, List<StatsEvent> pulledData) {
+    int pullBluetoothActivityInfo(int atomTag, List<StatsEvent> pulledData) {
         BluetoothActivityEnergyInfo info = fetchBluetoothData();
         if (info == null) {
             return StatsManager.PULL_SKIP;
@@ -1020,23 +1204,21 @@
         return StatsManager.PULL_SUCCESS;
     }
 
-    private static final long NS_PER_SEC = 1000000000;
-
     private void registerSystemElapsedRealtime() {
         int tagId = StatsLog.SYSTEM_ELAPSED_REALTIME;
-        PullAtomMetadata metadata = PullAtomMetadata.newBuilder()
+        PullAtomMetadata metadata = new PullAtomMetadata.Builder()
                 .setCoolDownNs(NS_PER_SEC)
                 .setTimeoutNs(NS_PER_SEC / 2)
                 .build();
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 metadata,
-                (atomTag, data) -> pullSystemElapsedRealtime(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullSystemElapsedRealtime(int atomTag, List<StatsEvent> pulledData) {
+    int pullSystemElapsedRealtime(int atomTag, List<StatsEvent> pulledData) {
         StatsEvent e = StatsEvent.newBuilder()
                 .setAtomId(atomTag)
                 .writeLong(SystemClock.elapsedRealtime())
@@ -1051,11 +1233,11 @@
                 tagId,
                 null, // use default PullAtomMetadata values
                 BackgroundThread.getExecutor(),
-                (atomTag, data) -> pullSystemUptime(atomTag, data)
+                mStatsCallbackImpl
         );
     }
 
-    private int pullSystemUptime(int atomTag, List<StatsEvent> pulledData) {
+    int pullSystemUptime(int atomTag, List<StatsEvent> pulledData) {
         StatsEvent e = StatsEvent.newBuilder()
                 .setAtomId(atomTag)
                 .writeLong(SystemClock.elapsedRealtime())
@@ -1064,60 +1246,20 @@
         return StatsManager.PULL_SUCCESS;
     }
 
-    private void registerRemainingBatteryCapacity() {
-        // No op.
-    }
-
-    private void pullRemainingBatteryCapacity() {
-        // No op.
-    }
-
-    private void registerFullBatteryCapacity() {
-        // No op.
-    }
-
-    private void pullFullBatteryCapacity() {
-        // No op.
-    }
-
-    private void registerBatteryVoltage() {
-        // No op.
-    }
-
-    private void pullBatteryVoltage() {
-        // No op.
-    }
-
-    private void registerBatteryLevel() {
-        // No op.
-    }
-
-    private void pullBatteryLevel() {
-        // No op.
-    }
-
-    private void registerBatteryCycleCount() {
-        // No op.
-    }
-
-    private void pullBatteryCycleCount() {
-        // No op.
-    }
-
     private void registerProcessMemoryState() {
         int tagId = StatsLog.PROCESS_MEMORY_STATE;
-        PullAtomMetadata metadata = PullAtomMetadata.newBuilder()
+        PullAtomMetadata metadata = new PullAtomMetadata.Builder()
                 .setAdditiveFields(new int[] {4, 5, 6, 7, 8})
                 .build();
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 metadata,
-                (atomTag, data) -> pullProcessMemoryState(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullProcessMemoryState(int atomTag, List<StatsEvent> pulledData) {
+    int pullProcessMemoryState(int atomTag, List<StatsEvent> pulledData) {
         List<ProcessMemoryState> processMemoryStates =
                 LocalServices.getService(ActivityManagerInternal.class)
                         .getMemoryStateForProcesses();
@@ -1146,14 +1288,6 @@
         return StatsManager.PULL_SUCCESS;
     }
 
-    /**
-     * Lowest available uid for apps.
-     *
-     * <p>Used to quickly discard memory snapshots of the zygote forks from native process
-     * measurements.
-     */
-    private static final int MIN_APP_UID = 10_000;
-
     private static boolean isAppUid(int uid) {
         return uid >= MIN_APP_UID;
     }
@@ -1163,12 +1297,12 @@
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                (atomTag, data) -> pullProcessMemoryHighWaterMark(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullProcessMemoryHighWaterMark(int atomTag, List<StatsEvent> pulledData) {
+    int pullProcessMemoryHighWaterMark(int atomTag, List<StatsEvent> pulledData) {
         List<ProcessMemoryState> managedProcessList =
                 LocalServices.getService(ActivityManagerInternal.class)
                         .getMemoryStateForProcesses();
@@ -1216,12 +1350,12 @@
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                (atomTag, data) -> pullProcessMemorySnapshot(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullProcessMemorySnapshot(int atomTag, List<StatsEvent> pulledData) {
+    int pullProcessMemorySnapshot(int atomTag, List<StatsEvent> pulledData) {
         List<ProcessMemoryState> managedProcessList =
                 LocalServices.getService(ActivityManagerInternal.class)
                         .getMemoryStateForProcesses();
@@ -1276,12 +1410,12 @@
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                (atomTag, data) -> pullSystemIonHeapSize(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullSystemIonHeapSize(int atomTag, List<StatsEvent> pulledData) {
+    int pullSystemIonHeapSize(int atomTag, List<StatsEvent> pulledData) {
         final long systemIonHeapSizeInBytes = readSystemIonHeapSizeFromDebugfs();
         StatsEvent e = StatsEvent.newBuilder()
                 .setAtomId(atomTag)
@@ -1297,11 +1431,11 @@
                 tagId,
                 /* PullAtomMetadata */ null,
                 BackgroundThread.getExecutor(),
-                (atomTag, data) -> pullIonHeapSize(atomTag, data)
+                mStatsCallbackImpl
         );
     }
 
-    private int pullIonHeapSize(int atomTag, List<StatsEvent> pulledData) {
+    int pullIonHeapSize(int atomTag, List<StatsEvent> pulledData) {
         int ionHeapSizeInKilobytes = (int) getIonHeapsSizeKb();
         StatsEvent e = StatsEvent.newBuilder()
               .setAtomId(atomTag)
@@ -1316,12 +1450,12 @@
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                (atomTag, data) -> pullProcessSystemIonHeapSize(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullProcessSystemIonHeapSize(int atomTag, List<StatsEvent> pulledData) {
+    int pullProcessSystemIonHeapSize(int atomTag, List<StatsEvent> pulledData) {
         List<IonAllocations> result = readProcessSystemIonHeapSizesFromDebugfs();
         for (IonAllocations allocations : result) {
             StatsEvent e = StatsEvent.newBuilder()
@@ -1342,12 +1476,12 @@
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                (atomTag, data) -> pullTemperature(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullTemperature(int atomTag, List<StatsEvent> pulledData) {
+    int pullTemperature(int atomTag, List<StatsEvent> pulledData) {
         IThermalService thermalService = getIThermalService();
         if (thermalService == null) {
             return StatsManager.PULL_SKIP;
@@ -1380,12 +1514,12 @@
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                (atomTag, data) -> pullCooldownDevice(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullCooldownDevice(int atomTag, List<StatsEvent> pulledData) {
+    int pullCooldownDevice(int atomTag, List<StatsEvent> pulledData) {
         IThermalService thermalService = getIThermalService();
         if (thermalService == null) {
             return StatsManager.PULL_SKIP;
@@ -1414,18 +1548,18 @@
 
     private void registerBinderCallsStats() {
         int tagId = StatsLog.BINDER_CALLS;
-        PullAtomMetadata metadata = PullAtomMetadata.newBuilder()
+        PullAtomMetadata metadata = new PullAtomMetadata.Builder()
                 .setAdditiveFields(new int[] {4, 5, 6, 8, 12})
                 .build();
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 metadata,
-                (atomTag, data) -> pullBinderCallsStats(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullBinderCallsStats(int atomTag, List<StatsEvent> pulledData) {
+    int pullBinderCallsStats(int atomTag, List<StatsEvent> pulledData) {
         BinderCallsStatsService.Internal binderStats =
                 LocalServices.getService(BinderCallsStatsService.Internal.class);
         if (binderStats == null) {
@@ -1463,12 +1597,12 @@
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                (atomTag, data) -> pullBinderCallsStatsExceptions(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullBinderCallsStatsExceptions(int atomTag, List<StatsEvent> pulledData) {
+    int pullBinderCallsStatsExceptions(int atomTag, List<StatsEvent> pulledData) {
         BinderCallsStatsService.Internal binderStats =
                 LocalServices.getService(BinderCallsStatsService.Internal.class);
         if (binderStats == null) {
@@ -1492,18 +1626,18 @@
 
     private void registerLooperStats() {
         int tagId = StatsLog.LOOPER_STATS;
-        PullAtomMetadata metadata = PullAtomMetadata.newBuilder()
+        PullAtomMetadata metadata = new PullAtomMetadata.Builder()
                 .setAdditiveFields(new int[] {5, 6, 7, 8, 9})
                 .build();
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 metadata,
-                (atomTag, data) -> pullLooperStats(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullLooperStats(int atomTag, List<StatsEvent> pulledData) {
+    int pullLooperStats(int atomTag, List<StatsEvent> pulledData) {
         LooperStats looperStats = LocalServices.getService(LooperStats.class);
         if (looperStats == null) {
             return StatsManager.PULL_SKIP;
@@ -1540,12 +1674,12 @@
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                (atomTag, data) -> pullDiskStats(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullDiskStats(int atomTag, List<StatsEvent> pulledData) {
+    int pullDiskStats(int atomTag, List<StatsEvent> pulledData) {
         // Run a quick-and-dirty performance test: write 512 bytes
         byte[] junk = new byte[512];
         for (int i = 0; i < junk.length; i++) junk[i] = (byte) i;  // Write nonzero bytes
@@ -1606,12 +1740,12 @@
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                (atomTag, data) -> pullDirectoryUsage(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullDirectoryUsage(int atomTag, List<StatsEvent> pulledData) {
+    int pullDirectoryUsage(int atomTag, List<StatsEvent> pulledData) {
         StatFs statFsData = new StatFs(Environment.getDataDirectory().getAbsolutePath());
         StatFs statFsSystem = new StatFs(Environment.getRootDirectory().getAbsolutePath());
         StatFs statFsCache = new StatFs(Environment.getDownloadCacheDirectory().getAbsolutePath());
@@ -1647,12 +1781,12 @@
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                (atomTag, data) -> pullAppSize(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullAppSize(int atomTag, List<StatsEvent> pulledData) {
+    int pullAppSize(int atomTag, List<StatsEvent> pulledData) {
         try {
             String jsonStr = IoUtils.readFileAsString(DiskStatsLoggingService.DUMPSYS_CACHE_PATH);
             JSONObject json = new JSONObject(jsonStr);
@@ -1691,12 +1825,12 @@
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                (atomTag, data) -> pullCategorySize(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullCategorySize(int atomTag, List<StatsEvent> pulledData) {
+    int pullCategorySize(int atomTag, List<StatsEvent> pulledData) {
         try {
             String jsonStr = IoUtils.readFileAsString(DiskStatsLoggingService.DUMPSYS_CACHE_PATH);
             JSONObject json = new JSONObject(jsonStr);
@@ -1794,9 +1928,8 @@
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                (atomTag, data) -> pullNumBiometricsEnrolled(
-                        BiometricsProtoEnums.MODALITY_FINGERPRINT, atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
@@ -1805,9 +1938,8 @@
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                (atomTag, data) -> pullNumBiometricsEnrolled(
-                        BiometricsProtoEnums.MODALITY_FACE, atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
@@ -1859,15 +1991,13 @@
         return StatsManager.PULL_SUCCESS;
     }
 
-    private File mBaseDir = new File(SystemServiceManager.ensureSystemDir(), "stats_companion");
-
     private void registerProcStats() {
         int tagId = StatsLog.PROC_STATS;
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                (atomTag, data) -> pullProcStats(ProcessStats.REPORT_ALL, atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
@@ -1876,8 +2006,8 @@
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                (atomTag, data) -> pullProcStats(ProcessStats.REPORT_PKG_PROC_STATS, atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
@@ -1940,25 +2070,21 @@
         return 0;
     }
 
-
-    private StoragedUidIoStatsReader mStoragedUidIoStatsReader =
-            new StoragedUidIoStatsReader();
-
     private void registerDiskIO() {
         int tagId = StatsLog.DISK_IO;
-        PullAtomMetadata metadata = PullAtomMetadata.newBuilder()
+        PullAtomMetadata metadata = new PullAtomMetadata.Builder()
                 .setAdditiveFields(new int[] {2, 3, 4, 5, 6, 7, 8, 9, 10, 11})
                 .setCoolDownNs(3 * NS_PER_SEC)
                 .build();
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 metadata,
-                (atomTag, data) -> pullDiskIO(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullDiskIO(int atomTag, List<StatsEvent> pulledData) {
+    int pullDiskIO(int atomTag, List<StatsEvent> pulledData) {
         mStoragedUidIoStatsReader.readAbsolute((uid, fgCharsRead, fgCharsWrite, fgBytesRead,
                 fgBytesWrite, bgCharsRead, bgCharsWrite, bgBytesRead, bgBytesWrite,
                 fgFsync, bgFsync) -> {
@@ -1987,11 +2113,11 @@
                 tagId,
                 /* PullAtomMetadata */ null,
                 BackgroundThread.getExecutor(),
-                (atomTag, data) -> pullPowerProfile(atomTag, data)
+                mStatsCallbackImpl
         );
     }
 
-    private int pullPowerProfile(int atomTag, List<StatsEvent> pulledData) {
+    int pullPowerProfile(int atomTag, List<StatsEvent> pulledData) {
         PowerProfile powerProfile = new PowerProfile(mContext);
         ProtoOutputStream proto = new ProtoOutputStream();
         powerProfile.dumpDebug(proto);
@@ -2004,25 +2130,21 @@
         return StatsManager.PULL_SUCCESS;
     }
 
-    private final Object mCpuTrackerLock = new Object();
-    @GuardedBy("mCpuTrackerLock")
-    private ProcessCpuTracker mProcessCpuTracker;
-
     private void registerProcessCpuTime() {
         int tagId = StatsLog.PROCESS_CPU_TIME;
         // Min cool-down is 5 sec, in line with what ActivityManagerService uses.
-        PullAtomMetadata metadata = PullAtomMetadata.newBuilder()
+        PullAtomMetadata metadata = new PullAtomMetadata.Builder()
                 .setCoolDownNs(5 * NS_PER_SEC)
                 .build();
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 metadata,
-                (atomTag, data) -> pullProcessCpuTime(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullProcessCpuTime(int atomTag, List<StatsEvent> pulledData) {
+    int pullProcessCpuTime(int atomTag, List<StatsEvent> pulledData) {
         synchronized (mCpuTrackerLock) {
             if (mProcessCpuTracker == null) {
                 mProcessCpuTracker = new ProcessCpuTracker(false);
@@ -2044,24 +2166,20 @@
         return StatsManager.PULL_SUCCESS;
     }
 
-    @Nullable
-    private KernelCpuThreadReaderDiff mKernelCpuThreadReader;
-    private static final int CPU_TIME_PER_THREAD_FREQ_MAX_NUM_FREQUENCIES = 8;
-
     private void registerCpuTimePerThreadFreq() {
         int tagId = StatsLog.CPU_TIME_PER_THREAD_FREQ;
-        PullAtomMetadata metadata = PullAtomMetadata.newBuilder()
+        PullAtomMetadata metadata = new PullAtomMetadata.Builder()
                 .setAdditiveFields(new int[] {7, 9, 11, 13, 15, 17, 19, 21})
                 .build();
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 metadata,
-                (atomTag, data) -> pullCpuTimePerThreadFreq(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullCpuTimePerThreadFreq(int atomTag, List<StatsEvent> pulledData) {
+    int pullCpuTimePerThreadFreq(int atomTag, List<StatsEvent> pulledData) {
         if (this.mKernelCpuThreadReader == null) {
             Slog.e(TAG, "mKernelCpuThreadReader is null");
             return StatsManager.PULL_SKIP;
@@ -2118,12 +2236,6 @@
         return StatsManager.PULL_SUCCESS;
     }
 
-    // TODO: move to top of file when all migrations are complete
-    private BatteryStatsHelper mBatteryStatsHelper = null;
-    private static final int MAX_BATTERY_STATS_HELPER_FREQUENCY_MS = 1000;
-    private long mBatteryStatsHelperTimestampMs = -MAX_BATTERY_STATS_HELPER_FREQUENCY_MS;
-    private static final long MILLI_AMP_HR_TO_NANO_AMP_SECS = 1_000_000L * 3600L;
-
     private BatteryStatsHelper getBatteryStatsHelper() {
         if (mBatteryStatsHelper == null) {
             final long callingToken = Binder.clearCallingIdentity();
@@ -2155,12 +2267,12 @@
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                (atomTag, data) -> pullDeviceCalculatedPowerUse(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullDeviceCalculatedPowerUse(int atomTag, List<StatsEvent> pulledData) {
+    int pullDeviceCalculatedPowerUse(int atomTag, List<StatsEvent> pulledData) {
         BatteryStatsHelper bsHelper = getBatteryStatsHelper();
         StatsEvent e = StatsEvent.newBuilder()
                 .setAtomId(atomTag)
@@ -2175,12 +2287,12 @@
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                (atomTag, data) -> pullDeviceCalculatedPowerBlameUid(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullDeviceCalculatedPowerBlameUid(int atomTag, List<StatsEvent> pulledData) {
+    int pullDeviceCalculatedPowerBlameUid(int atomTag, List<StatsEvent> pulledData) {
         final List<BatterySipper> sippers = getBatteryStatsHelper().getUsageList();
         if (sippers == null) {
             return StatsManager.PULL_SKIP;
@@ -2205,12 +2317,12 @@
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                (atomTag, data) -> pullDeviceCalculatedPowerBlameOther(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullDeviceCalculatedPowerBlameOther(int atomTag, List<StatsEvent> pulledData) {
+    int pullDeviceCalculatedPowerBlameOther(int atomTag, List<StatsEvent> pulledData) {
         final List<BatterySipper> sippers = getBatteryStatsHelper().getUsageList();
         if (sippers == null) {
             return StatsManager.PULL_SKIP;
@@ -2233,24 +2345,20 @@
         return StatsManager.PULL_SUCCESS;
     }
 
-    private final Object mDebugElapsedClockLock = new Object();
-    private long mDebugElapsedClockPreviousValue = 0;
-    private long mDebugElapsedClockPullCount = 0;
-
     private void registerDebugElapsedClock() {
         int tagId = StatsLog.DEBUG_ELAPSED_CLOCK;
-        PullAtomMetadata metadata = PullAtomMetadata.newBuilder()
+        PullAtomMetadata metadata = new PullAtomMetadata.Builder()
                 .setAdditiveFields(new int[] {1, 2, 3, 4})
                 .build();
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 metadata,
-                (atomTag, data) -> pullDebugElapsedClock(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullDebugElapsedClock(int atomTag, List<StatsEvent> pulledData) {
+    int pullDebugElapsedClock(int atomTag, List<StatsEvent> pulledData) {
         final long elapsedMillis = SystemClock.elapsedRealtime();
 
         synchronized (mDebugElapsedClockLock) {
@@ -2288,24 +2396,20 @@
         return StatsManager.PULL_SUCCESS;
     }
 
-    private final Object mDebugFailingElapsedClockLock = new Object();
-    private long mDebugFailingElapsedClockPreviousValue = 0;
-    private long mDebugFailingElapsedClockPullCount = 0;
-
     private void registerDebugFailingElapsedClock() {
         int tagId = StatsLog.DEBUG_FAILING_ELAPSED_CLOCK;
-        PullAtomMetadata metadata = PullAtomMetadata.newBuilder()
+        PullAtomMetadata metadata = new PullAtomMetadata.Builder()
                 .setAdditiveFields(new int[] {1, 2, 3, 4})
                 .build();
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 metadata,
-                (atomTag, data) -> pullDebugFailingElapsedClock(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullDebugFailingElapsedClock(int atomTag, List<StatsEvent> pulledData) {
+    int pullDebugFailingElapsedClock(int atomTag, List<StatsEvent> pulledData) {
         final long elapsedMillis = SystemClock.elapsedRealtime();
 
         synchronized (mDebugFailingElapsedClockLock) {
@@ -2339,11 +2443,11 @@
                 tagId,
                 null, // use default PullAtomMetadata values
                 BackgroundThread.getExecutor(),
-                (atomTag, data) -> pullBuildInformation(atomTag, data)
+                mStatsCallbackImpl
         );
     }
 
-    private int pullBuildInformation(int atomTag, List<StatsEvent> pulledData) {
+    int pullBuildInformation(int atomTag, List<StatsEvent> pulledData) {
         StatsEvent e = StatsEvent.newBuilder()
                 .setAtomId(atomTag)
                 .writeString(Build.FINGERPRINT)
@@ -2365,13 +2469,13 @@
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                (atomTag, data) -> pullRoleHolder(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
     // Add a RoleHolder atom for each package that holds a role.
-    private int pullRoleHolder(int atomTag, List<StatsEvent> pulledData) {
+    int pullRoleHolder(int atomTag, List<StatsEvent> pulledData) {
         long callingToken = Binder.clearCallingIdentity();
         try {
             PackageManager pm = mContext.getPackageManager();
@@ -2423,12 +2527,12 @@
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                (atomTag, data) -> pullDangerousPermissionState(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullDangerousPermissionState(int atomTag, List<StatsEvent> pulledData) {
+    int pullDangerousPermissionState(int atomTag, List<StatsEvent> pulledData) {
         final long token = Binder.clearCallingIdentity();
         Set<Integer> reportedUids = new HashSet<>();
         try {
@@ -2509,12 +2613,12 @@
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                (atomTag, data) -> pullTimeZoneDataInfo(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullTimeZoneDataInfo(int atomTag, List<StatsEvent> pulledData) {
+    int pullTimeZoneDataInfo(int atomTag, List<StatsEvent> pulledData) {
         String tzDbVersion = "Unknown";
         try {
             tzDbVersion = android.icu.util.TimeZone.getTZDataVersion();
@@ -2536,12 +2640,12 @@
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                (atomTag, data) -> pullExternalStorageInfo(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullExternalStorageInfo(int atomTag, List<StatsEvent> pulledData) {
+    int pullExternalStorageInfo(int atomTag, List<StatsEvent> pulledData) {
         if (mStorageManager == null) {
             return StatsManager.PULL_SKIP;
         }
@@ -2586,12 +2690,12 @@
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                (atomTag, data) -> pullAppsOnExternalStorageInfo(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullAppsOnExternalStorageInfo(int atomTag, List<StatsEvent> pulledData) {
+    int pullAppsOnExternalStorageInfo(int atomTag, List<StatsEvent> pulledData) {
         if (mStorageManager == null) {
             return StatsManager.PULL_SKIP;
         }
@@ -2642,12 +2746,12 @@
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                (atomTag, data) -> pullFaceSettings(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullFaceSettings(int atomTag, List<StatsEvent> pulledData) {
+    int pullFaceSettings(int atomTag, List<StatsEvent> pulledData) {
         final long callingToken = Binder.clearCallingIdentity();
         try {
             List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
@@ -2696,13 +2800,13 @@
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                (atomTag, data) -> pullAppOps(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
 
     }
 
-    private int pullAppOps(int atomTag, List<StatsEvent> pulledData) {
+    int pullAppOps(int atomTag, List<StatsEvent> pulledData) {
         final long token = Binder.clearCallingIdentity();
         try {
             AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class);
@@ -2807,12 +2911,12 @@
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                (atomTag, data) -> pullNotificationRemoteViews(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
-    private int pullNotificationRemoteViews(int atomTag, List<StatsEvent> pulledData) {
+    int pullNotificationRemoteViews(int atomTag, List<StatsEvent> pulledData) {
         INotificationManager notificationManagerService = getINotificationManagerService();
         if (notificationManagerService == null) {
             return StatsManager.PULL_SKIP;
@@ -2851,8 +2955,8 @@
         mStatsManager.registerPullAtomCallback(
                 tagId,
                 null, // use default PullAtomMetadata values
-                (atomTag, data) -> pullDangerousPermissionState(atomTag, data),
-                BackgroundThread.getExecutor()
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
         );
     }
 
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 3f7d373..9a30f1d 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -79,7 +79,6 @@
 
     private final Context mContext;
 
-    private final WindowManagerService mWindowManager;
     private Handler mHandler = new Handler();
     private NotificationDelegate mNotificationDelegate;
     private volatile IStatusBar mBar;
@@ -93,6 +92,7 @@
     private final Object mLock = new Object();
     private final DeathRecipient mDeathRecipient = new DeathRecipient();
     private int mCurrentUserId;
+    private boolean mTracingEnabled;
 
     private SparseArray<UiState> mDisplayUiState = new SparseArray<>();
 
@@ -176,11 +176,10 @@
     }
 
     /**
-     * Construct the service, add the status bar view to the window manager
+     * Construct the service
      */
-    public StatusBarManagerService(Context context, WindowManagerService windowManager) {
+    public StatusBarManagerService(Context context) {
         mContext = context;
-        mWindowManager = windowManager;
 
         LocalServices.addService(StatusBarManagerInternal.class, mInternalService);
         LocalServices.addService(GlobalActionsProvider.class, mGlobalActionsProvider);
@@ -720,6 +719,31 @@
         }
     }
 
+    @Override
+    public void startTracing() {
+        if (mBar != null) {
+            try {
+                mBar.startTracing();
+                mTracingEnabled = true;
+            } catch (RemoteException ex) {}
+        }
+    }
+
+    @Override
+    public void stopTracing() {
+        if (mBar != null) {
+            try {
+                mTracingEnabled = false;
+                mBar.stopTracing();
+            } catch (RemoteException ex) {}
+        }
+    }
+
+    @Override
+    public boolean isTracing() {
+        return mTracingEnabled;
+    }
+
     // TODO(b/117478341): make it aware of multi-display if needed.
     @Override
     public void disable(int what, IBinder token, String pkg) {
@@ -1364,6 +1388,17 @@
     }
 
     @Override
+    public void onBubbleNotificationSuppressionChanged(String key, boolean isNotifSuppressed) {
+        enforceStatusBarService();
+        long identity = Binder.clearCallingIdentity();
+        try {
+            mNotificationDelegate.onBubbleNotificationSuppressionChanged(key, isNotifSuppressed);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    @Override
     public void grantInlineReplyUriPermission(String key, Uri uri, UserHandle user,
             String packageName) {
         enforceStatusBarService();
diff --git a/services/core/java/com/android/server/statusbar/StatusBarShellCommand.java b/services/core/java/com/android/server/statusbar/StatusBarShellCommand.java
index d7f86cd..a79c19f 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarShellCommand.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarShellCommand.java
@@ -72,6 +72,8 @@
                     return runDisableForSetup();
                 case "send-disable-flag":
                     return runSendDisableFlag();
+                case "tracing":
+                    return runTracing();
                 default:
                     return handleDefaultCommands(cmd);
             }
@@ -185,6 +187,18 @@
         return 0;
     }
 
+    private int runTracing() {
+        switch (getNextArg()) {
+            case "start":
+                mInterface.startTracing();
+                break;
+            case "stop":
+                mInterface.stopTracing();
+                break;
+        }
+        return 0;
+    }
+
     @Override
     public void onHelp() {
         final PrintWriter pw = getOutPrintWriter();
@@ -233,6 +247,9 @@
         pw.println("        clock               - disable clock appearing in status bar");
         pw.println("        notification-icons  - disable notification icons from status bar");
         pw.println("");
+        pw.println("  tracing (start | stop)");
+        pw.println("    Start or stop SystemUI tracing");
+        pw.println("");
     }
 
     /**
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index e8704ab..4f010d5 100755
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -1681,7 +1681,8 @@
         }
 
         @Override
-        public void startRecording(IBinder sessionToken, @Nullable Uri programUri, int userId) {
+        public void startRecording(IBinder sessionToken, @Nullable Uri programUri,
+                @Nullable Bundle params, int userId) {
             final int callingUid = Binder.getCallingUid();
             final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
                     userId, "startRecording");
@@ -1690,7 +1691,7 @@
                 synchronized (mLock) {
                     try {
                         getSessionLocked(sessionToken, callingUid, resolvedUserId).startRecording(
-                                programUri);
+                                programUri, params);
                     } catch (RemoteException | SessionNotFoundException e) {
                         Slog.e(TAG, "error in startRecording", e);
                     }
diff --git a/services/core/java/com/android/server/utils/TraceBuffer.java b/services/core/java/com/android/server/utils/TraceBuffer.java
deleted file mode 100644
index 0567960..0000000
--- a/services/core/java/com/android/server/utils/TraceBuffer.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.utils;
-
-import android.util.proto.ProtoOutputStream;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.ArrayDeque;
-import java.util.Arrays;
-import java.util.Queue;
-
-/**
- * Buffer used for tracing and logging.
- */
-public class TraceBuffer {
-    private final Object mBufferLock = new Object();
-
-    private final Queue<ProtoOutputStream> mBuffer = new ArrayDeque<>();
-    private int mBufferUsedSize;
-    private int mBufferCapacity;
-
-    public TraceBuffer(int bufferCapacity) {
-        mBufferCapacity = bufferCapacity;
-        resetBuffer();
-    }
-
-    public int getAvailableSpace() {
-        return mBufferCapacity - mBufferUsedSize;
-    }
-
-    /**
-     * Returns buffer size.
-     */
-    public int size() {
-        return mBuffer.size();
-    }
-
-    public void setCapacity(int capacity) {
-        mBufferCapacity = capacity;
-    }
-
-    /**
-     * Inserts the specified element into this buffer.
-     *
-     * @param proto the element to add
-     * @throws IllegalStateException if the element cannot be added because it is larger
-     *                               than the buffer size.
-     */
-    public void add(ProtoOutputStream proto) {
-        int protoLength = proto.getRawSize();
-        if (protoLength > mBufferCapacity) {
-            throw new IllegalStateException("Trace object too large for the buffer. Buffer size:"
-                    + mBufferCapacity + " Object size: " + protoLength);
-        }
-        synchronized (mBufferLock) {
-            discardOldest(protoLength);
-            mBuffer.add(proto);
-            mBufferUsedSize += protoLength;
-            mBufferLock.notify();
-        }
-    }
-
-    boolean contains(byte[] other) {
-        return mBuffer.stream()
-                .anyMatch(p -> Arrays.equals(p.getBytes(), other));
-    }
-
-    /**
-     * Writes the trace buffer to disk inside the encapsulatingProto..
-     */
-    public void writeTraceToFile(File traceFile, ProtoOutputStream encapsulatingProto)
-            throws IOException {
-        synchronized (mBufferLock) {
-            traceFile.delete();
-            try (OutputStream os = new FileOutputStream(traceFile)) {
-                traceFile.setReadable(true /* readable */, false /* ownerOnly */);
-                os.write(encapsulatingProto.getBytes());
-                for (ProtoOutputStream protoOutputStream : mBuffer) {
-                    encapsulatingProto = protoOutputStream;
-                    byte[] protoBytes = encapsulatingProto.getBytes();
-                    os.write(protoBytes);
-                }
-                os.flush();
-            }
-        }
-    }
-
-    /**
-     * Checks if the element can be added to the buffer. The element is already certain to be
-     * smaller than the overall buffer size.
-     *
-     * @param protoLength byte array representation of the Proto object to add
-     */
-    private void discardOldest(int protoLength) {
-        long availableSpace = getAvailableSpace();
-
-        while (availableSpace < protoLength) {
-
-            ProtoOutputStream item = mBuffer.poll();
-            if (item == null) {
-                throw new IllegalStateException("No element to discard from buffer");
-            }
-            mBufferUsedSize -= item.getRawSize();
-            availableSpace = getAvailableSpace();
-        }
-    }
-
-    /**
-     * Removes all elements form the buffer
-     */
-    public void resetBuffer() {
-        synchronized (mBufferLock) {
-            mBuffer.clear();
-            mBufferUsedSize = 0;
-        }
-    }
-
-    @VisibleForTesting
-    int getBufferSize() {
-        return mBufferUsedSize;
-    }
-
-    /**
-     * Returns the buffer status in human-readable form.
-     */
-    public String getStatus() {
-        synchronized (mBufferLock) {
-            return "Buffer size: "
-                    + mBufferCapacity
-                    + " bytes"
-                    + "\n"
-                    + "Buffer usage: "
-                    + mBufferUsedSize
-                    + " bytes"
-                    + "\n"
-                    + "Elements in the buffer: "
-                    + mBuffer.size();
-        }
-    }
-}
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 33e18c1..f8f286a 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -112,16 +112,36 @@
 import static android.view.WindowManager.TRANSIT_UNSET;
 import static android.view.WindowManager.TRANSIT_WALLPAPER_OPEN;
 
-import static com.android.server.am.ActivityRecordProto.APP_WINDOW_TOKEN;
-import static com.android.server.am.ActivityRecordProto.FRONT_OF_TASK;
-import static com.android.server.am.ActivityRecordProto.IDENTIFIER;
-import static com.android.server.am.ActivityRecordProto.PROC_ID;
-import static com.android.server.am.ActivityRecordProto.STATE;
-import static com.android.server.am.ActivityRecordProto.TRANSLUCENT;
-import static com.android.server.am.ActivityRecordProto.VISIBLE;
-import static com.android.server.am.ActivityRecordProto.VISIBLE_REQUESTED;
 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+import static com.android.server.wm.ActivityRecordProto.ALL_DRAWN;
+import static com.android.server.wm.ActivityRecordProto.APP_STOPPED;
+import static com.android.server.wm.ActivityRecordProto.CLIENT_VISIBLE;
+import static com.android.server.wm.ActivityRecordProto.DEFER_HIDING_CLIENT;
+import static com.android.server.wm.ActivityRecordProto.FILLS_PARENT;
+import static com.android.server.wm.ActivityRecordProto.FRONT_OF_TASK;
+import static com.android.server.wm.ActivityRecordProto.FROZEN_BOUNDS;
+import static com.android.server.wm.ActivityRecordProto.IDENTIFIER;
+import static com.android.server.wm.ActivityRecordProto.IS_ANIMATING;
+import static com.android.server.wm.ActivityRecordProto.IS_WAITING_FOR_TRANSITION_START;
+import static com.android.server.wm.ActivityRecordProto.LAST_ALL_DRAWN;
+import static com.android.server.wm.ActivityRecordProto.LAST_SURFACE_SHOWING;
+import static com.android.server.wm.ActivityRecordProto.NAME;
+import static com.android.server.wm.ActivityRecordProto.NUM_DRAWN_WINDOWS;
+import static com.android.server.wm.ActivityRecordProto.NUM_INTERESTING_WINDOWS;
+import static com.android.server.wm.ActivityRecordProto.PROC_ID;
+import static com.android.server.wm.ActivityRecordProto.REPORTED_DRAWN;
+import static com.android.server.wm.ActivityRecordProto.REPORTED_VISIBLE;
+import static com.android.server.wm.ActivityRecordProto.STARTING_DISPLAYED;
+import static com.android.server.wm.ActivityRecordProto.STARTING_MOVED;
+import static com.android.server.wm.ActivityRecordProto.STARTING_WINDOW;
+import static com.android.server.wm.ActivityRecordProto.STATE;
+import static com.android.server.wm.ActivityRecordProto.THUMBNAIL;
+import static com.android.server.wm.ActivityRecordProto.TRANSLUCENT;
+import static com.android.server.wm.ActivityRecordProto.VISIBLE;
+import static com.android.server.wm.ActivityRecordProto.VISIBLE_REQUESTED;
+import static com.android.server.wm.ActivityRecordProto.VISIBLE_SET_FROM_TRANSFERRED_STARTING_WINDOW;
+import static com.android.server.wm.ActivityRecordProto.WINDOW_TOKEN;
 import static com.android.server.wm.ActivityStack.ActivityState.DESTROYED;
 import static com.android.server.wm.ActivityStack.ActivityState.DESTROYING;
 import static com.android.server.wm.ActivityStack.ActivityState.FINISHING;
@@ -167,27 +187,6 @@
 import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_NONE;
 import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_WINDOWING_MODE_RESIZE;
 import static com.android.server.wm.ActivityTaskManagerService.getInputDispatchingTimeoutLocked;
-import static com.android.server.wm.AppWindowTokenProto.ALL_DRAWN;
-import static com.android.server.wm.AppWindowTokenProto.APP_STOPPED;
-import static com.android.server.wm.AppWindowTokenProto.CLIENT_VISIBLE;
-import static com.android.server.wm.AppWindowTokenProto.DEFER_HIDING_CLIENT;
-import static com.android.server.wm.AppWindowTokenProto.FILLS_PARENT;
-import static com.android.server.wm.AppWindowTokenProto.FROZEN_BOUNDS;
-import static com.android.server.wm.AppWindowTokenProto.IS_ANIMATING;
-import static com.android.server.wm.AppWindowTokenProto.IS_WAITING_FOR_TRANSITION_START;
-import static com.android.server.wm.AppWindowTokenProto.LAST_ALL_DRAWN;
-import static com.android.server.wm.AppWindowTokenProto.LAST_SURFACE_SHOWING;
-import static com.android.server.wm.AppWindowTokenProto.NAME;
-import static com.android.server.wm.AppWindowTokenProto.NUM_DRAWN_WINDOWS;
-import static com.android.server.wm.AppWindowTokenProto.NUM_INTERESTING_WINDOWS;
-import static com.android.server.wm.AppWindowTokenProto.REPORTED_DRAWN;
-import static com.android.server.wm.AppWindowTokenProto.REPORTED_VISIBLE;
-import static com.android.server.wm.AppWindowTokenProto.STARTING_DISPLAYED;
-import static com.android.server.wm.AppWindowTokenProto.STARTING_MOVED;
-import static com.android.server.wm.AppWindowTokenProto.STARTING_WINDOW;
-import static com.android.server.wm.AppWindowTokenProto.THUMBNAIL;
-import static com.android.server.wm.AppWindowTokenProto.VISIBLE_SET_FROM_TRANSFERRED_STARTING_WINDOW;
-import static com.android.server.wm.AppWindowTokenProto.WINDOW_TOKEN;
 import static com.android.server.wm.IdentifierProto.HASH_CODE;
 import static com.android.server.wm.IdentifierProto.TITLE;
 import static com.android.server.wm.IdentifierProto.USER_ID;
@@ -7496,7 +7495,36 @@
      * {@code ActivityRecordProto} is the outer-most proto data.
      */
     void dumpDebug(ProtoOutputStream proto) {
-        dumpDebug(proto, APP_WINDOW_TOKEN, WindowTraceLogLevel.ALL);
+        writeNameToProto(proto, NAME);
+        super.dumpDebug(proto, WINDOW_TOKEN, WindowTraceLogLevel.ALL);
+        proto.write(LAST_SURFACE_SHOWING, mLastSurfaceShowing);
+        proto.write(IS_WAITING_FOR_TRANSITION_START, isWaitingForTransitionStart());
+        proto.write(IS_ANIMATING, isAnimating());
+        if (mThumbnail != null) {
+            mThumbnail.dumpDebug(proto, THUMBNAIL);
+        }
+        proto.write(FILLS_PARENT, mOccludesParent);
+        proto.write(APP_STOPPED, mAppStopped);
+        proto.write(VISIBLE_REQUESTED, mVisibleRequested);
+        proto.write(CLIENT_VISIBLE, mClientVisible);
+        proto.write(DEFER_HIDING_CLIENT, mDeferHidingClient);
+        proto.write(REPORTED_DRAWN, reportedDrawn);
+        proto.write(REPORTED_VISIBLE, reportedVisible);
+        proto.write(NUM_INTERESTING_WINDOWS, mNumInterestingWindows);
+        proto.write(NUM_DRAWN_WINDOWS, mNumDrawnWindows);
+        proto.write(ALL_DRAWN, allDrawn);
+        proto.write(LAST_ALL_DRAWN, mLastAllDrawn);
+        if (startingWindow != null) {
+            startingWindow.writeIdentifierToProto(proto, STARTING_WINDOW);
+        }
+        proto.write(STARTING_DISPLAYED, startingDisplayed);
+        proto.write(STARTING_MOVED, startingMoved);
+        proto.write(VISIBLE_SET_FROM_TRANSFERRED_STARTING_WINDOW,
+                mVisibleSetFromTransferredStartingWindow);
+        for (Rect bounds : mFrozenBounds) {
+            bounds.dumpDebug(proto, FROZEN_BOUNDS);
+        }
+
         writeIdentifierToProto(proto, IDENTIFIER);
         proto.write(STATE, mState.toString());
         proto.write(VISIBLE_REQUESTED, mVisibleRequested);
@@ -7536,7 +7564,7 @@
         }
         proto.write(FILLS_PARENT, mOccludesParent);
         proto.write(APP_STOPPED, mAppStopped);
-        proto.write(com.android.server.wm.AppWindowTokenProto.VISIBLE_REQUESTED, mVisibleRequested);
+        proto.write(VISIBLE_REQUESTED, mVisibleRequested);
         proto.write(CLIENT_VISIBLE, mClientVisible);
         proto.write(DEFER_HIDING_CLIENT, mDeferHidingClient);
         proto.write(REPORTED_DRAWN, reportedDrawn);
@@ -7555,7 +7583,7 @@
         for (Rect bounds : mFrozenBounds) {
             bounds.dumpDebug(proto, FROZEN_BOUNDS);
         }
-        proto.write(com.android.server.wm.AppWindowTokenProto.VISIBLE, mVisible);
+        proto.write(VISIBLE, mVisible);
         proto.end(token);
     }
 
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index 663423f..ddf0117 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -660,6 +660,8 @@
 
         super.onConfigurationChanged(newParentConfig);
 
+        updateTaskOrganizerState();
+
         // Only need to update surface size here since the super method will handle updating
         // surface position.
         updateSurfaceSize(getPendingTransaction());
@@ -762,6 +764,22 @@
         }
     }
 
+    void updateTaskOrganizerState() {
+        if (!isRootTask()) {
+            return;
+        }
+
+        final int windowingMode = getWindowingMode();
+        /*
+         * Different windowing modes may be managed by different task organizers. If
+         * getTaskOrganizer returns null, we still call setTaskOrganizer to
+         * make sure we clear it.
+         */
+        final ITaskOrganizer org =
+            mWmService.mAtmService.mTaskOrganizerController.getTaskOrganizer(windowingMode);
+        setTaskOrganizer(org);
+    }
+
     @Override
     public void setWindowingMode(int windowingMode) {
         // Calling Task#setWindowingMode() for leaf task since this is the a specialization of
@@ -774,15 +792,6 @@
         setWindowingMode(windowingMode, false /* animate */, false /* showRecents */,
                 false /* enteringSplitScreenMode */, false /* deferEnsuringVisibility */,
                 false /* creating */);
-        windowingMode = getWindowingMode();
-        /*
-         * Different windowing modes may be managed by different task organizers. If
-         * getTaskOrganizer returns null, we still call transferToTaskOrganizer to
-         * make sure we clear it.
-         */
-        final ITaskOrganizer org =
-            mWmService.mAtmService.mTaskOrganizerController.getTaskOrganizer(windowingMode);
-        transferToTaskOrganizer(org);
     }
 
     /**
@@ -1583,24 +1592,6 @@
         return topActivity != null && topActivity.mVisibleRequested;
     }
 
-    private static void transferSingleTaskToOrganizer(Task tr, ITaskOrganizer organizer) {
-        tr.setTaskOrganizer(organizer);
-    }
-
-    /**
-     * Transfer control of the leashes and IWindowContainers to the given ITaskOrganizer.
-     * This will (or shortly there-after) invoke the taskAppeared callbacks.
-     * If the tasks had a previous TaskOrganizer, setTaskOrganizer will take care of
-     * emitting the taskVanished callbacks.
-     */
-    void transferToTaskOrganizer(ITaskOrganizer organizer) {
-        final PooledConsumer c = PooledLambda.obtainConsumer(
-                ActivityStack::transferSingleTaskToOrganizer,
-                PooledLambda.__(Task.class), organizer);
-        forAllTasks(c, true /* traverseTopToBottom */, this);
-        c.recycle();
-    }
-
     /**
      * Returns true if the stack should be visible.
      *
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 26812f4..9e3292b 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -1595,11 +1595,11 @@
                 mRootWindowContainer.resumeFocusedStacksTopActivities(
                         mTargetStack, mStartActivity, mOptions);
             }
-        } else if (mStartActivity != null) {
-            mSupervisor.mRecentTasks.add(mStartActivity.getTask());
         }
         mRootWindowContainer.updateUserStack(mStartActivity.mUserId, mTargetStack);
 
+        // Update the recent tasks list immediately when the activity starts
+        mSupervisor.mRecentTasks.add(mStartActivity.getTask());
         mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(),
                 preferredWindowingMode, mPreferredDisplayId, mTargetStack);
 
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index bf89bab..c50048e 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -112,7 +112,6 @@
 import static com.android.server.wm.DisplayContentProto.IME_WINDOWS;
 import static com.android.server.wm.DisplayContentProto.OPENING_APPS;
 import static com.android.server.wm.DisplayContentProto.OVERLAY_WINDOWS;
-import static com.android.server.wm.DisplayContentProto.PINNED_STACK_CONTROLLER;
 import static com.android.server.wm.DisplayContentProto.ROTATION;
 import static com.android.server.wm.DisplayContentProto.SCREEN_ROTATION_ANIMATION;
 import static com.android.server.wm.DisplayContentProto.STACKS;
@@ -2779,7 +2778,6 @@
             stack.dumpDebugInnerStackOnly(proto, STACKS, logLevel);
         }
         mDividerControllerLocked.dumpDebug(proto, DOCKED_STACK_DIVIDER_CONTROLLER);
-        mPinnedStackControllerLocked.dumpDebug(proto, PINNED_STACK_CONTROLLER);
         for (int i = mAboveAppWindowsContainers.getChildCount() - 1; i >= 0; --i) {
             final WindowToken windowToken = mAboveAppWindowsContainers.getChildAt(i);
             windowToken.dumpDebug(proto, ABOVE_APP_WINDOWS, logLevel);
@@ -4732,7 +4730,7 @@
             // exists so it get's layered above the starting window.
             if (imeTarget != null && !(imeTarget.mActivityRecord != null
                     && imeTarget.mActivityRecord.hasStartingWindow()) && (
-                    !(imeTarget.inSplitScreenWindowingMode()
+                    !(imeTarget.inMultiWindowMode()
                             || imeTarget.mToken.isAppTransitioning()) && (
                             imeTarget.getSurfaceControl() != null))) {
                 mImeWindowsContainers.assignRelativeLayer(t, imeTarget.getSurfaceControl(),
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index f8df883..d211cfd 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -1014,8 +1014,19 @@
                 mNavigationBarController.setWindow(win);
                 mNavigationBarController.setOnBarVisibilityChangedListener(
                         mNavBarVisibilityListener, true);
-                mDisplayContent.setInsetProvider(ITYPE_NAVIGATION_BAR,
-                        win, null /* frameProvider */);
+                mDisplayContent.setInsetProvider(ITYPE_NAVIGATION_BAR, win,
+                        (displayFrames, windowState, inOutFrame) -> {
+
+                            // In Gesture Nav, navigation bar frame is larger than frame to
+                            // calculate inset.
+                            if (mNavigationBarPosition == NAV_BAR_BOTTOM) {
+                                sTmpRect.set(displayFrames.mUnrestricted);
+                                sTmpRect.intersectUnchecked(displayFrames.mDisplayCutoutSafe);
+                                inOutFrame.top = sTmpRect.bottom
+                                        - getNavigationBarHeight(displayFrames.mRotation,
+                                                mDisplayContent.getConfiguration().uiMode);
+                            }
+                        });
                 mDisplayContent.setInsetProvider(ITYPE_BOTTOM_GESTURES, win,
                         (displayFrames, windowState, inOutFrame) -> {
                             inOutFrame.top -= mBottomGestureAdditionalInset;
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index 4c5914b..faa6e52 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -161,7 +161,13 @@
 
     void onDisplayRemoved() {
         mHandler.removeCallbacks(mUpdateInputWindows);
-        mService.mInputManager.onDisplayRemoved(mDisplayId);
+        mHandler.post(() -> {
+            // Make sure any pending setInputWindowInfo transactions are completed. That prevents
+            // the timing of updating input info of removed display after cleanup.
+            mService.mTransactionFactory.get().syncInputWindows().apply();
+            // It calls InputDispatcher::setInputWindows directly.
+            mService.mInputManager.onDisplayRemoved(mDisplayId);
+        });
         mDisplayRemoved = true;
     }
 
diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
index 5a591ec..2bb58dd 100644
--- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java
+++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
@@ -233,7 +233,7 @@
             // window crop of the surface controls (including the leash) until the client finishes
             // drawing the new frame of the new orientation. Although we cannot defer the reparent
             // operation, it is fine, because reparent won't cause any visual effect.
-            final SurfaceControl barrier = mWin.mWinAnimator.mSurfaceController.mSurfaceControl;
+            final SurfaceControl barrier = mWin.getDeferTransactionBarrier();
             t.deferTransactionUntil(mWin.getSurfaceControl(), barrier, frameNumber);
             t.deferTransactionUntil(leash, barrier, frameNumber);
         }
diff --git a/services/core/java/com/android/server/wm/PinnedStackController.java b/services/core/java/com/android/server/wm/PinnedStackController.java
index 1d5b5d1..668b609 100644
--- a/services/core/java/com/android/server/wm/PinnedStackController.java
+++ b/services/core/java/com/android/server/wm/PinnedStackController.java
@@ -18,8 +18,6 @@
 
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
 
-import static com.android.server.wm.PinnedStackControllerProto.DEFAULT_BOUNDS;
-import static com.android.server.wm.PinnedStackControllerProto.MOVEMENT_BOUNDS;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 
@@ -34,7 +32,6 @@
 import android.util.DisplayMetrics;
 import android.util.Log;
 import android.util.Slog;
-import android.util.proto.ProtoOutputStream;
 import android.view.DisplayInfo;
 import android.view.IPinnedStackController;
 import android.view.IPinnedStackListener;
@@ -97,11 +94,6 @@
     // Temp vars for calculation
     private final DisplayMetrics mTmpMetrics = new DisplayMetrics();
 
-    // TODO(b/141200935): remove this when we have default/movement bounds tests in SysUI.
-    // Keep record of the default and movement bounds
-    private final Rect mLastReportedDefaultBounds = new Rect();
-    private final Rect mLastReportedMovementBounds = new Rect();
-
     /**
      * The callback object passed to listeners for them to notify the controller of state changes.
      */
@@ -143,14 +135,6 @@
                 }
             }
         }
-
-        @Override
-        public void reportBounds(Rect defaultBounds, Rect movementBounds) {
-            synchronized (mService.mGlobalLock) {
-                mLastReportedDefaultBounds.set(defaultBounds);
-                mLastReportedMovementBounds.set(movementBounds);
-            }
-        }
     }
 
     /**
@@ -421,8 +405,6 @@
 
     void dump(String prefix, PrintWriter pw) {
         pw.println(prefix + "PinnedStackController");
-        pw.println(prefix + "  mLastReportedDefaultBounds=" + mLastReportedDefaultBounds);
-        pw.println(prefix + "  mLastReportedMovementBounds=" + mLastReportedMovementBounds);
         pw.println(prefix + "  mDefaultAspectRatio=" + mDefaultAspectRatio);
         pw.println(prefix + "  mIsImeShowing=" + mIsImeShowing);
         pw.println(prefix + "  mImeHeight=" + mImeHeight);
@@ -443,11 +425,4 @@
         }
         pw.println(prefix + "  mDisplayInfo=" + mDisplayInfo);
     }
-
-    void dumpDebug(ProtoOutputStream proto, long fieldId) {
-        final long token = proto.start(fieldId);
-        mLastReportedDefaultBounds.dumpDebug(proto, DEFAULT_BOUNDS);
-        mLastReportedMovementBounds.dumpDebug(proto, MOVEMENT_BOUNDS);
-        proto.end(token);
-    }
 }
diff --git a/services/core/java/com/android/server/wm/RecentTasks.java b/services/core/java/com/android/server/wm/RecentTasks.java
index 292e8aa..a9dc36d 100644
--- a/services/core/java/com/android/server/wm/RecentTasks.java
+++ b/services/core/java/com/android/server/wm/RecentTasks.java
@@ -173,6 +173,9 @@
     private final ArrayList<Task> mTasks = new ArrayList<>();
     private final ArrayList<Callbacks> mCallbacks = new ArrayList<>();
 
+    /** The non-empty tasks that are removed from recent tasks (see {@link #removeForAddTask}). */
+    private final ArrayList<Task> mHiddenTasks = new ArrayList<>();
+
     // These values are generally loaded from resources, but can be set dynamically in the tests
     private boolean mHasVisibleRecentTasks;
     private int mGlobalMaxNumTasks;
@@ -1024,6 +1027,12 @@
     void add(Task task) {
         if (DEBUG_RECENTS_TRIM_TASKS) Slog.d(TAG, "add: task=" + task);
 
+        // Clean up the hidden tasks when going to home because the user may not be unable to return
+        // to the task from recents.
+        if (!mHiddenTasks.isEmpty() && task.isActivityTypeHome()) {
+            removeUnreachableHiddenTasks(task.getWindowingMode());
+        }
+
         final boolean isAffiliated = task.mAffiliatedTaskId != task.mTaskId
                 || task.mNextAffiliateTaskId != INVALID_TASK_ID
                 || task.mPrevAffiliateTaskId != INVALID_TASK_ID;
@@ -1390,6 +1399,28 @@
         return display.getIndexOf(stack) < display.getIndexOf(display.getRootHomeTask());
     }
 
+    /** Remove the tasks that user may not be able to return. */
+    private void removeUnreachableHiddenTasks(int windowingMode) {
+        for (int i = mHiddenTasks.size() - 1; i >= 0; i--) {
+            final Task hiddenTask = mHiddenTasks.get(i);
+            if (!hiddenTask.hasChild()) {
+                // The task was removed by other path.
+                mHiddenTasks.remove(i);
+                continue;
+            }
+            if (hiddenTask.getWindowingMode() != windowingMode
+                    || hiddenTask.getTopVisibleActivity() != null) {
+                // The task may be reachable from the back stack of other windowing mode or it is
+                // currently in use. Keep the task in the hidden list to avoid losing track, e.g.
+                // after dismissing primary split screen.
+                continue;
+            }
+            mHiddenTasks.remove(i);
+            mSupervisor.removeTask(hiddenTask, false /* killProcess */,
+                    !REMOVE_FROM_RECENTS, "remove-hidden-task");
+        }
+    }
+
     /**
      * If needed, remove oldest existing entries in recents that are for the same kind
      * of task as the given one.
@@ -1406,6 +1437,14 @@
         // callbacks here.
         final Task removedTask = mTasks.remove(removeIndex);
         if (removedTask != task) {
+            // The added task is in recents so it is not hidden.
+            mHiddenTasks.remove(task);
+            if (removedTask.hasChild()) {
+                // A non-empty task is replaced by a new task. Because the removed task is no longer
+                // managed by the recent tasks list, add it to the hidden list to prevent the task
+                // from becoming dangling.
+                mHiddenTasks.add(removedTask);
+            }
             notifyTaskRemoved(removedTask, false /* wasTrimmed */, false /* killProcess */);
             if (DEBUG_RECENTS_TRIM_TASKS) Slog.d(TAG, "Trimming task=" + removedTask
                     + " for addition of task=" + task);
@@ -1662,6 +1701,9 @@
         pw.println("mFreezeTaskListReordering=" + mFreezeTaskListReordering);
         pw.println("mFreezeTaskListReorderingPendingTimeout="
                 + mService.mH.hasCallbacks(mResetFreezeTaskListOnTimeoutRunnable));
+        if (!mHiddenTasks.isEmpty()) {
+            pw.println("mHiddenTasks=" + mHiddenTasks);
+        }
         if (mTasks.isEmpty()) {
             return;
         }
diff --git a/services/core/java/com/android/server/wm/SeamlessRotator.java b/services/core/java/com/android/server/wm/SeamlessRotator.java
index ba31818..c621c48 100644
--- a/services/core/java/com/android/server/wm/SeamlessRotator.java
+++ b/services/core/java/com/android/server/wm/SeamlessRotator.java
@@ -101,9 +101,9 @@
         t.setPosition(win.mSurfaceControl, win.mLastSurfacePosition.x, win.mLastSurfacePosition.y);
         if (win.mWinAnimator.mSurfaceController != null && !timeout) {
             t.deferTransactionUntil(win.mSurfaceControl,
-                    win.mWinAnimator.mSurfaceController.mSurfaceControl, win.getFrameNumber());
+                    win.getDeferTransactionBarrier(), win.getFrameNumber());
             t.deferTransactionUntil(win.mWinAnimator.mSurfaceController.mSurfaceControl,
-                    win.mWinAnimator.mSurfaceController.mSurfaceControl, win.getFrameNumber());
+                    win.getDeferTransactionBarrier(), win.getFrameNumber());
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 5babdaf..de7f9e4 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -191,7 +191,7 @@
             Rect outStableInsets, Rect outBackdropFrame,
             DisplayCutout.ParcelableWrapper cutout, MergedConfiguration mergedConfiguration,
             SurfaceControl outSurfaceControl, InsetsState outInsetsState,
-            Point outSurfaceSize) {
+            Point outSurfaceSize, SurfaceControl outBLASTSurfaceControl) {
         if (false) Slog.d(TAG_WM, ">>>>>> ENTERED relayout from "
                 + Binder.getCallingPid());
         Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, mRelayoutTag);
@@ -199,7 +199,8 @@
                 requestedWidth, requestedHeight, viewFlags, flags, frameNumber,
                 outFrame, outContentInsets, outVisibleInsets,
                 outStableInsets, outBackdropFrame, cutout,
-                mergedConfiguration, outSurfaceControl, outInsetsState, outSurfaceSize);
+                mergedConfiguration, outSurfaceControl, outInsetsState, outSurfaceSize,
+                outBLASTSurfaceControl);
         Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
         if (false) Slog.d(TAG_WM, "<<<<<< EXITING relayout to "
                 + Binder.getCallingPid());
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 9dba0d3..36cae1f 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -90,7 +90,7 @@
 import static com.android.server.wm.ActivityTaskManagerService.TAG_STACK;
 import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER;
 import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
-import static com.android.server.wm.TaskProto.APP_WINDOW_TOKENS;
+import static com.android.server.wm.TaskProto.ACTIVITY;
 import static com.android.server.wm.TaskProto.DISPLAYED_BOUNDS;
 import static com.android.server.wm.TaskProto.FILLS_PARENT;
 import static com.android.server.wm.TaskProto.SURFACE_HEIGHT;
@@ -3171,7 +3171,7 @@
         super.dumpDebug(proto, WINDOW_CONTAINER, logLevel);
         proto.write(TaskProto.ID, mTaskId);
         forAllActivities((r) -> {
-            r.dumpDebug(proto, APP_WINDOW_TOKENS, logLevel);
+            r.dumpDebug(proto, ACTIVITY);
         });
         proto.write(FILLS_PARENT, matchParentBounds());
         getBounds().dumpDebug(proto, TaskProto.BOUNDS);
@@ -3864,9 +3864,8 @@
     }
 
     boolean isControlledByTaskOrganizer() {
-        // TODO(b/147849315): Clean-up relationship between task-org and task-hierarchy. Ideally
-        //  we only give control of the root task.
-        return getTopMostTask().mTaskOrganizer != null;
+        final Task rootTask = getRootTask();
+        return rootTask == this && rootTask.mTaskOrganizer != null;
     }
 
     @Override
@@ -3938,23 +3937,6 @@
         super.getRelativeDisplayedPosition(outPos);
     }
 
-    @Override
-    public void setWindowingMode(int windowingMode) {
-        super.setWindowingMode(windowingMode);
-        windowingMode = getWindowingMode();
-
-        // TODO(b/147849315): Clean-up relationship between task-org and task-hierarchy. Ideally
-        //  we only give control of the root task.
-        // Different windowing modes may be managed by different task organizers. If
-        // getTaskOrganizer returns null, we still call transferToTaskOrganizer to make sure we
-        // clear it.
-        if (!isRootTask()) {
-            final ITaskOrganizer org =
-                    mAtmService.mTaskOrganizerController.getTaskOrganizer(windowingMode);
-            setTaskOrganizer(org);
-        }
-    }
-
     /**
      * @return true if the task is currently focused.
      */
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index 57de753..e47eaee 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -116,7 +116,11 @@
     private static final String TAG = TAG_WITH_CLASS_NAME ? "SnapshotStartingWindow" : TAG_WM;
     private static final int MSG_REPORT_DRAW = 0;
     private static final String TITLE_FORMAT = "SnapshotStartingWindow for taskId=%s";
-    private static final Point sSurfaceSize = new Point(); //tmp var for unused relayout param
+
+    //tmp vars for unused relayout params
+    private static final Point sTmpSurfaceSize = new Point();
+    private static final SurfaceControl sTmpSurfaceControl = new SurfaceControl();
+
     private final Window mWindow;
     private final Surface mSurface;
     private SurfaceControl mSurfaceControl;
@@ -230,7 +234,7 @@
             session.relayout(window, window.mSeq, layoutParams, -1, -1, View.VISIBLE, 0, -1,
                     tmpFrame, tmpContentInsets, tmpRect, tmpStableInsets, tmpRect,
                     tmpCutout, tmpMergedConfiguration, surfaceControl, mTmpInsetsState,
-                    sSurfaceSize);
+                    sTmpSurfaceSize, sTmpSurfaceControl);
         } catch (RemoteException e) {
             // Local call.
         }
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index e130830..2c6c756 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2071,7 +2071,7 @@
             Rect outVisibleInsets, Rect outStableInsets, Rect outBackdropFrame,
             DisplayCutout.ParcelableWrapper outCutout, MergedConfiguration mergedConfiguration,
             SurfaceControl outSurfaceControl, InsetsState outInsetsState,
-            Point outSurfaceSize) {
+            Point outSurfaceSize, SurfaceControl outBLASTSurfaceControl) {
         int result = 0;
         boolean configChanged;
         final int pid = Binder.getCallingPid();
@@ -2238,7 +2238,8 @@
                 result = win.relayoutVisibleWindow(result, attrChanges);
 
                 try {
-                    result = createSurfaceControl(outSurfaceControl, result, win, winAnimator);
+                    result = createSurfaceControl(outSurfaceControl, outBLASTSurfaceControl,
+                            result, win, winAnimator);
                 } catch (Exception e) {
                     displayContent.getInputMonitor().updateInputWindowsLw(true /*force*/);
 
@@ -2270,6 +2271,7 @@
                     // surface, let the client use that, but don't create new surface at this point.
                     Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "relayoutWindow: getSurface");
                     winAnimator.mSurfaceController.getSurfaceControl(outSurfaceControl);
+                    winAnimator.mSurfaceController.getBLASTSurfaceControl(outBLASTSurfaceControl);
                     Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
                 } else {
                     if (DEBUG_VISIBILITY) Slog.i(TAG_WM, "Releasing surface in: " + win);
@@ -2451,7 +2453,8 @@
     }
 
     private int createSurfaceControl(SurfaceControl outSurfaceControl,
-            int result, WindowState win, WindowStateAnimator winAnimator) {
+            SurfaceControl outBLASTSurfaceControl, int result,
+            WindowState win, WindowStateAnimator winAnimator) {
         if (!win.mHasSurface) {
             result |= RELAYOUT_RES_SURFACE_CHANGED;
         }
@@ -2465,6 +2468,7 @@
         }
         if (surfaceController != null) {
             surfaceController.getSurfaceControl(outSurfaceControl);
+            surfaceController.getBLASTSurfaceControl(outBLASTSurfaceControl);
             ProtoLog.i(WM_SHOW_TRANSACTIONS, "OUT SURFACE %s: copied", outSurfaceControl);
 
         } else {
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 73984fd..b9694c3 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -5616,4 +5616,8 @@
     boolean isNonToastWindowVisibleForPid(int pid) {
         return mSession.mPid == pid && isNonToastOrStarting() && isVisibleNow();
     }
+
+    SurfaceControl getDeferTransactionBarrier() {
+        return mWinAnimator.getDeferTransactionBarrier();
+    }
 }
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 069ee4f..9552df7 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -1010,7 +1010,7 @@
                         // the WS position is reset (so the stack position is shown) at the same
                         // time that the buffer size changes.
                         setOffsetPositionForStackResize(false);
-                        mSurfaceController.deferTransactionUntil(mSurfaceController.mSurfaceControl,
+                        mSurfaceController.deferTransactionUntil(mWin.getDeferTransactionBarrier(),
                                 mWin.getFrameNumber());
                     } else {
                         final ActivityStack stack = mWin.getRootTask();
@@ -1041,7 +1041,7 @@
         // comes in at the new size (normally position and crop are unfrozen).
         // deferTransactionUntil accomplishes this for us.
         if (wasForceScaled && !mForceScaleUntilResize) {
-            mSurfaceController.deferTransactionUntil(mSurfaceController.mSurfaceControl,
+            mSurfaceController.deferTransactionUntil(mWin.getDeferTransactionBarrier(),
                     mWin.getFrameNumber());
             mSurfaceController.forceScaleableInTransaction(false);
         }
@@ -1518,4 +1518,11 @@
     void setOffsetPositionForStackResize(boolean offsetPositionForStackResize) {
         mOffsetPositionForStackResize = offsetPositionForStackResize;
     }
+
+    SurfaceControl getDeferTransactionBarrier() {
+        if (!hasSurface()) {
+            return null;
+        }
+        return mSurfaceController.getDeferTransactionBarrier();
+    }
 }
diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index 5b8015b..383c0d9 100644
--- a/services/core/java/com/android/server/wm/WindowSurfaceController.java
+++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java
@@ -51,6 +51,11 @@
 
     SurfaceControl mSurfaceControl;
 
+    /**
+     * WM only uses for deferred transactions.
+     */
+    SurfaceControl mBLASTSurfaceControl;
+
     // Should only be set from within setShown().
     private boolean mSurfaceShown = false;
     private float mSurfaceX = 0;
@@ -110,13 +115,22 @@
                 .setMetadata(METADATA_WINDOW_TYPE, windowType)
                 .setMetadata(METADATA_OWNER_UID, ownerUid);
 
-        if ((win.getAttrs().privateFlags &
-                WindowManager.LayoutParams.PRIVATE_FLAG_USE_BLAST) != 0) {
+        final boolean useBLAST = (win.getAttrs().privateFlags &
+                WindowManager.LayoutParams.PRIVATE_FLAG_USE_BLAST) != 0;
+        if (useBLAST) {
             b.setContainerLayer();
         }
 
-
         mSurfaceControl = b.build();
+
+        if (useBLAST) {
+            mBLASTSurfaceControl = win.makeSurface()
+                .setParent(mSurfaceControl)
+                .setName("BLAST Adapter Layer")
+                .setBLASTLayer()
+                .build();
+        }
+
         Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
     }
 
@@ -168,6 +182,9 @@
         } finally {
             setShown(false);
             mSurfaceControl = null;
+            if (mBLASTSurfaceControl != null) {
+                mBLASTSurfaceControl.release();
+            }
         }
     }
 
@@ -474,6 +491,12 @@
         outSurfaceControl.copyFrom(mSurfaceControl);
     }
 
+    void getBLASTSurfaceControl(SurfaceControl outSurfaceControl) {
+        if (mBLASTSurfaceControl != null) {
+            outSurfaceControl.copyFrom(mBLASTSurfaceControl);
+        }
+    }
+
     int getLayer() {
         return mSurfaceLayer;
     }
@@ -510,6 +533,13 @@
         return mSurfaceH;
     }
 
+    SurfaceControl getDeferTransactionBarrier() {
+        if (mBLASTSurfaceControl != null) {
+            return mBLASTSurfaceControl;
+        }
+        return mSurfaceControl;
+    }
+
     void dumpDebug(ProtoOutputStream proto, long fieldId) {
         final long token = proto.start(fieldId);
         proto.write(SHOWN, mSurfaceShown);
diff --git a/services/core/java/com/android/server/wm/WindowTracing.java b/services/core/java/com/android/server/wm/WindowTracing.java
index 0be90fc..ba3dc60 100644
--- a/services/core/java/com/android/server/wm/WindowTracing.java
+++ b/services/core/java/com/android/server/wm/WindowTracing.java
@@ -35,7 +35,7 @@
 import android.view.Choreographer;
 
 import com.android.server.protolog.ProtoLogImpl;
-import com.android.server.utils.TraceBuffer;
+import com.android.internal.util.TraceBuffer;
 
 import java.io.File;
 import java.io.IOException;
@@ -64,7 +64,7 @@
 
     private final Object mEnabledLock = new Object();
     private final File mTraceFile;
-    private final com.android.server.utils.TraceBuffer mBuffer;
+    private final TraceBuffer mBuffer;
     private final Choreographer.FrameCallback mFrameCallback = (frameTimeNanos) ->
             log("onFrame" /* where */);
 
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index 77d814e..4a2636e 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -14,6 +14,7 @@
 
     srcs: [
         ":graphicsstats_proto",
+        ":lib_alarmManagerService_native",
         "BroadcastRadio/JavaRef.cpp",
         "BroadcastRadio/NativeCallbackThread.cpp",
         "BroadcastRadio/BroadcastRadioService.cpp",
@@ -21,7 +22,6 @@
         "BroadcastRadio/TunerCallback.cpp",
         "BroadcastRadio/convert.cpp",
         "BroadcastRadio/regions.cpp",
-        "com_android_server_AlarmManagerService.cpp",
         "com_android_server_am_BatteryStatsService.cpp",
         "com_android_server_connectivity_Vpn.cpp",
         "com_android_server_ConsumerIrService.cpp",
@@ -182,3 +182,10 @@
         "com_android_server_net_NetworkStatsFactory.cpp",
     ],
 }
+
+filegroup {
+    name: "lib_alarmManagerService_native",
+    srcs: [
+        "com_android_server_AlarmManagerService.cpp",
+    ],
+}
diff --git a/services/core/jni/com_android_server_VibratorService.cpp b/services/core/jni/com_android_server_VibratorService.cpp
index 6811e6d..5a8e25e4 100644
--- a/services/core/jni/com_android_server_VibratorService.cpp
+++ b/services/core/jni/com_android_server_VibratorService.cpp
@@ -49,6 +49,12 @@
 
 static jmethodID sMethodIdOnComplete;
 
+static struct {
+    jfieldID id;
+    jfieldID scale;
+    jfieldID delay;
+} gPrimitiveClassInfo;
+
 static_assert(static_cast<uint8_t>(V1_0::EffectStrength::LIGHT) ==
                 static_cast<uint8_t>(aidl::EffectStrength::LIGHT));
 static_assert(static_cast<uint8_t>(V1_0::EffectStrength::MEDIUM) ==
@@ -333,6 +339,21 @@
     }
 }
 
+static jintArray vibratorGetSupportedEffects(JNIEnv *env, jclass) {
+    if (auto hal = getHal<aidl::IVibrator>()) {
+        std::vector<aidl::Effect> supportedEffects;
+        if (!hal->call(&aidl::IVibrator::getSupportedEffects, &supportedEffects).isOk()) {
+            return nullptr;
+        }
+        jintArray arr = env->NewIntArray(supportedEffects.size());
+        env->SetIntArrayRegion(arr, 0, supportedEffects.size(),
+                reinterpret_cast<jint*>(supportedEffects.data()));
+        return arr;
+    } else {
+        return nullptr;
+    }
+}
+
 static jlong vibratorPerformEffect(JNIEnv* env, jclass, jlong effect, jlong strength,
                                    jobject vibration) {
     if (auto hal = getHal<aidl::IVibrator>()) {
@@ -398,6 +419,37 @@
     return -1;
 }
 
+static aidl::CompositeEffect effectFromJavaPrimitive(JNIEnv* env, jobject primitive) {
+    aidl::CompositeEffect effect;
+    effect.primitive = static_cast<aidl::CompositePrimitive>(
+            env->GetIntField(primitive, gPrimitiveClassInfo.id));
+    effect.scale = static_cast<float>(env->GetFloatField(primitive, gPrimitiveClassInfo.scale));
+    effect.delayMs = static_cast<int>(env->GetIntField(primitive, gPrimitiveClassInfo.delay));
+    return effect;
+}
+
+static void vibratorPerformComposedEffect(JNIEnv* env, jclass, jobjectArray composition,
+                                   jobject vibration) {
+    auto hal = getHal<aidl::IVibrator>();
+    if (!hal) {
+        return;
+    }
+    size_t size = env->GetArrayLength(composition);
+    std::vector<aidl::CompositeEffect> effects;
+    for (size_t i = 0; i < size; i++) {
+        jobject element = env->GetObjectArrayElement(composition, i);
+        effects.push_back(effectFromJavaPrimitive(env, element));
+    }
+    sp<AidlVibratorCallback> effectCallback = new AidlVibratorCallback(env, vibration);
+
+    auto status = hal->call(&aidl::IVibrator::compose, effects, effectCallback);
+    if (!status.isOk()) {
+        if (status.exceptionCode() != binder::Status::EX_UNSUPPORTED_OPERATION) {
+            ALOGE("Failed to play haptic effect composition");
+        }
+    }
+}
+
 static jlong vibratorGetCapabilities(JNIEnv*, jclass) {
     if (auto hal = getHal<aidl::IVibrator>()) {
         int32_t cap = 0;
@@ -433,7 +485,12 @@
     { "vibratorSupportsAmplitudeControl", "()Z", (void*)vibratorSupportsAmplitudeControl},
     { "vibratorSetAmplitude", "(I)V", (void*)vibratorSetAmplitude},
     { "vibratorPerformEffect", "(JJLcom/android/server/VibratorService$Vibration;)J",
-        (void*)vibratorPerformEffect},
+            (void*)vibratorPerformEffect},
+    { "vibratorPerformComposedEffect",
+            "([Landroid/os/VibrationEffect$Composition$PrimitiveEffect;Lcom/android/server/VibratorService$Vibration;)V",
+            (void*)vibratorPerformComposedEffect},
+    { "vibratorGetSupportedEffects", "()[I",
+            (void*)vibratorGetSupportedEffects},
     { "vibratorSupportsExternalControl", "()Z", (void*)vibratorSupportsExternalControl},
     { "vibratorSetExternalControl", "(Z)V", (void*)vibratorSetExternalControl},
     { "vibratorGetCapabilities", "()J", (void*)vibratorGetCapabilities},
@@ -441,11 +498,15 @@
     { "vibratorAlwaysOnDisable", "(J)V", (void*)vibratorAlwaysOnDisable},
 };
 
-int register_android_server_VibratorService(JNIEnv *env)
-{
+int register_android_server_VibratorService(JNIEnv *env) {
     sMethodIdOnComplete = GetMethodIDOrDie(env,
             FindClassOrDie(env, "com/android/server/VibratorService$Vibration"),
             "onComplete", "()V");
+    jclass primitiveClass = FindClassOrDie(env,
+            "android/os/VibrationEffect$Composition$PrimitiveEffect");
+    gPrimitiveClassInfo.id = GetFieldIDOrDie(env, primitiveClass, "id", "I");
+    gPrimitiveClassInfo.scale = GetFieldIDOrDie(env, primitiveClass, "scale", "F");
+    gPrimitiveClassInfo.delay = GetFieldIDOrDie(env, primitiveClass, "delay", "I");
     return jniRegisterNativeMethods(env, "com/android/server/VibratorService",
             method_table, NELEM(method_table));
 }
diff --git a/services/incremental/Android.bp b/services/incremental/Android.bp
index ddf4dd5..323e7f1 100644
--- a/services/incremental/Android.bp
+++ b/services/incremental/Android.bp
@@ -47,6 +47,8 @@
     shared_libs: [
         "libandroidfw",
         "libbinder",
+        "libcrypto",
+        "libcutils",
         "libincfs",
         "liblog",
         "libz",
diff --git a/services/incremental/BinderIncrementalService.cpp b/services/incremental/BinderIncrementalService.cpp
index bb26c1f..f1b637f 100644
--- a/services/incremental/BinderIncrementalService.cpp
+++ b/services/incremental/BinderIncrementalService.cpp
@@ -46,10 +46,10 @@
     return incfs::enabled();
 }
 
-static bool incFsVersionValid(const sp<IVold>& vold) {
-    int version = -1;
-    auto status = vold->incFsVersion(&version);
-    if (!status.isOk() || version <= 0) {
+static bool incFsValid(const sp<IVold>& vold) {
+    bool enabled = false;
+    auto status = vold->incFsEnabled(&enabled);
+    if (!status.isOk() || !enabled) {
         return false;
     }
     return true;
@@ -74,7 +74,7 @@
         return nullptr;
     }
     sp<IVold> vold = interface_cast<IVold>(voldBinder);
-    if (!incFsVersionValid(vold)) {
+    if (!incFsValid(vold)) {
         return nullptr;
     }
 
@@ -86,6 +86,7 @@
     sp<ProcessState> ps(ProcessState::self());
     ps->startThreadPool();
     ps->giveThreadPoolName();
+    // sm->addService increments the reference count, and now we're OK with returning the pointer.
     return self.get();
 }
 
@@ -107,9 +108,9 @@
     return ok();
 }
 
-binder::Status BinderIncrementalService::createStorage(
-        const std::string& path, const DataLoaderParamsParcel& params,
-        int32_t createMode, int32_t* _aidl_return) {
+binder::Status BinderIncrementalService::createStorage(const std::string& path,
+                                                       const DataLoaderParamsParcel& params,
+                                                       int32_t createMode, int32_t* _aidl_return) {
     *_aidl_return =
             mImpl.createStorage(path, const_cast<DataLoaderParamsParcel&&>(params),
                                 android::incremental::IncrementalService::CreateOptions(
@@ -129,10 +130,10 @@
 }
 
 binder::Status BinderIncrementalService::makeBindMount(int32_t storageId,
-                                                       const std::string& pathUnderStorage,
+                                                       const std::string& sourcePath,
                                                        const std::string& targetFullPath,
                                                        int32_t bindType, int32_t* _aidl_return) {
-    *_aidl_return = mImpl.bind(storageId, pathUnderStorage, targetFullPath,
+    *_aidl_return = mImpl.bind(storageId, sourcePath, targetFullPath,
                                android::incremental::IncrementalService::BindKind(bindType));
     return ok();
 }
@@ -149,75 +150,127 @@
     return ok();
 }
 
-binder::Status BinderIncrementalService::makeDirectory(int32_t storageId,
-                                                       const std::string& pathUnderStorage,
+binder::Status BinderIncrementalService::makeDirectory(int32_t storageId, const std::string& path,
                                                        int32_t* _aidl_return) {
-    auto inode = mImpl.makeDir(storageId, pathUnderStorage);
-    *_aidl_return = inode < 0 ? inode : 0;
+    *_aidl_return = mImpl.makeDir(storageId, path);
     return ok();
 }
 
-binder::Status BinderIncrementalService::makeDirectories(int32_t storageId,
-                                                         const std::string& pathUnderStorage,
-                                                         int32_t* _aidl_return) {
-    auto inode = mImpl.makeDirs(storageId, pathUnderStorage);
-    *_aidl_return = inode < 0 ? inode : 0;
-    return ok();
+static std::tuple<int, incfs::FileId, incfs::NewFileParams> toMakeFileParams(
+        const android::os::incremental::IncrementalNewFileParams& params) {
+    incfs::FileId id;
+    if (params.fileId.empty()) {
+        if (params.metadata.empty()) {
+            return {EINVAL, {}, {}};
+        }
+        id = IncrementalService::idFromMetadata(params.metadata);
+    } else if (params.fileId.size() != sizeof(id)) {
+        return {EINVAL, {}, {}};
+    } else {
+        memcpy(&id, params.fileId.data(), sizeof(id));
+    }
+    incfs::NewFileParams nfp;
+    nfp.size = params.size;
+    nfp.metadata = {(const char*)params.metadata.data(), (IncFsSize)params.metadata.size()};
+    if (!params.signature) {
+        nfp.verification = {};
+    } else {
+        nfp.verification.hashAlgorithm = IncFsHashAlgortithm(params.signature->hashAlgorithm);
+        nfp.verification.rootHash = {(const char*)params.signature->rootHash.data(),
+                                     (IncFsSize)params.signature->rootHash.size()};
+        nfp.verification.additionalData = {(const char*)params.signature->additionalData.data(),
+                                           (IncFsSize)params.signature->additionalData.size()};
+        nfp.verification.signature = {(const char*)params.signature->signature.data(),
+                                      (IncFsSize)params.signature->signature.size()};
+    }
+    return {0, id, nfp};
 }
 
-binder::Status BinderIncrementalService::makeFile(int32_t storageId,
-                                                  const std::string& pathUnderStorage, int64_t size,
-                                                  const std::vector<uint8_t>& metadata,
-                                                  int32_t* _aidl_return) {
-    auto inode = mImpl.makeFile(storageId, pathUnderStorage, size,
-                                {(const char*)metadata.data(), metadata.size()}, {});
-    *_aidl_return = inode < 0 ? inode : 0;
+binder::Status BinderIncrementalService::makeFile(
+        int32_t storageId, const std::string& path,
+        const ::android::os::incremental::IncrementalNewFileParams& params, int32_t* _aidl_return) {
+    auto [err, fileId, nfp] = toMakeFileParams(params);
+    if (err) {
+        *_aidl_return = err;
+        return ok();
+    }
+
+    *_aidl_return = mImpl.makeFile(storageId, path, 0555, fileId, nfp);
     return ok();
 }
-binder::Status BinderIncrementalService::makeFileFromRange(
-        int32_t storageId, const std::string& pathUnderStorage,
-        const std::string& sourcePathUnderStorage, int64_t start, int64_t end,
-        int32_t* _aidl_return) {
-    // TODO(b/136132412): implement this
-    *_aidl_return = -1;
-    return ok();
-}
-binder::Status BinderIncrementalService::makeLink(int32_t sourceStorageId,
-                                                  const std::string& relativeSourcePath,
-                                                  int32_t destStorageId,
-                                                  const std::string& relativeDestPath,
-                                                  int32_t* _aidl_return) {
-    auto sourceInode = mImpl.nodeFor(sourceStorageId, relativeSourcePath);
-    auto [targetParentInode, name] = mImpl.parentAndNameFor(destStorageId, relativeDestPath);
-    *_aidl_return = mImpl.link(sourceStorageId, sourceInode, targetParentInode, name);
-    return ok();
-}
-binder::Status BinderIncrementalService::unlink(int32_t storageId,
-                                                const std::string& pathUnderStorage,
-                                                int32_t* _aidl_return) {
-    auto [parentNode, name] = mImpl.parentAndNameFor(storageId, pathUnderStorage);
-    *_aidl_return = mImpl.unlink(storageId, parentNode, name);
-    return ok();
-}
-binder::Status BinderIncrementalService::isFileRangeLoaded(int32_t storageId,
-                                                           const std::string& relativePath,
+binder::Status BinderIncrementalService::makeFileFromRange(int32_t storageId,
+                                                           const std::string& targetPath,
+                                                           const std::string& sourcePath,
                                                            int64_t start, int64_t end,
-                                                           bool* _aidl_return) {
+                                                           int32_t* _aidl_return) {
+    // TODO(b/136132412): implement this
+    *_aidl_return = ENOSYS; // not implemented
+    return ok();
+}
+
+binder::Status BinderIncrementalService::makeLink(int32_t sourceStorageId,
+                                                  const std::string& sourcePath,
+                                                  int32_t destStorageId,
+                                                  const std::string& destPath,
+                                                  int32_t* _aidl_return) {
+    *_aidl_return = mImpl.link(sourceStorageId, sourcePath, destStorageId, destPath);
+    return ok();
+}
+
+binder::Status BinderIncrementalService::unlink(int32_t storageId, const std::string& path,
+                                                int32_t* _aidl_return) {
+    *_aidl_return = mImpl.unlink(storageId, path);
+    return ok();
+}
+
+binder::Status BinderIncrementalService::isFileRangeLoaded(int32_t storageId,
+                                                           const std::string& path, int64_t start,
+                                                           int64_t end, bool* _aidl_return) {
+    // TODO: implement
     *_aidl_return = false;
     return ok();
 }
-binder::Status BinderIncrementalService::getFileMetadata(int32_t storageId,
-                                                         const std::string& relativePath,
+
+binder::Status BinderIncrementalService::getMetadataByPath(int32_t storageId,
+                                                           const std::string& path,
+                                                           std::vector<uint8_t>* _aidl_return) {
+    auto fid = mImpl.nodeFor(storageId, path);
+    if (fid != kIncFsInvalidFileId) {
+        auto metadata = mImpl.getMetadata(storageId, fid);
+        _aidl_return->assign(metadata.begin(), metadata.end());
+    }
+    return ok();
+}
+
+static FileId toFileId(const std::vector<uint8_t>& id) {
+    FileId fid;
+    memcpy(&fid, id.data(), id.size());
+    return fid;
+}
+
+binder::Status BinderIncrementalService::getMetadataById(int32_t storageId,
+                                                         const std::vector<uint8_t>& id,
                                                          std::vector<uint8_t>* _aidl_return) {
-    auto inode = mImpl.nodeFor(storageId, relativePath);
-    auto metadata = mImpl.getMetadata(storageId, inode);
+    if (id.size() != sizeof(incfs::FileId)) {
+        return ok();
+    }
+    auto fid = toFileId(id);
+    auto metadata = mImpl.getMetadata(storageId, fid);
     _aidl_return->assign(metadata.begin(), metadata.end());
     return ok();
 }
+
+binder::Status BinderIncrementalService::makeDirectories(int32_t storageId, const std::string& path,
+                                                         int32_t* _aidl_return) {
+    *_aidl_return = mImpl.makeDirs(storageId, path);
+    return ok();
+}
+
 binder::Status BinderIncrementalService::startLoading(int32_t storageId, bool* _aidl_return) {
     *_aidl_return = mImpl.startLoading(storageId);
     return ok();
 }
+
 } // namespace android::os::incremental
 
 jlong Incremental_IncrementalService_Start() {
diff --git a/services/incremental/BinderIncrementalService.h b/services/incremental/BinderIncrementalService.h
index 37c9661d..a94a75a 100644
--- a/services/incremental/BinderIncrementalService.h
+++ b/services/incremental/BinderIncrementalService.h
@@ -37,38 +37,39 @@
     void onSystemReady();
     void onInvalidStorage(int mountId);
 
-    binder::Status openStorage(const std::string &path, int32_t *_aidl_return) final;
-    binder::Status createStorage(
-            const std::string &path,
-            const ::android::content::pm::DataLoaderParamsParcel &params,
-            int32_t createMode, int32_t *_aidl_return) final;
-    binder::Status createLinkedStorage(const std::string &path, int32_t otherStorageId,
-                                       int32_t createMode, int32_t *_aidl_return) final;
-    binder::Status makeBindMount(int32_t storageId, const std::string &pathUnderStorage,
-                                 const std::string &targetFullPath, int32_t bindType,
-                                 int32_t *_aidl_return) final;
-    binder::Status deleteBindMount(int32_t storageId, const std::string &targetFullPath,
-                                   int32_t *_aidl_return) final;
+    binder::Status openStorage(const std::string& path, int32_t* _aidl_return) final;
+    binder::Status createStorage(const std::string& path,
+                                 const ::android::content::pm::DataLoaderParamsParcel& params,
+                                 int32_t createMode, int32_t* _aidl_return) final;
+    binder::Status createLinkedStorage(const std::string& path, int32_t otherStorageId,
+                                       int32_t createMode, int32_t* _aidl_return) final;
+    binder::Status makeBindMount(int32_t storageId, const std::string& sourcePath,
+                                 const std::string& targetFullPath, int32_t bindType,
+                                 int32_t* _aidl_return) final;
+    binder::Status deleteBindMount(int32_t storageId, const std::string& targetFullPath,
+                                   int32_t* _aidl_return) final;
+    binder::Status makeDirectory(int32_t storageId, const std::string& path,
+                                 int32_t* _aidl_return) final;
+    binder::Status makeDirectories(int32_t storageId, const std::string& path,
+                                   int32_t* _aidl_return) final;
+    binder::Status makeFile(int32_t storageId, const std::string& path,
+                            const ::android::os::incremental::IncrementalNewFileParams& params,
+                            int32_t* _aidl_return) final;
+    binder::Status makeFileFromRange(int32_t storageId, const std::string& targetPath,
+                                     const std::string& sourcePath, int64_t start, int64_t end,
+                                     int32_t* _aidl_return) final;
+    binder::Status makeLink(int32_t sourceStorageId, const std::string& sourcePath,
+                            int32_t destStorageId, const std::string& destPath,
+                            int32_t* _aidl_return) final;
+    binder::Status unlink(int32_t storageId, const std::string& path, int32_t* _aidl_return) final;
+    binder::Status isFileRangeLoaded(int32_t storageId, const std::string& path, int64_t start,
+                                     int64_t end, bool* _aidl_return) final;
+    binder::Status getMetadataByPath(int32_t storageId, const std::string& path,
+                                     std::vector<uint8_t>* _aidl_return) final;
+    binder::Status getMetadataById(int32_t storageId, const std::vector<uint8_t>& id,
+                                   std::vector<uint8_t>* _aidl_return) final;
+    binder::Status startLoading(int32_t storageId, bool* _aidl_return) final;
     binder::Status deleteStorage(int32_t storageId) final;
-    binder::Status makeDirectory(int32_t storageId, const std::string &pathUnderStorage,
-                                 int32_t *_aidl_return) final;
-    binder::Status makeDirectories(int32_t storageId, const std::string &pathUnderStorage,
-                                   int32_t *_aidl_return) final;
-    binder::Status makeFile(int32_t storageId, const std::string &pathUnderStorage, int64_t size,
-                            const std::vector<uint8_t> &metadata, int32_t *_aidl_return) final;
-    binder::Status makeFileFromRange(int32_t storageId, const std::string &pathUnderStorage,
-                                     const std::string &sourcePathUnderStorage, int64_t start,
-                                     int64_t end, int32_t *_aidl_return);
-    binder::Status makeLink(int32_t sourceStorageId, const std::string &relativeSourcePath,
-                            int32_t destStorageId, const std::string &relativeDestPath,
-                            int32_t *_aidl_return) final;
-    binder::Status unlink(int32_t storageId, const std::string &pathUnderStorage,
-                          int32_t *_aidl_return) final;
-    binder::Status isFileRangeLoaded(int32_t storageId, const std::string &relativePath,
-                                     int64_t start, int64_t end, bool *_aidl_return) final;
-    binder::Status getFileMetadata(int32_t storageId, const std::string &relativePath,
-                                   std::vector<uint8_t> *_aidl_return) final;
-    binder::Status startLoading(int32_t storageId, bool *_aidl_return) final;
 
 private:
     android::incremental::IncrementalService mImpl;
diff --git a/services/incremental/IncrementalService.cpp b/services/incremental/IncrementalService.cpp
index afce260..414c66c 100644
--- a/services/incremental/IncrementalService.cpp
+++ b/services/incremental/IncrementalService.cpp
@@ -30,6 +30,8 @@
 #include <binder/BinderService.h>
 #include <binder/ParcelFileDescriptor.h>
 #include <binder/Status.h>
+
+#include <openssl/sha.h>
 #include <sys/stat.h>
 #include <uuid/uuid.h>
 #include <zlib.h>
@@ -55,7 +57,6 @@
 struct Constants {
     static constexpr auto backing = "backing_store"sv;
     static constexpr auto mount = "mount"sv;
-    static constexpr auto image = "incfs.img"sv;
     static constexpr auto storagePrefix = "st"sv;
     static constexpr auto mountpointMdPrefix = ".mountpoint."sv;
     static constexpr auto infoMdName = ".info"sv;
@@ -70,7 +71,7 @@
 bool mkdirOrLog(std::string_view name, int mode = 0770, bool allowExisting = true) {
     auto cstr = path::c_str(name);
     if (::mkdir(cstr, mode)) {
-        if (errno != EEXIST) {
+        if (!allowExisting || errno != EEXIST) {
             PLOG(level) << "Can't create directory '" << name << '\'';
             return false;
         }
@@ -80,6 +81,11 @@
             return false;
         }
     }
+    if (::chmod(cstr, mode)) {
+        PLOG(level) << "Changing permission failed for '" << name << '\'';
+        return false;
+    }
+
     return true;
 }
 
@@ -106,7 +112,7 @@
     for (int counter = 0; counter < 1000;
          mountKey.resize(prefixSize), base::StringAppendF(&mountKey, "%d", counter++)) {
         auto mountRoot = path::join(incrementalDir, mountKey);
-        if (mkdirOrLog(mountRoot, 0770, false)) {
+        if (mkdirOrLog(mountRoot, 0777, false)) {
             return {mountKey, mountRoot};
         }
     }
@@ -116,11 +122,7 @@
 template <class ProtoMessage, class Control>
 static ProtoMessage parseFromIncfs(const IncFsWrapper* incfs, Control&& control,
                                    std::string_view path) {
-    struct stat st;
-    if (::stat(path::c_str(path), &st)) {
-        return {};
-    }
-    auto md = incfs->getMetadata(control, st.st_ino);
+    auto md = incfs->getMetadata(control, path);
     ProtoMessage message;
     return message.ParseFromArray(md.data(), md.size()) ? message : ProtoMessage{};
 }
@@ -161,35 +163,66 @@
 }
 
 auto IncrementalService::IncFsMount::makeStorage(StorageId id) -> StorageMap::iterator {
-    metadata::Storage st;
-    st.set_id(id);
-    auto metadata = st.SerializeAsString();
-
     std::string name;
     for (int no = nextStorageDirNo.fetch_add(1, std::memory_order_relaxed), i = 0;
          i < 1024 && no >= 0; no = nextStorageDirNo.fetch_add(1, std::memory_order_relaxed), ++i) {
         name.clear();
-        base::StringAppendF(&name, "%.*s%d", int(constants().storagePrefix.size()),
-                            constants().storagePrefix.data(), no);
-        if (auto node =
-                    incrementalService.mIncFs->makeDir(control, name, INCFS_ROOT_INODE, metadata);
-            node >= 0) {
+        base::StringAppendF(&name, "%.*s_%d_%d", int(constants().storagePrefix.size()),
+                            constants().storagePrefix.data(), id, no);
+        auto fullName = path::join(root, constants().mount, name);
+        if (auto err = incrementalService.mIncFs->makeDir(control, fullName); !err) {
             std::lock_guard l(lock);
-            return storages.insert_or_assign(id, Storage{std::move(name), node}).first;
+            return storages.insert_or_assign(id, Storage{std::move(fullName)}).first;
+        } else if (err != EEXIST) {
+            LOG(ERROR) << __func__ << "(): failed to create dir |" << fullName << "| " << err;
+            break;
         }
     }
     nextStorageDirNo = 0;
     return storages.end();
 }
 
+static std::unique_ptr<DIR, decltype(&::closedir)> openDir(const char* path) {
+    return {::opendir(path), ::closedir};
+}
+
+static int rmDirContent(const char* path) {
+    auto dir = openDir(path);
+    if (!dir) {
+        return -EINVAL;
+    }
+    while (auto entry = ::readdir(dir.get())) {
+        if (entry->d_name == "."sv || entry->d_name == ".."sv) {
+            continue;
+        }
+        auto fullPath = android::base::StringPrintf("%s/%s", path, entry->d_name);
+        if (entry->d_type == DT_DIR) {
+            if (const auto err = rmDirContent(fullPath.c_str()); err != 0) {
+                PLOG(WARNING) << "Failed to delete " << fullPath << " content";
+                return err;
+            }
+            if (const auto err = ::rmdir(fullPath.c_str()); err != 0) {
+                PLOG(WARNING) << "Failed to rmdir " << fullPath;
+                return err;
+            }
+        } else {
+            if (const auto err = ::unlink(fullPath.c_str()); err != 0) {
+                PLOG(WARNING) << "Failed to delete " << fullPath;
+                return err;
+            }
+        }
+    }
+    return 0;
+}
+
 void IncrementalService::IncFsMount::cleanupFilesystem(std::string_view root) {
-    ::unlink(path::join(root, constants().backing, constants().image).c_str());
+    rmDirContent(path::join(root, constants().backing).c_str());
     ::rmdir(path::join(root, constants().backing).c_str());
     ::rmdir(path::join(root, constants().mount).c_str());
     ::rmdir(path::c_str(root));
 }
 
-IncrementalService::IncrementalService(const ServiceManagerWrapper& sm, std::string_view rootDir)
+IncrementalService::IncrementalService(ServiceManagerWrapper&& sm, std::string_view rootDir)
       : mVold(sm.getVoldService()),
         mIncrementalManager(sm.getIncrementalManager()),
         mIncFs(sm.getIncFs()),
@@ -205,6 +238,23 @@
     // mountExistingImages();
 }
 
+FileId IncrementalService::idFromMetadata(std::span<const uint8_t> metadata) {
+    incfs::FileId id = {};
+    if (size_t(metadata.size()) <= sizeof(id)) {
+        memcpy(&id, metadata.data(), metadata.size());
+    } else {
+        uint8_t buffer[SHA_DIGEST_LENGTH];
+        static_assert(sizeof(buffer) >= sizeof(id));
+
+        SHA_CTX ctx;
+        SHA1_Init(&ctx);
+        SHA1_Update(&ctx, metadata.data(), metadata.size());
+        SHA1_Final(buffer, &ctx);
+        memcpy(&id, buffer, sizeof(id));
+    }
+    return id;
+}
+
 IncrementalService::~IncrementalService() = default;
 
 std::optional<std::future<void>> IncrementalService::onSystemReady() {
@@ -300,26 +350,36 @@
             std::unique_ptr<std::string, decltype(firstCleanup)>(&mountRoot, firstCleanup);
 
     auto mountTarget = path::join(mountRoot, constants().mount);
-    if (!mkdirOrLog(path::join(mountRoot, constants().backing)) || !mkdirOrLog(mountTarget)) {
+    const auto backing = path::join(mountRoot, constants().backing);
+    if (!mkdirOrLog(backing, 0777) || !mkdirOrLog(mountTarget)) {
         return kInvalidStorageId;
     }
 
-    const auto image = path::join(mountRoot, constants().backing, constants().image);
     IncFsMount::Control control;
     {
         std::lock_guard l(mMountOperationLock);
         IncrementalFileSystemControlParcel controlParcel;
-        auto status = mVold->mountIncFs(image, mountTarget, incfs::truncate, &controlParcel);
+
+        if (auto err = rmDirContent(backing.c_str())) {
+            LOG(ERROR) << "Coudn't clean the backing directory " << backing << ": " << err;
+            return kInvalidStorageId;
+        }
+        if (!mkdirOrLog(path::join(backing, ".index"), 0777)) {
+            return kInvalidStorageId;
+        }
+        auto status = mVold->mountIncFs(backing, mountTarget, 0, &controlParcel);
         if (!status.isOk()) {
             LOG(ERROR) << "Vold::mountIncFs() failed: " << status.toString8();
             return kInvalidStorageId;
         }
-        if (!controlParcel.cmd || !controlParcel.log) {
+        if (controlParcel.cmd.get() < 0 || controlParcel.pendingReads.get() < 0 ||
+            controlParcel.log.get() < 0) {
             LOG(ERROR) << "Vold::mountIncFs() returned invalid control parcel.";
             return kInvalidStorageId;
         }
-        control.cmdFd = controlParcel.cmd->release();
-        control.logFd = controlParcel.log->release();
+        control.cmd = controlParcel.cmd.release().release();
+        control.pendingReads = controlParcel.pendingReads.release().release();
+        control.logs = controlParcel.log.release().release();
     }
 
     std::unique_lock l(mLock);
@@ -344,7 +404,7 @@
 
     const auto storageIt = ifs->makeStorage(ifs->mountId);
     if (storageIt == ifs->storages.end()) {
-        LOG(ERROR) << "Can't create default storage directory";
+        LOG(ERROR) << "Can't create a default storage directory";
         return kInvalidStorageId;
     }
 
@@ -359,9 +419,12 @@
         m.mutable_loader()->release_arguments();
         m.mutable_loader()->release_class_name();
         m.mutable_loader()->release_package_name();
-        if (auto err = mIncFs->makeFile(ifs->control, constants().infoMdName, INCFS_ROOT_INODE, 0,
-                                        metadata);
-            err < 0) {
+        if (auto err =
+                    mIncFs->makeFile(ifs->control,
+                                     path::join(ifs->root, constants().mount,
+                                                constants().infoMdName),
+                                     0777, idFromMetadata(metadata),
+                                     {.metadata = {metadata.data(), (IncFsSize)metadata.size()}})) {
             LOG(ERROR) << "Saving mount metadata failed: " << -err;
             return kInvalidStorageId;
         }
@@ -369,8 +432,8 @@
 
     const auto bk =
             (options & CreateOptions::PermanentBind) ? BindKind::Permanent : BindKind::Temporary;
-    if (auto err = addBindMount(*ifs, storageIt->first, std::string(storageIt->second.name),
-                                std::move(mountNorm), bk, l);
+    if (auto err = addBindMount(*ifs, storageIt->first, storageIt->second.name,
+                                std::string(storageIt->second.name), std::move(mountNorm), bk, l);
         err < 0) {
         LOG(ERROR) << "adding bind mount failed: " << -err;
         return kInvalidStorageId;
@@ -419,8 +482,9 @@
 
     const auto bk =
             (options & CreateOptions::PermanentBind) ? BindKind::Permanent : BindKind::Temporary;
-    if (auto err = addBindMount(*ifs, storageIt->first, std::string(storageIt->second.name),
-                                path::normalize(mountPoint), bk, l);
+    if (auto err = addBindMount(*ifs, storageIt->first, storageIt->second.name,
+                                std::string(storageIt->second.name), path::normalize(mountPoint),
+                                bk, l);
         err < 0) {
         LOG(ERROR) << "bindMount failed with error: " << err;
         return kInvalidStorageId;
@@ -492,40 +556,36 @@
     return findStorageId(path::normalize(pathInMount));
 }
 
-Inode IncrementalService::nodeFor(StorageId storage, std::string_view subpath) const {
+FileId IncrementalService::nodeFor(StorageId storage, std::string_view subpath) const {
     const auto ifs = getIfs(storage);
     if (!ifs) {
-        return -1;
+        return kIncFsInvalidFileId;
     }
     std::unique_lock l(ifs->lock);
     auto storageIt = ifs->storages.find(storage);
     if (storageIt == ifs->storages.end()) {
-        return -1;
+        return kIncFsInvalidFileId;
     }
     if (subpath.empty() || subpath == "."sv) {
-        return storageIt->second.node;
+        return kIncFsInvalidFileId;
     }
     auto path = path::join(ifs->root, constants().mount, storageIt->second.name, subpath);
     l.unlock();
-    struct stat st;
-    if (::stat(path.c_str(), &st)) {
-        return -1;
-    }
-    return st.st_ino;
+    return mIncFs->getFileId(ifs->control, path);
 }
 
-std::pair<Inode, std::string_view> IncrementalService::parentAndNameFor(
+std::pair<FileId, std::string_view> IncrementalService::parentAndNameFor(
         StorageId storage, std::string_view subpath) const {
     auto name = path::basename(subpath);
     if (name.empty()) {
-        return {-1, {}};
+        return {kIncFsInvalidFileId, {}};
     }
     auto dir = path::dirname(subpath);
     if (dir.empty() || dir == "/"sv) {
-        return {-1, {}};
+        return {kIncFsInvalidFileId, {}};
     }
-    auto inode = nodeFor(storage, dir);
-    return {inode, name};
+    auto id = nodeFor(storage, dir);
+    return {id, name};
 }
 
 IncrementalService::IfsMountPtr IncrementalService::getIfs(StorageId storage) const {
@@ -542,8 +602,8 @@
     return it->second;
 }
 
-int IncrementalService::bind(StorageId storage, std::string_view sourceSubdir,
-                             std::string_view target, BindKind kind) {
+int IncrementalService::bind(StorageId storage, std::string_view source, std::string_view target,
+                             BindKind kind) {
     if (!isValidMountTarget(target)) {
         return -EINVAL;
     }
@@ -552,15 +612,20 @@
     if (!ifs) {
         return -EINVAL;
     }
+    auto normSource = path::normalize(source);
+
     std::unique_lock l(ifs->lock);
     const auto storageInfo = ifs->storages.find(storage);
     if (storageInfo == ifs->storages.end()) {
         return -EINVAL;
     }
-    auto source = path::join(storageInfo->second.name, sourceSubdir);
+    if (!path::startsWith(normSource, storageInfo->second.name)) {
+        return -EINVAL;
+    }
     l.unlock();
     std::unique_lock l2(mLock, std::defer_lock);
-    return addBindMount(*ifs, storage, std::move(source), path::normalize(target), kind, l2);
+    return addBindMount(*ifs, storage, storageInfo->second.name, std::move(normSource),
+                        path::normalize(target), kind, l2);
 }
 
 int IncrementalService::unbind(StorageId storage, std::string_view target) {
@@ -599,90 +664,72 @@
         ifs->bindPoints.erase(bindIt);
         l2.unlock();
         if (!savedFile.empty()) {
-            mIncFs->unlink(ifs->control, INCFS_ROOT_INODE, savedFile);
+            mIncFs->unlink(ifs->control, path::join(ifs->root, constants().mount, savedFile));
         }
     }
     return 0;
 }
 
-Inode IncrementalService::makeFile(StorageId storageId, std::string_view pathUnderStorage,
-                                   long size, std::string_view metadata,
-                                   std::string_view signature) {
-    (void)signature;
-    auto [parentInode, name] = parentAndNameFor(storageId, pathUnderStorage);
-    if (parentInode < 0) {
-        return -EINVAL;
-    }
-    if (auto ifs = getIfs(storageId)) {
-        auto inode = mIncFs->makeFile(ifs->control, name, parentInode, size, metadata);
-        if (inode < 0) {
-            return inode;
+int IncrementalService::makeFile(StorageId storage, std::string_view path, int mode, FileId id,
+                                 incfs::NewFileParams params) {
+    if (auto ifs = getIfs(storage)) {
+        auto err = mIncFs->makeFile(ifs->control, path, mode, id, params);
+        if (err) {
+            return err;
         }
-        auto metadataBytes = std::vector<uint8_t>();
-        if (metadata.data() != nullptr && metadata.size() > 0) {
-            metadataBytes.insert(metadataBytes.end(), &metadata.data()[0],
-                                 &metadata.data()[metadata.size()]);
+        std::vector<uint8_t> metadataBytes;
+        if (params.metadata.data && params.metadata.size > 0) {
+            metadataBytes.assign(params.metadata.data, params.metadata.data + params.metadata.size);
         }
-        mIncrementalManager->newFileForDataLoader(ifs->mountId, inode, metadataBytes);
-        return inode;
+        mIncrementalManager->newFileForDataLoader(ifs->mountId, id, metadataBytes);
+        return 0;
     }
     return -EINVAL;
 }
 
-Inode IncrementalService::makeDir(StorageId storageId, std::string_view pathUnderStorage,
-                                  std::string_view metadata) {
-    auto [parentInode, name] = parentAndNameFor(storageId, pathUnderStorage);
-    if (parentInode < 0) {
-        return -EINVAL;
-    }
+int IncrementalService::makeDir(StorageId storageId, std::string_view path, int mode) {
     if (auto ifs = getIfs(storageId)) {
-        return mIncFs->makeDir(ifs->control, name, parentInode, metadata);
+        return mIncFs->makeDir(ifs->control, path, mode);
     }
     return -EINVAL;
 }
 
-Inode IncrementalService::makeDirs(StorageId storageId, std::string_view pathUnderStorage,
-                                   std::string_view metadata) {
+int IncrementalService::makeDirs(StorageId storageId, std::string_view path, int mode) {
     const auto ifs = getIfs(storageId);
     if (!ifs) {
         return -EINVAL;
     }
-    std::string_view parentDir(pathUnderStorage);
-    auto p = parentAndNameFor(storageId, pathUnderStorage);
-    std::stack<std::string> pathsToCreate;
-    while (p.first < 0) {
-        parentDir = path::dirname(parentDir);
-        pathsToCreate.emplace(parentDir);
-        p = parentAndNameFor(storageId, parentDir);
+
+    auto err = mIncFs->makeDir(ifs->control, path, mode);
+    if (err == -EEXIST) {
+        return 0;
+    } else if (err != -ENOENT) {
+        return err;
     }
-    Inode inode;
-    while (!pathsToCreate.empty()) {
-        p = parentAndNameFor(storageId, pathsToCreate.top());
-        pathsToCreate.pop();
-        inode = mIncFs->makeDir(ifs->control, p.second, p.first, metadata);
-        if (inode < 0) {
-            return inode;
-        }
+    if (auto err = makeDirs(storageId, path::dirname(path), mode)) {
+        return err;
     }
-    return mIncFs->makeDir(ifs->control, path::basename(pathUnderStorage), inode, metadata);
+    return mIncFs->makeDir(ifs->control, path, mode);
 }
 
-int IncrementalService::link(StorageId storage, Inode item, Inode newParent,
-                             std::string_view newName) {
-    if (auto ifs = getIfs(storage)) {
-        return mIncFs->link(ifs->control, item, newParent, newName);
+int IncrementalService::link(StorageId sourceStorageId, std::string_view oldPath,
+                             StorageId destStorageId, std::string_view newPath) {
+    if (auto ifsSrc = getIfs(sourceStorageId), ifsDest = getIfs(destStorageId);
+        ifsSrc && ifsSrc == ifsDest) {
+        return mIncFs->link(ifsSrc->control, oldPath, newPath);
     }
     return -EINVAL;
 }
 
-int IncrementalService::unlink(StorageId storage, Inode parent, std::string_view name) {
+int IncrementalService::unlink(StorageId storage, std::string_view path) {
     if (auto ifs = getIfs(storage)) {
-        return mIncFs->unlink(ifs->control, parent, name);
+        return mIncFs->unlink(ifs->control, path);
     }
     return -EINVAL;
 }
 
-int IncrementalService::addBindMount(IncFsMount& ifs, StorageId storage, std::string&& sourceSubdir,
+int IncrementalService::addBindMount(IncFsMount& ifs, StorageId storage,
+                                     std::string_view storageRoot, std::string&& source,
                                      std::string&& target, BindKind kind,
                                      std::unique_lock<std::mutex>& mainLock) {
     if (!isValidMountTarget(target)) {
@@ -694,30 +741,30 @@
         metadata::BindPoint bp;
         bp.set_storage_id(storage);
         bp.set_allocated_dest_path(&target);
-        bp.set_allocated_source_subdir(&sourceSubdir);
+        bp.set_source_subdir(std::string(path::relativize(storageRoot, source)));
         const auto metadata = bp.SerializeAsString();
-        bp.release_source_subdir();
         bp.release_dest_path();
         mdFileName = makeBindMdName();
-        auto node = mIncFs->makeFile(ifs.control, mdFileName, INCFS_ROOT_INODE, 0, metadata);
-        if (node < 0) {
+        auto node =
+                mIncFs->makeFile(ifs.control, path::join(ifs.root, constants().mount, mdFileName),
+                                 0444, idFromMetadata(metadata),
+                                 {.metadata = {metadata.data(), (IncFsSize)metadata.size()}});
+        if (node) {
             return int(node);
         }
     }
 
-    return addBindMountWithMd(ifs, storage, std::move(mdFileName), std::move(sourceSubdir),
+    return addBindMountWithMd(ifs, storage, std::move(mdFileName), std::move(source),
                               std::move(target), kind, mainLock);
 }
 
 int IncrementalService::addBindMountWithMd(IncrementalService::IncFsMount& ifs, StorageId storage,
-                                           std::string&& metadataName, std::string&& sourceSubdir,
+                                           std::string&& metadataName, std::string&& source,
                                            std::string&& target, BindKind kind,
                                            std::unique_lock<std::mutex>& mainLock) {
-    LOG(INFO) << "Adding bind mount: " << sourceSubdir << " -> " << target;
     {
-        auto path = path::join(ifs.root, constants().mount, sourceSubdir);
         std::lock_guard l(mMountOperationLock);
-        const auto status = mVold->bindMount(path, target);
+        const auto status = mVold->bindMount(source, target);
         if (!status.isOk()) {
             LOG(ERROR) << "Calling Vold::bindMount() failed: " << status.toString8();
             return status.exceptionCode() == binder::Status::EX_SERVICE_SPECIFIC
@@ -736,12 +783,12 @@
     const auto [it, _] =
             ifs.bindPoints.insert_or_assign(target,
                                             IncFsMount::Bind{storage, std::move(metadataName),
-                                                             std::move(sourceSubdir), kind});
+                                                             std::move(source), kind});
     mBindsByPath[std::move(target)] = it;
     return 0;
 }
 
-RawMetadata IncrementalService::getMetadata(StorageId storage, Inode node) const {
+RawMetadata IncrementalService::getMetadata(StorageId storage, FileId node) const {
     const auto ifs = getIfs(storage);
     if (!ifs) {
         return {};
@@ -831,21 +878,18 @@
     LOG(INFO) << "Trying to mount: " << key;
 
     auto mountTarget = path::join(root, constants().mount);
-    const auto image = path::join(root, constants().backing, constants().image);
+    const auto backing = path::join(root, constants().backing);
 
     IncFsMount::Control control;
     IncrementalFileSystemControlParcel controlParcel;
-    auto status = mVold->mountIncFs(image, mountTarget, 0, &controlParcel);
+    auto status = mVold->mountIncFs(backing, mountTarget, 0, &controlParcel);
     if (!status.isOk()) {
         LOG(ERROR) << "Vold::mountIncFs() failed: " << status.toString8();
         return false;
     }
-    if (controlParcel.cmd) {
-        control.cmdFd = controlParcel.cmd->release();
-    }
-    if (controlParcel.log) {
-        control.logFd = controlParcel.log->release();
-    }
+    control.cmd = controlParcel.cmd.release().release();
+    control.pendingReads = controlParcel.pendingReads.release().release();
+    control.logs = controlParcel.log.release().release();
 
     auto ifs = std::make_shared<IncFsMount>(std::string(root), -1, std::move(control), *this);
 
@@ -860,8 +904,7 @@
     mNextId = std::max(mNextId, ifs->mountId + 1);
 
     std::vector<std::pair<std::string, metadata::BindPoint>> bindPoints;
-    auto d = std::unique_ptr<DIR, decltype(&::closedir)>(::opendir(path::c_str(mountTarget)),
-                                                         ::closedir);
+    auto d = openDir(path::c_str(mountTarget));
     while (auto e = ::readdir(d.get())) {
         if (e->d_type == DT_REG) {
             auto name = std::string_view(e->d_name);
@@ -874,7 +917,7 @@
                 if (bindPoints.back().second.dest_path().empty() ||
                     bindPoints.back().second.source_subdir().empty()) {
                     bindPoints.pop_back();
-                    mIncFs->unlink(ifs->control, INCFS_ROOT_INODE, name);
+                    mIncFs->unlink(ifs->control, path::join(ifs->root, constants().mount, name));
                 }
             }
         } else if (e->d_type == DT_DIR) {
@@ -891,9 +934,7 @@
                                  << " for mount " << root;
                     continue;
                 }
-                ifs->storages.insert_or_assign(md.id(),
-                                               IncFsMount::Storage{std::string(name),
-                                                                   Inode(e->d_ino)});
+                ifs->storages.insert_or_assign(md.id(), IncFsMount::Storage{std::string(name)});
                 mNextId = std::max(mNextId, md.id() + 1);
             }
         }
@@ -973,10 +1014,10 @@
     }
     FileSystemControlParcel fsControlParcel;
     fsControlParcel.incremental = std::make_unique<IncrementalFileSystemControlParcel>();
-    fsControlParcel.incremental->cmd =
-            std::make_unique<os::ParcelFileDescriptor>(base::unique_fd(::dup(ifs.control.cmdFd)));
-    fsControlParcel.incremental->log =
-            std::make_unique<os::ParcelFileDescriptor>(base::unique_fd(::dup(ifs.control.logFd)));
+    fsControlParcel.incremental->cmd.reset(base::unique_fd(::dup(ifs.control.cmd)));
+    fsControlParcel.incremental->pendingReads.reset(
+            base::unique_fd(::dup(ifs.control.pendingReads)));
+    fsControlParcel.incremental->log.reset(base::unique_fd(::dup(ifs.control.logs)));
     sp<IncrementalDataLoaderListener> listener = new IncrementalDataLoaderListener(*this);
     bool created = false;
     auto status = mIncrementalManager->prepareDataLoader(ifs.mountId, fsControlParcel, *dlp,
diff --git a/services/incremental/IncrementalService.h b/services/incremental/IncrementalService.h
index a03ffa0..ca5e4db 100644
--- a/services/incremental/IncrementalService.h
+++ b/services/incremental/IncrementalService.h
@@ -52,16 +52,16 @@
 
 using MountId = int;
 using StorageId = int;
-using Inode = incfs::Inode;
+using FileId = incfs::FileId;
 using BlockIndex = incfs::BlockIndex;
 using RawMetadata = incfs::RawMetadata;
 using Clock = std::chrono::steady_clock;
 using TimePoint = std::chrono::time_point<Clock>;
 using Seconds = std::chrono::seconds;
 
-class IncrementalService {
+class IncrementalService final {
 public:
-    explicit IncrementalService(const ServiceManagerWrapper& sm, std::string_view rootDir);
+    explicit IncrementalService(ServiceManagerWrapper&& sm, std::string_view rootDir);
 
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
@@ -85,6 +85,11 @@
         Permanent = 1,
     };
 
+    static FileId idFromMetadata(std::span<const uint8_t> metadata);
+    static inline FileId idFromMetadata(std::span<const char> metadata) {
+        return idFromMetadata({(const uint8_t*)metadata.data(), metadata.size()});
+    }
+
     std::optional<std::future<void>> onSystemReady();
 
     StorageId createStorage(std::string_view mountPoint,
@@ -92,30 +97,31 @@
                             CreateOptions options = CreateOptions::Default);
     StorageId createLinkedStorage(std::string_view mountPoint, StorageId linkedStorage,
                                   CreateOptions options = CreateOptions::Default);
-    StorageId openStorage(std::string_view pathInMount);
+    StorageId openStorage(std::string_view path);
 
-    Inode nodeFor(StorageId storage, std::string_view subpath) const;
-    std::pair<Inode, std::string_view> parentAndNameFor(StorageId storage,
-                                                        std::string_view subpath) const;
+    FileId nodeFor(StorageId storage, std::string_view path) const;
+    std::pair<FileId, std::string_view> parentAndNameFor(StorageId storage,
+                                                         std::string_view path) const;
 
-    int bind(StorageId storage, std::string_view subdir, std::string_view target, BindKind kind);
+    int bind(StorageId storage, std::string_view source, std::string_view target, BindKind kind);
     int unbind(StorageId storage, std::string_view target);
     void deleteStorage(StorageId storage);
 
-    Inode makeFile(StorageId storage, std::string_view name, long size, std::string_view metadata,
-                   std::string_view signature);
-    Inode makeDir(StorageId storage, std::string_view name, std::string_view metadata = {});
-    Inode makeDirs(StorageId storage, std::string_view name, std::string_view metadata = {});
+    int makeFile(StorageId storage, std::string_view path, int mode, FileId id,
+                 incfs::NewFileParams params);
+    int makeDir(StorageId storage, std::string_view path, int mode = 0555);
+    int makeDirs(StorageId storage, std::string_view path, int mode = 0555);
 
-    int link(StorageId storage, Inode item, Inode newParent, std::string_view newName);
-    int unlink(StorageId storage, Inode parent, std::string_view name);
+    int link(StorageId sourceStorageId, std::string_view oldPath, StorageId destStorageId,
+             std::string_view newPath);
+    int unlink(StorageId storage, std::string_view path);
 
-    bool isRangeLoaded(StorageId storage, Inode file, std::pair<BlockIndex, BlockIndex> range) {
+    bool isRangeLoaded(StorageId storage, FileId file, std::pair<BlockIndex, BlockIndex> range) {
         return false;
     }
 
-    RawMetadata getMetadata(StorageId storage, Inode node) const;
-    std::string getSigngatureData(StorageId storage, Inode node) const { return {}; }
+    RawMetadata getMetadata(StorageId storage, FileId node) const;
+    std::string getSignatureData(StorageId storage, FileId node) const;
 
     std::vector<std::string> listFiles(StorageId storage) const;
     bool startLoading(StorageId storage) const;
@@ -142,19 +148,9 @@
 
         struct Storage {
             std::string name;
-            Inode node;
         };
 
-        struct Control {
-            operator IncFsControl() const { return {cmdFd, logFd}; }
-            void reset() {
-                cmdFd.reset();
-                logFd.reset();
-            }
-
-            base::unique_fd cmdFd;
-            base::unique_fd logFd;
-        };
+        using Control = incfs::UniqueControl;
 
         using BindMap = std::map<std::string, Bind>;
         using StorageMap = std::unordered_map<StorageId, Storage>;
@@ -196,11 +192,12 @@
 
     IfsMountPtr getIfs(StorageId storage) const;
     const IfsMountPtr& getIfsLocked(StorageId storage) const;
-    int addBindMount(IncFsMount& ifs, StorageId storage, std::string&& sourceSubdir,
-                     std::string&& target, BindKind kind, std::unique_lock<std::mutex>& mainLock);
+    int addBindMount(IncFsMount& ifs, StorageId storage, std::string_view storageRoot,
+                     std::string&& source, std::string&& target, BindKind kind,
+                     std::unique_lock<std::mutex>& mainLock);
 
     int addBindMountWithMd(IncFsMount& ifs, StorageId storage, std::string&& metadataName,
-                           std::string&& sourceSubdir, std::string&& target, BindKind kind,
+                           std::string&& source, std::string&& target, BindKind kind,
                            std::unique_lock<std::mutex>& mainLock);
 
     bool prepareDataLoader(IncFsMount& ifs, DataLoaderParamsParcel* params);
@@ -212,10 +209,9 @@
     MountMap::iterator getStorageSlotLocked();
 
     // Member variables
-    // These are shared pointers for the sake of unit testing
-    std::shared_ptr<VoldServiceWrapper> mVold;
-    std::shared_ptr<IncrementalManagerWrapper> mIncrementalManager;
-    std::shared_ptr<IncFsWrapper> mIncFs;
+    std::unique_ptr<VoldServiceWrapper> mVold;
+    std::unique_ptr<IncrementalManagerWrapper> mIncrementalManager;
+    std::unique_ptr<IncFsWrapper> mIncFs;
     const std::string mIncrementalDir;
 
     mutable std::mutex mLock;
diff --git a/services/incremental/ServiceWrappers.cpp b/services/incremental/ServiceWrappers.cpp
index a79b26a..5d978a1c 100644
--- a/services/incremental/ServiceWrappers.cpp
+++ b/services/incremental/ServiceWrappers.cpp
@@ -16,14 +16,8 @@
 
 #include "ServiceWrappers.h"
 
-#include <android-base/strings.h>
-#include <android-base/unique_fd.h>
-#include <binder/IServiceManager.h>
 #include <utils/String16.h>
 
-#include <string>
-#include <string_view>
-
 using namespace std::literals;
 
 namespace android::os::incremental {
@@ -31,37 +25,38 @@
 static constexpr auto kVoldServiceName = "vold"sv;
 static constexpr auto kIncrementalManagerName = "incremental"sv;
 
-RealServiceManager::RealServiceManager(const sp<IServiceManager>& serviceManager)
-      : mServiceManager(serviceManager) {}
+RealServiceManager::RealServiceManager(sp<IServiceManager> serviceManager)
+      : mServiceManager(std::move(serviceManager)) {}
 
 template <class INTERFACE>
 sp<INTERFACE> RealServiceManager::getRealService(std::string_view serviceName) const {
-    sp<IBinder> binder = mServiceManager->getService(String16(serviceName.data()));
-    if (binder == 0) {
-        return 0;
+    sp<IBinder> binder =
+            mServiceManager->getService(String16(serviceName.data(), serviceName.size()));
+    if (!binder) {
+        return nullptr;
     }
     return interface_cast<INTERFACE>(binder);
 }
 
-std::shared_ptr<VoldServiceWrapper> RealServiceManager::getVoldService() const {
+std::unique_ptr<VoldServiceWrapper> RealServiceManager::getVoldService() {
     sp<os::IVold> vold = RealServiceManager::getRealService<os::IVold>(kVoldServiceName);
     if (vold != 0) {
-        return std::make_shared<RealVoldService>(vold);
+        return std::make_unique<RealVoldService>(vold);
     }
     return nullptr;
 }
 
-std::shared_ptr<IncrementalManagerWrapper> RealServiceManager::getIncrementalManager() const {
+std::unique_ptr<IncrementalManagerWrapper> RealServiceManager::getIncrementalManager() {
     sp<IIncrementalManager> manager =
             RealServiceManager::getRealService<IIncrementalManager>(kIncrementalManagerName);
-    if (manager != 0) {
-        return std::make_shared<RealIncrementalManager>(manager);
+    if (manager) {
+        return std::make_unique<RealIncrementalManager>(manager);
     }
     return nullptr;
 }
 
-std::shared_ptr<IncFsWrapper> RealServiceManager::getIncFs() const {
-    return std::make_shared<RealIncFs>();
+std::unique_ptr<IncFsWrapper> RealServiceManager::getIncFs() {
+    return std::make_unique<RealIncFs>();
 }
 
 } // namespace android::os::incremental
diff --git a/services/incremental/ServiceWrappers.h b/services/incremental/ServiceWrappers.h
index 5704582..ae3739d 100644
--- a/services/incremental/ServiceWrappers.h
+++ b/services/incremental/ServiceWrappers.h
@@ -26,6 +26,7 @@
 #include <binder/IServiceManager.h>
 #include <incfs.h>
 
+#include <memory>
 #include <string>
 #include <string_view>
 
@@ -36,10 +37,12 @@
 
 // --- Wrapper interfaces ---
 
+using MountId = int32_t;
+
 class VoldServiceWrapper {
 public:
-    virtual ~VoldServiceWrapper(){};
-    virtual binder::Status mountIncFs(const std::string& imagePath, const std::string& targetDir,
+    virtual ~VoldServiceWrapper() = default;
+    virtual binder::Status mountIncFs(const std::string& backingPath, const std::string& targetDir,
                                       int32_t flags,
                                       IncrementalFileSystemControlParcel* _aidl_return) const = 0;
     virtual binder::Status unmountIncFs(const std::string& dir) const = 0;
@@ -49,52 +52,52 @@
 
 class IncrementalManagerWrapper {
 public:
-    virtual ~IncrementalManagerWrapper() {}
-    virtual binder::Status prepareDataLoader(
-            int32_t mountId, const FileSystemControlParcel& control,
-            const DataLoaderParamsParcel& params,
-            const sp<IDataLoaderStatusListener>& listener,
-            bool* _aidl_return) const = 0;
-    virtual binder::Status startDataLoader(int32_t mountId, bool* _aidl_return) const = 0;
-    virtual binder::Status destroyDataLoader(int32_t mountId) const = 0;
-    virtual binder::Status newFileForDataLoader(int32_t mountId, int64_t inode,
-                                                const ::std::vector<uint8_t>& metadata) const = 0;
-    virtual binder::Status showHealthBlockedUI(int32_t mountId) const = 0;
+    virtual ~IncrementalManagerWrapper() = default;
+    virtual binder::Status prepareDataLoader(MountId mountId,
+                                             const FileSystemControlParcel& control,
+                                             const DataLoaderParamsParcel& params,
+                                             const sp<IDataLoaderStatusListener>& listener,
+                                             bool* _aidl_return) const = 0;
+    virtual binder::Status startDataLoader(MountId mountId, bool* _aidl_return) const = 0;
+    virtual binder::Status destroyDataLoader(MountId mountId) const = 0;
+    virtual binder::Status newFileForDataLoader(MountId mountId, FileId fileid,
+                                                const std::vector<uint8_t>& metadata) const = 0;
+    virtual binder::Status showHealthBlockedUI(MountId mountId) const = 0;
 };
 
 class IncFsWrapper {
 public:
-    virtual ~IncFsWrapper() {}
-    virtual Inode makeFile(Control control, std::string_view name, Inode parent, Size size,
-                           std::string_view metadata) const = 0;
-    virtual Inode makeDir(Control control, std::string_view name, Inode parent,
-                          std::string_view metadata, int mode = 0555) const = 0;
-    virtual RawMetadata getMetadata(Control control, Inode inode) const = 0;
-    virtual ErrorCode link(Control control, Inode item, Inode targetParent,
-                           std::string_view name) const = 0;
-    virtual ErrorCode unlink(Control control, Inode parent, std::string_view name) const = 0;
-    virtual ErrorCode writeBlocks(Control control, const incfs_new_data_block blocks[],
-                                  int blocksCount) const = 0;
+    virtual ~IncFsWrapper() = default;
+    virtual ErrorCode makeFile(Control control, std::string_view path, int mode, FileId id,
+                               NewFileParams params) const = 0;
+    virtual ErrorCode makeDir(Control control, std::string_view path, int mode = 0555) const = 0;
+    virtual RawMetadata getMetadata(Control control, FileId fileid) const = 0;
+    virtual RawMetadata getMetadata(Control control, std::string_view path) const = 0;
+    virtual FileId getFileId(Control control, std::string_view path) const = 0;
+    virtual ErrorCode link(Control control, std::string_view from, std::string_view to) const = 0;
+    virtual ErrorCode unlink(Control control, std::string_view path) const = 0;
+    virtual base::unique_fd openWrite(Control control, FileId id) const = 0;
+    virtual ErrorCode writeBlocks(std::span<const DataBlock> blocks) const = 0;
 };
 
 class ServiceManagerWrapper {
 public:
-    virtual ~ServiceManagerWrapper() {}
-    virtual std::shared_ptr<VoldServiceWrapper> getVoldService() const = 0;
-    virtual std::shared_ptr<IncrementalManagerWrapper> getIncrementalManager() const = 0;
-    virtual std::shared_ptr<IncFsWrapper> getIncFs() const = 0;
+    virtual ~ServiceManagerWrapper() = default;
+    virtual std::unique_ptr<VoldServiceWrapper> getVoldService() = 0;
+    virtual std::unique_ptr<IncrementalManagerWrapper> getIncrementalManager() = 0;
+    virtual std::unique_ptr<IncFsWrapper> getIncFs() = 0;
 };
 
 // --- Real stuff ---
 
 class RealVoldService : public VoldServiceWrapper {
 public:
-    RealVoldService(const sp<os::IVold> vold) : mInterface(vold) {}
+    RealVoldService(const sp<os::IVold> vold) : mInterface(std::move(vold)) {}
     ~RealVoldService() = default;
-    binder::Status mountIncFs(const std::string& imagePath, const std::string& targetDir,
+    binder::Status mountIncFs(const std::string& backingPath, const std::string& targetDir,
                               int32_t flags,
                               IncrementalFileSystemControlParcel* _aidl_return) const override {
-        return mInterface->mountIncFs(imagePath, targetDir, flags, _aidl_return);
+        return mInterface->mountIncFs(backingPath, targetDir, flags, _aidl_return);
     }
     binder::Status unmountIncFs(const std::string& dir) const override {
         return mInterface->unmountIncFs(dir);
@@ -113,24 +116,26 @@
     RealIncrementalManager(const sp<os::incremental::IIncrementalManager> manager)
           : mInterface(manager) {}
     ~RealIncrementalManager() = default;
-    binder::Status prepareDataLoader(
-            int32_t mountId, const FileSystemControlParcel& control,
-            const DataLoaderParamsParcel& params,
-            const sp<IDataLoaderStatusListener>& listener,
-            bool* _aidl_return) const override {
+    binder::Status prepareDataLoader(MountId mountId, const FileSystemControlParcel& control,
+                                     const DataLoaderParamsParcel& params,
+                                     const sp<IDataLoaderStatusListener>& listener,
+                                     bool* _aidl_return) const override {
         return mInterface->prepareDataLoader(mountId, control, params, listener, _aidl_return);
     }
-    binder::Status startDataLoader(int32_t mountId, bool* _aidl_return) const override {
+    binder::Status startDataLoader(MountId mountId, bool* _aidl_return) const override {
         return mInterface->startDataLoader(mountId, _aidl_return);
     }
-    binder::Status destroyDataLoader(int32_t mountId) const override {
+    binder::Status destroyDataLoader(MountId mountId) const override {
         return mInterface->destroyDataLoader(mountId);
     }
-    binder::Status newFileForDataLoader(int32_t mountId, int64_t inode,
-                                        const ::std::vector<uint8_t>& metadata) const override {
-        return mInterface->newFileForDataLoader(mountId, inode, metadata);
+    binder::Status newFileForDataLoader(MountId mountId, FileId fileid,
+                                        const std::vector<uint8_t>& metadata) const override {
+        return mInterface->newFileForDataLoader(mountId,
+                                                {(const uint8_t*)fileid.data,
+                                                 (const uint8_t*)fileid.data + sizeof(fileid.data)},
+                                                metadata);
     }
-    binder::Status showHealthBlockedUI(int32_t mountId) const override {
+    binder::Status showHealthBlockedUI(MountId mountId) const override {
         return mInterface->showHealthBlockedUI(mountId);
     }
 
@@ -140,11 +145,11 @@
 
 class RealServiceManager : public ServiceManagerWrapper {
 public:
-    RealServiceManager(const sp<IServiceManager>& serviceManager);
+    RealServiceManager(sp<IServiceManager> serviceManager);
     ~RealServiceManager() = default;
-    std::shared_ptr<VoldServiceWrapper> getVoldService() const override;
-    std::shared_ptr<IncrementalManagerWrapper> getIncrementalManager() const override;
-    std::shared_ptr<IncFsWrapper> getIncFs() const override;
+    std::unique_ptr<VoldServiceWrapper> getVoldService() override;
+    std::unique_ptr<IncrementalManagerWrapper> getIncrementalManager() override;
+    std::unique_ptr<IncFsWrapper> getIncFs() override;
 
 private:
     template <class INTERFACE>
@@ -156,27 +161,33 @@
 public:
     RealIncFs() = default;
     ~RealIncFs() = default;
-    Inode makeFile(Control control, std::string_view name, Inode parent, Size size,
-                   std::string_view metadata) const override {
-        return incfs::makeFile(control, name, parent, size, metadata);
+    ErrorCode makeFile(Control control, std::string_view path, int mode, FileId id,
+                       NewFileParams params) const override {
+        return incfs::makeFile(control, path, mode, id, params);
     }
-    Inode makeDir(Control control, std::string_view name, Inode parent, std::string_view metadata,
-                  int mode) const override {
-        return incfs::makeDir(control, name, parent, metadata, mode);
+    ErrorCode makeDir(Control control, std::string_view path, int mode) const override {
+        return incfs::makeDir(control, path, mode);
     }
-    RawMetadata getMetadata(Control control, Inode inode) const override {
-        return incfs::getMetadata(control, inode);
+    RawMetadata getMetadata(Control control, FileId fileid) const override {
+        return incfs::getMetadata(control, fileid);
     }
-    ErrorCode link(Control control, Inode item, Inode targetParent,
-                   std::string_view name) const override {
-        return incfs::link(control, item, targetParent, name);
+    RawMetadata getMetadata(Control control, std::string_view path) const override {
+        return incfs::getMetadata(control, path);
     }
-    ErrorCode unlink(Control control, Inode parent, std::string_view name) const override {
-        return incfs::unlink(control, parent, name);
+    FileId getFileId(Control control, std::string_view path) const override {
+        return incfs::getFileId(control, path);
     }
-    ErrorCode writeBlocks(Control control, const incfs_new_data_block blocks[],
-                          int blocksCount) const override {
-        return incfs::writeBlocks(control, blocks, blocksCount);
+    ErrorCode link(Control control, std::string_view from, std::string_view to) const override {
+        return incfs::link(control, from, to);
+    }
+    ErrorCode unlink(Control control, std::string_view path) const override {
+        return incfs::unlink(control, path);
+    }
+    base::unique_fd openWrite(Control control, FileId id) const override {
+        return base::unique_fd{incfs::openWrite(control, id)};
+    }
+    ErrorCode writeBlocks(std::span<const DataBlock> blocks) const override {
+        return incfs::writeBlocks(blocks);
     }
 };
 
diff --git a/services/incremental/path.cpp b/services/incremental/path.cpp
index c529d61..0d86f2a 100644
--- a/services/incremental/path.cpp
+++ b/services/incremental/path.cpp
@@ -44,16 +44,45 @@
                                         PathCharsLess());
 }
 
+static void preparePathComponent(std::string_view path, bool trimFront) {
+    if (trimFront) {
+        while (!path.empty() && path.front() == '/') {
+            path.remove_prefix(1);
+        }
+    }
+    while (!path.empty() && path.back() == '/') {
+        path.remove_suffix(1);
+    }
+}
+
 void details::append_next_path(std::string& target, std::string_view path) {
+    preparePathComponent(path, true);
     if (path.empty()) {
         return;
     }
-    if (!target.empty()) {
+    if (!target.empty() && !target.ends_with('/')) {
         target.push_back('/');
     }
     target += path;
 }
 
+std::string_view relativize(std::string_view parent, std::string_view nested) {
+    if (!nested.starts_with(parent)) {
+        return nested;
+    }
+    if (nested.size() == parent.size()) {
+        return {};
+    }
+    if (nested[parent.size()] != '/') {
+        return nested;
+    }
+    auto relative = nested.substr(parent.size());
+    while (relative.front() == '/') {
+        relative.remove_prefix(1);
+    }
+    return relative;
+}
+
 bool isAbsolute(std::string_view path) {
     return !path.empty() && path[0] == '/';
 }
diff --git a/services/incremental/path.h b/services/incremental/path.h
index a1f4b8e..3e5fd21 100644
--- a/services/incremental/path.h
+++ b/services/incremental/path.h
@@ -67,6 +67,20 @@
     return {sv};
 }
 
+std::string_view relativize(std::string_view parent, std::string_view nested);
+inline std::string_view relativize(const char* parent, const char* nested) {
+    return relativize(std::string_view(parent), std::string_view(nested));
+}
+inline std::string_view relativize(std::string_view parent, const char* nested) {
+    return relativize(parent, std::string_view(nested));
+}
+inline std::string_view relativize(const char* parent, std::string_view nested) {
+    return relativize(std::string_view(parent), nested);
+}
+
+std::string_view relativize(std::string&& parent, std::string_view nested) = delete;
+std::string_view relativize(std::string_view parent, std::string&& nested) = delete;
+
 bool isAbsolute(std::string_view path);
 std::string normalize(std::string_view path);
 std::string_view dirname(std::string_view path);
diff --git a/services/incremental/test/IncrementalServiceTest.cpp b/services/incremental/test/IncrementalServiceTest.cpp
index ca1e1a9..2826818 100644
--- a/services/incremental/test/IncrementalServiceTest.cpp
+++ b/services/incremental/test/IncrementalServiceTest.cpp
@@ -46,7 +46,7 @@
 class MockVoldService : public VoldServiceWrapper {
 public:
     MOCK_CONST_METHOD4(mountIncFs,
-                       binder::Status(const std::string& imagePath, const std::string& targetDir,
+                       binder::Status(const std::string& backingPath, const std::string& targetDir,
                                       int32_t flags,
                                       IncrementalFileSystemControlParcel* _aidl_return));
     MOCK_CONST_METHOD1(unmountIncFs, binder::Status(const std::string& dir));
@@ -77,22 +77,20 @@
     binder::Status getInvalidControlParcel(const std::string& imagePath,
                                            const std::string& targetDir, int32_t flags,
                                            IncrementalFileSystemControlParcel* _aidl_return) {
-        _aidl_return->cmd = nullptr;
-        _aidl_return->log = nullptr;
+        _aidl_return = {};
         return binder::Status::ok();
     }
     binder::Status incFsSuccess(const std::string& imagePath, const std::string& targetDir,
                                 int32_t flags, IncrementalFileSystemControlParcel* _aidl_return) {
-        _aidl_return->cmd = std::make_unique<os::ParcelFileDescriptor>(std::move(cmdFd));
-        _aidl_return->log = std::make_unique<os::ParcelFileDescriptor>(std::move(logFd));
+        _aidl_return->pendingReads.reset(base::unique_fd(dup(STDIN_FILENO)));
+        _aidl_return->cmd.reset(base::unique_fd(dup(STDIN_FILENO)));
+        _aidl_return->log.reset(base::unique_fd(dup(STDIN_FILENO)));
         return binder::Status::ok();
     }
 
 private:
     TemporaryFile cmdFile;
     TemporaryFile logFile;
-    base::unique_fd cmdFd;
-    base::unique_fd logFd;
 };
 
 class MockIncrementalManager : public IncrementalManagerWrapper {
@@ -105,7 +103,7 @@
     MOCK_CONST_METHOD2(startDataLoader, binder::Status(int32_t mountId, bool* _aidl_return));
     MOCK_CONST_METHOD1(destroyDataLoader, binder::Status(int32_t mountId));
     MOCK_CONST_METHOD3(newFileForDataLoader,
-                       binder::Status(int32_t mountId, int64_t inode,
+                       binder::Status(int32_t mountId, FileId fileId,
                                       const ::std::vector<uint8_t>& metadata));
     MOCK_CONST_METHOD1(showHealthBlockedUI, binder::Status(int32_t mountId));
 
@@ -152,23 +150,21 @@
 class MockIncFs : public IncFsWrapper {
 public:
     MOCK_CONST_METHOD5(makeFile,
-                       Inode(Control control, std::string_view name, Inode parent, Size size,
-                             std::string_view metadata));
-    MOCK_CONST_METHOD5(makeDir,
-                       Inode(Control control, std::string_view name, Inode parent,
-                             std::string_view metadata, int mode));
-    MOCK_CONST_METHOD2(getMetadata, RawMetadata(Control control, Inode inode));
-    MOCK_CONST_METHOD4(link,
-                       ErrorCode(Control control, Inode item, Inode targetParent,
-                                 std::string_view name));
-    MOCK_CONST_METHOD3(unlink, ErrorCode(Control control, Inode parent, std::string_view name));
-    MOCK_CONST_METHOD3(writeBlocks,
-                       ErrorCode(Control control, const incfs_new_data_block blocks[],
-                                 int blocksCount));
+                       ErrorCode(Control control, std::string_view path, int mode, FileId id,
+                                 NewFileParams params));
+    MOCK_CONST_METHOD3(makeDir, ErrorCode(Control control, std::string_view path, int mode));
+    MOCK_CONST_METHOD2(getMetadata, RawMetadata(Control control, FileId fileid));
+    MOCK_CONST_METHOD2(getMetadata, RawMetadata(Control control, std::string_view path));
+    MOCK_CONST_METHOD2(getFileId, FileId(Control control, std::string_view path));
+    MOCK_CONST_METHOD3(link,
+                       ErrorCode(Control control, std::string_view from, std::string_view to));
+    MOCK_CONST_METHOD2(unlink, ErrorCode(Control control, std::string_view path));
+    MOCK_CONST_METHOD2(openWrite, base::unique_fd(Control control, FileId id));
+    MOCK_CONST_METHOD1(writeBlocks, ErrorCode(std::span<const DataBlock> blocks));
 
     void makeFileFails() { ON_CALL(*this, makeFile(_, _, _, _, _)).WillByDefault(Return(-1)); }
     void makeFileSuccess() { ON_CALL(*this, makeFile(_, _, _, _, _)).WillByDefault(Return(0)); }
-    RawMetadata getMountInfoMetadata(Control control, Inode inode) {
+    RawMetadata getMountInfoMetadata(Control control, std::string_view path) {
         metadata::Mount m;
         m.mutable_storage()->set_id(100);
         m.mutable_loader()->set_package_name("com.test");
@@ -176,15 +172,15 @@
         const auto metadata = m.SerializeAsString();
         m.mutable_loader()->release_arguments();
         m.mutable_loader()->release_package_name();
-        return std::vector<char>(metadata.begin(), metadata.end());
+        return {metadata.begin(), metadata.end()};
     }
-    RawMetadata getStorageMetadata(Control control, Inode inode) {
+    RawMetadata getStorageMetadata(Control control, std::string_view path) {
         metadata::Storage st;
         st.set_id(100);
         auto metadata = st.SerializeAsString();
-        return std::vector<char>(metadata.begin(), metadata.end());
+        return {metadata.begin(), metadata.end()};
     }
-    RawMetadata getBindPointMetadata(Control control, Inode inode) {
+    RawMetadata getBindPointMetadata(Control control, std::string_view path) {
         metadata::BindPoint bp;
         std::string destPath = "dest";
         std::string srcPath = "src";
@@ -200,40 +196,41 @@
 
 class MockServiceManager : public ServiceManagerWrapper {
 public:
-    MockServiceManager(std::shared_ptr<MockVoldService> vold,
-                       std::shared_ptr<MockIncrementalManager> manager,
-                       std::shared_ptr<MockIncFs> incfs)
-          : mVold(vold), mIncrementalManager(manager), mIncFs(incfs) {}
-    std::shared_ptr<VoldServiceWrapper> getVoldService() const override { return mVold; }
-    std::shared_ptr<IncrementalManagerWrapper> getIncrementalManager() const override {
-        return mIncrementalManager;
+    MockServiceManager(std::unique_ptr<MockVoldService> vold,
+                       std::unique_ptr<MockIncrementalManager> manager,
+                       std::unique_ptr<MockIncFs> incfs)
+          : mVold(std::move(vold)),
+            mIncrementalManager(std::move(manager)),
+            mIncFs(std::move(incfs)) {}
+    std::unique_ptr<VoldServiceWrapper> getVoldService() final { return std::move(mVold); }
+    std::unique_ptr<IncrementalManagerWrapper> getIncrementalManager() final {
+        return std::move(mIncrementalManager);
     }
-    std::shared_ptr<IncFsWrapper> getIncFs() const override { return mIncFs; }
+    std::unique_ptr<IncFsWrapper> getIncFs() final { return std::move(mIncFs); }
 
 private:
-    std::shared_ptr<MockVoldService> mVold;
-    std::shared_ptr<MockIncrementalManager> mIncrementalManager;
-    std::shared_ptr<MockIncFs> mIncFs;
+    std::unique_ptr<MockVoldService> mVold;
+    std::unique_ptr<MockIncrementalManager> mIncrementalManager;
+    std::unique_ptr<MockIncFs> mIncFs;
 };
 
 // --- IncrementalServiceTest ---
 
-static Inode inode(std::string_view path) {
-    struct stat st;
-    if (::stat(path::c_str(path), &st)) {
-        return -1;
-    }
-    return st.st_ino;
-}
-
 class IncrementalServiceTest : public testing::Test {
 public:
     void SetUp() override {
-        mVold = std::make_shared<NiceMock<MockVoldService>>();
-        mIncrementalManager = std::make_shared<NiceMock<MockIncrementalManager>>();
-        mIncFs = std::make_shared<NiceMock<MockIncFs>>();
-        MockServiceManager serviceManager = MockServiceManager(mVold, mIncrementalManager, mIncFs);
-        mIncrementalService = std::make_unique<IncrementalService>(serviceManager, mRootDir.path);
+        auto vold = std::make_unique<NiceMock<MockVoldService>>();
+        mVold = vold.get();
+        auto incrementalManager = std::make_unique<NiceMock<MockIncrementalManager>>();
+        mIncrementalManager = incrementalManager.get();
+        auto incFs = std::make_unique<NiceMock<MockIncFs>>();
+        mIncFs = incFs.get();
+        mIncrementalService =
+                std::make_unique<IncrementalService>(MockServiceManager(std::move(vold),
+                                                                        std::move(
+                                                                                incrementalManager),
+                                                                        std::move(incFs)),
+                                                     mRootDir.path);
         mDataLoaderParcel.packageName = "com.test";
         mDataLoaderParcel.arguments = "uri";
         mIncrementalService->onSystemReady();
@@ -252,20 +249,18 @@
         const auto mountPointsFile = rootDir + "/dir1/mount/.mountpoint.abcd";
         ASSERT_TRUE(base::WriteStringToFile("info", mountInfoFile));
         ASSERT_TRUE(base::WriteStringToFile("mounts", mountPointsFile));
-        ASSERT_GE(inode(mountInfoFile), 0);
-        ASSERT_GE(inode(mountPointsFile), 0);
-        ON_CALL(*mIncFs, getMetadata(_, inode(mountInfoFile)))
-                .WillByDefault(Invoke(mIncFs.get(), &MockIncFs::getMountInfoMetadata));
-        ON_CALL(*mIncFs, getMetadata(_, inode(mountPointsFile)))
-                .WillByDefault(Invoke(mIncFs.get(), &MockIncFs::getBindPointMetadata));
-        ON_CALL(*mIncFs, getMetadata(_, inode(rootDir + "/dir1/mount/st0")))
-                .WillByDefault(Invoke(mIncFs.get(), &MockIncFs::getStorageMetadata));
+        ON_CALL(*mIncFs, getMetadata(_, std::string_view(mountInfoFile)))
+                .WillByDefault(Invoke(mIncFs, &MockIncFs::getMountInfoMetadata));
+        ON_CALL(*mIncFs, getMetadata(_, std::string_view(mountPointsFile)))
+                .WillByDefault(Invoke(mIncFs, &MockIncFs::getBindPointMetadata));
+        ON_CALL(*mIncFs, getMetadata(_, std::string_view(rootDir + "/dir1/mount/st0")))
+                .WillByDefault(Invoke(mIncFs, &MockIncFs::getStorageMetadata));
     }
 
 protected:
-    std::shared_ptr<NiceMock<MockVoldService>> mVold;
-    std::shared_ptr<NiceMock<MockIncFs>> mIncFs;
-    std::shared_ptr<NiceMock<MockIncrementalManager>> mIncrementalManager;
+    NiceMock<MockVoldService>* mVold;
+    NiceMock<MockIncFs>* mIncFs;
+    NiceMock<MockIncrementalManager>* mIncrementalManager;
     std::unique_ptr<IncrementalService> mIncrementalService;
     TemporaryDir mRootDir;
     DataLoaderParamsParcel mDataLoaderParcel;
@@ -412,12 +407,12 @@
             mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
                                                IncrementalService::CreateOptions::CreateNew);
     std::string_view dir_path("test");
-    EXPECT_CALL(*mIncFs, makeDir(_, dir_path, _, _, _));
-    int fileIno = mIncrementalService->makeDir(storageId, dir_path, "");
-    ASSERT_GE(fileIno, 0);
+    EXPECT_CALL(*mIncFs, makeDir(_, dir_path, _));
+    auto res = mIncrementalService->makeDir(storageId, dir_path, 0555);
+    ASSERT_EQ(res, 0);
 }
 
-TEST_F(IncrementalServiceTest, testMakeDirectoryNoParent) {
+TEST_F(IncrementalServiceTest, testMakeDirectoryNested) {
     mVold->mountIncFsSuccess();
     mIncFs->makeFileSuccess();
     mVold->bindMountSuccess();
@@ -427,13 +422,15 @@
     int storageId =
             mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
                                                IncrementalService::CreateOptions::CreateNew);
-    std::string_view first("first");
-    std::string_view second("second");
+    auto first = "first"sv;
+    auto second = "second"sv;
     std::string dir_path = std::string(first) + "/" + std::string(second);
-    EXPECT_CALL(*mIncFs, makeDir(_, first, _, _, _)).Times(0);
-    EXPECT_CALL(*mIncFs, makeDir(_, second, _, _, _)).Times(0);
-    int fileIno = mIncrementalService->makeDir(storageId, dir_path, "");
-    ASSERT_LT(fileIno, 0);
+    EXPECT_CALL(*mIncFs, makeDir(_, first, _)).Times(0);
+    EXPECT_CALL(*mIncFs, makeDir(_, second, _)).Times(0);
+    EXPECT_CALL(*mIncFs, makeDir(_, std::string_view(dir_path), _)).Times(1);
+
+    auto res = mIncrementalService->makeDir(storageId, dir_path, 0555);
+    ASSERT_EQ(res, 0);
 }
 
 TEST_F(IncrementalServiceTest, testMakeDirectories) {
@@ -446,16 +443,18 @@
     int storageId =
             mIncrementalService->createStorage(tempDir.path, std::move(mDataLoaderParcel),
                                                IncrementalService::CreateOptions::CreateNew);
-    std::string_view first("first");
-    std::string_view second("second");
-    std::string_view third("third");
+    auto first = "first"sv;
+    auto second = "second"sv;
+    auto third = "third"sv;
     InSequence seq;
-    EXPECT_CALL(*mIncFs, makeDir(_, first, _, _, _));
-    EXPECT_CALL(*mIncFs, makeDir(_, second, _, _, _));
-    EXPECT_CALL(*mIncFs, makeDir(_, third, _, _, _));
-    std::string dir_path =
-            std::string(first) + "/" + std::string(second) + "/" + std::string(third);
-    int fileIno = mIncrementalService->makeDirs(storageId, dir_path, "");
-    ASSERT_GE(fileIno, 0);
+    auto parent_path = std::string(first) + "/" + std::string(second);
+    auto dir_path = parent_path + "/" + std::string(third);
+    EXPECT_CALL(*mIncFs, makeDir(_, std::string_view(dir_path), _)).WillOnce(Return(-ENOENT));
+    EXPECT_CALL(*mIncFs, makeDir(_, std::string_view(parent_path), _)).WillOnce(Return(-ENOENT));
+    EXPECT_CALL(*mIncFs, makeDir(_, first, _)).WillOnce(Return(0));
+    EXPECT_CALL(*mIncFs, makeDir(_, std::string_view(parent_path), _)).WillOnce(Return(0));
+    EXPECT_CALL(*mIncFs, makeDir(_, std::string_view(dir_path), _)).WillOnce(Return(0));
+    auto res = mIncrementalService->makeDirs(storageId, dir_path, 0555);
+    ASSERT_EQ(res, 0);
 }
 } // namespace android::os::incremental
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 258d762..4f5c1ab 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -1327,7 +1327,7 @@
             if (!isWatch) {
                 t.traceBegin("StartStatusBarManagerService");
                 try {
-                    statusBar = new StatusBarManagerService(context, wm);
+                    statusBar = new StatusBarManagerService(context);
                     ServiceManager.addService(Context.STATUS_BAR_SERVICE, statusBar);
                 } catch (Throwable e) {
                     reportWtf("starting StatusBarManagerService", e);
@@ -1724,9 +1724,11 @@
             mSystemServiceManager.startService(SensorNotificationService.class);
             t.traceEnd();
 
-            t.traceBegin("StartContextHubSystemService");
-            mSystemServiceManager.startService(ContextHubSystemService.class);
-            t.traceEnd();
+            if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_CONTEXTHUB)) {
+                t.traceBegin("StartContextHubSystemService");
+                mSystemServiceManager.startService(ContextHubSystemService.class);
+                t.traceEnd();
+            }
 
             t.traceBegin("StartDiskStatsService");
             try {
diff --git a/services/net/java/android/net/IpMemoryStore.java b/services/net/java/android/net/IpMemoryStore.java
index 6f91e00..dcefb53 100644
--- a/services/net/java/android/net/IpMemoryStore.java
+++ b/services/net/java/android/net/IpMemoryStore.java
@@ -52,6 +52,11 @@
                     public int getInterfaceVersion() {
                         return this.VERSION;
                     }
+
+                    @Override
+                    public String getInterfaceHash() {
+                        return this.HASH;
+                    }
                 });
     }
 
diff --git a/services/net/java/android/net/ip/IpClientUtil.java b/services/net/java/android/net/ip/IpClientUtil.java
index 7f723b1..a3618b4 100644
--- a/services/net/java/android/net/ip/IpClientUtil.java
+++ b/services/net/java/android/net/ip/IpClientUtil.java
@@ -189,6 +189,11 @@
         public int getInterfaceVersion() {
             return this.VERSION;
         }
+
+        @Override
+        public String getInterfaceHash() {
+            return this.HASH;
+        }
     }
 
     /**
diff --git a/services/people/java/com/android/server/people/PeopleService.java b/services/people/java/com/android/server/people/PeopleService.java
index 9569c6e..2d18a29 100644
--- a/services/people/java/com/android/server/people/PeopleService.java
+++ b/services/people/java/com/android/server/people/PeopleService.java
@@ -16,6 +16,7 @@
 
 package com.android.server.people;
 
+import android.annotation.NonNull;
 import android.app.prediction.AppPredictionContext;
 import android.app.prediction.AppPredictionSessionId;
 import android.app.prediction.AppTarget;
@@ -29,6 +30,7 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.SystemService;
+import com.android.server.people.data.DataManager;
 
 import java.util.List;
 import java.util.Map;
@@ -41,6 +43,8 @@
 
     private static final String TAG = "PeopleService";
 
+    private final DataManager mDataManager;
+
     /**
      * Initializes the system service.
      *
@@ -48,6 +52,15 @@
      */
     public PeopleService(Context context) {
         super(context);
+
+        mDataManager = new DataManager(context);
+    }
+
+    @Override
+    public void onBootPhase(int phase) {
+        if (phase == PHASE_SYSTEM_SERVICES_READY) {
+            mDataManager.initialize();
+        }
     }
 
     @Override
@@ -55,6 +68,16 @@
         publishLocalService(PeopleServiceInternal.class, new LocalService());
     }
 
+    @Override
+    public void onUnlockUser(@NonNull TargetUser targetUser) {
+        mDataManager.onUserUnlocked(targetUser.getUserIdentifier());
+    }
+
+    @Override
+    public void onStopUser(@NonNull TargetUser targetUser) {
+        mDataManager.onUserStopped(targetUser.getUserIdentifier());
+    }
+
     @VisibleForTesting
     final class LocalService extends PeopleServiceInternal {
 
@@ -63,7 +86,7 @@
         @Override
         public void onCreatePredictionSession(AppPredictionContext context,
                 AppPredictionSessionId sessionId) {
-            mSessions.put(sessionId, new SessionInfo(context));
+            mSessions.put(sessionId, new SessionInfo(context, mDataManager));
         }
 
         @Override
diff --git a/services/people/java/com/android/server/people/SessionInfo.java b/services/people/java/com/android/server/people/SessionInfo.java
index df7cedf..eb08e03 100644
--- a/services/people/java/com/android/server/people/SessionInfo.java
+++ b/services/people/java/com/android/server/people/SessionInfo.java
@@ -24,6 +24,7 @@
 import android.os.RemoteException;
 import android.util.Slog;
 
+import com.android.server.people.data.DataManager;
 import com.android.server.people.prediction.ConversationPredictor;
 
 import java.util.List;
@@ -37,9 +38,9 @@
     private final RemoteCallbackList<IPredictionCallback> mCallbacks =
             new RemoteCallbackList<>();
 
-    SessionInfo(AppPredictionContext predictionContext) {
+    SessionInfo(AppPredictionContext predictionContext, DataManager dataManager) {
         mConversationPredictor = new ConversationPredictor(predictionContext,
-                this::updatePredictions);
+                this::updatePredictions, dataManager);
     }
 
     void addCallback(IPredictionCallback callback) {
diff --git a/services/people/java/com/android/server/people/data/AggregateEventHistoryImpl.java b/services/people/java/com/android/server/people/data/AggregateEventHistoryImpl.java
new file mode 100644
index 0000000..4ac346b
--- /dev/null
+++ b/services/people/java/com/android/server/people/data/AggregateEventHistoryImpl.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2020 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.people.data;
+
+import android.annotation.NonNull;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+/** An {@link EventHistory} that aggregates multiple {@link EventHistory}.  */
+class AggregateEventHistoryImpl implements EventHistory {
+
+    private final List<EventHistory> mEventHistoryList = new ArrayList<>();
+
+    @NonNull
+    @Override
+    public EventIndex getEventIndex(int eventType) {
+        for (EventHistory eventHistory : mEventHistoryList) {
+            EventIndex eventIndex = eventHistory.getEventIndex(eventType);
+            if (!eventIndex.isEmpty()) {
+                return eventIndex;
+            }
+        }
+        return EventIndex.EMPTY;
+    }
+
+    @NonNull
+    @Override
+    public EventIndex getEventIndex(Set<Integer> eventTypes) {
+        EventIndex merged = new EventIndex();
+        for (EventHistory eventHistory : mEventHistoryList) {
+            EventIndex eventIndex = eventHistory.getEventIndex(eventTypes);
+            if (!eventIndex.isEmpty()) {
+                merged = EventIndex.combine(merged, eventIndex);
+            }
+        }
+        return merged;
+    }
+
+    @NonNull
+    @Override
+    public List<Event> queryEvents(Set<Integer> eventTypes, long startTime, long endTime) {
+        List<Event> results = new ArrayList<>();
+        for (EventHistory eventHistory : mEventHistoryList) {
+            EventIndex eventIndex = eventHistory.getEventIndex(eventTypes);
+            if (eventIndex.isEmpty()) {
+                continue;
+            }
+            List<Event> queryResults = eventHistory.queryEvents(eventTypes, startTime, endTime);
+            results = combineEventLists(results, queryResults);
+        }
+        return results;
+    }
+
+    void addEventHistory(EventHistory eventHistory) {
+        mEventHistoryList.add(eventHistory);
+    }
+
+    /**
+     * Combines the sorted events (in chronological order) from the given 2 lists {@code lhs}
+     * and {@code rhs} and preserves the order.
+     */
+    private List<Event> combineEventLists(List<Event> lhs, List<Event> rhs) {
+        List<Event> results = new ArrayList<>();
+        int i = 0, j = 0;
+        while (i < lhs.size() && j < rhs.size()) {
+            if (lhs.get(i).getTimestamp() < rhs.get(j).getTimestamp()) {
+                results.add(lhs.get(i++));
+            } else {
+                results.add(rhs.get(j++));
+            }
+        }
+        if (i < lhs.size()) {
+            results.addAll(lhs.subList(i, lhs.size()));
+        } else if (j < rhs.size()) {
+            results.addAll(rhs.subList(j, rhs.size()));
+        }
+        return results;
+    }
+}
diff --git a/services/people/java/com/android/server/people/data/ContactsQueryHelper.java b/services/people/java/com/android/server/people/data/ContactsQueryHelper.java
new file mode 100644
index 0000000..8a3a44ae
--- /dev/null
+++ b/services/people/java/com/android/server/people/data/ContactsQueryHelper.java
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2020 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.people.data;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.WorkerThread;
+import android.content.Context;
+import android.database.Cursor;
+import android.net.Uri;
+import android.provider.ContactsContract;
+import android.provider.ContactsContract.Contacts;
+import android.text.TextUtils;
+import android.util.Slog;
+
+/** A helper class that queries the Contacts database. */
+class ContactsQueryHelper {
+
+    private static final String TAG = "ContactsQueryHelper";
+
+    private final Context mContext;
+    private Uri mContactUri;
+    private boolean mIsStarred;
+    private String mPhoneNumber;
+    private long mLastUpdatedTimestamp;
+
+    ContactsQueryHelper(Context context) {
+        mContext = context;
+    }
+
+    /**
+     * Queries the Contacts database with the given contact URI and returns whether the query runs
+     * successfully.
+     */
+    @WorkerThread
+    boolean query(@NonNull String contactUri) {
+        if (TextUtils.isEmpty(contactUri)) {
+            return false;
+        }
+        Uri uri = Uri.parse(contactUri);
+        if ("tel".equals(uri.getScheme())) {
+            return queryWithPhoneNumber(uri.getSchemeSpecificPart());
+        } else if ("mailto".equals(uri.getScheme())) {
+            return queryWithEmail(uri.getSchemeSpecificPart());
+        } else if (contactUri.startsWith(Contacts.CONTENT_LOOKUP_URI.toString())) {
+            return queryWithUri(uri);
+        }
+        return false;
+    }
+
+    /** Queries the Contacts database and read the most recently updated contact. */
+    @WorkerThread
+    boolean querySince(long sinceTime) {
+        final String[] projection = new String[] {
+                Contacts._ID, Contacts.LOOKUP_KEY, Contacts.STARRED, Contacts.HAS_PHONE_NUMBER,
+                Contacts.CONTACT_LAST_UPDATED_TIMESTAMP };
+        String selection = Contacts.CONTACT_LAST_UPDATED_TIMESTAMP + " > ?";
+        String[] selectionArgs = new String[] {Long.toString(sinceTime)};
+        return queryContact(Contacts.CONTENT_URI, projection, selection, selectionArgs);
+    }
+
+    @Nullable
+    Uri getContactUri() {
+        return mContactUri;
+    }
+
+    boolean isStarred() {
+        return mIsStarred;
+    }
+
+    @Nullable
+    String getPhoneNumber() {
+        return mPhoneNumber;
+    }
+
+    long getLastUpdatedTimestamp() {
+        return mLastUpdatedTimestamp;
+    }
+
+    private boolean queryWithPhoneNumber(String phoneNumber) {
+        Uri phoneUri = Uri.withAppendedPath(
+                ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber));
+        return queryWithUri(phoneUri);
+    }
+
+    private boolean queryWithEmail(String email) {
+        Uri emailUri = Uri.withAppendedPath(
+                ContactsContract.CommonDataKinds.Email.CONTENT_LOOKUP_URI, Uri.encode(email));
+        return queryWithUri(emailUri);
+    }
+
+    private boolean queryWithUri(@NonNull Uri uri) {
+        final String[] projection = new String[] {
+                Contacts._ID, Contacts.LOOKUP_KEY, Contacts.STARRED, Contacts.HAS_PHONE_NUMBER };
+        return queryContact(uri, projection, /* selection= */ null, /* selectionArgs= */ null);
+    }
+
+    private boolean queryContact(@NonNull Uri uri, @NonNull String[] projection,
+            @Nullable String selection, @Nullable String[] selectionArgs) {
+        long contactId;
+        String lookupKey = null;
+        boolean hasPhoneNumber = false;
+        boolean found = false;
+        try (Cursor cursor = mContext.getContentResolver().query(
+                uri, projection, selection, selectionArgs, /* sortOrder= */ null)) {
+            if (cursor == null) {
+                Slog.w(TAG, "Cursor is null when querying contact.");
+                return false;
+            }
+            while (cursor.moveToNext()) {
+                // Contact ID
+                int idIndex = cursor.getColumnIndex(Contacts._ID);
+                contactId = cursor.getLong(idIndex);
+
+                // Lookup key
+                int lookupKeyIndex = cursor.getColumnIndex(Contacts.LOOKUP_KEY);
+                lookupKey = cursor.getString(lookupKeyIndex);
+
+                mContactUri = Contacts.getLookupUri(contactId, lookupKey);
+
+                // Starred
+                int starredIndex = cursor.getColumnIndex(Contacts.STARRED);
+                mIsStarred = cursor.getInt(starredIndex) != 0;
+
+                // Has phone number
+                int hasPhoneNumIndex = cursor.getColumnIndex(Contacts.HAS_PHONE_NUMBER);
+                hasPhoneNumber = cursor.getInt(hasPhoneNumIndex) != 0;
+
+                // Last updated timestamp
+                int lastUpdatedTimestampIndex = cursor.getColumnIndex(
+                        Contacts.CONTACT_LAST_UPDATED_TIMESTAMP);
+                if (lastUpdatedTimestampIndex >= 0) {
+                    mLastUpdatedTimestamp = cursor.getLong(lastUpdatedTimestampIndex);
+                }
+
+                found = true;
+            }
+        }
+        if (found && lookupKey != null && hasPhoneNumber) {
+            return queryPhoneNumber(lookupKey);
+        }
+        return found;
+    }
+
+    private boolean queryPhoneNumber(String lookupKey) {
+        String[] projection = new String[] {
+                ContactsContract.CommonDataKinds.Phone.NORMALIZED_NUMBER };
+        String selection = Contacts.LOOKUP_KEY + " = ?";
+        String[] selectionArgs = new String[] { lookupKey };
+        try (Cursor cursor = mContext.getContentResolver().query(
+                ContactsContract.CommonDataKinds.Phone.CONTENT_URI, projection, selection,
+                selectionArgs, /* sortOrder= */ null)) {
+            if (cursor == null) {
+                Slog.w(TAG, "Cursor is null when querying contact phone number.");
+                return false;
+            }
+            while (cursor.moveToNext()) {
+                // Phone number
+                int phoneNumIdx = cursor.getColumnIndex(
+                        ContactsContract.CommonDataKinds.Phone.NORMALIZED_NUMBER);
+                if (phoneNumIdx >= 0) {
+                    mPhoneNumber = cursor.getString(phoneNumIdx);
+                }
+            }
+        }
+        return true;
+    }
+}
diff --git a/services/people/java/com/android/server/people/data/ConversationInfo.java b/services/people/java/com/android/server/people/data/ConversationInfo.java
new file mode 100644
index 0000000..bb97533
--- /dev/null
+++ b/services/people/java/com/android/server/people/data/ConversationInfo.java
@@ -0,0 +1,372 @@
+/*
+ * Copyright (C) 2020 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.people.data;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.LocusId;
+import android.content.pm.ShortcutInfo;
+import android.content.pm.ShortcutInfo.ShortcutFlags;
+import android.net.Uri;
+
+import com.android.internal.util.Preconditions;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
+
+/**
+ * Represents a conversation that is provided by the app based on {@link ShortcutInfo}.
+ */
+public class ConversationInfo {
+
+    private static final int FLAG_VIP = 1;
+
+    private static final int FLAG_NOTIFICATION_SILENCED = 1 << 1;
+
+    private static final int FLAG_BUBBLED = 1 << 2;
+
+    private static final int FLAG_PERSON_IMPORTANT = 1 << 3;
+
+    private static final int FLAG_PERSON_BOT = 1 << 4;
+
+    private static final int FLAG_CONTACT_STARRED = 1 << 5;
+
+    private static final int FLAG_DEMOTED = 1 << 6;
+
+    @IntDef(flag = true, prefix = {"FLAG_"}, value = {
+            FLAG_VIP,
+            FLAG_NOTIFICATION_SILENCED,
+            FLAG_BUBBLED,
+            FLAG_PERSON_IMPORTANT,
+            FLAG_PERSON_BOT,
+            FLAG_CONTACT_STARRED,
+            FLAG_DEMOTED,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    private @interface ConversationFlags {
+    }
+
+    @NonNull
+    private String mShortcutId;
+
+    @Nullable
+    private LocusId mLocusId;
+
+    @Nullable
+    private Uri mContactUri;
+
+    @Nullable
+    private String mContactPhoneNumber;
+
+    @Nullable
+    private String mNotificationChannelId;
+
+    @ShortcutFlags
+    private int mShortcutFlags;
+
+    @ConversationFlags
+    private int mConversationFlags;
+
+    private ConversationInfo(Builder builder) {
+        mShortcutId = builder.mShortcutId;
+        mLocusId = builder.mLocusId;
+        mContactUri = builder.mContactUri;
+        mContactPhoneNumber = builder.mContactPhoneNumber;
+        mNotificationChannelId = builder.mNotificationChannelId;
+        mShortcutFlags = builder.mShortcutFlags;
+        mConversationFlags = builder.mConversationFlags;
+    }
+
+    @NonNull
+    public String getShortcutId() {
+        return mShortcutId;
+    }
+
+    @Nullable
+    LocusId getLocusId() {
+        return mLocusId;
+    }
+
+    /** The URI to look up the entry in the contacts data provider. */
+    @Nullable
+    Uri getContactUri() {
+        return mContactUri;
+    }
+
+    /** The phone number of the associated contact. */
+    @Nullable
+    String getContactPhoneNumber() {
+        return mContactPhoneNumber;
+    }
+
+    /**
+     * ID of the {@link android.app.NotificationChannel} where the notifications for this
+     * conversation are posted.
+     */
+    @Nullable
+    String getNotificationChannelId() {
+        return mNotificationChannelId;
+    }
+
+    /** Whether the shortcut for this conversation is set long-lived by the app. */
+    public boolean isShortcutLongLived() {
+        return hasShortcutFlags(ShortcutInfo.FLAG_LONG_LIVED);
+    }
+
+    /** Whether this conversation is marked as VIP by the user. */
+    public boolean isVip() {
+        return hasConversationFlags(FLAG_VIP);
+    }
+
+    /** Whether the notifications for this conversation should be silenced. */
+    public boolean isNotificationSilenced() {
+        return hasConversationFlags(FLAG_NOTIFICATION_SILENCED);
+    }
+
+    /** Whether the notifications for this conversation should show in bubbles. */
+    public boolean isBubbled() {
+        return hasConversationFlags(FLAG_BUBBLED);
+    }
+
+    /**
+     * Whether this conversation is demoted by the user. New notifications for the demoted
+     * conversation will not show in the conversation space.
+     */
+    public boolean isDemoted() {
+        return hasConversationFlags(FLAG_DEMOTED);
+    }
+
+    /** Whether the associated person is marked as important by the app. */
+    public boolean isPersonImportant() {
+        return hasConversationFlags(FLAG_PERSON_IMPORTANT);
+    }
+
+    /** Whether the associated person is marked as a bot by the app. */
+    public boolean isPersonBot() {
+        return hasConversationFlags(FLAG_PERSON_BOT);
+    }
+
+    /** Whether the associated contact is marked as starred by the user. */
+    public boolean isContactStarred() {
+        return hasConversationFlags(FLAG_CONTACT_STARRED);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (!(obj instanceof ConversationInfo)) {
+            return false;
+        }
+        ConversationInfo other = (ConversationInfo) obj;
+        return Objects.equals(mShortcutId, other.mShortcutId)
+                && Objects.equals(mLocusId, other.mLocusId)
+                && Objects.equals(mContactUri, other.mContactUri)
+                && Objects.equals(mContactPhoneNumber, other.mContactPhoneNumber)
+                && Objects.equals(mNotificationChannelId, other.mNotificationChannelId)
+                && mShortcutFlags == other.mShortcutFlags
+                && mConversationFlags == other.mConversationFlags;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mShortcutId, mLocusId, mContactUri, mContactPhoneNumber,
+                mNotificationChannelId, mShortcutFlags, mConversationFlags);
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("ConversationInfo {");
+        sb.append("shortcutId=").append(mShortcutId);
+        sb.append(", locusId=").append(mLocusId);
+        sb.append(", contactUri=").append(mContactUri);
+        sb.append(", phoneNumber=").append(mContactPhoneNumber);
+        sb.append(", notificationChannelId=").append(mNotificationChannelId);
+        sb.append(", shortcutFlags=0x").append(Integer.toHexString(mShortcutFlags));
+        sb.append(" [");
+        if (isShortcutLongLived()) {
+            sb.append("Liv");
+        }
+        sb.append("]");
+        sb.append(", conversationFlags=0x").append(Integer.toHexString(mConversationFlags));
+        sb.append(" [");
+        if (isVip()) {
+            sb.append("Vip");
+        }
+        if (isNotificationSilenced()) {
+            sb.append("Sil");
+        }
+        if (isBubbled()) {
+            sb.append("Bub");
+        }
+        if (isDemoted()) {
+            sb.append("Dem");
+        }
+        if (isPersonImportant()) {
+            sb.append("Imp");
+        }
+        if (isPersonBot()) {
+            sb.append("Bot");
+        }
+        if (isContactStarred()) {
+            sb.append("Sta");
+        }
+        sb.append("]}");
+        return sb.toString();
+    }
+
+    private boolean hasShortcutFlags(@ShortcutFlags int flags) {
+        return (mShortcutFlags & flags) == flags;
+    }
+
+    private boolean hasConversationFlags(@ConversationFlags int flags) {
+        return (mConversationFlags & flags) == flags;
+    }
+
+    /**
+     * Builder class for {@link ConversationInfo} objects.
+     */
+    static class Builder {
+
+        private String mShortcutId;
+
+        @Nullable
+        private LocusId mLocusId;
+
+        @Nullable
+        private Uri mContactUri;
+
+        @Nullable
+        private String mContactPhoneNumber;
+
+        @Nullable
+        private String mNotificationChannelId;
+
+        @ShortcutFlags
+        private int mShortcutFlags;
+
+        @ConversationFlags
+        private int mConversationFlags;
+
+        Builder() {
+        }
+
+        Builder(@NonNull ConversationInfo conversationInfo) {
+            if (mShortcutId == null) {
+                mShortcutId = conversationInfo.mShortcutId;
+            } else {
+                Preconditions.checkArgument(mShortcutId.equals(conversationInfo.mShortcutId));
+            }
+            mLocusId = conversationInfo.mLocusId;
+            mContactUri = conversationInfo.mContactUri;
+            mContactPhoneNumber = conversationInfo.mContactPhoneNumber;
+            mNotificationChannelId = conversationInfo.mNotificationChannelId;
+            mShortcutFlags = conversationInfo.mShortcutFlags;
+            mConversationFlags = conversationInfo.mConversationFlags;
+        }
+
+        Builder setShortcutId(@NonNull String shortcutId) {
+            mShortcutId = shortcutId;
+            return this;
+        }
+
+        Builder setLocusId(LocusId locusId) {
+            mLocusId = locusId;
+            return this;
+        }
+
+        Builder setContactUri(Uri contactUri) {
+            mContactUri = contactUri;
+            return this;
+        }
+
+        Builder setContactPhoneNumber(String phoneNumber) {
+            mContactPhoneNumber = phoneNumber;
+            return this;
+        }
+
+        Builder setNotificationChannelId(String notificationChannelId) {
+            mNotificationChannelId = notificationChannelId;
+            return this;
+        }
+
+        Builder setShortcutFlags(@ShortcutFlags int shortcutFlags) {
+            mShortcutFlags = shortcutFlags;
+            return this;
+        }
+
+        Builder setConversationFlags(@ConversationFlags int conversationFlags) {
+            mConversationFlags = conversationFlags;
+            return this;
+        }
+
+        Builder setVip(boolean value) {
+            return setConversationFlag(FLAG_VIP, value);
+        }
+
+        Builder setNotificationSilenced(boolean value) {
+            return setConversationFlag(FLAG_NOTIFICATION_SILENCED, value);
+        }
+
+        Builder setBubbled(boolean value) {
+            return setConversationFlag(FLAG_BUBBLED, value);
+        }
+
+        Builder setDemoted(boolean value) {
+            return setConversationFlag(FLAG_DEMOTED, value);
+        }
+
+        Builder setPersonImportant(boolean value) {
+            return setConversationFlag(FLAG_PERSON_IMPORTANT, value);
+        }
+
+        Builder setPersonBot(boolean value) {
+            return setConversationFlag(FLAG_PERSON_BOT, value);
+        }
+
+        Builder setContactStarred(boolean value) {
+            return setConversationFlag(FLAG_CONTACT_STARRED, value);
+        }
+
+        private Builder setConversationFlag(@ConversationFlags int flags, boolean value) {
+            if (value) {
+                return addConversationFlags(flags);
+            } else {
+                return removeConversationFlags(flags);
+            }
+        }
+
+        private Builder addConversationFlags(@ConversationFlags int flags) {
+            mConversationFlags |= flags;
+            return this;
+        }
+
+        private Builder removeConversationFlags(@ConversationFlags int flags) {
+            mConversationFlags &= ~flags;
+            return this;
+        }
+
+        ConversationInfo build() {
+            Objects.requireNonNull(mShortcutId);
+            return new ConversationInfo(this);
+        }
+    }
+}
diff --git a/services/people/java/com/android/server/people/data/ConversationStore.java b/services/people/java/com/android/server/people/data/ConversationStore.java
new file mode 100644
index 0000000..f17e1b9
--- /dev/null
+++ b/services/people/java/com/android/server/people/data/ConversationStore.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2020 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.people.data;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.LocusId;
+import android.net.Uri;
+import android.util.ArrayMap;
+
+import java.util.Map;
+import java.util.function.Consumer;
+
+/** The store that stores and accesses the conversations data for a package. */
+class ConversationStore {
+
+    // Shortcut ID -> Conversation Info
+    private final Map<String, ConversationInfo> mConversationInfoMap = new ArrayMap<>();
+
+    // Locus ID -> Shortcut ID
+    private final Map<LocusId, String> mLocusIdToShortcutIdMap = new ArrayMap<>();
+
+    // Contact URI -> Shortcut ID
+    private final Map<Uri, String> mContactUriToShortcutIdMap = new ArrayMap<>();
+
+    // Phone Number -> Shortcut ID
+    private final Map<String, String> mPhoneNumberToShortcutIdMap = new ArrayMap<>();
+
+    void addOrUpdate(@NonNull ConversationInfo conversationInfo) {
+        mConversationInfoMap.put(conversationInfo.getShortcutId(), conversationInfo);
+
+        LocusId locusId = conversationInfo.getLocusId();
+        if (locusId != null) {
+            mLocusIdToShortcutIdMap.put(locusId, conversationInfo.getShortcutId());
+        }
+
+        Uri contactUri = conversationInfo.getContactUri();
+        if (contactUri != null) {
+            mContactUriToShortcutIdMap.put(contactUri, conversationInfo.getShortcutId());
+        }
+
+        String phoneNumber = conversationInfo.getContactPhoneNumber();
+        if (phoneNumber != null) {
+            mPhoneNumberToShortcutIdMap.put(phoneNumber, conversationInfo.getShortcutId());
+        }
+    }
+
+    void deleteConversation(@NonNull String shortcutId) {
+        ConversationInfo conversationInfo = mConversationInfoMap.remove(shortcutId);
+        if (conversationInfo == null) {
+            return;
+        }
+
+        LocusId locusId = conversationInfo.getLocusId();
+        if (locusId != null) {
+            mLocusIdToShortcutIdMap.remove(locusId);
+        }
+
+        Uri contactUri = conversationInfo.getContactUri();
+        if (contactUri != null) {
+            mContactUriToShortcutIdMap.remove(contactUri);
+        }
+
+        String phoneNumber = conversationInfo.getContactPhoneNumber();
+        if (phoneNumber != null) {
+            mPhoneNumberToShortcutIdMap.remove(phoneNumber);
+        }
+    }
+
+    void forAllConversations(@NonNull Consumer<ConversationInfo> consumer) {
+        for (ConversationInfo ci : mConversationInfoMap.values()) {
+            consumer.accept(ci);
+        }
+    }
+
+    @Nullable
+    ConversationInfo getConversation(@Nullable String shortcutId) {
+        return shortcutId != null ? mConversationInfoMap.get(shortcutId) : null;
+    }
+
+    @Nullable
+    ConversationInfo getConversationByLocusId(@NonNull LocusId locusId) {
+        return getConversation(mLocusIdToShortcutIdMap.get(locusId));
+    }
+
+    @Nullable
+    ConversationInfo getConversationByContactUri(@NonNull Uri contactUri) {
+        return getConversation(mContactUriToShortcutIdMap.get(contactUri));
+    }
+
+    @Nullable
+    ConversationInfo getConversationByPhoneNumber(@NonNull String phoneNumber) {
+        return getConversation(mPhoneNumberToShortcutIdMap.get(phoneNumber));
+    }
+}
diff --git a/services/people/java/com/android/server/people/data/DataManager.java b/services/people/java/com/android/server/people/data/DataManager.java
new file mode 100644
index 0000000..13cce41
--- /dev/null
+++ b/services/people/java/com/android/server/people/data/DataManager.java
@@ -0,0 +1,559 @@
+/*
+ * Copyright (C) 2020 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.people.data;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.UserIdInt;
+import android.annotation.WorkerThread;
+import android.app.Notification;
+import android.app.Person;
+import android.app.prediction.AppTarget;
+import android.app.prediction.AppTargetEvent;
+import android.app.usage.UsageEvents;
+import android.app.usage.UsageStatsManagerInternal;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.LauncherApps.ShortcutQuery;
+import android.content.pm.ShortcutInfo;
+import android.content.pm.ShortcutManager;
+import android.content.pm.ShortcutManager.ShareShortcutInfo;
+import android.content.pm.ShortcutServiceInternal;
+import android.content.pm.UserInfo;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Binder;
+import android.os.Handler;
+import android.os.Process;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.provider.ContactsContract.Contacts;
+import android.service.notification.NotificationListenerService;
+import android.service.notification.StatusBarNotification;
+import android.telecom.TelecomManager;
+import android.text.TextUtils;
+import android.text.format.DateUtils;
+import android.util.SparseArray;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.app.ChooserActivity;
+import com.android.internal.os.BackgroundThread;
+import com.android.internal.telephony.SmsApplication;
+import com.android.server.LocalServices;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Consumer;
+
+/**
+ * A class manages the lifecycle of the conversations and associated data, and exposes the methods
+ * to access the data in People Service and other system services.
+ */
+public class DataManager {
+
+    private static final String PLATFORM_PACKAGE_NAME = "android";
+    private static final int MY_UID = Process.myUid();
+    private static final int MY_PID = Process.myPid();
+    private static final long USAGE_STATS_QUERY_MAX_EVENT_AGE_MS = DateUtils.DAY_IN_MILLIS;
+    private static final long USAGE_STATS_QUERY_INTERVAL_SEC = 120L;
+
+    private final Context mContext;
+    private final Injector mInjector;
+    private final ScheduledExecutorService mUsageStatsQueryExecutor;
+
+    private final SparseArray<UserData> mUserDataArray = new SparseArray<>();
+    private final SparseArray<BroadcastReceiver> mBroadcastReceivers = new SparseArray<>();
+    private final SparseArray<ContentObserver> mContactsContentObservers = new SparseArray<>();
+    private final SparseArray<ScheduledFuture<?>> mUsageStatsQueryFutures = new SparseArray<>();
+    private final SparseArray<NotificationListenerService> mNotificationListeners =
+            new SparseArray<>();
+
+    private ShortcutServiceInternal mShortcutServiceInternal;
+    private UsageStatsManagerInternal mUsageStatsManagerInternal;
+    private ShortcutManager mShortcutManager;
+    private UserManager mUserManager;
+
+    public DataManager(Context context) {
+        mContext = context;
+        mInjector = new Injector();
+        mUsageStatsQueryExecutor = mInjector.createScheduledExecutor();
+    }
+
+    @VisibleForTesting
+    DataManager(Context context, Injector injector) {
+        mContext = context;
+        mInjector = injector;
+        mUsageStatsQueryExecutor = mInjector.createScheduledExecutor();
+    }
+
+    /** Initialization. Called when the system services are up running. */
+    public void initialize() {
+        mShortcutServiceInternal = LocalServices.getService(ShortcutServiceInternal.class);
+        mUsageStatsManagerInternal = LocalServices.getService(UsageStatsManagerInternal.class);
+        mShortcutManager = mContext.getSystemService(ShortcutManager.class);
+        mUserManager = mContext.getSystemService(UserManager.class);
+
+        mShortcutServiceInternal.addListener(new ShortcutServiceListener());
+    }
+
+    /** This method is called when a user is unlocked. */
+    public void onUserUnlocked(int userId) {
+        UserData userData = mUserDataArray.get(userId);
+        if (userData == null) {
+            userData = new UserData(userId);
+            mUserDataArray.put(userId, userData);
+        }
+        userData.setUserUnlocked();
+        updateDefaultDialer(userData);
+        updateDefaultSmsApp(userData);
+
+        ScheduledFuture<?> scheduledFuture = mUsageStatsQueryExecutor.scheduleAtFixedRate(
+                new UsageStatsQueryRunnable(userId), 1L, USAGE_STATS_QUERY_INTERVAL_SEC,
+                TimeUnit.SECONDS);
+        mUsageStatsQueryFutures.put(userId, scheduledFuture);
+
+        IntentFilter intentFilter = new IntentFilter();
+        intentFilter.addAction(TelecomManager.ACTION_DEFAULT_DIALER_CHANGED);
+        intentFilter.addAction(SmsApplication.ACTION_DEFAULT_SMS_PACKAGE_CHANGED_INTERNAL);
+        BroadcastReceiver broadcastReceiver = new PerUserBroadcastReceiver(userId);
+        mBroadcastReceivers.put(userId, broadcastReceiver);
+        mContext.registerReceiverAsUser(
+                broadcastReceiver, UserHandle.of(userId), intentFilter, null, null);
+
+        ContentObserver contactsContentObserver = new ContactsContentObserver(
+                BackgroundThread.getHandler());
+        mContactsContentObservers.put(userId, contactsContentObserver);
+        mContext.getContentResolver().registerContentObserver(
+                Contacts.CONTENT_URI, /* notifyForDescendants= */ true,
+                contactsContentObserver, userId);
+
+        NotificationListener notificationListener = new NotificationListener();
+        mNotificationListeners.put(userId, notificationListener);
+        try {
+            notificationListener.registerAsSystemService(mContext,
+                    new ComponentName(PLATFORM_PACKAGE_NAME, getClass().getSimpleName()),
+                    UserHandle.myUserId());
+        } catch (RemoteException e) {
+            // Should never occur for local calls.
+        }
+    }
+
+    /** This method is called when a user is stopped. */
+    public void onUserStopped(int userId) {
+        if (mUserDataArray.indexOfKey(userId) >= 0) {
+            mUserDataArray.get(userId).setUserStopped();
+        }
+        if (mUsageStatsQueryFutures.indexOfKey(userId) >= 0) {
+            mUsageStatsQueryFutures.valueAt(userId).cancel(true);
+        }
+        if (mBroadcastReceivers.indexOfKey(userId) >= 0) {
+            mContext.unregisterReceiver(mBroadcastReceivers.get(userId));
+        }
+        if (mContactsContentObservers.indexOfKey(userId) >= 0) {
+            mContext.getContentResolver().unregisterContentObserver(
+                    mContactsContentObservers.get(userId));
+        }
+        if (mNotificationListeners.indexOfKey(userId) >= 0) {
+            try {
+                mNotificationListeners.get(userId).unregisterAsSystemService();
+            } catch (RemoteException e) {
+                // Should never occur for local calls.
+            }
+        }
+    }
+
+    /**
+     * Iterates through all the {@link PackageData}s owned by the unlocked users who are in the
+     * same profile group as the calling user.
+     */
+    public void forAllPackages(Consumer<PackageData> consumer) {
+        List<UserInfo> users = mUserManager.getEnabledProfiles(mInjector.getCallingUserId());
+        for (UserInfo userInfo : users) {
+            UserData userData = getUnlockedUserData(userInfo.id);
+            if (userData != null) {
+                userData.forAllPackages(consumer);
+            }
+        }
+    }
+
+    /** Gets the {@link ShortcutInfo} for the given shortcut ID. */
+    @Nullable
+    public ShortcutInfo getShortcut(@NonNull String packageName, @UserIdInt int userId,
+            @NonNull String shortcutId) {
+        List<ShortcutInfo> shortcuts = getShortcuts(packageName, userId,
+                Collections.singletonList(shortcutId));
+        if (shortcuts != null && !shortcuts.isEmpty()) {
+            return shortcuts.get(0);
+        }
+        return null;
+    }
+
+    /**
+     * Gets the conversation {@link ShareShortcutInfo}s from all packages owned by the calling user
+     * that match the specified {@link IntentFilter}.
+     */
+    public List<ShareShortcutInfo> getConversationShareTargets(
+            @NonNull IntentFilter intentFilter) {
+        List<ShareShortcutInfo> shareShortcuts = mShortcutManager.getShareTargets(intentFilter);
+        List<ShareShortcutInfo> result = new ArrayList<>();
+        for (ShareShortcutInfo shareShortcut : shareShortcuts) {
+            ShortcutInfo si = shareShortcut.getShortcutInfo();
+            if (getConversationInfo(si.getPackage(), si.getUserId(), si.getId()) != null) {
+                result.add(shareShortcut);
+            }
+        }
+        return result;
+    }
+
+    /** Reports the {@link AppTargetEvent} from App Prediction Manager. */
+    public void reportAppTargetEvent(@NonNull AppTargetEvent event,
+            @Nullable IntentFilter intentFilter) {
+        AppTarget appTarget = event.getTarget();
+        ShortcutInfo shortcutInfo = appTarget != null ? appTarget.getShortcutInfo() : null;
+        if (shortcutInfo == null || event.getAction() != AppTargetEvent.ACTION_LAUNCH) {
+            return;
+        }
+        PackageData packageData = getPackageData(appTarget.getPackageName(),
+                appTarget.getUser().getIdentifier());
+        if (packageData == null) {
+            return;
+        }
+        if (ChooserActivity.LAUNCH_LOCATON_DIRECT_SHARE.equals(event.getLaunchLocation())) {
+            String mimeType = intentFilter != null ? intentFilter.getDataType(0) : null;
+            String shortcutId = shortcutInfo.getId();
+            if (packageData.getConversationStore().getConversation(shortcutId) == null
+                    || TextUtils.isEmpty(mimeType)) {
+                return;
+            }
+            EventHistoryImpl eventHistory =
+                    packageData.getEventStore().getOrCreateShortcutEventHistory(
+                            shortcutInfo.getId());
+            @Event.EventType int eventType;
+            if (mimeType.startsWith("text/")) {
+                eventType = Event.TYPE_SHARE_TEXT;
+            } else if (mimeType.startsWith("image/")) {
+                eventType = Event.TYPE_SHARE_IMAGE;
+            } else if (mimeType.startsWith("video/")) {
+                eventType = Event.TYPE_SHARE_VIDEO;
+            } else {
+                eventType = Event.TYPE_SHARE_OTHER;
+            }
+            eventHistory.addEvent(new Event(System.currentTimeMillis(), eventType));
+        }
+    }
+
+    /** Gets a list of {@link ShortcutInfo}s with the given shortcut IDs. */
+    private List<ShortcutInfo> getShortcuts(
+            @NonNull String packageName, @UserIdInt int userId,
+            @Nullable List<String> shortcutIds) {
+        @ShortcutQuery.QueryFlags int queryFlags = ShortcutQuery.FLAG_MATCH_DYNAMIC
+                | ShortcutQuery.FLAG_MATCH_PINNED | ShortcutQuery.FLAG_MATCH_PINNED_BY_ANY_LAUNCHER;
+        return mShortcutServiceInternal.getShortcuts(
+                mInjector.getCallingUserId(), /*callingPackage=*/ PLATFORM_PACKAGE_NAME,
+                /*changedSince=*/ 0, packageName, shortcutIds, /*componentName=*/ null, queryFlags,
+                userId, MY_PID, MY_UID);
+    }
+
+    @Nullable
+    private UserData getUnlockedUserData(int userId) {
+        UserData userData = mUserDataArray.get(userId);
+        return userData != null && userData.isUnlocked() ? userData : null;
+    }
+
+    @Nullable
+    private PackageData getPackageData(@NonNull String packageName, int userId) {
+        UserData userData = getUnlockedUserData(userId);
+        return userData != null ? userData.getPackageData(packageName) : null;
+    }
+
+    @Nullable
+    private ConversationInfo getConversationInfo(@NonNull String packageName, @UserIdInt int userId,
+            @NonNull String shortcutId) {
+        PackageData packageData = getPackageData(packageName, userId);
+        return packageData != null ? packageData.getConversationStore().getConversation(shortcutId)
+                : null;
+    }
+
+    private void updateDefaultDialer(@NonNull UserData userData) {
+        TelecomManager telecomManager = mContext.getSystemService(TelecomManager.class);
+        String defaultDialer = telecomManager != null
+                ? telecomManager.getDefaultDialerPackage(userData.getUserId()) : null;
+        userData.setDefaultDialer(defaultDialer);
+    }
+
+    private void updateDefaultSmsApp(@NonNull UserData userData) {
+        ComponentName component = SmsApplication.getDefaultSmsApplicationAsUser(
+                mContext, /* updateIfNeeded= */ false, userData.getUserId());
+        String defaultSmsApp = component != null ? component.getPackageName() : null;
+        userData.setDefaultSmsApp(defaultSmsApp);
+    }
+
+    @Nullable
+    private EventHistoryImpl getEventHistoryIfEligible(StatusBarNotification sbn) {
+        Notification notification = sbn.getNotification();
+        String shortcutId = notification.getShortcutId();
+        if (shortcutId == null) {
+            return null;
+        }
+        PackageData packageData = getPackageData(sbn.getPackageName(),
+                sbn.getUser().getIdentifier());
+        if (packageData == null
+                || packageData.getConversationStore().getConversation(shortcutId) == null) {
+            return null;
+        }
+        return packageData.getEventStore().getOrCreateShortcutEventHistory(shortcutId);
+    }
+
+    @VisibleForTesting
+    @WorkerThread
+    void onShortcutAddedOrUpdated(@NonNull ShortcutInfo shortcutInfo) {
+        if (shortcutInfo.getPersons() == null || shortcutInfo.getPersons().length == 0) {
+            return;
+        }
+        UserData userData = getUnlockedUserData(shortcutInfo.getUserId());
+        if (userData == null) {
+            return;
+        }
+        PackageData packageData = userData.getOrCreatePackageData(shortcutInfo.getPackage());
+        ConversationStore conversationStore = packageData.getConversationStore();
+        ConversationInfo oldConversationInfo =
+                conversationStore.getConversation(shortcutInfo.getId());
+        ConversationInfo.Builder builder = oldConversationInfo != null
+                ? new ConversationInfo.Builder(oldConversationInfo)
+                : new ConversationInfo.Builder();
+
+        builder.setShortcutId(shortcutInfo.getId());
+        builder.setLocusId(shortcutInfo.getLocusId());
+        builder.setShortcutFlags(shortcutInfo.getFlags());
+
+        Person person = shortcutInfo.getPersons()[0];
+        builder.setPersonImportant(person.isImportant());
+        builder.setPersonBot(person.isBot());
+        String contactUri = person.getUri();
+        if (contactUri != null) {
+            ContactsQueryHelper helper = mInjector.createContactsQueryHelper(mContext);
+            if (helper.query(contactUri)) {
+                builder.setContactUri(helper.getContactUri());
+                builder.setContactStarred(helper.isStarred());
+                builder.setContactPhoneNumber(helper.getPhoneNumber());
+            }
+        } else {
+            builder.setContactUri(null);
+            builder.setContactPhoneNumber(null);
+            builder.setContactStarred(false);
+        }
+
+        conversationStore.addOrUpdate(builder.build());
+    }
+
+    @VisibleForTesting
+    @WorkerThread
+    void queryUsageStatsService(@UserIdInt int userId, long currentTime, long lastQueryTime) {
+        UsageEvents usageEvents = mUsageStatsManagerInternal.queryEventsForUser(
+                userId, lastQueryTime, currentTime, false);
+        if (usageEvents == null) {
+            return;
+        }
+        while (usageEvents.hasNextEvent()) {
+            UsageEvents.Event e = new UsageEvents.Event();
+            usageEvents.getNextEvent(e);
+
+            String packageName = e.getPackageName();
+            PackageData packageData = getPackageData(packageName, userId);
+            if (packageData == null) {
+                continue;
+            }
+            if (e.getEventType() == UsageEvents.Event.SHORTCUT_INVOCATION) {
+                String shortcutId = e.getShortcutId();
+                if (packageData.getConversationStore().getConversation(shortcutId) != null) {
+                    EventHistoryImpl eventHistory =
+                            packageData.getEventStore().getOrCreateShortcutEventHistory(
+                                    shortcutId);
+                    eventHistory.addEvent(
+                            new Event(e.getTimeStamp(), Event.TYPE_SHORTCUT_INVOCATION));
+                }
+            }
+        }
+    }
+
+    @VisibleForTesting
+    ContentObserver getContactsContentObserverForTesting(@UserIdInt int userId) {
+        return mContactsContentObservers.get(userId);
+    }
+
+    @VisibleForTesting
+    NotificationListenerService getNotificationListenerServiceForTesting(@UserIdInt int userId) {
+        return mNotificationListeners.get(userId);
+    }
+
+    /** Observer that observes the changes in the Contacts database. */
+    private class ContactsContentObserver extends ContentObserver {
+
+        private long mLastUpdatedTimestamp;
+
+        private ContactsContentObserver(Handler handler) {
+            super(handler);
+            mLastUpdatedTimestamp = System.currentTimeMillis();
+        }
+
+        @Override
+        public void onChange(boolean selfChange, Uri uri, @UserIdInt int userId) {
+            ContactsQueryHelper helper = mInjector.createContactsQueryHelper(mContext);
+            if (!helper.querySince(mLastUpdatedTimestamp)) {
+                return;
+            }
+            Uri contactUri = helper.getContactUri();
+
+            final ConversationSelector conversationSelector = new ConversationSelector();
+            UserData userData = getUnlockedUserData(userId);
+            if (userData == null) {
+                return;
+            }
+            userData.forAllPackages(packageData -> {
+                ConversationInfo ci =
+                        packageData.getConversationStore().getConversationByContactUri(contactUri);
+                if (ci != null) {
+                    conversationSelector.mConversationStore =
+                            packageData.getConversationStore();
+                    conversationSelector.mConversationInfo = ci;
+                }
+            });
+            if (conversationSelector.mConversationInfo == null) {
+                return;
+            }
+
+            ConversationInfo.Builder builder =
+                    new ConversationInfo.Builder(conversationSelector.mConversationInfo);
+            builder.setContactStarred(helper.isStarred());
+            builder.setContactPhoneNumber(helper.getPhoneNumber());
+            conversationSelector.mConversationStore.addOrUpdate(builder.build());
+            mLastUpdatedTimestamp = helper.getLastUpdatedTimestamp();
+        }
+
+        private class ConversationSelector {
+            private ConversationStore mConversationStore = null;
+            private ConversationInfo mConversationInfo = null;
+        }
+    }
+
+    /** Listener for the shortcut data changes. */
+    private class ShortcutServiceListener implements
+            ShortcutServiceInternal.ShortcutChangeListener {
+
+        @Override
+        public void onShortcutChanged(@NonNull String packageName, int userId) {
+            BackgroundThread.getExecutor().execute(() -> {
+                List<ShortcutInfo> shortcuts = getShortcuts(packageName, userId,
+                        /*shortcutIds=*/ null);
+                for (ShortcutInfo shortcut : shortcuts) {
+                    onShortcutAddedOrUpdated(shortcut);
+                }
+            });
+        }
+    }
+
+    /** Listener for the notifications and their settings changes. */
+    private class NotificationListener extends NotificationListenerService {
+
+        @Override
+        public void onNotificationRemoved(StatusBarNotification sbn, RankingMap rankingMap,
+                int reason) {
+            if (reason != REASON_CLICK) {
+                return;
+            }
+            EventHistoryImpl eventHistory = getEventHistoryIfEligible(sbn);
+            if (eventHistory == null) {
+                return;
+            }
+            long currentTime = System.currentTimeMillis();
+            eventHistory.addEvent(new Event(currentTime, Event.TYPE_NOTIFICATION_OPENED));
+        }
+    }
+
+    /**
+     * A {@link Runnable} that queries the Usage Stats Service for recent events for a specified
+     * user.
+     */
+    private class UsageStatsQueryRunnable implements Runnable {
+
+        private final int mUserId;
+        private long mLastQueryTime;
+
+        private UsageStatsQueryRunnable(int userId) {
+            mUserId = userId;
+            mLastQueryTime = System.currentTimeMillis() - USAGE_STATS_QUERY_MAX_EVENT_AGE_MS;
+        }
+
+        @Override
+        public void run() {
+            long currentTime = System.currentTimeMillis();
+            queryUsageStatsService(mUserId, currentTime, mLastQueryTime);
+            mLastQueryTime = currentTime;
+        }
+    }
+
+    /** A {@link BroadcastReceiver} that receives the intents for a specified user. */
+    private class PerUserBroadcastReceiver extends BroadcastReceiver {
+
+        private final int mUserId;
+
+        private PerUserBroadcastReceiver(int userId) {
+            mUserId = userId;
+        }
+
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            UserData userData = getUnlockedUserData(mUserId);
+            if (userData == null) {
+                return;
+            }
+            if (TelecomManager.ACTION_DEFAULT_DIALER_CHANGED.equals(intent.getAction())) {
+                String defaultDialer = intent.getStringExtra(
+                        TelecomManager.EXTRA_CHANGE_DEFAULT_DIALER_PACKAGE_NAME);
+                userData.setDefaultDialer(defaultDialer);
+            } else if (SmsApplication.ACTION_DEFAULT_SMS_PACKAGE_CHANGED_INTERNAL.equals(
+                    intent.getAction())) {
+                updateDefaultSmsApp(userData);
+            }
+        }
+    }
+
+    @VisibleForTesting
+    static class Injector {
+
+        ScheduledExecutorService createScheduledExecutor() {
+            return Executors.newSingleThreadScheduledExecutor();
+        }
+
+        ContactsQueryHelper createContactsQueryHelper(Context context) {
+            return new ContactsQueryHelper(context);
+        }
+
+        int getCallingUserId() {
+            return Binder.getCallingUserHandle().getIdentifier();
+        }
+    }
+}
diff --git a/services/people/java/com/android/server/people/data/Event.java b/services/people/java/com/android/server/people/data/Event.java
new file mode 100644
index 0000000..c2364a2
--- /dev/null
+++ b/services/people/java/com/android/server/people/data/Event.java
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2020 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.people.data;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.text.format.DateFormat;
+import android.util.ArraySet;
+
+import com.android.internal.util.Preconditions;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Set;
+
+/** An event representing the interaction with a specific conversation or app. */
+public class Event {
+
+    public static final int TYPE_SHORTCUT_INVOCATION = 1;
+
+    public static final int TYPE_NOTIFICATION_POSTED = 2;
+
+    public static final int TYPE_NOTIFICATION_OPENED = 3;
+
+    public static final int TYPE_SHARE_TEXT = 4;
+
+    public static final int TYPE_SHARE_IMAGE = 5;
+
+    public static final int TYPE_SHARE_VIDEO = 6;
+
+    public static final int TYPE_SHARE_OTHER = 7;
+
+    public static final int TYPE_SMS_OUTGOING = 8;
+
+    public static final int TYPE_SMS_INCOMING = 9;
+
+    public static final int TYPE_CALL_OUTGOING = 10;
+
+    public static final int TYPE_CALL_INCOMING = 11;
+
+    public static final int TYPE_CALL_MISSED = 12;
+
+    @IntDef(prefix = { "TYPE_" }, value = {
+            TYPE_SHORTCUT_INVOCATION,
+            TYPE_NOTIFICATION_POSTED,
+            TYPE_NOTIFICATION_OPENED,
+            TYPE_SHARE_TEXT,
+            TYPE_SHARE_IMAGE,
+            TYPE_SHARE_VIDEO,
+            TYPE_SHARE_OTHER,
+            TYPE_SMS_OUTGOING,
+            TYPE_SMS_INCOMING,
+            TYPE_CALL_OUTGOING,
+            TYPE_CALL_INCOMING,
+            TYPE_CALL_MISSED,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface EventType {}
+
+    public static final Set<Integer> NOTIFICATION_EVENT_TYPES = new ArraySet<>();
+    public static final Set<Integer> SHARE_EVENT_TYPES = new ArraySet<>();
+    public static final Set<Integer> SMS_EVENT_TYPES = new ArraySet<>();
+    public static final Set<Integer> CALL_EVENT_TYPES = new ArraySet<>();
+    public static final Set<Integer> ALL_EVENT_TYPES = new ArraySet<>();
+
+    static {
+        NOTIFICATION_EVENT_TYPES.add(TYPE_NOTIFICATION_POSTED);
+        NOTIFICATION_EVENT_TYPES.add(TYPE_NOTIFICATION_OPENED);
+
+        SHARE_EVENT_TYPES.add(TYPE_SHARE_TEXT);
+        SHARE_EVENT_TYPES.add(TYPE_SHARE_IMAGE);
+        SHARE_EVENT_TYPES.add(TYPE_SHARE_VIDEO);
+        SHARE_EVENT_TYPES.add(TYPE_SHARE_OTHER);
+
+        SMS_EVENT_TYPES.add(TYPE_SMS_INCOMING);
+        SMS_EVENT_TYPES.add(TYPE_SMS_OUTGOING);
+
+        CALL_EVENT_TYPES.add(TYPE_CALL_INCOMING);
+        CALL_EVENT_TYPES.add(TYPE_CALL_OUTGOING);
+        CALL_EVENT_TYPES.add(TYPE_CALL_MISSED);
+
+        ALL_EVENT_TYPES.add(TYPE_SHORTCUT_INVOCATION);
+        ALL_EVENT_TYPES.addAll(NOTIFICATION_EVENT_TYPES);
+        ALL_EVENT_TYPES.addAll(SHARE_EVENT_TYPES);
+        ALL_EVENT_TYPES.addAll(SMS_EVENT_TYPES);
+        ALL_EVENT_TYPES.addAll(CALL_EVENT_TYPES);
+    }
+
+    private final long mTimestamp;
+
+    private final int mType;
+
+    private final CallDetails mCallDetails;
+
+    Event(long timestamp, @EventType int type) {
+        mTimestamp = timestamp;
+        mType = type;
+        mCallDetails = null;
+    }
+
+    private Event(@NonNull Builder builder) {
+        mTimestamp = builder.mTimestamp;
+        mType = builder.mType;
+        mCallDetails = builder.mCallDetails;
+    }
+
+    public long getTimestamp() {
+        return mTimestamp;
+    }
+
+    public @EventType int getType() {
+        return mType;
+    }
+
+    /**
+     * Gets the {@link CallDetails} of the event. It is only available if the event type is one of
+     * {@code CALL_EVENT_TYPES}, otherwise, it's always {@code null}.
+     */
+    @Nullable
+    public CallDetails getCallDetails() {
+        return mCallDetails;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("Event {");
+        sb.append("timestamp=").append(DateFormat.format("yyyy-MM-dd HH:mm:ss", mTimestamp));
+        sb.append(", type=").append(mType);
+        if (mCallDetails != null) {
+            sb.append(", callDetails=").append(mCallDetails);
+        }
+        sb.append("}");
+        return sb.toString();
+    }
+
+    /** Type-specific details of a call event. */
+    public static class CallDetails {
+
+        private final long mDurationSeconds;
+
+        CallDetails(long durationSeconds) {
+            mDurationSeconds = durationSeconds;
+        }
+
+        public long getDurationSeconds() {
+            return mDurationSeconds;
+        }
+
+        @Override
+        public String toString() {
+            return "CallDetails {durationSeconds=" + mDurationSeconds + "}";
+        }
+    }
+
+    /** Builder class for {@link Event} objects. */
+    static class Builder {
+
+        private final long mTimestamp;
+
+        private final int mType;
+
+        private CallDetails mCallDetails;
+
+        Builder(long timestamp, @EventType int type) {
+            mTimestamp = timestamp;
+            mType = type;
+        }
+
+        Builder setCallDetails(CallDetails callDetails) {
+            Preconditions.checkArgument(CALL_EVENT_TYPES.contains(mType));
+            mCallDetails = callDetails;
+            return this;
+        }
+
+        Event build() {
+            return new Event(this);
+        }
+    }
+}
diff --git a/services/people/java/com/android/server/people/data/EventHistory.java b/services/people/java/com/android/server/people/data/EventHistory.java
new file mode 100644
index 0000000..5b11fd0
--- /dev/null
+++ b/services/people/java/com/android/server/people/data/EventHistory.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2020 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.people.data;
+
+import android.annotation.NonNull;
+
+import java.util.List;
+import java.util.Set;
+
+/** The interface for querying the event time distribution and details. */
+public interface EventHistory {
+
+    /** Gets the {@link EventIndex} for the specified event type. */
+    @NonNull
+    EventIndex getEventIndex(@Event.EventType int eventType);
+
+    /** Gets the combined {@link EventIndex} for a set of event types. */
+    @NonNull
+    EventIndex getEventIndex(Set<Integer> eventTypes);
+
+    /**
+     * Returns a {@link List} of {@link Event}s those timestamps are between the specified {@code
+     * fromTimestamp}, inclusive, and {@code toTimestamp} exclusive, and match the specified event
+     * types.
+     *
+     * @return a list of matched events in chronological order.
+     */
+    @NonNull
+    List<Event> queryEvents(Set<Integer> eventTypes, long fromTimestamp, long toTimestamp);
+}
diff --git a/services/people/java/com/android/server/people/data/EventHistoryImpl.java b/services/people/java/com/android/server/people/data/EventHistoryImpl.java
new file mode 100644
index 0000000..6b6bd7e
--- /dev/null
+++ b/services/people/java/com/android/server/people/data/EventHistoryImpl.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2020 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.people.data;
+
+import android.annotation.NonNull;
+import android.util.SparseArray;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.List;
+import java.util.Set;
+
+class EventHistoryImpl implements EventHistory {
+
+    private final Injector mInjector;
+
+    // Event Type -> Event Index
+    private final SparseArray<EventIndex> mEventIndexArray = new SparseArray<>();
+
+    private final EventList mRecentEvents = new EventList();
+
+    EventHistoryImpl() {
+        mInjector = new Injector();
+    }
+
+    @VisibleForTesting
+    EventHistoryImpl(Injector injector) {
+        mInjector = injector;
+    }
+
+    @Override
+    @NonNull
+    public EventIndex getEventIndex(@Event.EventType int eventType) {
+        EventIndex eventIndex = mEventIndexArray.get(eventType);
+        return eventIndex != null ? new EventIndex(eventIndex) : mInjector.createEventIndex();
+    }
+
+    @Override
+    @NonNull
+    public EventIndex getEventIndex(Set<Integer> eventTypes) {
+        EventIndex combined = mInjector.createEventIndex();
+        for (@Event.EventType int eventType : eventTypes) {
+            EventIndex eventIndex = mEventIndexArray.get(eventType);
+            if (eventIndex != null) {
+                combined = EventIndex.combine(combined, eventIndex);
+            }
+        }
+        return combined;
+    }
+
+    @Override
+    @NonNull
+    public List<Event> queryEvents(Set<Integer> eventTypes, long startTime, long endTime) {
+        return mRecentEvents.queryEvents(eventTypes, startTime, endTime);
+    }
+
+    void addEvent(Event event) {
+        EventIndex eventIndex = mEventIndexArray.get(event.getType());
+        if (eventIndex == null) {
+            eventIndex = mInjector.createEventIndex();
+            mEventIndexArray.put(event.getType(), eventIndex);
+        }
+        eventIndex.addEvent(event.getTimestamp());
+        mRecentEvents.add(event);
+    }
+
+    @VisibleForTesting
+    static class Injector {
+
+        EventIndex createEventIndex() {
+            return new EventIndex();
+        }
+    }
+}
diff --git a/services/people/java/com/android/server/people/data/EventIndex.java b/services/people/java/com/android/server/people/data/EventIndex.java
new file mode 100644
index 0000000..b74a3fa
--- /dev/null
+++ b/services/people/java/com/android/server/people/data/EventIndex.java
@@ -0,0 +1,377 @@
+/*
+ * Copyright (C) 2020 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.people.data;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.text.format.DateFormat;
+import android.util.Range;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.time.temporal.ChronoUnit;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.TimeZone;
+import java.util.function.Function;
+
+/**
+ * The index of {@link Event}s. It is used for quickly looking up the time distribution of
+ * {@link Event}s based on {@code Event#getTimestamp()}.
+ *
+ * <p>The 64-bits {code long} is used as the bitmap index. Each bit is to denote whether there are
+ * any events in a specified time slot. The least significant bit is for the most recent time slot.
+ * And the most significant bit is for the oldest time slot.
+ *
+ * <p>Multiple {code long}s are used to index the events in different time grains. For the recent
+ * events, the fine-grained bitmap index can provide the narrower time range. For the older events,
+ * the coarse-grained bitmap index can cover longer period but can only provide wider time range.
+ *
+ * <p>E.g. the below chart shows how the bitmap indexes index the events in the past 24 hours:
+ * <pre>
+ * 2020/1/3                                                             2020/1/4
+ *   0:00        4:00        8:00       12:00       16:00       20:00        0:00
+ *  --+-----------------------------------------------------------------------+-  1 day per bit
+ *  --+-----------+-----------+-----------+-----------+-----------+-----------+-  4 hours per bit
+ *  --+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+-  1 hour per bit
+ *                                                                     +++++++++  2 minutes per bit
+ *  </pre>
+ */
+public class EventIndex {
+
+    private static final int LONG_SIZE_BITS = 64;
+
+    private static final int TIME_SLOT_ONE_DAY = 0;
+
+    private static final int TIME_SLOT_FOUR_HOURS = 1;
+
+    private static final int TIME_SLOT_ONE_HOUR = 2;
+
+    private static final int TIME_SLOT_TWO_MINUTES = 3;
+
+    @IntDef(prefix = {"TIME_SLOT_"}, value = {
+            TIME_SLOT_ONE_DAY,
+            TIME_SLOT_FOUR_HOURS,
+            TIME_SLOT_ONE_HOUR,
+            TIME_SLOT_TWO_MINUTES,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    private @interface TimeSlotType {
+    }
+
+    private static final int TIME_SLOT_TYPES_COUNT = 4;
+
+    static final EventIndex EMPTY = new EventIndex();
+
+    private static final List<Function<Long, Range<Long>>> TIME_SLOT_FACTORIES =
+            Collections.unmodifiableList(
+                    Arrays.asList(
+                            EventIndex::createOneDayLongTimeSlot,
+                            EventIndex::createFourHoursLongTimeSlot,
+                            EventIndex::createOneHourLongTimeSlot,
+                            EventIndex::createTwoMinutesLongTimeSlot
+                    )
+            );
+
+    /** Combines the two {@link EventIndex} objects and returns the combined result. */
+    static EventIndex combine(EventIndex lhs, EventIndex rhs) {
+        EventIndex older = lhs.mLastUpdatedTime < rhs.mLastUpdatedTime ? lhs : rhs;
+        EventIndex younger = lhs.mLastUpdatedTime >= rhs.mLastUpdatedTime ? lhs : rhs;
+
+        EventIndex combined = new EventIndex(older);
+        combined.updateEventBitmaps(younger.mLastUpdatedTime);
+
+        for (int slotType = 0; slotType < TIME_SLOT_TYPES_COUNT; slotType++) {
+            combined.mEventBitmaps[slotType] |= younger.mEventBitmaps[slotType];
+        }
+        return combined;
+    }
+
+    private final long[] mEventBitmaps;
+
+    private long mLastUpdatedTime;
+
+    private final Object mLock = new Object();
+
+    private final Injector mInjector;
+
+    EventIndex() {
+        mInjector = new Injector();
+        mEventBitmaps = new long[]{0L, 0L, 0L, 0L};
+        mLastUpdatedTime = mInjector.currentTimeMillis();
+    }
+
+    EventIndex(EventIndex from) {
+        mInjector = new Injector();
+        mEventBitmaps = Arrays.copyOf(from.mEventBitmaps, TIME_SLOT_TYPES_COUNT);
+        mLastUpdatedTime = from.mLastUpdatedTime;
+    }
+
+    @VisibleForTesting
+    EventIndex(Injector injector) {
+        mInjector = injector;
+        mEventBitmaps = new long[]{0L, 0L, 0L, 0L};
+        mLastUpdatedTime = mInjector.currentTimeMillis();
+    }
+
+    /**
+     * Gets the most recent active time slot. A time slot is active if there is at least one event
+     * occurred in that time slot.
+     */
+    @Nullable
+    public Range<Long> getMostRecentActiveTimeSlot() {
+        synchronized (mLock) {
+            for (int slotType = TIME_SLOT_TYPES_COUNT - 1; slotType >= 0; slotType--) {
+                if (mEventBitmaps[slotType] == 0L) {
+                    continue;
+                }
+                Range<Long> lastTimeSlot =
+                        TIME_SLOT_FACTORIES.get(slotType).apply(mLastUpdatedTime);
+                int numberOfTrailingZeros = Long.numberOfTrailingZeros(mEventBitmaps[slotType]);
+                long offset = getDuration(lastTimeSlot) * numberOfTrailingZeros;
+                return Range.create(lastTimeSlot.getLower() - offset,
+                        lastTimeSlot.getUpper() - offset);
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Gets the active time slots. A time slot is active if there is at least one event occurred
+     * in that time slot.
+     *
+     * @return active time slots in chronological order.
+     */
+    @NonNull
+    public List<Range<Long>> getActiveTimeSlots() {
+        List<Range<Long>> activeTimeSlots = new ArrayList<>();
+        synchronized (mLock) {
+            for (int slotType = 0; slotType < TIME_SLOT_TYPES_COUNT; slotType++) {
+                activeTimeSlots = combineTimeSlotLists(activeTimeSlots,
+                        getActiveTimeSlotsForType(slotType));
+            }
+        }
+        Collections.reverse(activeTimeSlots);
+        return activeTimeSlots;
+    }
+
+    /** Returns whether this {@link EventIndex} instance is empty. */
+    public boolean isEmpty() {
+        synchronized (mLock) {
+            for (int slotType = 0; slotType < TIME_SLOT_TYPES_COUNT; slotType++) {
+                if (mEventBitmaps[slotType] != 0L) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Adds an event to this index with the given event time. Before the new event is recorded, the
+     * index is updated first with the current timestamp.
+     */
+    void addEvent(long eventTime) {
+        if (EMPTY == this) {
+            throw new IllegalStateException("EMPTY instance is immutable");
+        }
+        synchronized (mLock) {
+            long currentTime = mInjector.currentTimeMillis();
+            updateEventBitmaps(currentTime);
+            for (int slotType = 0; slotType < TIME_SLOT_TYPES_COUNT; slotType++) {
+                int offset = diffTimeSlots(slotType, eventTime, currentTime);
+                if (offset < LONG_SIZE_BITS) {
+                    mEventBitmaps[slotType] |= (1L << offset);
+                }
+            }
+        }
+    }
+
+    /** Updates to make all bitmaps up to date. */
+    void update() {
+        updateEventBitmaps(mInjector.currentTimeMillis());
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("EventIndex {");
+        sb.append("perDayEventBitmap=0b");
+        sb.append(Long.toBinaryString(mEventBitmaps[TIME_SLOT_ONE_DAY]));
+        sb.append(", perFourHoursEventBitmap=0b");
+        sb.append(Long.toBinaryString(mEventBitmaps[TIME_SLOT_FOUR_HOURS]));
+        sb.append(", perHourEventBitmap=0b");
+        sb.append(Long.toBinaryString(mEventBitmaps[TIME_SLOT_ONE_HOUR]));
+        sb.append(", perTwoMinutesEventBitmap=0b");
+        sb.append(Long.toBinaryString(mEventBitmaps[TIME_SLOT_TWO_MINUTES]));
+        sb.append(", lastUpdatedTime=");
+        sb.append(DateFormat.format("yyyy-MM-dd HH:mm:ss", mLastUpdatedTime));
+        sb.append("}");
+        return sb.toString();
+    }
+
+    /** Shifts the event bitmaps to make them up-to-date. */
+    private void updateEventBitmaps(long currentTimeMillis) {
+        for (int slotType = 0; slotType < TIME_SLOT_TYPES_COUNT; slotType++) {
+            int offset = diffTimeSlots(slotType, mLastUpdatedTime, currentTimeMillis);
+            if (offset < LONG_SIZE_BITS) {
+                mEventBitmaps[slotType] <<= offset;
+            } else {
+                mEventBitmaps[slotType] = 0L;
+            }
+        }
+        mLastUpdatedTime = currentTimeMillis;
+    }
+
+    private static LocalDateTime toLocalDateTime(long epochMilli) {
+        return LocalDateTime.ofInstant(
+                Instant.ofEpochMilli(epochMilli), TimeZone.getDefault().toZoneId());
+    }
+
+    private static long toEpochMilli(LocalDateTime localDateTime) {
+        return localDateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
+    }
+
+    private static long getDuration(Range<Long> timeSlot) {
+        return timeSlot.getUpper() - timeSlot.getLower();
+    }
+
+    /**
+     * Finds the time slots for the given two timestamps and returns the distance (in the number
+     * of time slots) between these two time slots.
+     */
+    private static int diffTimeSlots(@TimeSlotType int timeSlotType, long fromTime, long toTime) {
+        Function<Long, Range<Long>> timeSlotFactory = TIME_SLOT_FACTORIES.get(timeSlotType);
+        Range<Long> fromSlot = timeSlotFactory.apply(fromTime);
+        Range<Long> toSlot = timeSlotFactory.apply(toTime);
+        return (int) ((toSlot.getLower() - fromSlot.getLower()) / getDuration(fromSlot));
+    }
+
+    /**
+     * Returns the active time slots for a specified type. The returned time slots are in
+     * reverse-chronological order.
+     */
+    private List<Range<Long>> getActiveTimeSlotsForType(@TimeSlotType int timeSlotType) {
+        long eventBitmap = mEventBitmaps[timeSlotType];
+        Range<Long> latestTimeSlot = TIME_SLOT_FACTORIES.get(timeSlotType).apply(mLastUpdatedTime);
+        long startTime = latestTimeSlot.getLower();
+        final long duration = getDuration(latestTimeSlot);
+        List<Range<Long>> timeSlots = new ArrayList<>();
+        while (eventBitmap != 0) {
+            int trailingZeros = Long.numberOfTrailingZeros(eventBitmap);
+            if (trailingZeros > 0) {
+                startTime -= duration * trailingZeros;
+                eventBitmap >>>= trailingZeros;
+            }
+            if (eventBitmap != 0) {
+                timeSlots.add(Range.create(startTime, startTime + duration));
+                startTime -= duration;
+                eventBitmap >>>= 1;
+            }
+        }
+        return timeSlots;
+    }
+
+    /**
+     * Combines two lists of time slots into one. If one longer time slot covers one or multiple
+     * shorter time slots, the smaller time slot(s) will be added to the result and the longer one
+     * will be dropped. This ensures the returned list does not contain any overlapping time slots.
+     */
+    private static List<Range<Long>> combineTimeSlotLists(List<Range<Long>> longerSlots,
+            List<Range<Long>> shorterSlots) {
+        List<Range<Long>> result = new ArrayList<>();
+        int i = 0;
+        int j = 0;
+        while (i < longerSlots.size() && j < shorterSlots.size()) {
+            Range<Long> longerSlot = longerSlots.get(i);
+            Range<Long> shorterSlot = shorterSlots.get(j);
+            if (longerSlot.contains(shorterSlot)) {
+                result.add(shorterSlot);
+                i++;
+                j++;
+            } else if (longerSlot.getLower() < shorterSlot.getLower()) {
+                result.add(shorterSlot);
+                j++;
+            } else {
+                result.add(longerSlot);
+                i++;
+            }
+        }
+        if (i < longerSlots.size()) {
+            result.addAll(longerSlots.subList(i, longerSlots.size()));
+        } else if (j < shorterSlots.size()) {
+            result.addAll(shorterSlots.subList(j, shorterSlots.size()));
+        }
+        return result;
+    }
+
+    /**
+     * Finds and creates the time slot (duration = 1 day) that the given time falls into.
+     */
+    @NonNull
+    private static Range<Long> createOneDayLongTimeSlot(long time) {
+        LocalDateTime beginTime = toLocalDateTime(time).truncatedTo(ChronoUnit.DAYS);
+        return Range.create(toEpochMilli(beginTime), toEpochMilli(beginTime.plusDays(1)));
+    }
+
+    /**
+     * Finds and creates the time slot (duration = 4 hours) that the given time falls into.
+     */
+    @NonNull
+    private static Range<Long> createFourHoursLongTimeSlot(long time) {
+        int hourOfDay = toLocalDateTime(time).getHour();
+        LocalDateTime beginTime =
+                toLocalDateTime(time).truncatedTo(ChronoUnit.HOURS).minusHours(hourOfDay % 4);
+        return Range.create(toEpochMilli(beginTime), toEpochMilli(beginTime.plusHours(4)));
+    }
+
+    /**
+     * Finds and creates the time slot (duration = 1 hour) that the given time falls into.
+     */
+    @NonNull
+    private static Range<Long> createOneHourLongTimeSlot(long time) {
+        LocalDateTime beginTime = toLocalDateTime(time).truncatedTo(ChronoUnit.HOURS);
+        return Range.create(toEpochMilli(beginTime), toEpochMilli(beginTime.plusHours(1)));
+    }
+
+    /**
+     * Finds and creates the time slot (duration = 2 minutes) that the given time falls into.
+     */
+    @NonNull
+    private static Range<Long> createTwoMinutesLongTimeSlot(long time) {
+        int minuteOfHour = toLocalDateTime(time).getMinute();
+        LocalDateTime beginTime = toLocalDateTime(time).truncatedTo(
+                ChronoUnit.MINUTES).minusMinutes(minuteOfHour % 2);
+        return Range.create(toEpochMilli(beginTime), toEpochMilli(beginTime.plusMinutes(2)));
+    }
+
+    @VisibleForTesting
+    static class Injector {
+        /** This should be the only way to get the current timestamp in {@code EventIndex}. */
+        long currentTimeMillis() {
+            return System.currentTimeMillis();
+        }
+    }
+}
diff --git a/services/people/java/com/android/server/people/data/EventList.java b/services/people/java/com/android/server/people/data/EventList.java
new file mode 100644
index 0000000..b267d66
--- /dev/null
+++ b/services/people/java/com/android/server/people/data/EventList.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2020 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.people.data;
+
+import android.annotation.NonNull;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+/** A container that holds a list of {@link Event}s in chronological order. */
+class EventList {
+
+    private final List<Event> mEvents = new ArrayList<>();
+
+    /**
+     * Adds an event to the list unless there is an existing event with the same timestamp and
+     * type.
+     */
+    void add(@NonNull Event event) {
+        int index = firstIndexOnOrAfter(event.getTimestamp());
+        if (index < mEvents.size()
+                && mEvents.get(index).getTimestamp() == event.getTimestamp()
+                && isDuplicate(event, index)) {
+            return;
+        }
+        mEvents.add(index, event);
+    }
+
+    /**
+     * Returns a {@link List} of {@link Event}s whose timestamps are between the specified {@code
+     * fromTimestamp}, inclusive, and {@code toTimestamp} exclusive, and match the specified event
+     * types.
+     *
+     * @return a {@link List} of matched {@link Event}s in chronological order.
+     */
+    @NonNull
+    List<Event> queryEvents(@NonNull Set<Integer> eventTypes, long fromTimestamp,
+            long toTimestamp) {
+        int fromIndex = firstIndexOnOrAfter(fromTimestamp);
+        if (fromIndex == mEvents.size()) {
+            return new ArrayList<>();
+        }
+        int toIndex = firstIndexOnOrAfter(toTimestamp);
+        if (toIndex < fromIndex) {
+            return new ArrayList<>();
+        }
+        List<Event> result = new ArrayList<>();
+        for (int i = fromIndex; i < toIndex; i++) {
+            Event e = mEvents.get(i);
+            if (eventTypes.contains(e.getType())) {
+                result.add(e);
+            }
+        }
+        return result;
+    }
+
+    /** Returns the first index whose timestamp is greater or equal to the provided timestamp. */
+    private int firstIndexOnOrAfter(long timestamp) {
+        int result = mEvents.size();
+        int low = 0;
+        int high = mEvents.size() - 1;
+        while (low <= high) {
+            int mid = (low + high) >>> 1;
+            if (mEvents.get(mid).getTimestamp() >= timestamp) {
+                high = mid - 1;
+                result = mid;
+            } else {
+                low = mid + 1;
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Checks whether the {@link Event} is duplicate with one of the existing events. The checking
+     * starts from the {@code startIndex}.
+     */
+    private boolean isDuplicate(Event event, int startIndex) {
+        int size = mEvents.size();
+        int index = startIndex;
+        while (index < size && mEvents.get(index).getTimestamp() <= event.getTimestamp()) {
+            if (mEvents.get(index++).getType() == event.getType()) {
+                return true;
+            }
+        }
+        return false;
+    }
+}
diff --git a/services/people/java/com/android/server/people/data/EventStore.java b/services/people/java/com/android/server/people/data/EventStore.java
new file mode 100644
index 0000000..d6b7a86
--- /dev/null
+++ b/services/people/java/com/android/server/people/data/EventStore.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2020 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.people.data;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.LocusId;
+import android.util.ArrayMap;
+
+import java.util.Map;
+
+/** The store that stores and accesses the events data for a package. */
+class EventStore {
+
+    private final EventHistoryImpl mPackageEventHistory = new EventHistoryImpl();
+
+    // Shortcut ID -> Event History
+    private final Map<String, EventHistoryImpl> mShortcutEventHistoryMap = new ArrayMap<>();
+
+    // Locus ID -> Event History
+    private final Map<LocusId, EventHistoryImpl> mLocusEventHistoryMap = new ArrayMap<>();
+
+    // Phone Number -> Event History
+    private final Map<String, EventHistoryImpl> mCallEventHistoryMap = new ArrayMap<>();
+
+    // Phone Number -> Event History
+    private final Map<String, EventHistoryImpl> mSmsEventHistoryMap = new ArrayMap<>();
+
+    /** Gets the package level {@link EventHistory}. */
+    @NonNull
+    EventHistory getPackageEventHistory() {
+        return mPackageEventHistory;
+    }
+
+    /** Gets the {@link EventHistory} for the specified {@code shortcutId} if exists. */
+    @Nullable
+    EventHistory getShortcutEventHistory(String shortcutId) {
+        return mShortcutEventHistoryMap.get(shortcutId);
+    }
+
+    /** Gets the {@link EventHistory} for the specified {@code locusId} if exists. */
+    @Nullable
+    EventHistory getLocusEventHistory(LocusId locusId) {
+        return mLocusEventHistoryMap.get(locusId);
+    }
+
+    /** Gets the phone call {@link EventHistory} for the specified {@code phoneNumber} if exists. */
+    @Nullable
+    EventHistory getCallEventHistory(String phoneNumber) {
+        return mCallEventHistoryMap.get(phoneNumber);
+    }
+
+    /** Gets the SMS {@link EventHistory} for the specified {@code phoneNumber} if exists. */
+    @Nullable
+    EventHistory getSmsEventHistory(String phoneNumber) {
+        return mSmsEventHistoryMap.get(phoneNumber);
+    }
+
+    /**
+     * Gets the {@link EventHistoryImpl} for the specified {@code shortcutId} or creates a new
+     * instance and put it into the store if not exists. The caller needs to verify if a
+     * conversation with this shortcut ID exists before calling this method.
+     */
+    @NonNull
+    EventHistoryImpl getOrCreateShortcutEventHistory(String shortcutId) {
+        return mShortcutEventHistoryMap.computeIfAbsent(shortcutId, key -> new EventHistoryImpl());
+    }
+
+    /**
+     * Gets the {@link EventHistoryImpl} for the specified {@code locusId} or creates a new
+     * instance and put it into the store if not exists. The caller needs to ensure a conversation
+     * with this locus ID exists before calling this method.
+     */
+    @NonNull
+    EventHistoryImpl getOrCreateLocusEventHistory(LocusId locusId) {
+        return mLocusEventHistoryMap.computeIfAbsent(locusId, key -> new EventHistoryImpl());
+    }
+
+    /**
+     * Gets the {@link EventHistoryImpl} for the specified {@code phoneNumber} for call events
+     * or creates a new instance and put it into the store if not exists. The caller needs to ensure
+     * a conversation with this phone number exists and this package is the default dialer
+     * before calling this method.
+     */
+    @NonNull
+    EventHistoryImpl getOrCreateCallEventHistory(String phoneNumber) {
+        return mCallEventHistoryMap.computeIfAbsent(phoneNumber, key -> new EventHistoryImpl());
+    }
+
+    /**
+     * Gets the {@link EventHistoryImpl} for the specified {@code phoneNumber} for SMS events
+     * or creates a new instance and put it into the store if not exists. The caller needs to ensure
+     * a conversation with this phone number exists and this package is the default SMS app
+     * before calling this method.
+     */
+    @NonNull
+    EventHistoryImpl getOrCreateSmsEventHistory(String phoneNumber) {
+        return mSmsEventHistoryMap.computeIfAbsent(phoneNumber, key -> new EventHistoryImpl());
+    }
+}
diff --git a/services/people/java/com/android/server/people/data/PackageData.java b/services/people/java/com/android/server/people/data/PackageData.java
new file mode 100644
index 0000000..9c22a7f
--- /dev/null
+++ b/services/people/java/com/android/server/people/data/PackageData.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2020 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.people.data;
+
+import android.annotation.NonNull;
+import android.annotation.UserIdInt;
+import android.content.LocusId;
+import android.text.TextUtils;
+
+import java.util.function.Consumer;
+
+/** The data associated with a package. */
+public class PackageData {
+
+    @NonNull
+    private final String mPackageName;
+
+    private final @UserIdInt int mUserId;
+
+    @NonNull
+    private final ConversationStore mConversationStore;
+
+    @NonNull
+    private final EventStore mEventStore;
+
+    private boolean mIsDefaultDialer;
+
+    private boolean mIsDefaultSmsApp;
+
+    PackageData(@NonNull String packageName, @UserIdInt int userId) {
+        mPackageName = packageName;
+        mUserId = userId;
+        mConversationStore = new ConversationStore();
+        mEventStore = new EventStore();
+    }
+
+    @NonNull
+    public String getPackageName() {
+        return mPackageName;
+    }
+
+    public @UserIdInt int getUserId() {
+        return mUserId;
+    }
+
+    /** Iterates over all the conversations in this package. */
+    public void forAllConversations(@NonNull Consumer<ConversationInfo> consumer) {
+        mConversationStore.forAllConversations(consumer);
+    }
+
+    @NonNull
+    public EventHistory getPackageLevelEventHistory() {
+        return getEventStore().getPackageEventHistory();
+    }
+
+    /**
+     * Gets the combined {@link EventHistory} for a given shortcut ID. This returned {@link
+     * EventHistory} has events of all types, no matter whether they're annotated with shortcut ID,
+     * Locus ID, or phone number etc.
+     */
+    @NonNull
+    public EventHistory getEventHistory(@NonNull String shortcutId) {
+        AggregateEventHistoryImpl result = new AggregateEventHistoryImpl();
+
+        ConversationInfo conversationInfo = mConversationStore.getConversation(shortcutId);
+        if (conversationInfo == null) {
+            return result;
+        }
+
+        EventHistory shortcutEventHistory = getEventStore().getShortcutEventHistory(shortcutId);
+        if (shortcutEventHistory != null) {
+            result.addEventHistory(shortcutEventHistory);
+        }
+
+        LocusId locusId = conversationInfo.getLocusId();
+        if (locusId != null) {
+            EventHistory locusEventHistory = getEventStore().getLocusEventHistory(locusId);
+            if (locusEventHistory != null) {
+                result.addEventHistory(locusEventHistory);
+            }
+        }
+
+        String phoneNumber = conversationInfo.getContactPhoneNumber();
+        if (TextUtils.isEmpty(phoneNumber)) {
+            return result;
+        }
+        if (isDefaultDialer()) {
+            EventHistory callEventHistory = getEventStore().getCallEventHistory(phoneNumber);
+            if (callEventHistory != null) {
+                result.addEventHistory(callEventHistory);
+            }
+        }
+        if (isDefaultSmsApp()) {
+            EventHistory smsEventHistory = getEventStore().getSmsEventHistory(phoneNumber);
+            if (smsEventHistory != null) {
+                result.addEventHistory(smsEventHistory);
+            }
+        }
+        return result;
+    }
+
+    public boolean isDefaultDialer() {
+        return mIsDefaultDialer;
+    }
+
+    public boolean isDefaultSmsApp() {
+        return mIsDefaultSmsApp;
+    }
+
+    @NonNull
+    ConversationStore getConversationStore() {
+        return mConversationStore;
+    }
+
+    @NonNull
+    EventStore getEventStore() {
+        return mEventStore;
+    }
+
+    void setIsDefaultDialer(boolean value) {
+        mIsDefaultDialer = value;
+    }
+
+    void setIsDefaultSmsApp(boolean value) {
+        mIsDefaultSmsApp = value;
+    }
+
+    void onDestroy() {
+        // TODO: STOPSHIP: Implements this method for the case of package being uninstalled.
+    }
+}
diff --git a/services/people/java/com/android/server/people/data/UserData.java b/services/people/java/com/android/server/people/data/UserData.java
new file mode 100644
index 0000000..2c16059
--- /dev/null
+++ b/services/people/java/com/android/server/people/data/UserData.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2020 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.people.data;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.UserIdInt;
+import android.text.TextUtils;
+import android.util.ArrayMap;
+
+import java.util.Map;
+import java.util.function.Consumer;
+
+/** The data associated with a user profile. */
+class UserData {
+
+    private final @UserIdInt int mUserId;
+
+    private boolean mIsUnlocked;
+
+    private Map<String, PackageData> mPackageDataMap = new ArrayMap<>();
+
+    UserData(@UserIdInt int userId) {
+        mUserId = userId;
+    }
+
+    @UserIdInt int getUserId() {
+        return mUserId;
+    }
+
+    void forAllPackages(@NonNull Consumer<PackageData> consumer) {
+        for (PackageData packageData : mPackageDataMap.values()) {
+            consumer.accept(packageData);
+        }
+    }
+
+    void setUserUnlocked() {
+        mIsUnlocked = true;
+    }
+
+    void setUserStopped() {
+        mIsUnlocked = false;
+    }
+
+    boolean isUnlocked() {
+        return mIsUnlocked;
+    }
+
+    /**
+     * Gets the {@link PackageData} for the specified {@code packageName} if exists; otherwise
+     * creates a new instance and returns it.
+     */
+    @NonNull
+    PackageData getOrCreatePackageData(String packageName) {
+        return mPackageDataMap.computeIfAbsent(
+                packageName, key -> new PackageData(packageName, mUserId));
+    }
+
+    /**
+     * Gets the {@link PackageData} for the specified {@code packageName} if exists; otherwise
+     * returns {@code null}.
+     */
+    @Nullable
+    PackageData getPackageData(@NonNull String packageName) {
+        return mPackageDataMap.get(packageName);
+    }
+
+    void setDefaultDialer(@Nullable String packageName) {
+        for (PackageData packageData : mPackageDataMap.values()) {
+            if (packageData.isDefaultDialer()) {
+                packageData.setIsDefaultDialer(false);
+            }
+            if (TextUtils.equals(packageName, packageData.getPackageName())) {
+                packageData.setIsDefaultDialer(true);
+            }
+        }
+    }
+
+    void setDefaultSmsApp(@Nullable String packageName) {
+        for (PackageData packageData : mPackageDataMap.values()) {
+            if (packageData.isDefaultSmsApp()) {
+                packageData.setIsDefaultSmsApp(false);
+            }
+            if (TextUtils.equals(packageName, packageData.getPackageName())) {
+                packageData.setIsDefaultSmsApp(true);
+            }
+        }
+    }
+}
diff --git a/services/people/java/com/android/server/people/prediction/ConversationData.java b/services/people/java/com/android/server/people/prediction/ConversationData.java
new file mode 100644
index 0000000..0cc7633
--- /dev/null
+++ b/services/people/java/com/android/server/people/prediction/ConversationData.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2020 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.people.prediction;
+
+import android.annotation.NonNull;
+
+import com.android.server.people.data.ConversationInfo;
+import com.android.server.people.data.EventHistory;
+
+/** The conversation data which is used for scoring and then ranking the conversations. */
+class ConversationData {
+
+    private final String mPackageName;
+    private final int mUserId;
+    private final ConversationInfo mConversationInfo;
+    private final EventHistory mEventHistory;
+
+    ConversationData(@NonNull String packageName, int userId,
+            @NonNull ConversationInfo conversationInfo, @NonNull EventHistory eventHistory) {
+        mPackageName = packageName;
+        mUserId = userId;
+        mConversationInfo = conversationInfo;
+        mEventHistory = eventHistory;
+    }
+
+    String getPackageName() {
+        return mPackageName;
+    }
+
+    int getUserId() {
+        return mUserId;
+    }
+
+    ConversationInfo getConversationInfo() {
+        return mConversationInfo;
+    }
+
+    EventHistory getEventHistory() {
+        return mEventHistory;
+    }
+}
diff --git a/services/people/java/com/android/server/people/prediction/ConversationPredictor.java b/services/people/java/com/android/server/people/prediction/ConversationPredictor.java
index de71d29..ed8a56b 100644
--- a/services/people/java/com/android/server/people/prediction/ConversationPredictor.java
+++ b/services/people/java/com/android/server/people/prediction/ConversationPredictor.java
@@ -17,12 +17,20 @@
 package com.android.server.people.prediction;
 
 import android.annotation.MainThread;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.app.prediction.AppPredictionContext;
 import android.app.prediction.AppTarget;
 import android.app.prediction.AppTargetEvent;
 import android.app.prediction.AppTargetId;
+import android.content.IntentFilter;
+import android.content.pm.ShortcutInfo;
+import android.content.pm.ShortcutManager.ShareShortcutInfo;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.app.ChooserActivity;
+import com.android.server.people.data.DataManager;
+import com.android.server.people.data.EventHistory;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -35,15 +43,28 @@
  */
 public class ConversationPredictor {
 
+    private static final String UI_SURFACE_SHARE = "share";
+
     private final AppPredictionContext mPredictionContext;
     private final Consumer<List<AppTarget>> mUpdatePredictionsMethod;
+    private final DataManager mDataManager;
     private final ExecutorService mCallbackExecutor;
+    @Nullable
+    private final IntentFilter mIntentFilter;
 
-    public ConversationPredictor(AppPredictionContext predictionContext,
-            Consumer<List<AppTarget>> updatePredictionsMethod) {
+    public ConversationPredictor(@NonNull AppPredictionContext predictionContext,
+            @NonNull Consumer<List<AppTarget>> updatePredictionsMethod,
+            @NonNull DataManager dataManager) {
         mPredictionContext = predictionContext;
         mUpdatePredictionsMethod = updatePredictionsMethod;
+        mDataManager = dataManager;
         mCallbackExecutor = Executors.newSingleThreadExecutor();
+        if (UI_SURFACE_SHARE.equals(mPredictionContext.getUiSurface())) {
+            mIntentFilter = mPredictionContext.getExtras().getParcelable(
+                    ChooserActivity.APP_PREDICTION_INTENT_FILTER_KEY);
+        } else {
+            mIntentFilter = null;
+        }
     }
 
     /**
@@ -51,14 +72,14 @@
      */
     @MainThread
     public void onAppTargetEvent(AppTargetEvent event) {
+        mDataManager.reportAppTargetEvent(event, mIntentFilter);
     }
 
     /**
      * Called by the client app to indicate a particular location has been shown to the user.
      */
     @MainThread
-    public void onLaunchLocationShown(String launchLocation, List<AppTargetId> targetIds) {
-    }
+    public void onLaunchLocationShown(String launchLocation, List<AppTargetId> targetIds) {}
 
     /**
      * Called by the client app to request sorting of the provided targets based on the prediction
@@ -74,8 +95,44 @@
      */
     @MainThread
     public void onRequestPredictionUpdate() {
-        List<AppTarget> targets = new ArrayList<>();
-        mCallbackExecutor.execute(() -> mUpdatePredictionsMethod.accept(targets));
+        // TODO: Re-route the call to different ranking classes for different surfaces.
+        mCallbackExecutor.execute(() -> {
+            List<AppTarget> targets = new ArrayList<>();
+            if (mIntentFilter != null) {
+                List<ShareShortcutInfo> shareShortcuts =
+                        mDataManager.getConversationShareTargets(mIntentFilter);
+                for (ShareShortcutInfo shareShortcut : shareShortcuts) {
+                    ShortcutInfo shortcutInfo = shareShortcut.getShortcutInfo();
+                    AppTargetId appTargetId = new AppTargetId(shortcutInfo.getId());
+                    String shareTargetClass = shareShortcut.getTargetComponent().getClassName();
+                    targets.add(new AppTarget.Builder(appTargetId, shortcutInfo)
+                            .setClassName(shareTargetClass)
+                            .build());
+                }
+            } else {
+                List<ConversationData> conversationDataList = new ArrayList<>();
+                mDataManager.forAllPackages(packageData ->
+                        packageData.forAllConversations(conversationInfo -> {
+                            EventHistory eventHistory = packageData.getEventHistory(
+                                    conversationInfo.getShortcutId());
+                            ConversationData conversationData = new ConversationData(
+                                    packageData.getPackageName(), packageData.getUserId(),
+                                    conversationInfo, eventHistory);
+                            conversationDataList.add(conversationData);
+                        }));
+                for (ConversationData conversationData : conversationDataList) {
+                    String shortcutId = conversationData.getConversationInfo().getShortcutId();
+                    ShortcutInfo shortcut = mDataManager.getShortcut(
+                            conversationData.getPackageName(), conversationData.getUserId(),
+                            shortcutId);
+                    if (shortcut != null) {
+                        AppTargetId appTargetId = new AppTargetId(shortcut.getId());
+                        targets.add(new AppTarget.Builder(appTargetId, shortcut).build());
+                    }
+                }
+            }
+            mUpdatePredictionsMethod.accept(targets);
+        });
     }
 
     @VisibleForTesting
diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml
index d2ddff3..b7c9001 100644
--- a/services/tests/servicestests/AndroidManifest.xml
+++ b/services/tests/servicestests/AndroidManifest.xml
@@ -66,6 +66,8 @@
     <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
     <uses-permission android:name="android.permission.SUSPEND_APPS"/>
     <uses-permission android:name="android.permission.CONTROL_KEYGUARD"/>
+    <uses-permission android:name="android.permission.READ_COMPAT_CHANGE_CONFIG"/>
+    <uses-permission android:name="android.permission.LOG_COMPAT_CHANGE"/>
     <uses-permission android:name="android.permission.MANAGE_BIND_INSTANT_SERVICE"/>
     <uses-permission android:name="android.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS" />
     <uses-permission android:name="android.permission.READ_DEVICE_CONFIG" />
diff --git a/services/tests/servicestests/src/com/android/server/backup/restore/PerformUnifiedRestoreTaskTest.java b/services/tests/servicestests/src/com/android/server/backup/restore/PerformUnifiedRestoreTaskTest.java
index 6359edf..3d22043 100644
--- a/services/tests/servicestests/src/com/android/server/backup/restore/PerformUnifiedRestoreTaskTest.java
+++ b/services/tests/servicestests/src/com/android/server/backup/restore/PerformUnifiedRestoreTaskTest.java
@@ -20,7 +20,6 @@
 import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertTrue;
 
-import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.when;
 
@@ -55,6 +54,8 @@
     private static final String INCLUDED_KEY = "included_key";
     private static final String EXCLUDED_KEY_1 = "excluded_key_1";
     private static final String EXCLUDED_KEY_2 = "excluded_key_2";
+    private static final String SYSTEM_PACKAGE_NAME = "android";
+    private static final String NON_SYSTEM_PACKAGE_NAME = "package";
 
     @Mock private BackupDataInput mBackupDataInput;
     @Mock private BackupDataOutput mBackupDataOutput;
@@ -98,9 +99,6 @@
                         return null;
                     }
                 });
-
-        mRestoreTask = new PerformUnifiedRestoreTask(Collections.singletonMap(
-                PACKAGE_NAME, mExcludedkeys));
     }
 
     private void populateTestData() {
@@ -116,6 +114,8 @@
 
     @Test
     public void testFilterExcludedKeys() throws Exception {
+        mRestoreTask = new PerformUnifiedRestoreTask(Collections.singletonMap(
+                PACKAGE_NAME, mExcludedkeys));
         mRestoreTask.filterExcludedKeys(PACKAGE_NAME, mBackupDataInput, mBackupDataOutput);
 
         // Verify only the correct were written into BackupDataOutput object.
@@ -123,4 +123,34 @@
         allowedBackupKeys.removeAll(mExcludedkeys);
         assertEquals(allowedBackupKeys, mBackupDataDump);
     }
+
+    @Test
+    public void testStageBackupData_stageForNonSystemPackageWithKeysToExclude() {
+        mRestoreTask = new PerformUnifiedRestoreTask(Collections.singletonMap(
+                PACKAGE_NAME, mExcludedkeys));
+
+        assertTrue(mRestoreTask.shouldStageBackupData(NON_SYSTEM_PACKAGE_NAME));
+    }
+
+    @Test
+    public void testStageBackupData_stageForNonSystemPackageWithNoKeysToExclude() {
+        mRestoreTask = new PerformUnifiedRestoreTask(Collections.emptyMap());
+
+        assertTrue(mRestoreTask.shouldStageBackupData(NON_SYSTEM_PACKAGE_NAME));
+    }
+
+    @Test
+    public void testStageBackupData_doNotStageForSystemPackageWithNoKeysToExclude() {
+        mRestoreTask = new PerformUnifiedRestoreTask(Collections.emptyMap());
+
+        assertFalse(mRestoreTask.shouldStageBackupData(SYSTEM_PACKAGE_NAME));
+    }
+
+    @Test
+    public void testStageBackupData_stageForSystemPackageWithKeysToExclude() {
+        mRestoreTask = new PerformUnifiedRestoreTask(Collections.singletonMap(
+                PACKAGE_NAME, mExcludedkeys));
+
+        assertTrue(mRestoreTask.shouldStageBackupData(NON_SYSTEM_PACKAGE_NAME));
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java b/services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java
index 770afb0..49ad866 100644
--- a/services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java
@@ -328,10 +328,11 @@
         when(mRuleEvaluationEngine.evaluate(any(), any()))
                 .thenReturn(
                         IntegrityCheckResult.deny(
-                                new Rule(
-                                        new AtomicFormula.BooleanAtomicFormula(
-                                                AtomicFormula.PRE_INSTALLED, false),
-                                        Rule.DENY)));
+                                Arrays.asList(
+                                        new Rule(
+                                                new AtomicFormula.BooleanAtomicFormula(
+                                                        AtomicFormula.PRE_INSTALLED, false),
+                                                Rule.DENY))));
         Intent intent = makeVerificationIntent();
 
         broadcastReceiverCaptor.getValue().onReceive(mMockContext, intent);
diff --git a/services/tests/servicestests/src/com/android/server/integrity/engine/RuleEvaluatorTest.java b/services/tests/servicestests/src/com/android/server/integrity/engine/RuleEvaluatorTest.java
index 629fd14..7b53e5e 100644
--- a/services/tests/servicestests/src/com/android/server/integrity/engine/RuleEvaluatorTest.java
+++ b/services/tests/servicestests/src/com/android/server/integrity/engine/RuleEvaluatorTest.java
@@ -63,7 +63,7 @@
 
     @Test
     public void testEvaluateRules_noMatchedRules_allow() {
-        Rule rule1 =
+        Rule rule =
                 new Rule(
                         new StringAtomicFormula(
                                 AtomicFormula.PACKAGE_NAME,
@@ -72,7 +72,7 @@
                         Rule.DENY);
 
         IntegrityCheckResult result =
-                RuleEvaluator.evaluateRules(Collections.singletonList(rule1), APP_INSTALL_METADATA);
+                RuleEvaluator.evaluateRules(Collections.singletonList(rule), APP_INSTALL_METADATA);
 
         assertThat(result.getEffect()).isEqualTo(ALLOW);
     }
@@ -98,7 +98,7 @@
                 RuleEvaluator.evaluateRules(Arrays.asList(rule1, rule2), APP_INSTALL_METADATA);
 
         assertThat(result.getEffect()).isEqualTo(DENY);
-        assertThat(result.getRule()).isEqualTo(rule1);
+        assertThat(result.getMatchedRules()).containsExactly(rule1);
     }
 
     @Test
@@ -110,7 +110,7 @@
                                 PACKAGE_NAME_1,
                                 /* isHashedValue= */ false),
                         Rule.DENY);
-        CompoundFormula compoundFormula2 =
+        Rule rule2 = new Rule(
                 new CompoundFormula(
                         CompoundFormula.AND,
                         Arrays.asList(
@@ -121,33 +121,33 @@
                                 new StringAtomicFormula(
                                         AtomicFormula.APP_CERTIFICATE,
                                         APP_CERTIFICATE,
-                                        /* isHashedValue= */ false)));
-        Rule rule2 = new Rule(compoundFormula2, Rule.DENY);
+                                        /* isHashedValue= */ false))),
+                Rule.DENY);
 
         IntegrityCheckResult result =
                 RuleEvaluator.evaluateRules(Arrays.asList(rule1, rule2), APP_INSTALL_METADATA);
 
         assertThat(result.getEffect()).isEqualTo(DENY);
-        assertThat(result.getRule()).isEqualTo(rule1);
+        assertThat(result.getMatchedRules()).containsExactly(rule1, rule2);
     }
 
     @Test
     public void testEvaluateRules_ruleWithNot_deny() {
-        CompoundFormula compoundFormula =
+        Rule rule = new Rule(
                 new CompoundFormula(
                         CompoundFormula.NOT,
                         Collections.singletonList(
                                 new StringAtomicFormula(
                                         AtomicFormula.PACKAGE_NAME,
                                         PACKAGE_NAME_2,
-                                        /* isHashedValue= */ false)));
-        Rule rule = new Rule(compoundFormula, Rule.DENY);
+                                        /* isHashedValue= */ false))),
+                Rule.DENY);
 
         IntegrityCheckResult result =
                 RuleEvaluator.evaluateRules(Collections.singletonList(rule), APP_INSTALL_METADATA);
 
         assertThat(result.getEffect()).isEqualTo(DENY);
-        assertThat(result.getRule()).isEqualTo(rule);
+        assertThat(result.getMatchedRules()).containsExactly(rule);
     }
 
     @Test
@@ -162,12 +162,12 @@
                 RuleEvaluator.evaluateRules(Collections.singletonList(rule), APP_INSTALL_METADATA);
 
         assertThat(result.getEffect()).isEqualTo(DENY);
-        assertThat(result.getRule()).isEqualTo(rule);
+        assertThat(result.getMatchedRules()).containsExactly(rule);
     }
 
     @Test
     public void testEvaluateRules_validForm_deny() {
-        CompoundFormula compoundFormula =
+        Rule rule = new Rule(
                 new CompoundFormula(
                         CompoundFormula.AND,
                         Arrays.asList(
@@ -178,19 +178,19 @@
                                 new StringAtomicFormula(
                                         AtomicFormula.APP_CERTIFICATE,
                                         APP_CERTIFICATE,
-                                        /* isHashedValue= */ false)));
-        Rule rule = new Rule(compoundFormula, Rule.DENY);
+                                        /* isHashedValue= */ false))),
+                Rule.DENY);
 
         IntegrityCheckResult result =
                 RuleEvaluator.evaluateRules(Collections.singletonList(rule), APP_INSTALL_METADATA);
 
         assertThat(result.getEffect()).isEqualTo(DENY);
-        assertThat(result.getRule()).isEqualTo(rule);
+        assertThat(result.getMatchedRules()).containsExactly(rule);
     }
 
     @Test
     public void testEvaluateRules_orRules() {
-        CompoundFormula compoundFormula =
+        Rule rule = new Rule(
                 new CompoundFormula(
                         CompoundFormula.OR,
                         Arrays.asList(
@@ -201,13 +201,14 @@
                                 new StringAtomicFormula(
                                         AtomicFormula.APP_CERTIFICATE,
                                         APP_CERTIFICATE,
-                                        /* isHashedValue= */ false)));
-        Rule rule = new Rule(compoundFormula, Rule.DENY);
+                                        /* isHashedValue= */ false))),
+                Rule.DENY);
 
         IntegrityCheckResult result =
                 RuleEvaluator.evaluateRules(Collections.singletonList(rule), APP_INSTALL_METADATA);
 
         assertThat(result.getEffect()).isEqualTo(DENY);
+        assertThat(result.getMatchedRules()).containsExactly(rule);
     }
 
     @Test
@@ -232,6 +233,7 @@
                 RuleEvaluator.evaluateRules(Collections.singletonList(rule), APP_INSTALL_METADATA);
 
         assertThat(result.getEffect()).isEqualTo(DENY);
+        assertThat(result.getMatchedRules()).containsExactly(rule);
     }
 
     @Test
@@ -243,7 +245,7 @@
                                 PACKAGE_NAME_1,
                                 /* isHashedValue= */ false),
                         Rule.FORCE_ALLOW);
-        CompoundFormula compoundFormula2 =
+        Rule rule2 = new Rule(
                 new CompoundFormula(
                         CompoundFormula.AND,
                         Arrays.asList(
@@ -254,13 +256,43 @@
                                 new StringAtomicFormula(
                                         AtomicFormula.APP_CERTIFICATE,
                                         APP_CERTIFICATE,
-                                        /* isHashedValue= */ false)));
-        Rule rule2 = new Rule(compoundFormula2, Rule.DENY);
+                                        /* isHashedValue= */ false))),
+                Rule.DENY);
 
         IntegrityCheckResult result =
                 RuleEvaluator.evaluateRules(Arrays.asList(rule1, rule2), APP_INSTALL_METADATA);
 
         assertThat(result.getEffect()).isEqualTo(ALLOW);
-        assertThat(result.getRule()).isEqualTo(rule1);
+        assertThat(result.getMatchedRules()).containsExactly(rule1);
+    }
+
+    @Test
+    public void testEvaluateRules_multipleMatches_forceAllow() {
+        Rule rule1 =
+                new Rule(
+                        new StringAtomicFormula(
+                                AtomicFormula.PACKAGE_NAME,
+                                PACKAGE_NAME_1,
+                                /* isHashedValue= */ false),
+                        Rule.FORCE_ALLOW);
+        Rule rule2 = new Rule(
+                new CompoundFormula(
+                        CompoundFormula.AND,
+                        Arrays.asList(
+                                new StringAtomicFormula(
+                                        AtomicFormula.PACKAGE_NAME,
+                                        PACKAGE_NAME_1,
+                                        /* isHashedValue= */ false),
+                                new StringAtomicFormula(
+                                        AtomicFormula.APP_CERTIFICATE,
+                                        APP_CERTIFICATE,
+                                        /* isHashedValue= */ false))),
+                Rule.FORCE_ALLOW);
+
+        IntegrityCheckResult result =
+                RuleEvaluator.evaluateRules(Arrays.asList(rule1, rule2), APP_INSTALL_METADATA);
+
+        assertThat(result.getEffect()).isEqualTo(ALLOW);
+        assertThat(result.getMatchedRules()).containsExactly(rule1, rule2);
     }
 }
\ No newline at end of file
diff --git a/services/tests/servicestests/src/com/android/server/integrity/model/IntegrityCheckResultTest.java b/services/tests/servicestests/src/com/android/server/integrity/model/IntegrityCheckResultTest.java
new file mode 100644
index 0000000..9cc9f10
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/integrity/model/IntegrityCheckResultTest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.integrity.model;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.integrity.AtomicFormula;
+import android.content.integrity.Rule;
+import android.util.StatsLog;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.util.Collections;
+
+@RunWith(JUnit4.class)
+public class IntegrityCheckResultTest {
+
+    @Test
+    public void createAllowResult() {
+        IntegrityCheckResult allowResult = IntegrityCheckResult.allow();
+
+        assertThat(allowResult.getEffect()).isEqualTo(IntegrityCheckResult.Effect.ALLOW);
+        assertThat(allowResult.getMatchedRules()).isEmpty();
+        assertThat(allowResult.getLoggingResponse())
+                .isEqualTo(StatsLog.INTEGRITY_CHECK_RESULT_REPORTED__RESPONSE__ALLOWED);
+    }
+
+    @Test
+    public void createAllowResultWithRule() {
+        String packageName = "com.test.deny";
+        Rule forceAllowRule =
+                new Rule(
+                        new AtomicFormula.StringAtomicFormula(AtomicFormula.PACKAGE_NAME,
+                                packageName),
+                        Rule.FORCE_ALLOW);
+
+        IntegrityCheckResult allowResult =
+                IntegrityCheckResult.allow(Collections.singletonList(forceAllowRule));
+
+        assertThat(allowResult.getEffect()).isEqualTo(IntegrityCheckResult.Effect.ALLOW);
+        assertThat(allowResult.getMatchedRules()).containsExactly(forceAllowRule);
+        assertThat(allowResult.getLoggingResponse())
+                .isEqualTo(StatsLog.INTEGRITY_CHECK_RESULT_REPORTED__RESPONSE__FORCE_ALLOWED);
+    }
+
+    @Test
+    public void createDenyResultWithRule() {
+        String packageName = "com.test.deny";
+        Rule failedRule =
+                new Rule(
+                        new AtomicFormula.StringAtomicFormula(AtomicFormula.PACKAGE_NAME,
+                                packageName),
+                        Rule.DENY);
+
+        IntegrityCheckResult denyResult =
+                IntegrityCheckResult.deny(Collections.singletonList(failedRule));
+
+        assertThat(denyResult.getEffect()).isEqualTo(IntegrityCheckResult.Effect.DENY);
+        assertThat(denyResult.getMatchedRules()).containsExactly(failedRule);
+        assertThat(denyResult.getLoggingResponse())
+                .isEqualTo(StatsLog.INTEGRITY_CHECK_RESULT_REPORTED__RESPONSE__REJECTED);
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/people/data/AggregateEventHistoryImplTest.java b/services/tests/servicestests/src/com/android/server/people/data/AggregateEventHistoryImplTest.java
new file mode 100644
index 0000000..b614a4f
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/people/data/AggregateEventHistoryImplTest.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2020 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.people.data;
+
+import static com.android.server.people.data.TestUtils.timestamp;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.util.List;
+
+@RunWith(JUnit4.class)
+public final class AggregateEventHistoryImplTest {
+
+    private static final long CURRENT_TIMESTAMP = timestamp("01-30 18:50");
+
+    private static final Event E1 = new Event(timestamp("01-06 05:26"),
+            Event.TYPE_NOTIFICATION_OPENED);
+    private static final Event E2 = new Event(timestamp("01-27 18:41"),
+            Event.TYPE_NOTIFICATION_OPENED);
+    private static final Event E3 = new Event(timestamp("01-30 03:06"),
+            Event.TYPE_SMS_OUTGOING);
+    private static final Event E4 = new Event(timestamp("01-30 18:14"),
+            Event.TYPE_SMS_INCOMING);
+
+    private EventHistoryImpl mEventHistory1;
+    private EventHistoryImpl mEventHistory2;
+
+    private AggregateEventHistoryImpl mAggEventHistory;
+
+    private EventIndex.Injector mInjector = new EventIndex.Injector() {
+        @Override
+        long currentTimeMillis() {
+            return CURRENT_TIMESTAMP;
+        }
+    };
+
+    @Before
+    public void setUp() {
+        mAggEventHistory = new AggregateEventHistoryImpl();
+
+        EventHistoryImpl.Injector injector = new EventHistoryImplInjector();
+
+        mEventHistory1 = new EventHistoryImpl(injector);
+        mEventHistory1.addEvent(E1);
+        mEventHistory1.addEvent(E2);
+
+        mEventHistory2 = new EventHistoryImpl(injector);
+        mEventHistory2.addEvent(E3);
+        mEventHistory2.addEvent(E4);
+    }
+
+    @Test
+    public void testEmptyAggregateEventHistory() {
+        assertTrue(mAggEventHistory.getEventIndex(Event.TYPE_SHORTCUT_INVOCATION).isEmpty());
+        assertTrue(mAggEventHistory.getEventIndex(Event.ALL_EVENT_TYPES).isEmpty());
+        assertTrue(mAggEventHistory.queryEvents(
+                Event.ALL_EVENT_TYPES, 0L, Long.MAX_VALUE).isEmpty());
+    }
+
+    @Test
+    public void testQueryEventIndexForSingleEventType() {
+        mAggEventHistory.addEventHistory(mEventHistory1);
+        mAggEventHistory.addEventHistory(mEventHistory2);
+
+        EventIndex eventIndex;
+
+        eventIndex = mAggEventHistory.getEventIndex(Event.TYPE_NOTIFICATION_OPENED);
+        assertEquals(2, eventIndex.getActiveTimeSlots().size());
+
+        eventIndex = mAggEventHistory.getEventIndex(Event.TYPE_SMS_OUTGOING);
+        assertEquals(1, eventIndex.getActiveTimeSlots().size());
+
+        eventIndex = mAggEventHistory.getEventIndex(Event.TYPE_SHORTCUT_INVOCATION);
+        assertTrue(eventIndex.isEmpty());
+    }
+
+    @Test
+    public void testQueryEventIndexForMultipleEventTypes() {
+        mAggEventHistory.addEventHistory(mEventHistory1);
+        mAggEventHistory.addEventHistory(mEventHistory2);
+
+        EventIndex eventIndex;
+
+        eventIndex = mAggEventHistory.getEventIndex(Event.SMS_EVENT_TYPES);
+        assertEquals(2, eventIndex.getActiveTimeSlots().size());
+
+        eventIndex = mAggEventHistory.getEventIndex(Event.ALL_EVENT_TYPES);
+        assertEquals(4, eventIndex.getActiveTimeSlots().size());
+    }
+
+    @Test
+    public void testQueryEvents() {
+        mAggEventHistory.addEventHistory(mEventHistory1);
+        mAggEventHistory.addEventHistory(mEventHistory2);
+
+        List<Event> events;
+
+        events = mAggEventHistory.queryEvents(Event.NOTIFICATION_EVENT_TYPES, 0L, Long.MAX_VALUE);
+        assertEquals(2, events.size());
+
+        events = mAggEventHistory.queryEvents(Event.ALL_EVENT_TYPES, 0L, Long.MAX_VALUE);
+        assertEquals(4, events.size());
+    }
+
+    private class EventHistoryImplInjector extends EventHistoryImpl.Injector {
+
+        EventIndex createEventIndex() {
+            return new EventIndex(mInjector);
+        }
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/people/data/ContactsQueryHelperTest.java b/services/tests/servicestests/src/com/android/server/people/data/ContactsQueryHelperTest.java
new file mode 100644
index 0000000..96302b9
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/people/data/ContactsQueryHelperTest.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2020 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.people.data;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.when;
+
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.net.Uri;
+import android.provider.ContactsContract;
+import android.provider.ContactsContract.Contacts;
+import android.test.mock.MockContentProvider;
+import android.test.mock.MockContentResolver;
+import android.test.mock.MockContext;
+import android.util.ArrayMap;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.Map;
+
+@RunWith(JUnit4.class)
+public final class ContactsQueryHelperTest {
+
+    private static final String CONTACT_LOOKUP_KEY = "123";
+    private static final String PHONE_NUMBER = "+1234567890";
+
+    private static final String[] CONTACTS_COLUMNS = new String[] {
+            Contacts._ID, Contacts.LOOKUP_KEY, Contacts.STARRED, Contacts.HAS_PHONE_NUMBER,
+            Contacts.CONTACT_LAST_UPDATED_TIMESTAMP };
+    private static final String[] CONTACTS_LOOKUP_COLUMNS = new String[] {
+            Contacts._ID, Contacts.LOOKUP_KEY, Contacts.STARRED, Contacts.HAS_PHONE_NUMBER };
+    private static final String[] PHONE_COLUMNS = new String[] {
+            ContactsContract.CommonDataKinds.Phone.NORMALIZED_NUMBER };
+
+    @Mock
+    private MockContext mContext;
+
+    private MatrixCursor mContactsCursor;
+    private MatrixCursor mContactsLookupCursor;
+    private MatrixCursor mPhoneCursor;
+    private ContactsQueryHelper mHelper;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        mContactsCursor = new MatrixCursor(CONTACTS_COLUMNS);
+        mContactsLookupCursor = new MatrixCursor(CONTACTS_LOOKUP_COLUMNS);
+        mPhoneCursor = new MatrixCursor(PHONE_COLUMNS);
+
+        MockContentResolver contentResolver = new MockContentResolver();
+        ContactsContentProvider contentProvider = new ContactsContentProvider();
+        contentProvider.registerCursor(Contacts.CONTENT_URI, mContactsCursor);
+        contentProvider.registerCursor(
+                ContactsContract.PhoneLookup.CONTENT_FILTER_URI, mContactsLookupCursor);
+        contentProvider.registerCursor(
+                ContactsContract.CommonDataKinds.Email.CONTENT_LOOKUP_URI, mContactsLookupCursor);
+        contentProvider.registerCursor(
+                ContactsContract.CommonDataKinds.Phone.CONTENT_URI, mPhoneCursor);
+
+        contentResolver.addProvider(ContactsContract.AUTHORITY, contentProvider);
+        when(mContext.getContentResolver()).thenReturn(contentResolver);
+
+        mHelper = new ContactsQueryHelper(mContext);
+    }
+
+    @Test
+    public void testQueryWithUri() {
+        mContactsCursor.addRow(new Object[] {
+                /* id= */ 11, CONTACT_LOOKUP_KEY, /* starred= */ 1, /* hasPhoneNumber= */ 1,
+                /* lastUpdatedTimestamp= */ 100L });
+        mPhoneCursor.addRow(new String[] { PHONE_NUMBER });
+        Uri contactUri = Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, CONTACT_LOOKUP_KEY);
+        assertTrue(mHelper.query(contactUri.toString()));
+        assertNotNull(mHelper.getContactUri());
+        assertEquals(PHONE_NUMBER, mHelper.getPhoneNumber());
+        assertEquals(100L, mHelper.getLastUpdatedTimestamp());
+        assertTrue(mHelper.isStarred());
+    }
+
+    @Test
+    public void testQueryWithUriNotStarredNoPhoneNumber() {
+        mContactsCursor.addRow(new Object[] {
+                /* id= */ 11, CONTACT_LOOKUP_KEY, /* starred= */ 0, /* hasPhoneNumber= */ 0,
+                /* lastUpdatedTimestamp= */ 100L });
+        Uri contactUri = Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, CONTACT_LOOKUP_KEY);
+        assertTrue(mHelper.query(contactUri.toString()));
+        assertNotNull(mHelper.getContactUri());
+        assertNull(mHelper.getPhoneNumber());
+        assertFalse(mHelper.isStarred());
+        assertEquals(100L, mHelper.getLastUpdatedTimestamp());
+    }
+
+    @Test
+    public void testQueryWithUriNotFound() {
+        Uri contactUri = Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, CONTACT_LOOKUP_KEY);
+        assertFalse(mHelper.query(contactUri.toString()));
+    }
+
+    @Test
+    public void testQueryWithPhoneNumber() {
+        mContactsLookupCursor.addRow(new Object[] {
+                /* id= */ 11, CONTACT_LOOKUP_KEY, /* starred= */ 1, /* hasPhoneNumber= */ 1 });
+        mPhoneCursor.addRow(new String[] { PHONE_NUMBER });
+        String contactUri = "tel:" + PHONE_NUMBER;
+        assertTrue(mHelper.query(contactUri));
+        assertNotNull(mHelper.getContactUri());
+        assertEquals(PHONE_NUMBER, mHelper.getPhoneNumber());
+        assertTrue(mHelper.isStarred());
+    }
+
+    @Test
+    public void testQueryWithEmail() {
+        mContactsLookupCursor.addRow(new Object[] {
+                /* id= */ 11, CONTACT_LOOKUP_KEY, /* starred= */ 1, /* hasPhoneNumber= */ 0 });
+        String contactUri = "mailto:test@gmail.com";
+        assertTrue(mHelper.query(contactUri));
+        assertNotNull(mHelper.getContactUri());
+        assertNull(mHelper.getPhoneNumber());
+        assertTrue(mHelper.isStarred());
+    }
+
+    @Test
+    public void testQueryUpdatedContactSinceTime() {
+        mContactsCursor.addRow(new Object[] {
+                /* id= */ 11, CONTACT_LOOKUP_KEY, /* starred= */ 1, /* hasPhoneNumber= */ 0,
+                /* lastUpdatedTimestamp= */ 100L });
+        assertTrue(mHelper.querySince(50L));
+        assertNotNull(mHelper.getContactUri());
+        assertNull(mHelper.getPhoneNumber());
+        assertTrue(mHelper.isStarred());
+        assertEquals(100L, mHelper.getLastUpdatedTimestamp());
+    }
+
+    @Test
+    public void testQueryWithUnsupportedScheme() {
+        mContactsLookupCursor.addRow(new Object[] {
+                /* id= */ 11, CONTACT_LOOKUP_KEY, /* starred= */ 1, /* hasPhoneNumber= */ 1 });
+        mPhoneCursor.addRow(new String[] { PHONE_NUMBER });
+        String contactUri = "unknown:test";
+        assertFalse(mHelper.query(contactUri));
+    }
+
+    private class ContactsContentProvider extends MockContentProvider {
+
+        private Map<Uri, Cursor> mUriPrefixToCursorMap = new ArrayMap<>();
+
+        @Override
+        public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+                String sortOrder) {
+            for (Uri prefixUri : mUriPrefixToCursorMap.keySet()) {
+                if (uri.isPathPrefixMatch(prefixUri)) {
+                    return mUriPrefixToCursorMap.get(prefixUri);
+                }
+            }
+            return mUriPrefixToCursorMap.get(uri);
+        }
+
+        private void registerCursor(Uri uriPrefix, Cursor cursor) {
+            mUriPrefixToCursorMap.put(uriPrefix, cursor);
+        }
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/people/data/ConversationInfoTest.java b/services/tests/servicestests/src/com/android/server/people/data/ConversationInfoTest.java
new file mode 100644
index 0000000..05a9a80
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/people/data/ConversationInfoTest.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2020 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.people.data;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import android.content.LocusId;
+import android.content.pm.ShortcutInfo;
+import android.net.Uri;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public final class ConversationInfoTest {
+
+    private static final String SHORTCUT_ID = "abc";
+    private static final LocusId LOCUS_ID = new LocusId("def");
+    private static final Uri CONTACT_URI = Uri.parse("tel:+1234567890");
+    private static final String PHONE_NUMBER = "+1234567890";
+    private static final String NOTIFICATION_CHANNEL_ID = "test : abc";
+
+    @Test
+    public void testBuild() {
+        ConversationInfo conversationInfo = new ConversationInfo.Builder()
+                .setShortcutId(SHORTCUT_ID)
+                .setLocusId(LOCUS_ID)
+                .setContactUri(CONTACT_URI)
+                .setContactPhoneNumber(PHONE_NUMBER)
+                .setNotificationChannelId(NOTIFICATION_CHANNEL_ID)
+                .setShortcutFlags(ShortcutInfo.FLAG_LONG_LIVED)
+                .setVip(true)
+                .setNotificationSilenced(true)
+                .setBubbled(true)
+                .setDemoted(true)
+                .setPersonImportant(true)
+                .setPersonBot(true)
+                .setContactStarred(true)
+                .build();
+
+        assertEquals(SHORTCUT_ID, conversationInfo.getShortcutId());
+        assertEquals(LOCUS_ID, conversationInfo.getLocusId());
+        assertEquals(CONTACT_URI, conversationInfo.getContactUri());
+        assertEquals(PHONE_NUMBER, conversationInfo.getContactPhoneNumber());
+        assertEquals(NOTIFICATION_CHANNEL_ID, conversationInfo.getNotificationChannelId());
+        assertTrue(conversationInfo.isShortcutLongLived());
+        assertTrue(conversationInfo.isVip());
+        assertTrue(conversationInfo.isNotificationSilenced());
+        assertTrue(conversationInfo.isBubbled());
+        assertTrue(conversationInfo.isDemoted());
+        assertTrue(conversationInfo.isPersonImportant());
+        assertTrue(conversationInfo.isPersonBot());
+        assertTrue(conversationInfo.isContactStarred());
+    }
+
+    @Test
+    public void testBuildEmpty() {
+        ConversationInfo conversationInfo = new ConversationInfo.Builder()
+                .setShortcutId(SHORTCUT_ID)
+                .build();
+
+        assertEquals(SHORTCUT_ID, conversationInfo.getShortcutId());
+        assertNull(conversationInfo.getLocusId());
+        assertNull(conversationInfo.getContactUri());
+        assertNull(conversationInfo.getContactPhoneNumber());
+        assertNull(conversationInfo.getNotificationChannelId());
+        assertFalse(conversationInfo.isShortcutLongLived());
+        assertFalse(conversationInfo.isVip());
+        assertFalse(conversationInfo.isNotificationSilenced());
+        assertFalse(conversationInfo.isBubbled());
+        assertFalse(conversationInfo.isDemoted());
+        assertFalse(conversationInfo.isPersonImportant());
+        assertFalse(conversationInfo.isPersonBot());
+        assertFalse(conversationInfo.isContactStarred());
+    }
+
+    @Test
+    public void testBuildFromAnotherConversationInfo() {
+        ConversationInfo source = new ConversationInfo.Builder()
+                .setShortcutId(SHORTCUT_ID)
+                .setLocusId(LOCUS_ID)
+                .setContactUri(CONTACT_URI)
+                .setContactPhoneNumber(PHONE_NUMBER)
+                .setNotificationChannelId(NOTIFICATION_CHANNEL_ID)
+                .setShortcutFlags(ShortcutInfo.FLAG_LONG_LIVED)
+                .setVip(true)
+                .setNotificationSilenced(true)
+                .setBubbled(true)
+                .setPersonImportant(true)
+                .setPersonBot(true)
+                .setContactStarred(true)
+                .build();
+
+        ConversationInfo destination = new ConversationInfo.Builder(source)
+                .setVip(false)
+                .setContactStarred(false)
+                .build();
+
+        assertEquals(SHORTCUT_ID, destination.getShortcutId());
+        assertEquals(LOCUS_ID, destination.getLocusId());
+        assertEquals(CONTACT_URI, destination.getContactUri());
+        assertEquals(PHONE_NUMBER, destination.getContactPhoneNumber());
+        assertEquals(NOTIFICATION_CHANNEL_ID, destination.getNotificationChannelId());
+        assertTrue(destination.isShortcutLongLived());
+        assertFalse(destination.isVip());
+        assertTrue(destination.isNotificationSilenced());
+        assertTrue(destination.isBubbled());
+        assertTrue(destination.isPersonImportant());
+        assertTrue(destination.isPersonBot());
+        assertFalse(destination.isContactStarred());
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/people/data/ConversationStoreTest.java b/services/tests/servicestests/src/com/android/server/people/data/ConversationStoreTest.java
new file mode 100644
index 0000000..a40c6ab
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/people/data/ConversationStoreTest.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2020 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.people.data;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import android.content.LocusId;
+import android.content.pm.ShortcutInfo;
+import android.net.Uri;
+import android.util.ArraySet;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.util.Set;
+
+@RunWith(JUnit4.class)
+public final class ConversationStoreTest {
+
+    private static final String SHORTCUT_ID = "abc";
+    private static final LocusId LOCUS_ID = new LocusId("def");
+    private static final Uri CONTACT_URI = Uri.parse("tel:+1234567890");
+    private static final String PHONE_NUMBER = "+1234567890";
+
+    private ConversationStore mConversationStore;
+
+    @Before
+    public void setUp() {
+        mConversationStore = new ConversationStore();
+    }
+
+    @Test
+    public void testAddConversation() {
+        mConversationStore.addOrUpdate(buildConversationInfo(SHORTCUT_ID));
+
+        ConversationInfo out = mConversationStore.getConversation(SHORTCUT_ID);
+        assertNotNull(out);
+        assertEquals(SHORTCUT_ID, out.getShortcutId());
+    }
+
+    @Test
+    public void testUpdateConversation() {
+        ConversationInfo original =
+                buildConversationInfo(SHORTCUT_ID, LOCUS_ID, CONTACT_URI, PHONE_NUMBER);
+        mConversationStore.addOrUpdate(original);
+        assertEquals(LOCUS_ID, mConversationStore.getConversation(SHORTCUT_ID).getLocusId());
+
+        LocusId newLocusId = new LocusId("ghi");
+        ConversationInfo update = buildConversationInfo(
+                SHORTCUT_ID, newLocusId, CONTACT_URI, PHONE_NUMBER);
+        mConversationStore.addOrUpdate(update);
+        assertEquals(newLocusId, mConversationStore.getConversation(SHORTCUT_ID).getLocusId());
+    }
+
+    @Test
+    public void testDeleteConversation() {
+        mConversationStore.addOrUpdate(buildConversationInfo(SHORTCUT_ID));
+        assertNotNull(mConversationStore.getConversation(SHORTCUT_ID));
+
+        mConversationStore.deleteConversation(SHORTCUT_ID);
+        assertNull(mConversationStore.getConversation(SHORTCUT_ID));
+    }
+
+    @Test
+    public void testForAllConversations() {
+        mConversationStore.addOrUpdate(buildConversationInfo("a"));
+        mConversationStore.addOrUpdate(buildConversationInfo("b"));
+        mConversationStore.addOrUpdate(buildConversationInfo("c"));
+
+        Set<String> shortcutIds = new ArraySet<>();
+
+        mConversationStore.forAllConversations(
+                conversationInfo -> shortcutIds.add(conversationInfo.getShortcutId()));
+        assertTrue(shortcutIds.contains("a"));
+        assertTrue(shortcutIds.contains("b"));
+        assertTrue(shortcutIds.contains("c"));
+    }
+
+    @Test
+    public void testGetConversationByLocusId() {
+        ConversationInfo in =
+                buildConversationInfo(SHORTCUT_ID, LOCUS_ID, CONTACT_URI, PHONE_NUMBER);
+        mConversationStore.addOrUpdate(in);
+        ConversationInfo out = mConversationStore.getConversationByLocusId(LOCUS_ID);
+        assertNotNull(out);
+        assertEquals(SHORTCUT_ID, out.getShortcutId());
+
+        mConversationStore.deleteConversation(SHORTCUT_ID);
+        assertNull(mConversationStore.getConversationByLocusId(LOCUS_ID));
+    }
+
+    @Test
+    public void testGetConversationByContactUri() {
+        ConversationInfo in =
+                buildConversationInfo(SHORTCUT_ID, LOCUS_ID, CONTACT_URI, PHONE_NUMBER);
+        mConversationStore.addOrUpdate(in);
+        ConversationInfo out = mConversationStore.getConversationByContactUri(CONTACT_URI);
+        assertNotNull(out);
+        assertEquals(SHORTCUT_ID, out.getShortcutId());
+
+        mConversationStore.deleteConversation(SHORTCUT_ID);
+        assertNull(mConversationStore.getConversationByContactUri(CONTACT_URI));
+    }
+
+    @Test
+    public void testGetConversationByPhoneNumber() {
+        ConversationInfo in =
+                buildConversationInfo(SHORTCUT_ID, LOCUS_ID, CONTACT_URI, PHONE_NUMBER);
+        mConversationStore.addOrUpdate(in);
+        ConversationInfo out = mConversationStore.getConversationByPhoneNumber(PHONE_NUMBER);
+        assertNotNull(out);
+        assertEquals(SHORTCUT_ID, out.getShortcutId());
+
+        mConversationStore.deleteConversation(SHORTCUT_ID);
+        assertNull(mConversationStore.getConversationByPhoneNumber(PHONE_NUMBER));
+    }
+
+    private static ConversationInfo buildConversationInfo(String shortcutId) {
+        return buildConversationInfo(shortcutId, null, null, null);
+    }
+
+    private static ConversationInfo buildConversationInfo(
+            String shortcutId, LocusId locusId, Uri contactUri, String phoneNumber) {
+        return new ConversationInfo.Builder()
+                .setShortcutId(shortcutId)
+                .setLocusId(locusId)
+                .setContactUri(contactUri)
+                .setContactPhoneNumber(phoneNumber)
+                .setShortcutFlags(ShortcutInfo.FLAG_LONG_LIVED)
+                .setVip(true)
+                .setBubbled(true)
+                .build();
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java b/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java
new file mode 100644
index 0000000..9f3d656
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java
@@ -0,0 +1,451 @@
+/*
+ * Copyright (C) 2020 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.people.data;
+
+import static android.app.usage.UsageEvents.Event.SHORTCUT_INVOCATION;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.Notification;
+import android.app.Person;
+import android.app.prediction.AppTarget;
+import android.app.prediction.AppTargetEvent;
+import android.app.prediction.AppTargetId;
+import android.app.usage.UsageEvents;
+import android.app.usage.UsageStatsManagerInternal;
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.ShortcutInfo;
+import android.content.pm.ShortcutManager;
+import android.content.pm.ShortcutManager.ShareShortcutInfo;
+import android.content.pm.ShortcutServiceInternal;
+import android.content.pm.UserInfo;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Looper;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.provider.ContactsContract;
+import android.service.notification.NotificationListenerService;
+import android.service.notification.StatusBarNotification;
+import android.telephony.TelephonyManager;
+import android.util.Range;
+
+import com.android.internal.app.ChooserActivity;
+import com.android.server.LocalServices;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+
+@RunWith(JUnit4.class)
+public final class DataManagerTest {
+
+    private static final int USER_ID_PRIMARY = 0;
+    private static final int USER_ID_PRIMARY_MANAGED = 10;
+    private static final int USER_ID_SECONDARY = 11;
+    private static final String TEST_PKG_NAME = "pkg";
+    private static final String TEST_SHORTCUT_ID = "sc";
+    private static final String CONTACT_URI = "content://com.android.contacts/contacts/lookup/123";
+    private static final String PHONE_NUMBER = "+1234567890";
+
+    @Mock private Context mContext;
+    @Mock private ShortcutServiceInternal mShortcutServiceInternal;
+    @Mock private UsageStatsManagerInternal mUsageStatsManagerInternal;
+    @Mock private ShortcutManager mShortcutManager;
+    @Mock private UserManager mUserManager;
+    @Mock private TelephonyManager mTelephonyManager;
+    @Mock private ContentResolver mContentResolver;
+    @Mock private ScheduledExecutorService mExecutorService;
+    @Mock private ScheduledFuture mScheduledFuture;
+    @Mock private StatusBarNotification mStatusBarNotification;
+    @Mock private Notification mNotification;
+
+    private DataManager mDataManager;
+    private int mCallingUserId;
+    private TestInjector mInjector;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        addLocalServiceMock(ShortcutServiceInternal.class, mShortcutServiceInternal);
+
+        addLocalServiceMock(UsageStatsManagerInternal.class, mUsageStatsManagerInternal);
+
+        when(mContext.getMainLooper()).thenReturn(Looper.getMainLooper());
+
+        when(mContext.getSystemService(Context.SHORTCUT_SERVICE)).thenReturn(mShortcutManager);
+        when(mContext.getSystemServiceName(ShortcutManager.class)).thenReturn(
+                Context.SHORTCUT_SERVICE);
+
+        when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
+        when(mContext.getSystemServiceName(UserManager.class)).thenReturn(
+                Context.USER_SERVICE);
+
+        when(mContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephonyManager);
+
+        when(mExecutorService.scheduleAtFixedRate(any(Runnable.class), anyLong(), anyLong(), any(
+                TimeUnit.class))).thenReturn(mScheduledFuture);
+
+        when(mUserManager.getEnabledProfiles(USER_ID_PRIMARY))
+                .thenReturn(Arrays.asList(
+                        buildUserInfo(USER_ID_PRIMARY),
+                        buildUserInfo(USER_ID_PRIMARY_MANAGED)));
+        when(mUserManager.getEnabledProfiles(USER_ID_SECONDARY))
+                .thenReturn(Collections.singletonList(buildUserInfo(USER_ID_SECONDARY)));
+
+        when(mContext.getContentResolver()).thenReturn(mContentResolver);
+
+        when(mStatusBarNotification.getNotification()).thenReturn(mNotification);
+        when(mStatusBarNotification.getPackageName()).thenReturn(TEST_PKG_NAME);
+        when(mStatusBarNotification.getUser()).thenReturn(UserHandle.of(USER_ID_PRIMARY));
+        when(mNotification.getShortcutId()).thenReturn(TEST_SHORTCUT_ID);
+
+        mCallingUserId = USER_ID_PRIMARY;
+
+        mInjector = new TestInjector();
+        mDataManager = new DataManager(mContext, mInjector);
+        mDataManager.initialize();
+    }
+
+    @After
+    public void tearDown() {
+        LocalServices.removeServiceForTest(ShortcutServiceInternal.class);
+        LocalServices.removeServiceForTest(UsageStatsManagerInternal.class);
+    }
+
+    @Test
+    public void testAccessConversationFromTheSameProfileGroup() {
+        mDataManager.onUserUnlocked(USER_ID_PRIMARY);
+        mDataManager.onUserUnlocked(USER_ID_PRIMARY_MANAGED);
+        mDataManager.onUserUnlocked(USER_ID_SECONDARY);
+
+        mDataManager.onShortcutAddedOrUpdated(
+                buildShortcutInfo("pkg_1", USER_ID_PRIMARY, "sc_1",
+                        buildPerson(true, false)));
+        mDataManager.onShortcutAddedOrUpdated(
+                buildShortcutInfo("pkg_2", USER_ID_PRIMARY_MANAGED, "sc_2",
+                        buildPerson(false, true)));
+        mDataManager.onShortcutAddedOrUpdated(
+                buildShortcutInfo("pkg_3", USER_ID_SECONDARY, "sc_3", buildPerson()));
+
+        List<ConversationInfo> conversations = new ArrayList<>();
+        mDataManager.forAllPackages(
+                packageData -> packageData.forAllConversations(conversations::add));
+
+        // USER_ID_SECONDARY is not in the same profile group as USER_ID_PRIMARY.
+        assertEquals(2, conversations.size());
+
+        assertEquals("sc_1", conversations.get(0).getShortcutId());
+        assertTrue(conversations.get(0).isPersonImportant());
+        assertFalse(conversations.get(0).isPersonBot());
+        assertFalse(conversations.get(0).isContactStarred());
+        assertEquals(PHONE_NUMBER, conversations.get(0).getContactPhoneNumber());
+
+        assertEquals("sc_2", conversations.get(1).getShortcutId());
+        assertFalse(conversations.get(1).isPersonImportant());
+        assertTrue(conversations.get(1).isPersonBot());
+        assertFalse(conversations.get(0).isContactStarred());
+        assertEquals(PHONE_NUMBER, conversations.get(0).getContactPhoneNumber());
+    }
+
+    @Test
+    public void testAccessConversationForUnlockedUsersOnly() {
+        mDataManager.onUserUnlocked(USER_ID_PRIMARY);
+        mDataManager.onShortcutAddedOrUpdated(
+                buildShortcutInfo("pkg_1", USER_ID_PRIMARY, "sc_1", buildPerson()));
+        mDataManager.onShortcutAddedOrUpdated(
+                buildShortcutInfo("pkg_2", USER_ID_PRIMARY_MANAGED, "sc_2", buildPerson()));
+
+        List<ConversationInfo> conversations = new ArrayList<>();
+        mDataManager.forAllPackages(
+                packageData -> packageData.forAllConversations(conversations::add));
+
+        // USER_ID_PRIMARY_MANAGED is not locked, so only USER_ID_PRIMARY's conversation is stored.
+        assertEquals(1, conversations.size());
+        assertEquals("sc_1", conversations.get(0).getShortcutId());
+
+        mDataManager.onUserStopped(USER_ID_PRIMARY);
+        conversations.clear();
+        mDataManager.forAllPackages(
+                packageData -> packageData.forAllConversations(conversations::add));
+        assertTrue(conversations.isEmpty());
+    }
+
+    @Test
+    public void testGetShortcut() {
+        mDataManager.getShortcut(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID);
+        verify(mShortcutServiceInternal).getShortcuts(anyInt(), anyString(), anyLong(),
+                eq(TEST_PKG_NAME), eq(Collections.singletonList(TEST_SHORTCUT_ID)),
+                eq(null), anyInt(), eq(USER_ID_PRIMARY), anyInt(), anyInt());
+    }
+
+    @Test
+    public void testGetShareTargets() {
+        mDataManager.onUserUnlocked(USER_ID_PRIMARY);
+
+        ShortcutInfo shortcut1 =
+                buildShortcutInfo("pkg_1", USER_ID_PRIMARY, "sc_1", buildPerson());
+        ShareShortcutInfo shareShortcut1 =
+                new ShareShortcutInfo(shortcut1, new ComponentName("pkg_1", "activity"));
+
+        ShortcutInfo shortcut2 =
+                buildShortcutInfo("pkg_2", USER_ID_PRIMARY, "sc_2", buildPerson());
+        ShareShortcutInfo shareShortcut2 =
+                new ShareShortcutInfo(shortcut2, new ComponentName("pkg_2", "activity"));
+        mDataManager.onShortcutAddedOrUpdated(shortcut2);
+
+        when(mShortcutManager.getShareTargets(any(IntentFilter.class)))
+                .thenReturn(Arrays.asList(shareShortcut1, shareShortcut2));
+
+        List<ShareShortcutInfo> shareShortcuts =
+                mDataManager.getConversationShareTargets(new IntentFilter());
+        // Only "sc_2" is stored as a conversation.
+        assertEquals(1, shareShortcuts.size());
+        assertEquals("sc_2", shareShortcuts.get(0).getShortcutInfo().getId());
+    }
+
+    @Test
+    public void testReportAppTargetEvent() throws IntentFilter.MalformedMimeTypeException {
+        mDataManager.onUserUnlocked(USER_ID_PRIMARY);
+        ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
+                buildPerson());
+        mDataManager.onShortcutAddedOrUpdated(shortcut);
+
+        AppTarget appTarget = new AppTarget.Builder(new AppTargetId(TEST_SHORTCUT_ID), shortcut)
+                .build();
+        AppTargetEvent appTargetEvent =
+                new AppTargetEvent.Builder(appTarget, AppTargetEvent.ACTION_LAUNCH)
+                        .setLaunchLocation(ChooserActivity.LAUNCH_LOCATON_DIRECT_SHARE)
+                        .build();
+        IntentFilter intentFilter = new IntentFilter(Intent.ACTION_SEND, "image/jpg");
+        mDataManager.reportAppTargetEvent(appTargetEvent, intentFilter);
+
+        List<Range<Long>> activeShareTimeSlots = new ArrayList<>();
+        mDataManager.forAllPackages(packageData ->
+                activeShareTimeSlots.addAll(
+                        packageData.getEventHistory(TEST_SHORTCUT_ID)
+                                .getEventIndex(Event.TYPE_SHARE_IMAGE)
+                                .getActiveTimeSlots()));
+        assertEquals(1, activeShareTimeSlots.size());
+    }
+
+    @Test
+    public void testContactsChanged() {
+        mDataManager.onUserUnlocked(USER_ID_PRIMARY);
+
+        ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
+                buildPerson());
+        mDataManager.onShortcutAddedOrUpdated(shortcut);
+
+        final String newPhoneNumber = "+1000000000";
+        mInjector.mContactsQueryHelper.mIsStarred = true;
+        mInjector.mContactsQueryHelper.mPhoneNumber = newPhoneNumber;
+
+        ContentObserver contentObserver = mDataManager.getContactsContentObserverForTesting(
+                USER_ID_PRIMARY);
+        contentObserver.onChange(false, ContactsContract.Contacts.CONTENT_URI, USER_ID_PRIMARY);
+
+        List<ConversationInfo> conversations = new ArrayList<>();
+        mDataManager.forAllPackages(
+                packageData -> packageData.forAllConversations(conversations::add));
+        assertEquals(1, conversations.size());
+
+        assertEquals(TEST_SHORTCUT_ID, conversations.get(0).getShortcutId());
+        assertTrue(conversations.get(0).isContactStarred());
+        assertEquals(newPhoneNumber, conversations.get(0).getContactPhoneNumber());
+    }
+
+    @Test
+    public void testNotificationListener() {
+        mDataManager.onUserUnlocked(USER_ID_PRIMARY);
+
+        ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
+                buildPerson());
+        mDataManager.onShortcutAddedOrUpdated(shortcut);
+
+        NotificationListenerService listenerService =
+                mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);
+
+        listenerService.onNotificationRemoved(mStatusBarNotification, null,
+                NotificationListenerService.REASON_CLICK);
+
+        List<Range<Long>> activeNotificationOpenTimeSlots = new ArrayList<>();
+        mDataManager.forAllPackages(packageData ->
+                activeNotificationOpenTimeSlots.addAll(
+                        packageData.getEventHistory(TEST_SHORTCUT_ID)
+                                .getEventIndex(Event.TYPE_NOTIFICATION_OPENED)
+                                .getActiveTimeSlots()));
+        assertEquals(1, activeNotificationOpenTimeSlots.size());
+    }
+
+    @Test
+    public void testQueryUsageStatsService() {
+        UsageEvents.Event e = new UsageEvents.Event(SHORTCUT_INVOCATION,
+                System.currentTimeMillis());
+        e.mPackage = TEST_PKG_NAME;
+        e.mShortcutId = TEST_SHORTCUT_ID;
+        List<UsageEvents.Event> events = new ArrayList<>();
+        events.add(e);
+        UsageEvents usageEvents = new UsageEvents(events, new String[]{});
+        when(mUsageStatsManagerInternal.queryEventsForUser(anyInt(), anyLong(), anyLong(),
+                anyBoolean())).thenReturn(usageEvents);
+
+        mDataManager.onUserUnlocked(USER_ID_PRIMARY);
+
+        ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
+                buildPerson());
+        mDataManager.onShortcutAddedOrUpdated(shortcut);
+
+        mDataManager.queryUsageStatsService(USER_ID_PRIMARY, 0L, Long.MAX_VALUE);
+
+        List<Range<Long>> activeShortcutInvocationTimeSlots = new ArrayList<>();
+        mDataManager.forAllPackages(packageData ->
+                activeShortcutInvocationTimeSlots.addAll(
+                        packageData.getEventHistory(TEST_SHORTCUT_ID)
+                                .getEventIndex(Event.TYPE_SHORTCUT_INVOCATION)
+                                .getActiveTimeSlots()));
+        assertEquals(1, activeShortcutInvocationTimeSlots.size());
+    }
+
+    private static <T> void addLocalServiceMock(Class<T> clazz, T mock) {
+        LocalServices.removeServiceForTest(clazz);
+        LocalServices.addService(clazz, mock);
+    }
+
+    private ShortcutInfo buildShortcutInfo(String packageName, int userId, String id,
+            @Nullable Person person) {
+        Context mockContext = mock(Context.class);
+        when(mockContext.getPackageName()).thenReturn(packageName);
+        when(mockContext.getUserId()).thenReturn(userId);
+        when(mockContext.getUser()).thenReturn(UserHandle.of(userId));
+        ShortcutInfo.Builder builder = new ShortcutInfo.Builder(mockContext, id)
+                .setShortLabel(id)
+                .setIntent(new Intent("TestIntent"));
+        if (person != null) {
+            builder.setPersons(new Person[] {person});
+        }
+        return builder.build();
+    }
+
+    private Person buildPerson() {
+        return buildPerson(true, false);
+    }
+
+    private Person buildPerson(boolean isImportant, boolean isBot) {
+        return new Person.Builder()
+                .setImportant(isImportant)
+                .setBot(isBot)
+                .setUri(CONTACT_URI)
+                .build();
+    }
+
+    private UserInfo buildUserInfo(int userId) {
+        return new UserInfo(userId, "", 0);
+    }
+
+    private class TestContactsQueryHelper extends ContactsQueryHelper {
+
+        private Uri mContactUri;
+        private boolean mIsStarred;
+        private String mPhoneNumber;
+
+        TestContactsQueryHelper(Context context) {
+            super(context);
+            mContactUri = Uri.parse(CONTACT_URI);
+            mIsStarred = false;
+            mPhoneNumber = PHONE_NUMBER;
+        }
+
+        @Override
+        boolean query(@NonNull String contactUri) {
+            return true;
+        }
+
+        @Override
+        boolean querySince(long sinceTime) {
+            return true;
+        }
+
+        @Override
+        @Nullable
+        Uri getContactUri() {
+            return mContactUri;
+        }
+
+        @Override
+        boolean isStarred() {
+            return mIsStarred;
+        }
+
+        @Override
+        @Nullable
+        String getPhoneNumber() {
+            return mPhoneNumber;
+        }
+    }
+
+    private class TestInjector extends DataManager.Injector {
+
+        private final TestContactsQueryHelper mContactsQueryHelper =
+                new TestContactsQueryHelper(mContext);
+
+        @Override
+        ScheduledExecutorService createScheduledExecutor() {
+            return mExecutorService;
+        }
+
+        @Override
+        ContactsQueryHelper createContactsQueryHelper(Context context) {
+            return mContactsQueryHelper;
+        }
+
+        @Override
+        int getCallingUserId() {
+            return mCallingUserId;
+        }
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/people/data/EventHistoryImplTest.java b/services/tests/servicestests/src/com/android/server/people/data/EventHistoryImplTest.java
new file mode 100644
index 0000000..43e1001
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/people/data/EventHistoryImplTest.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2020 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.people.data;
+
+import static com.android.server.people.data.TestUtils.timestamp;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import com.google.android.collect.Sets;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.util.List;
+
+@RunWith(JUnit4.class)
+public final class EventHistoryImplTest {
+
+    private static final long CURRENT_TIMESTAMP = timestamp("01-30 18:50");
+
+    private static final Event E1 = new Event(timestamp("01-06 05:26"),
+            Event.TYPE_NOTIFICATION_OPENED);
+    private static final Event E2 = new Event(timestamp("01-27 18:41"),
+            Event.TYPE_NOTIFICATION_OPENED);
+    private static final Event E3 = new Event(timestamp("01-30 03:06"),
+            Event.TYPE_SHARE_IMAGE);
+    private static final Event E4 = new Event(timestamp("01-30 18:14"),
+            Event.TYPE_SMS_INCOMING);
+
+    private EventHistoryImpl mEventHistory;
+
+    @Before
+    public void setUp() {
+        EventIndex.Injector eventIndexInjector = new EventIndex.Injector() {
+            @Override
+            long currentTimeMillis() {
+                return CURRENT_TIMESTAMP;
+            }
+        };
+        EventHistoryImpl.Injector eventHistoryInjector = new EventHistoryImpl.Injector() {
+            @Override
+            EventIndex createEventIndex() {
+                return new EventIndex(eventIndexInjector);
+            }
+        };
+        mEventHistory = new EventHistoryImpl(eventHistoryInjector);
+    }
+
+    @Test
+    public void testNoEvents() {
+        EventIndex eventIndex = mEventHistory.getEventIndex(Event.ALL_EVENT_TYPES);
+        assertTrue(eventIndex.isEmpty());
+
+        List<Event> events = mEventHistory.queryEvents(Event.ALL_EVENT_TYPES, 0L, 999L);
+        assertTrue(events.isEmpty());
+    }
+
+    @Test
+    public void testMultipleEvents() {
+        mEventHistory.addEvent(E1);
+        mEventHistory.addEvent(E2);
+        mEventHistory.addEvent(E3);
+        mEventHistory.addEvent(E4);
+
+        EventIndex eventIndex = mEventHistory.getEventIndex(Event.ALL_EVENT_TYPES);
+        assertEquals(4, eventIndex.getActiveTimeSlots().size());
+
+        List<Event> events = mEventHistory.queryEvents(Event.ALL_EVENT_TYPES, 0L, Long.MAX_VALUE);
+        assertEquals(4, events.size());
+    }
+
+    @Test
+    public void testQuerySomeEventTypes() {
+        mEventHistory.addEvent(E1);
+        mEventHistory.addEvent(E2);
+        mEventHistory.addEvent(E3);
+        mEventHistory.addEvent(E4);
+
+        EventIndex eventIndex = mEventHistory.getEventIndex(Event.NOTIFICATION_EVENT_TYPES);
+        assertEquals(2, eventIndex.getActiveTimeSlots().size());
+
+        List<Event> events = mEventHistory.queryEvents(
+                Event.NOTIFICATION_EVENT_TYPES, 0L, Long.MAX_VALUE);
+        assertEquals(2, events.size());
+    }
+
+    @Test
+    public void testQuerySingleEventType() {
+        mEventHistory.addEvent(E1);
+        mEventHistory.addEvent(E2);
+        mEventHistory.addEvent(E3);
+        mEventHistory.addEvent(E4);
+
+        EventIndex eventIndex = mEventHistory.getEventIndex(Event.TYPE_SHARE_IMAGE);
+        assertEquals(1, eventIndex.getActiveTimeSlots().size());
+
+        List<Event> events = mEventHistory.queryEvents(
+                Sets.newArraySet(Event.TYPE_SHARE_IMAGE), 0L, Long.MAX_VALUE);
+        assertEquals(1, events.size());
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/people/data/EventIndexTest.java b/services/tests/servicestests/src/com/android/server/people/data/EventIndexTest.java
new file mode 100644
index 0000000..e87f428
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/people/data/EventIndexTest.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2020 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.people.data;
+
+import static com.android.server.people.data.TestUtils.timestamp;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import android.util.Range;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.util.List;
+
+@RunWith(JUnit4.class)
+public final class EventIndexTest {
+
+    private static final long CURRENT_TIMESTAMP = timestamp("01-30 18:50");
+    private static final long SECONDS_PER_HOUR = 60L * 60L;
+    private static final long SECONDS_PER_DAY = SECONDS_PER_HOUR * 24L;
+
+    private TestInjector mInjector;
+    private EventIndex mEventIndex;
+
+    @Before
+    public void setUp() {
+        mInjector = new TestInjector(CURRENT_TIMESTAMP);
+        mEventIndex = new EventIndex(mInjector);
+    }
+
+    @Test
+    public void testNoEvents() {
+        assertTrue(mEventIndex.isEmpty());
+        assertNull(mEventIndex.getMostRecentActiveTimeSlot());
+        assertTrue(mEventIndex.getActiveTimeSlots().isEmpty());
+    }
+
+    @Test
+    public void testMultipleEvents() {
+        mEventIndex.addEvent(timestamp("01-06 05:26"));
+        mEventIndex.addEvent(timestamp("01-27 18:41"));
+        mEventIndex.addEvent(timestamp("01-30 03:06"));
+        mEventIndex.addEvent(timestamp("01-30 18:14"));
+
+        assertFalse(mEventIndex.isEmpty());
+        Range<Long> mostRecentSlot = mEventIndex.getMostRecentActiveTimeSlot();
+        assertNotNull(mostRecentSlot);
+        assertTimeSlot(timestamp("01-30 18:14"), timestamp("01-30 18:16"), mostRecentSlot);
+
+        List<Range<Long>> slots = mEventIndex.getActiveTimeSlots();
+        assertEquals(4, slots.size());
+        assertTimeSlot(timestamp("01-06 00:00"), timestamp("01-07 00:00"), slots.get(0));
+        assertTimeSlot(timestamp("01-27 16:00"), timestamp("01-27 20:00"), slots.get(1));
+        assertTimeSlot(timestamp("01-30 03:00"), timestamp("01-30 04:00"), slots.get(2));
+        assertTimeSlot(timestamp("01-30 18:14"), timestamp("01-30 18:16"), slots.get(3));
+    }
+
+    @Test
+    public void testBitmapShift() {
+        mEventIndex.addEvent(CURRENT_TIMESTAMP);
+        List<Range<Long>> slots;
+
+        slots = mEventIndex.getActiveTimeSlots();
+        assertEquals(1, slots.size());
+        assertTimeSlot(timestamp("01-30 18:50"), timestamp("01-30 18:52"), slots.get(0));
+
+        mInjector.moveTimeForwardSeconds(SECONDS_PER_HOUR * 3L);
+        mEventIndex.update();
+        slots = mEventIndex.getActiveTimeSlots();
+        assertEquals(1, slots.size());
+        assertTimeSlot(timestamp("01-30 18:00"), timestamp("01-30 19:00"), slots.get(0));
+
+        mInjector.moveTimeForwardSeconds(SECONDS_PER_DAY * 6L);
+        mEventIndex.update();
+        slots = mEventIndex.getActiveTimeSlots();
+        assertEquals(1, slots.size());
+        assertTimeSlot(timestamp("01-30 16:00"), timestamp("01-30 20:00"), slots.get(0));
+
+        mInjector.moveTimeForwardSeconds(SECONDS_PER_DAY * 30L);
+        mEventIndex.update();
+        slots = mEventIndex.getActiveTimeSlots();
+        assertEquals(1, slots.size());
+        assertTimeSlot(timestamp("01-30 00:00"), timestamp("01-31 00:00"), slots.get(0));
+
+        mInjector.moveTimeForwardSeconds(SECONDS_PER_DAY * 80L);
+        mEventIndex.update();
+        slots = mEventIndex.getActiveTimeSlots();
+        // The event has been shifted off the left end.
+        assertTrue(slots.isEmpty());
+    }
+
+    @Test
+    public void testCopyConstructor() {
+        mEventIndex.addEvent(timestamp("01-06 05:26"));
+        mEventIndex.addEvent(timestamp("01-27 18:41"));
+        mEventIndex.addEvent(timestamp("01-30 03:06"));
+        mEventIndex.addEvent(timestamp("01-30 18:14"));
+
+        List<Range<Long>> slots = mEventIndex.getActiveTimeSlots();
+
+        EventIndex newIndex = new EventIndex(mEventIndex);
+        List<Range<Long>> newSlots = newIndex.getActiveTimeSlots();
+
+        assertEquals(slots.size(), newSlots.size());
+        for (int i = 0; i < slots.size(); i++) {
+            assertEquals(slots.get(i), newSlots.get(i));
+        }
+    }
+
+    @Test
+    public void combineEventIndexes() {
+        EventIndex a = new EventIndex(mInjector);
+        mInjector.mCurrentTimeMillis = timestamp("01-27 18:41");
+        a.addEvent(mInjector.mCurrentTimeMillis);
+        mInjector.mCurrentTimeMillis = timestamp("01-30 03:06");
+        a.addEvent(mInjector.mCurrentTimeMillis);
+
+        mInjector.mCurrentTimeMillis = CURRENT_TIMESTAMP;
+        EventIndex b = new EventIndex(mInjector);
+        b.addEvent(timestamp("01-06 05:26"));
+        b.addEvent(timestamp("01-30 18:14"));
+
+        EventIndex combined = EventIndex.combine(a, b);
+        List<Range<Long>> slots = combined.getActiveTimeSlots();
+        assertEquals(4, slots.size());
+        assertTimeSlot(timestamp("01-06 00:00"), timestamp("01-07 00:00"), slots.get(0));
+        assertTimeSlot(timestamp("01-27 16:00"), timestamp("01-27 20:00"), slots.get(1));
+        assertTimeSlot(timestamp("01-30 03:00"), timestamp("01-30 04:00"), slots.get(2));
+        assertTimeSlot(timestamp("01-30 18:14"), timestamp("01-30 18:16"), slots.get(3));
+    }
+
+    private static void assertTimeSlot(
+            long expectedLower, long expectedUpper, Range<Long> actualSlot) {
+        assertEquals(expectedLower, actualSlot.getLower().longValue());
+        assertEquals(expectedUpper, actualSlot.getUpper().longValue());
+    }
+
+    private class TestInjector extends EventIndex.Injector {
+
+        private long mCurrentTimeMillis;
+
+        TestInjector(long currentTimeMillis) {
+            mCurrentTimeMillis = currentTimeMillis;
+        }
+
+        private void moveTimeForwardSeconds(long seconds) {
+            mCurrentTimeMillis += (seconds * 1000L);
+        }
+
+        @Override
+        long currentTimeMillis() {
+            return mCurrentTimeMillis;
+        }
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/people/data/EventListTest.java b/services/tests/servicestests/src/com/android/server/people/data/EventListTest.java
new file mode 100644
index 0000000..f2f372c
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/people/data/EventListTest.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2020 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.people.data;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import com.google.android.collect.Lists;
+import com.google.android.collect.Sets;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.util.List;
+
+@RunWith(JUnit4.class)
+public final class EventListTest {
+
+    private static final Event E1 = new Event(101L, Event.TYPE_NOTIFICATION_OPENED);
+    private static final Event E2 = new Event(103L, Event.TYPE_NOTIFICATION_OPENED);
+    private static final Event E3 = new Event(107L, Event.TYPE_SHARE_IMAGE);
+    private static final Event E4 = new Event(109L, Event.TYPE_SMS_INCOMING);
+
+    private EventList mEventList;
+
+    @Before
+    public void setUp() {
+        mEventList = new EventList();
+    }
+
+    @Test
+    public void testQueryEmptyEventList() {
+        List<Event> events = mEventList.queryEvents(Event.ALL_EVENT_TYPES, 0L, 999L);
+        assertTrue(events.isEmpty());
+    }
+
+    @Test
+    public void testAddAndQueryEvents() {
+        List<Event> in = Lists.newArrayList(E1, E2, E3, E4);
+        for (Event e : in) {
+            mEventList.add(e);
+        }
+
+        List<Event> out = mEventList.queryEvents(Event.ALL_EVENT_TYPES, 0L, 999L);
+        assertEventListEquals(in, out);
+    }
+
+    @Test
+    public void testAddEventsNotInOrder() {
+        mEventList.add(E3);
+        mEventList.add(E1);
+        mEventList.add(E4);
+        mEventList.add(E2);
+
+        List<Event> out = mEventList.queryEvents(Event.ALL_EVENT_TYPES, 0L, 999L);
+        List<Event> expected = Lists.newArrayList(E1, E2, E3, E4);
+        assertEventListEquals(expected, out);
+    }
+
+    @Test
+    public void testQueryEventsByType() {
+        mEventList.add(E1);
+        mEventList.add(E2);
+        mEventList.add(E3);
+        mEventList.add(E4);
+
+        List<Event> out = mEventList.queryEvents(
+                Sets.newArraySet(Event.TYPE_NOTIFICATION_OPENED), 0L, 999L);
+        assertEventListEquals(Lists.newArrayList(E1, E2), out);
+    }
+
+    @Test
+    public void testQueryEventsByTimeRange() {
+        mEventList.add(E1);
+        mEventList.add(E2);
+        mEventList.add(E3);
+        mEventList.add(E4);
+
+        List<Event> out = mEventList.queryEvents(Event.ALL_EVENT_TYPES, 103L, 109L);
+        // Only E2 and E3 are in the time range [103L, 109L).
+        assertEventListEquals(Lists.newArrayList(E2, E3), out);
+    }
+
+    @Test
+    public void testQueryEventsOutOfRange() {
+        mEventList.add(E1);
+        mEventList.add(E2);
+        mEventList.add(E3);
+        mEventList.add(E4);
+
+        List<Event> out = mEventList.queryEvents(Event.ALL_EVENT_TYPES, 900L, 900L);
+        assertTrue(out.isEmpty());
+    }
+
+    @Test
+    public void testAddDuplicateEvents() {
+        mEventList.add(E1);
+        mEventList.add(E2);
+        mEventList.add(E2);
+        mEventList.add(E3);
+        mEventList.add(E2);
+        mEventList.add(E3);
+        mEventList.add(E3);
+        mEventList.add(E4);
+        mEventList.add(E1);
+        mEventList.add(E3);
+        mEventList.add(E2);
+
+        List<Event> out = mEventList.queryEvents(Event.ALL_EVENT_TYPES, 0L, 999L);
+        List<Event> expected = Lists.newArrayList(E1, E2, E3, E4);
+        assertEventListEquals(expected, out);
+    }
+
+    private static void assertEventListEquals(List<Event> expected, List<Event> actual) {
+        assertEquals(expected.size(), actual.size());
+        for (int i = 0; i < expected.size(); i++) {
+            assertEquals(expected.get(i).getTimestamp(), actual.get(i).getTimestamp());
+            assertEquals(expected.get(i).getType(), actual.get(i).getType());
+        }
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/people/data/PackageDataTest.java b/services/tests/servicestests/src/com/android/server/people/data/PackageDataTest.java
new file mode 100644
index 0000000..1b80d6f
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/people/data/PackageDataTest.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2020 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.people.data;
+
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.content.LocusId;
+import android.content.pm.ShortcutInfo;
+import android.net.Uri;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.util.List;
+
+@RunWith(JUnit4.class)
+public final class PackageDataTest {
+
+    private static final String PACKAGE_NAME = "com.google.test";
+    private static final int USER_ID = 0;
+    private static final String SHORTCUT_ID = "abc";
+    private static final LocusId LOCUS_ID = new LocusId("def");
+    private static final Uri CONTACT_URI = Uri.parse("tel:+1234567890");
+    private static final String PHONE_NUMBER = "+1234567890";
+
+    private Event mE1;
+    private Event mE2;
+    private Event mE3;
+    private Event mE4;
+
+    private PackageData mPackageData;
+
+    @Before
+    public void setUp() {
+        mPackageData = new PackageData(PACKAGE_NAME, USER_ID);
+        ConversationInfo conversationInfo = new ConversationInfo.Builder()
+                .setShortcutId(SHORTCUT_ID)
+                .setLocusId(LOCUS_ID)
+                .setContactUri(CONTACT_URI)
+                .setContactPhoneNumber(PHONE_NUMBER)
+                .setShortcutFlags(ShortcutInfo.FLAG_LONG_LIVED)
+                .build();
+        mPackageData.getConversationStore().addOrUpdate(conversationInfo);
+
+        long currentTimestamp = System.currentTimeMillis();
+        mE1 = new Event(currentTimestamp - 800L, Event.TYPE_SHORTCUT_INVOCATION);
+        mE2 = new Event(currentTimestamp - 700L, Event.TYPE_NOTIFICATION_OPENED);
+        mE3 = new Event(currentTimestamp - 600L, Event.TYPE_CALL_INCOMING);
+        mE4 = new Event(currentTimestamp - 500L, Event.TYPE_SMS_OUTGOING);
+    }
+
+    @Test
+    public void testGetEventHistory() {
+        EventStore eventStore = mPackageData.getEventStore();
+        eventStore.getOrCreateShortcutEventHistory(SHORTCUT_ID).addEvent(mE1);
+        eventStore.getOrCreateLocusEventHistory(LOCUS_ID).addEvent(mE2);
+
+        EventHistory eventHistory = mPackageData.getEventHistory(SHORTCUT_ID);
+        List<Event> events = eventHistory.queryEvents(Event.ALL_EVENT_TYPES, 0L, Long.MAX_VALUE);
+        assertEquals(2, events.size());
+        assertEventEquals(mE1, events.get(0));
+        assertEventEquals(mE2, events.get(1));
+    }
+
+    @Test
+    public void testGetEventHistoryDefaultDialerAndSmsApp() {
+        mPackageData.setIsDefaultDialer(true);
+        mPackageData.setIsDefaultSmsApp(true);
+        EventStore eventStore = mPackageData.getEventStore();
+        eventStore.getOrCreateShortcutEventHistory(SHORTCUT_ID).addEvent(mE1);
+        eventStore.getOrCreateCallEventHistory(PHONE_NUMBER).addEvent(mE3);
+        eventStore.getOrCreateSmsEventHistory(PHONE_NUMBER).addEvent(mE4);
+
+        assertTrue(mPackageData.isDefaultDialer());
+        assertTrue(mPackageData.isDefaultSmsApp());
+        EventHistory eventHistory = mPackageData.getEventHistory(SHORTCUT_ID);
+        List<Event> events = eventHistory.queryEvents(Event.ALL_EVENT_TYPES, 0L, Long.MAX_VALUE);
+        assertEquals(3, events.size());
+        assertEventEquals(mE1, events.get(0));
+        assertEventEquals(mE3, events.get(1));
+        assertEventEquals(mE4, events.get(2));
+    }
+
+    @Test
+    public void testGetEventHistoryNotDefaultDialerOrSmsApp() {
+        EventStore eventStore = mPackageData.getEventStore();
+        eventStore.getOrCreateShortcutEventHistory(SHORTCUT_ID).addEvent(mE1);
+        eventStore.getOrCreateCallEventHistory(PHONE_NUMBER).addEvent(mE3);
+        eventStore.getOrCreateSmsEventHistory(PHONE_NUMBER).addEvent(mE4);
+
+        assertFalse(mPackageData.isDefaultDialer());
+        assertFalse(mPackageData.isDefaultSmsApp());
+        EventHistory eventHistory = mPackageData.getEventHistory(SHORTCUT_ID);
+        List<Event> events = eventHistory.queryEvents(Event.ALL_EVENT_TYPES, 0L, Long.MAX_VALUE);
+        assertEquals(1, events.size());
+        assertEventEquals(mE1, events.get(0));
+    }
+
+    private void assertEventEquals(Event expected, Event actual) {
+        assertEquals(expected.getTimestamp(), actual.getTimestamp());
+        assertEquals(expected.getType(), actual.getType());
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/people/data/TestUtils.java b/services/tests/servicestests/src/com/android/server/people/data/TestUtils.java
new file mode 100644
index 0000000..41889aa
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/people/data/TestUtils.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2020 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.people.data;
+
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
+
+final class TestUtils {
+
+    /**
+     * Gets the epoch time in millis for the specified time string.
+     * @param timeString e.g. "01-02 15:20"
+     * @return epoch time in millis
+     */
+    static long timestamp(String timeString) {
+        String str = String.format("2020-%s", timeString);
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
+        return toEpochMilli(LocalDateTime.parse(str, formatter));
+    }
+
+    private static long toEpochMilli(LocalDateTime localDateTime) {
+        return localDateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
+    }
+
+    private TestUtils() {
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java b/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
index 7f66f3c..3e3f40d 100644
--- a/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
@@ -27,6 +27,8 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageParser;
+import android.content.pm.Signature;
 import android.content.pm.parsing.AndroidPackage;
 import android.content.pm.parsing.ComponentParseUtils;
 import android.content.pm.parsing.ComponentParseUtils.ParsedActivity;
@@ -48,8 +50,10 @@
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
 import org.mockito.Mock;
+import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 
+import java.security.cert.CertificateException;
 import java.util.Collections;
 import java.util.Map;
 import java.util.Set;
@@ -284,6 +288,33 @@
         assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0));
     }
 
+
+    @Test
+    public void testSystemSignedTarget_DoesntFilter() throws CertificateException {
+        final AppsFilter appsFilter =
+                new AppsFilter(mFeatureConfigMock, new String[]{}, false, null);
+        appsFilter.onSystemReady();
+
+        final Signature frameworkSignature = Mockito.mock(Signature.class);
+        final PackageParser.SigningDetails frameworkSigningDetails =
+                new PackageParser.SigningDetails(new Signature[]{frameworkSignature}, 1);
+
+        final Signature otherSignature = Mockito.mock(Signature.class);
+        final PackageParser.SigningDetails otherSigningDetails =
+                new PackageParser.SigningDetails(new Signature[]{otherSignature}, 1);
+
+        simulateAddPackage(appsFilter, pkg("android"), 1000,
+                b -> b.setSigningDetails(frameworkSigningDetails));
+        PackageSetting target = simulateAddPackage(appsFilter, pkg("com.some.package"),
+                DUMMY_TARGET_UID,
+                b -> b.setSigningDetails(frameworkSigningDetails));
+        PackageSetting calling = simulateAddPackage(appsFilter,
+                pkg("com.some.other.package"), DUMMY_CALLING_UID,
+                b -> b.setSigningDetails(otherSigningDetails));
+
+        assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0));
+    }
+
     @Test
     public void testForceQueryableByDevice_NonSystemCaller_Filters() {
         final AppsFilter appsFilter =
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageSettingBuilder.java b/services/tests/servicestests/src/com/android/server/pm/PackageSettingBuilder.java
index 8441494..338d5fa 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageSettingBuilder.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageSettingBuilder.java
@@ -16,6 +16,7 @@
 
 package com.android.server.pm;
 
+import android.content.pm.PackageParser;
 import android.content.pm.PackageUserState;
 import android.content.pm.parsing.AndroidPackage;
 import android.util.SparseArray;
@@ -42,6 +43,7 @@
     private AndroidPackage mPkg;
     private int mAppId;
     private InstallSource mInstallSource;
+    private PackageParser.SigningDetails mSigningDetails;
 
     public PackageSettingBuilder setPackage(AndroidPackage pkg) {
         this.mPkg = pkg;
@@ -143,12 +145,21 @@
         return this;
     }
 
+    public PackageSettingBuilder setSigningDetails(
+            PackageParser.SigningDetails signingDetails) {
+        mSigningDetails = signingDetails;
+        return this;
+    }
+
     public PackageSetting build() {
         final PackageSetting packageSetting = new PackageSetting(mName, mRealName,
                 new File(mCodePath), new File(mResourcePath),
                 mLegacyNativeLibraryPathString, mPrimaryCpuAbiString, mSecondaryCpuAbiString,
                 mCpuAbiOverrideString, mPVersionCode, mPkgFlags, mPrivateFlags, mSharedUserId,
                 mUsesStaticLibraries, mUsesStaticLibrariesVersions);
+        packageSetting.signatures = mSigningDetails != null
+                ? new PackageSignatures(mSigningDetails)
+                : new PackageSignatures();
         packageSetting.pkg = mPkg;
         packageSetting.appId = mAppId;
         packageSetting.volumeUuid = this.mVolumeUuid;
diff --git a/services/tests/servicestests/src/com/android/server/power/WakeLockLogTest.java b/services/tests/servicestests/src/com/android/server/power/WakeLockLogTest.java
new file mode 100644
index 0000000..a03ba9c
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/power/WakeLockLogTest.java
@@ -0,0 +1,268 @@
+/*
+ * 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.power;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.os.Looper;
+import android.os.PowerManager;
+import android.os.test.TestLooper;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.text.SimpleDateFormat;
+import java.util.TimeZone;
+
+/**
+ * Tests for {@link WakeLockLog}.
+ */
+public class WakeLockLogTest {
+
+    private TestLooper mTestLooper;
+
+    @Before
+    public void setUp() throws Exception {
+        mTestLooper = new TestLooper();
+    }
+
+    @After
+    public void tearDown() throws Exception {
+    }
+
+    @Test
+    public void testAddTwoItems() {
+        final int tagDatabaseSize = 128;
+        final int logSize = 20;
+        TestInjector injectorSpy = spy(new TestInjector(tagDatabaseSize, logSize));
+        WakeLockLog log = new WakeLockLog(injectorSpy);
+
+        when(injectorSpy.currentTimeMillis()).thenReturn(1000L);
+        log.onWakeLockAcquired("TagPartial", 101,
+                PowerManager.PARTIAL_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE);
+
+        when(injectorSpy.currentTimeMillis()).thenReturn(1150L);
+        log.onWakeLockAcquired("TagFull", 102,
+                PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP);
+
+        assertEquals("Wake Lock Log\n"
+                + "  01-01 00:00:01.000 - 101 - ACQ TagPartial (partial,on-after-release)\n"
+                + "  01-01 00:00:01.150 - 102 - ACQ TagFull (full,acq-causes-wake)\n"
+                + "  -\n"
+                + "  Events: 2, Time-Resets: 0\n"
+                + "  Buffer, Bytes used: 6\n",
+                dispatchAndDump(log, false));
+    }
+
+    @Test
+    public void testAddTwoItemsWithTimeReset() {
+        final int tagDatabaseSize = 128;
+        final int logSize = 20;
+        TestInjector injectorSpy = spy(new TestInjector(tagDatabaseSize, logSize));
+        WakeLockLog log = new WakeLockLog(injectorSpy);
+
+        when(injectorSpy.currentTimeMillis()).thenReturn(1000L);
+        log.onWakeLockAcquired("TagPartial", 101, PowerManager.PARTIAL_WAKE_LOCK);
+
+        when(injectorSpy.currentTimeMillis()).thenReturn(1350L);
+        log.onWakeLockAcquired("TagFull", 102, PowerManager.FULL_WAKE_LOCK);
+
+        assertEquals("Wake Lock Log\n"
+                + "  01-01 00:00:01.000 - 101 - ACQ TagPartial (partial)\n"
+                + "  01-01 00:00:01.350 - 102 - ACQ TagFull (full)\n"
+                + "  -\n"
+                + "  Events: 2, Time-Resets: 1\n"
+                + "  Buffer, Bytes used: 15\n",
+                dispatchAndDump(log, false));
+    }
+
+    @Test
+    public void testAddTwoItemsWithTagOverwrite() {
+        final int tagDatabaseSize = 2;
+        final int logSize = 20;
+        TestInjector injectorSpy = spy(new TestInjector(tagDatabaseSize, logSize));
+        WakeLockLog log = new WakeLockLog(injectorSpy);
+
+        when(injectorSpy.currentTimeMillis()).thenReturn(1000L);
+        log.onWakeLockAcquired("TagPartial", 101, PowerManager.PARTIAL_WAKE_LOCK);
+
+        when(injectorSpy.currentTimeMillis()).thenReturn(1150L);
+        log.onWakeLockAcquired("TagFull", 102, PowerManager.FULL_WAKE_LOCK);
+
+        assertEquals("Wake Lock Log\n"
+                + "  01-01 00:00:01.000 - --- - ACQ UNKNOWN (partial)\n"
+                + "  01-01 00:00:01.150 - 102 - ACQ TagFull (full)\n"
+                + "  -\n"
+                + "  Events: 2, Time-Resets: 0\n"
+                + "  Buffer, Bytes used: 6\n",
+                dispatchAndDump(log, false));
+    }
+
+    @Test
+    public void testAddFourItemsWithRingBufferOverflow() {
+        final int tagDatabaseSize = 6;
+        final int logSize = 10;
+        TestInjector injectorSpy = spy(new TestInjector(tagDatabaseSize, logSize));
+        WakeLockLog log = new WakeLockLog(injectorSpy);
+
+        // This first item will get deleted when ring buffer loops around
+        when(injectorSpy.currentTimeMillis()).thenReturn(1000L);
+        log.onWakeLockAcquired("TagPartial", 101, PowerManager.PARTIAL_WAKE_LOCK);
+
+        when(injectorSpy.currentTimeMillis()).thenReturn(1150L);
+        log.onWakeLockAcquired("TagFull", 102, PowerManager.FULL_WAKE_LOCK);
+        when(injectorSpy.currentTimeMillis()).thenReturn(1151L);
+        log.onWakeLockAcquired("TagThree", 101, PowerManager.PARTIAL_WAKE_LOCK);
+        when(injectorSpy.currentTimeMillis()).thenReturn(1152L);
+        log.onWakeLockAcquired("TagFour", 101, PowerManager.PARTIAL_WAKE_LOCK);
+
+        assertEquals("Wake Lock Log\n"
+                + "  01-01 00:00:01.150 - 102 - ACQ TagFull (full)\n"
+                + "  01-01 00:00:01.151 - 101 - ACQ TagThree (partial)\n"
+                + "  01-01 00:00:01.152 - 101 - ACQ TagFour (partial)\n"
+                + "  -\n"
+                + "  Events: 3, Time-Resets: 0\n"
+                + "  Buffer, Bytes used: 9\n",
+                dispatchAndDump(log, false));
+    }
+
+    @Test
+    public void testAddItemWithBadTag() {
+        final int tagDatabaseSize = 6;
+        final int logSize = 10;
+        TestInjector injectorSpy = spy(new TestInjector(tagDatabaseSize, logSize));
+        WakeLockLog log = new WakeLockLog(injectorSpy);
+
+        // Bad tag means it wont get written
+        when(injectorSpy.currentTimeMillis()).thenReturn(1000L);
+        log.onWakeLockAcquired(null /* tag */, 0 /* ownerUid */, PowerManager.PARTIAL_WAKE_LOCK);
+
+        assertEquals("Wake Lock Log\n"
+                + "  -\n"
+                + "  Events: 0, Time-Resets: 0\n"
+                + "  Buffer, Bytes used: 0\n",
+                dispatchAndDump(log, false));
+    }
+
+    @Test
+    public void testAddItemWithReducedTagName() {
+        final int tagDatabaseSize = 6;
+        final int logSize = 10;
+        TestInjector injectorSpy = spy(new TestInjector(tagDatabaseSize, logSize));
+        WakeLockLog log = new WakeLockLog(injectorSpy);
+
+        when(injectorSpy.currentTimeMillis()).thenReturn(1000L);
+        log.onWakeLockAcquired("*job*/com.one.two.3hree/.one..Last", 101,
+                PowerManager.PARTIAL_WAKE_LOCK);
+
+        assertEquals("Wake Lock Log\n"
+                + "  01-01 00:00:01.000 - 101 - ACQ *job*/c.o.t.3/.o..Last (partial)\n"
+                + "  -\n"
+                + "  Events: 1, Time-Resets: 0\n"
+                + "  Buffer, Bytes used: 3\n",
+                dispatchAndDump(log, false));
+    }
+
+    @Test
+    public void testAddAcquireAndReleaseWithRepeatTagName() {
+        final int tagDatabaseSize = 6;
+        final int logSize = 10;
+        TestInjector injectorSpy = spy(new TestInjector(tagDatabaseSize, logSize));
+        WakeLockLog log = new WakeLockLog(injectorSpy);
+
+        when(injectorSpy.currentTimeMillis()).thenReturn(1000L);
+        log.onWakeLockAcquired("HowdyTag", 101, PowerManager.PARTIAL_WAKE_LOCK);
+        when(injectorSpy.currentTimeMillis()).thenReturn(1001L);
+        log.onWakeLockReleased("HowdyTag", 101);
+
+        assertEquals("Wake Lock Log\n"
+                + "  01-01 00:00:01.000 - 101 - ACQ HowdyTag (partial)\n"
+                + "  01-01 00:00:01.001 - 101 - REL HowdyTag\n"
+                + "  -\n"
+                + "  Events: 2, Time-Resets: 0\n"
+                + "  Buffer, Bytes used: 5\n"
+                + "  Tag Database: size(5), entries: 1, Bytes used: 80\n",
+                dispatchAndDump(log, true));
+    }
+
+    @Test
+    public void testAddAcquireAndReleaseWithTimeTravel() {
+        final int tagDatabaseSize = 6;
+        final int logSize = 10;
+        TestInjector injectorSpy = spy(new TestInjector(tagDatabaseSize, logSize));
+        WakeLockLog log = new WakeLockLog(injectorSpy);
+
+        when(injectorSpy.currentTimeMillis()).thenReturn(1100L);
+        log.onWakeLockAcquired("HowdyTag", 101, PowerManager.PARTIAL_WAKE_LOCK);
+
+        // New element goes back in time...should not be written to log.
+        when(injectorSpy.currentTimeMillis()).thenReturn(1000L);
+        log.onWakeLockReleased("HowdyTag", 101);
+
+        assertEquals("Wake Lock Log\n"
+                + "  01-01 00:00:01.100 - 101 - ACQ HowdyTag (partial)\n"
+                + "  -\n"
+                + "  Events: 1, Time-Resets: 0\n"
+                + "  Buffer, Bytes used: 3\n",
+                dispatchAndDump(log, false));
+    }
+
+    private String dispatchAndDump(WakeLockLog log, boolean includeTagDb) {
+        mTestLooper.dispatchAll();
+        StringWriter sw = new StringWriter();
+        PrintWriter pw = new PrintWriter(sw);
+        log.dump(pw, includeTagDb);
+        return sw.toString();
+    }
+
+    public class TestInjector extends WakeLockLog.Injector {
+        private final int mTagDatabaseSize;
+        private final int mLogSize;
+
+        public TestInjector(int tagDatabaseSize, int logSize) {
+            mTagDatabaseSize = tagDatabaseSize;
+            mLogSize = logSize;
+        }
+
+        @Override
+        public Looper getLooper() {
+            return mTestLooper.getLooper();
+        }
+
+        @Override
+        public int getTagDatabaseSize() {
+            return mTagDatabaseSize;
+        }
+
+        @Override
+        public int getLogSize() {
+            return mLogSize;
+        }
+
+        @Override
+        public SimpleDateFormat getDateFormat() {
+            SimpleDateFormat format = new SimpleDateFormat(super.getDateFormat().toPattern());
+            format.setTimeZone(TimeZone.getTimeZone("UTC"));
+            return format;
+        }
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/utils/TraceBufferTest.java b/services/tests/servicestests/src/com/android/server/utils/TraceBufferTest.java
index 09b75e7..0e50f2a 100644
--- a/services/tests/servicestests/src/com/android/server/utils/TraceBufferTest.java
+++ b/services/tests/servicestests/src/com/android/server/utils/TraceBufferTest.java
@@ -30,6 +30,7 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.internal.util.Preconditions;
+import com.android.internal.util.TraceBuffer;
 
 import org.junit.After;
 import org.junit.Before;
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 1b92abe..768b472 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -5438,6 +5438,46 @@
     }
 
     @Test
+    public void testOnBubbleNotificationSuppressionChanged() throws Exception {
+        // Bubble notification
+        NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, "tag");
+
+        // Bubbles are allowed!
+        setUpPrefsForBubbles(PKG, nr.sbn.getUserId(), true /* global */,
+                true /* app */, true /* channel */);
+
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.sbn.getTag(),
+                nr.sbn.getId(), nr.sbn.getNotification(), nr.sbn.getUserId());
+        waitForIdle();
+
+        // NOT suppressed
+        Notification n =  mBinderService.getActiveNotifications(PKG)[0].getNotification();
+        assertFalse(n.getBubbleMetadata().isNotificationSuppressed());
+
+        // Reset as this is called when the notif is first sent
+        reset(mListeners);
+
+        // Test: update suppression to true
+        mService.mNotificationDelegate.onBubbleNotificationSuppressionChanged(nr.getKey(), true);
+        waitForIdle();
+
+        // Check
+        n =  mBinderService.getActiveNotifications(PKG)[0].getNotification();
+        assertTrue(n.getBubbleMetadata().isNotificationSuppressed());
+
+        // Reset to check again
+        reset(mListeners);
+
+        // Test: update suppression to false
+        mService.mNotificationDelegate.onBubbleNotificationSuppressionChanged(nr.getKey(), false);
+        waitForIdle();
+
+        // Check
+        n = mBinderService.getActiveNotifications(PKG)[0].getNotification();
+        assertFalse(n.getBubbleMetadata().isNotificationSuppressed());
+    }
+
+    @Test
     public void testGrantInlineReplyUriPermission_recordExists() throws Exception {
         NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 0);
         mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
index 0fc2bc5..bab877e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -1008,4 +1008,18 @@
                 .setOutActivity(outActivity).execute();
         assertThat(outActivity[0].inSplitScreenSecondaryWindowingMode()).isTrue();
     }
+
+    @Test
+    public void testActivityStart_expectAddedToRecentTask() {
+        RecentTasks recentTasks = mock(RecentTasks.class);
+        mService.mStackSupervisor.setRecentTasks(recentTasks);
+        doReturn(true).when(recentTasks).isCallerRecents(anyInt());
+
+        final ActivityStarter starter = prepareStarter(0 /* flags */);
+
+        starter.setReason("testAddToTaskListOnActivityStart")
+                .execute();
+
+        verify(recentTasks, times(1)).add(any());
+    }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
index b5e7dd5..a672a95 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
@@ -39,6 +39,8 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import static org.mockito.ArgumentMatchers.anyBoolean;
@@ -83,6 +85,7 @@
 import java.util.List;
 import java.util.Random;
 import java.util.Set;
+import java.util.function.Function;
 
 /**
  * Build/Install/Run:
@@ -419,6 +422,36 @@
     }
 
     @Test
+    public void testAddTasksHomeClearUntrackedTasks_expectFinish() {
+        // There may be multiple tasks with the same base intent by flags (FLAG_ACTIVITY_NEW_TASK |
+        // FLAG_ACTIVITY_MULTIPLE_TASK). If the previous task is still active, it should be removed
+        // because user may not be able to return to the task.
+        final String className = ".PermissionsReview";
+        final Function<Boolean, Task> taskBuilder = visible -> {
+            final Task task = createTaskBuilder(className).build();
+            // Make the task non-empty.
+            final ActivityRecord r = new ActivityBuilder(mService).setTask(task).build();
+            r.setVisibility(visible);
+            return task;
+        };
+
+        final Task task1 = taskBuilder.apply(false /* visible */);
+        mRecentTasks.add(task1);
+        final Task task2 = taskBuilder.apply(true /* visible */);
+        mRecentTasks.add(task2);
+        // Only the last task is kept in recents and the previous 2 tasks will becomes untracked
+        // tasks because their intents are identical.
+        mRecentTasks.add(createTaskBuilder(className).build());
+        // Go home to trigger the removal of untracked tasks.
+        mRecentTasks.add(createTaskBuilder(".Home").setStack(mDisplay.getRootHomeTask()).build());
+
+        // All activities in the invisible task should be finishing or removed.
+        assertNull(task1.getTopNonFinishingActivity());
+        // The visible task should not be affected.
+        assertNotNull(task2.getTopNonFinishingActivity());
+    }
+
+    @Test
     public void testUsersTasks() {
         mRecentTasks.setOnlyTestVisibleRange();
         mRecentTasks.unloadUserDataFromMemoryLocked(TEST_USER_0_ID);
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java
index 8d2da1e..c9fd79f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java
@@ -80,7 +80,6 @@
 
         task.setTaskOrganizer(organizer);
         verify(organizer).taskAppeared(any(), any());
-        assertTrue(task.isControlledByTaskOrganizer());
 
         task.removeImmediately();
         verify(organizer).taskVanished(any());
@@ -106,48 +105,13 @@
         final Task task = createTaskInStack(stack, 0 /* userId */);
         final ITaskOrganizer organizer = makeAndRegisterMockOrganizer();
 
-        task.setTaskOrganizer(organizer);
+        stack.setTaskOrganizer(organizer);
         verify(organizer).taskAppeared(any(), any());
-        assertTrue(task.isControlledByTaskOrganizer());
+        assertTrue(stack.isControlledByTaskOrganizer());
 
-        task.setTaskOrganizer(null);
+        stack.setTaskOrganizer(null);
         verify(organizer).taskVanished(any());
-        assertFalse(task.isControlledByTaskOrganizer());
-    }
-
-    @Test
-    public void testTransferStackToOrganizer() throws RemoteException {
-        final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
-        final Task task = createTaskInStack(stack, 0 /* userId */);
-        final Task task2 = createTaskInStack(stack, 0 /* userId */);
-        final ITaskOrganizer organizer = makeAndRegisterMockOrganizer();
-
-        stack.transferToTaskOrganizer(organizer);
-
-        verify(organizer, times(2)).taskAppeared(any(), any());
-        assertTrue(task.isControlledByTaskOrganizer());
-        assertTrue(task2.isControlledByTaskOrganizer());
-
-        stack.transferToTaskOrganizer(null);
-
-        verify(organizer, times(2)).taskVanished(any());
-        assertFalse(task.isControlledByTaskOrganizer());
-        assertFalse(task2.isControlledByTaskOrganizer());
-    }
-
-    @Test
-    public void testRegisterTaskOrganizerTaskWindowingModeChanges() throws RemoteException {
-        final ITaskOrganizer organizer = makeAndRegisterMockOrganizer();
-
-        final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
-        final Task task = createTaskInStack(stack, 0 /* userId */);
-        task.setWindowingMode(WINDOWING_MODE_PINNED);
-        verify(organizer).taskAppeared(any(), any());
-        assertTrue(task.isControlledByTaskOrganizer());
-
-        task.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
-        verify(organizer).taskVanished(any());
-        assertFalse(task.isControlledByTaskOrganizer());
+        assertFalse(stack.isControlledByTaskOrganizer());
     }
 
     @Test
@@ -158,13 +122,9 @@
         final Task task = createTaskInStack(stack, 0 /* userId */);
         final Task task2 = createTaskInStack(stack, 0 /* userId */);
         stack.setWindowingMode(WINDOWING_MODE_PINNED);
-        verify(organizer, times(2)).taskAppeared(any(), any());
-        assertTrue(task.isControlledByTaskOrganizer());
-        assertTrue(task2.isControlledByTaskOrganizer());
+        verify(organizer, times(1)).taskAppeared(any(), any());
 
         stack.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
-        verify(organizer, times(2)).taskVanished(any());
-        assertFalse(task.isControlledByTaskOrganizer());
-        assertFalse(task2.isControlledByTaskOrganizer());
+        verify(organizer, times(1)).taskVanished(any());
     }
 }
diff --git a/telephony/common/com/android/internal/telephony/SmsApplication.java b/telephony/common/com/android/internal/telephony/SmsApplication.java
index a679a71..bb6f154 100644
--- a/telephony/common/com/android/internal/telephony/SmsApplication.java
+++ b/telephony/common/com/android/internal/telephony/SmsApplication.java
@@ -666,9 +666,21 @@
     }
 
     /**
+     * Broadcast action:
+     * Same as {@link Intent#ACTION_DEFAULT_SMS_PACKAGE_CHANGED} but it's implicit (e.g. sent to
+     * all apps) and requires
+     * {@link #PERMISSION_MONITOR_DEFAULT_SMS_PACKAGE} to receive.
+     */
+    public static final String ACTION_DEFAULT_SMS_PACKAGE_CHANGED_INTERNAL =
+            "android.provider.action.DEFAULT_SMS_PACKAGE_CHANGED_INTERNAL";
+
+    public static final String PERMISSION_MONITOR_DEFAULT_SMS_PACKAGE =
+            "android.permission.MONITOR_DEFAULT_SMS_PACKAGE";
+
+    /**
      * Sends broadcasts on sms app change:
      * {@link Intent#ACTION_DEFAULT_SMS_PACKAGE_CHANGED}
-     * {@link Intents.ACTION_DEFAULT_SMS_PACKAGE_CHANGED_INTERNAL}
+     * {@link #ACTION_DEFAULT_SMS_PACKAGE_CHANGED_INTERNAL}
      */
     public static void broadcastSmsAppChange(Context context,
             UserHandle userHandle, @Nullable String oldPackage, @Nullable String newPackage) {
@@ -718,11 +730,11 @@
         }
 
         // Send an implicit broadcast for the system server.
-        // (or anyone with MONITOR_DEFAULT_SMS_PACKAGE, really.)
+        // (or anyone with PERMISSION_MONITOR_DEFAULT_SMS_PACKAGE, really.)
         final Intent intent =
-                new Intent(Intents.ACTION_DEFAULT_SMS_PACKAGE_CHANGED_INTERNAL);
+                new Intent(ACTION_DEFAULT_SMS_PACKAGE_CHANGED_INTERNAL);
         context.sendBroadcastAsUser(intent, userHandle,
-                permission.MONITOR_DEFAULT_SMS_PACKAGE);
+                PERMISSION_MONITOR_DEFAULT_SMS_PACKAGE);
     }
 
     /**
diff --git a/telephony/common/com/android/internal/telephony/SmsNumberUtils.java b/telephony/common/com/android/internal/telephony/SmsNumberUtils.java
index cd365a1..95098e8 100644
--- a/telephony/common/com/android/internal/telephony/SmsNumberUtils.java
+++ b/telephony/common/com/android/internal/telephony/SmsNumberUtils.java
@@ -31,6 +31,7 @@
 
 import com.android.internal.telephony.HbpcdLookup.MccIdd;
 import com.android.internal.telephony.HbpcdLookup.MccLookup;
+import com.android.internal.telephony.util.TelephonyUtils;
 
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
@@ -677,7 +678,7 @@
      */
     private static String secureHash(byte[] input) {
         // Refrain from logging user personal information in user build.
-        if (android.os.Build.IS_USER) {
+        if (TelephonyUtils.IS_USER) {
             return "****";
         }
 
diff --git a/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java b/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java
index a7ad884..6826974 100644
--- a/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java
+++ b/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java
@@ -28,6 +28,8 @@
 import android.os.SystemProperties;
 
 import java.io.PrintWriter;
+import java.util.Collections;
+import java.util.List;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 import java.util.function.Supplier;
@@ -61,6 +63,11 @@
         return str == null ? "" : str;
     }
 
+    /** Returns an empty list if the input is {@code null}. */
+    public static @NonNull <T> List<T> emptyIfNull(@Nullable List<T> cur) {
+        return cur == null ? Collections.emptyList() : cur;
+    }
+
     /** Throws a {@link RuntimeException} that wrapps the {@link RemoteException}. */
     public static RuntimeException rethrowAsRuntimeException(RemoteException remoteException) {
         throw new RuntimeException(remoteException);
diff --git a/telephony/common/com/google/android/mms/util/DrmConvertSession.java b/telephony/common/com/google/android/mms/util/DrmConvertSession.java
index 156c7ad..17ab1547 100644
--- a/telephony/common/com/google/android/mms/util/DrmConvertSession.java
+++ b/telephony/common/com/google/android/mms/util/DrmConvertSession.java
@@ -20,7 +20,6 @@
 import android.content.Context;
 import android.drm.DrmConvertedStatus;
 import android.drm.DrmManagerClient;
-import android.provider.Downloads;
 import android.util.Log;
 
 import java.io.FileNotFoundException;
@@ -33,6 +32,13 @@
     private int mConvertSessionId;
     private static final String TAG = "DrmConvertSession";
 
+    // These values are copied from Downloads.Impl.* for backward compatibility since
+    // {@link #close()} that uses it is marked @UnsupportedAppUsage.
+    public static final int STATUS_SUCCESS = 200;
+    public static final int STATUS_NOT_ACCEPTABLE = 406;
+    public static final int STATUS_UNKNOWN_ERROR = 491;
+    public static final int STATUS_FILE_ERROR = 492;
+
     private DrmConvertSession(DrmManagerClient drmClient, int convertSessionId) {
         mDrmClient = drmClient;
         mConvertSessionId = convertSessionId;
@@ -118,38 +124,38 @@
      * Ends a conversion session of a file.
      *
      * @param fileName The filename of the converted file.
-     * @return Downloads.Impl.STATUS_SUCCESS if execution is ok.
-     *         Downloads.Impl.STATUS_FILE_ERROR in case converted file can not
-     *         be accessed. Downloads.Impl.STATUS_NOT_ACCEPTABLE if a problem
+     * @return STATUS_SUCCESS if execution is ok.
+     *         STATUS_FILE_ERROR in case converted file can not
+     *         be accessed. STATUS_NOT_ACCEPTABLE if a problem
      *         occurs when accessing drm framework.
-     *         Downloads.Impl.STATUS_UNKNOWN_ERROR if a general error occurred.
+     *         STATUS_UNKNOWN_ERROR if a general error occurred.
      */
     @UnsupportedAppUsage
     public int close(String filename) {
         DrmConvertedStatus convertedStatus = null;
-        int result = Downloads.Impl.STATUS_UNKNOWN_ERROR;
+        int result = STATUS_UNKNOWN_ERROR;
         if (mDrmClient != null && mConvertSessionId >= 0) {
             try {
                 convertedStatus = mDrmClient.closeConvertSession(mConvertSessionId);
                 if (convertedStatus == null ||
                         convertedStatus.statusCode != DrmConvertedStatus.STATUS_OK ||
                         convertedStatus.convertedData == null) {
-                    result = Downloads.Impl.STATUS_NOT_ACCEPTABLE;
+                    result = STATUS_NOT_ACCEPTABLE;
                 } else {
                     RandomAccessFile rndAccessFile = null;
                     try {
                         rndAccessFile = new RandomAccessFile(filename, "rw");
                         rndAccessFile.seek(convertedStatus.offset);
                         rndAccessFile.write(convertedStatus.convertedData);
-                        result = Downloads.Impl.STATUS_SUCCESS;
+                        result = STATUS_SUCCESS;
                     } catch (FileNotFoundException e) {
-                        result = Downloads.Impl.STATUS_FILE_ERROR;
+                        result = STATUS_FILE_ERROR;
                         Log.w(TAG, "File: " + filename + " could not be found.", e);
                     } catch (IOException e) {
-                        result = Downloads.Impl.STATUS_FILE_ERROR;
+                        result = STATUS_FILE_ERROR;
                         Log.w(TAG, "Could not access File: " + filename + " .", e);
                     } catch (IllegalArgumentException e) {
-                        result = Downloads.Impl.STATUS_FILE_ERROR;
+                        result = STATUS_FILE_ERROR;
                         Log.w(TAG, "Could not open file in mode: rw", e);
                     } catch (SecurityException e) {
                         Log.w(TAG, "Access to File: " + filename +
@@ -159,7 +165,7 @@
                             try {
                                 rndAccessFile.close();
                             } catch (IOException e) {
-                                result = Downloads.Impl.STATUS_FILE_ERROR;
+                                result = STATUS_FILE_ERROR;
                                 Log.w(TAG, "Failed to close File:" + filename
                                         + ".", e);
                             }
diff --git a/telephony/java/android/telephony/Annotation.java b/telephony/java/android/telephony/Annotation.java
index db17a95..d2a5905 100644
--- a/telephony/java/android/telephony/Annotation.java
+++ b/telephony/java/android/telephony/Annotation.java
@@ -1,6 +1,7 @@
 package android.telephony;
 
 import android.annotation.IntDef;
+import android.provider.Telephony;
 import android.telecom.Connection;
 import android.telephony.data.ApnSetting;
 
@@ -651,4 +652,13 @@
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface UiccAppType{}
+
+    /** @hide */
+    @IntDef({
+            Telephony.Carriers.SKIP_464XLAT_DEFAULT,
+            Telephony.Carriers.SKIP_464XLAT_DISABLE,
+            Telephony.Carriers.SKIP_464XLAT_ENABLE,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface Skip464XlatStatus {}
 }
diff --git a/telephony/java/android/telephony/PhoneCapability.java b/telephony/java/android/telephony/PhoneCapability.java
index 70931fb..a537928 100644
--- a/telephony/java/android/telephony/PhoneCapability.java
+++ b/telephony/java/android/telephony/PhoneCapability.java
@@ -25,7 +25,7 @@
 import android.telephony.AccessNetworkConstants.RadioAccessNetworkType;
 import android.telephony.TelephonyManager.NetworkTypeBitMask;
 
-import com.android.internal.util.CollectionUtils;
+import com.android.internal.telephony.util.TelephonyUtils;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -181,13 +181,13 @@
         this.mEutranUeCategoryUl = eutranUeCategoryUl;
         this.mPsDataConnectionLingerTimeMillis = psDataConnectionLingerTimeMillis;
         this.mSupportedRats = supportedRats;
-        this.mGeranBands = CollectionUtils.emptyIfNull(geranBands);
-        this.mUtranBands = CollectionUtils.emptyIfNull(utranBands);
-        this.mEutranBands = CollectionUtils.emptyIfNull(eutranBands);
-        this.mNgranBands = CollectionUtils.emptyIfNull(ngranBands);
-        this.mLogicalModemUuids = CollectionUtils.emptyIfNull(logicalModemUuids);
-        this.mSimSlotCapabilities = CollectionUtils.emptyIfNull(simSlotCapabilities);
-        this.mConcurrentFeaturesSupport = CollectionUtils.emptyIfNull(concurrentFeaturesSupport);
+        this.mGeranBands = TelephonyUtils.emptyIfNull(geranBands);
+        this.mUtranBands = TelephonyUtils.emptyIfNull(utranBands);
+        this.mEutranBands = TelephonyUtils.emptyIfNull(eutranBands);
+        this.mNgranBands = TelephonyUtils.emptyIfNull(ngranBands);
+        this.mLogicalModemUuids = TelephonyUtils.emptyIfNull(logicalModemUuids);
+        this.mSimSlotCapabilities = TelephonyUtils.emptyIfNull(simSlotCapabilities);
+        this.mConcurrentFeaturesSupport = TelephonyUtils.emptyIfNull(concurrentFeaturesSupport);
     }
 
     private PhoneCapability(Parcel in) {
diff --git a/telephony/java/android/telephony/SmsCbMessage.java b/telephony/java/android/telephony/SmsCbMessage.java
index 3c67094..c0dfec9 100644
--- a/telephony/java/android/telephony/SmsCbMessage.java
+++ b/telephony/java/android/telephony/SmsCbMessage.java
@@ -177,6 +177,9 @@
     @Nullable
     private final String mLanguage;
 
+    /** The 8-bit data coding scheme defined in 3GPP TS 23.038 section 4. */
+    private final int mDataCodingScheme;
+
     /** Message body, as a String. */
     @Nullable
     private final String mBody;
@@ -220,7 +223,7 @@
             @Nullable SmsCbCmasInfo cmasWarningInfo, int slotIndex, int subId) {
 
         this(messageFormat, geographicalScope, serialNumber, location, serviceCategory, language,
-                body, priority, etwsWarningInfo, cmasWarningInfo, 0 /* maximumWaitingTime */,
+                0, body, priority, etwsWarningInfo, cmasWarningInfo, 0 /* maximumWaitingTime */,
                 null /* geometries */, System.currentTimeMillis(), slotIndex, subId);
     }
 
@@ -230,8 +233,8 @@
      */
     public SmsCbMessage(int messageFormat, int geographicalScope, int serialNumber,
                         @NonNull SmsCbLocation location, int serviceCategory,
-                        @Nullable String language, @Nullable String body, int priority,
-                        @Nullable SmsCbEtwsInfo etwsWarningInfo,
+                        @Nullable String language, int dataCodingScheme, @Nullable String body,
+                        int priority, @Nullable SmsCbEtwsInfo etwsWarningInfo,
                         @Nullable SmsCbCmasInfo cmasWarningInfo, int maximumWaitTimeSec,
                         @Nullable List<Geometry> geometries, long receivedTimeMillis, int slotIndex,
                         int subId) {
@@ -241,6 +244,7 @@
         mLocation = location;
         mServiceCategory = serviceCategory;
         mLanguage = language;
+        mDataCodingScheme = dataCodingScheme;
         mBody = body;
         mPriority = priority;
         mEtwsWarningInfo = etwsWarningInfo;
@@ -263,6 +267,7 @@
         mLocation = new SmsCbLocation(in);
         mServiceCategory = in.readInt();
         mLanguage = in.readString();
+        mDataCodingScheme = in.readInt();
         mBody = in.readString();
         mPriority = in.readInt();
         int type = in.readInt();
@@ -305,6 +310,7 @@
         mLocation.writeToParcel(dest, flags);
         dest.writeInt(mServiceCategory);
         dest.writeString(mLanguage);
+        dest.writeInt(mDataCodingScheme);
         dest.writeString(mBody);
         dest.writeInt(mPriority);
         if (mEtwsWarningInfo != null) {
@@ -398,6 +404,15 @@
     }
 
     /**
+     * Get data coding scheme of the message
+     *
+     * @return The 8-bit data coding scheme defined in 3GPP TS 23.038 section 4.
+     */
+    public int getDataCodingScheme() {
+        return mDataCodingScheme;
+    }
+
+    /**
      * Get the body of this message, or null if no body available
      *
      * @return Body, or null
@@ -718,7 +733,7 @@
                 cursor.getColumnIndexOrThrow(CellBroadcasts.MAXIMUM_WAIT_TIME));
 
         return new SmsCbMessage(format, geoScope, serialNum, location, category,
-                language, body, priority, etwsInfo, cmasInfo, maximumWaitTimeSec, geometries,
+                language, 0, body, priority, etwsInfo, cmasInfo, maximumWaitTimeSec, geometries,
                 receivedTimeMillis, slotIndex, subId);
     }
 
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 584b000..26dc5f0 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -5640,13 +5640,6 @@
     //
 
     /**
-     * To check the SDK version for {@link TelephonyManager#listen}.
-     */
-    @ChangeId
-    @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.P)
-    private static final long LISTEN_CODE_CHANGE = 147600208L;
-
-    /**
      * Registers a listener object to receive notification of changes
      * in specified telephony states.
      * <p>
@@ -5683,19 +5676,7 @@
                 (TelephonyRegistryManager)
                         mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
         if (telephonyRegistry != null) {
-            // subId from PhoneStateListener is deprecated Q on forward, use the subId from
-            // TelephonyManager instance. keep using subId from PhoneStateListener for pre-Q.
-            int subId = mSubId;
-            if (Compatibility.isChangeEnabled(LISTEN_CODE_CHANGE)) {
-                // since mSubId in PhoneStateListener is deprecated from Q on forward, this is
-                // the only place to set mSubId and its for "informational" only.
-                //  TODO: remove this once we completely get rid of mSubId in PhoneStateListener
-                listener.mSubId = (events == PhoneStateListener.LISTEN_NONE)
-                        ? SubscriptionManager.INVALID_SUBSCRIPTION_ID : subId;
-            } else if (listener.mSubId != null) {
-                subId = listener.mSubId;
-            }
-            telephonyRegistry.listenForSubscriber(subId, getOpPackageName(), getFeatureId(),
+            telephonyRegistry.listenForSubscriber(mSubId, getOpPackageName(), getFeatureId(),
                     listener, events, notifyNow);
         } else {
             Rlog.w(TAG, "telephony registry not ready.");
@@ -5714,7 +5695,7 @@
     @NonNull
     public CdmaEriInformation getCdmaEriInformation() {
         return new CdmaEriInformation(
-               getCdmaEriIconMode(getSubId()), getCdmaEriIconIndex(getSubId()));
+               getCdmaEriIconIndex(getSubId()), getCdmaEriIconMode(getSubId()));
     }
 
     /**
diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java
index 7896320..f5dfacc6 100644
--- a/telephony/java/android/telephony/data/ApnSetting.java
+++ b/telephony/java/android/telephony/data/ApnSetting.java
@@ -27,6 +27,7 @@
 import android.os.Parcelable;
 import android.provider.Telephony;
 import android.provider.Telephony.Carriers;
+import android.telephony.Annotation;
 import android.telephony.Annotation.ApnType;
 import android.telephony.Annotation.NetworkType;
 import android.telephony.ServiceState;
@@ -744,7 +745,7 @@
      * @return SKIP_464XLAT_DEFAULT, SKIP_464XLAT_DISABLE or SKIP_464XLAT_ENABLE
      * @hide
      */
-    @Carriers.Skip464XlatStatus
+    @Annotation.Skip464XlatStatus
     public int getSkip464Xlat() {
         return mSkip464Xlat;
     }
@@ -2061,10 +2062,10 @@
         /**
          * Sets skip464xlat flag for this APN.
          *
-         * @param skip464xlat skip464xlat for this APN
+         * @param skip464xlat skip464xlat for this APN.
          * @hide
          */
-        public Builder setSkip464Xlat(@Carriers.Skip464XlatStatus int skip464xlat) {
+        public Builder setSkip464Xlat(@Annotation.Skip464XlatStatus int skip464xlat) {
             this.mSkip464Xlat = skip464xlat;
             return this;
         }
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ChangeAppRotationTest.java b/tests/FlickerTests/src/com/android/server/wm/flicker/ChangeAppRotationTest.java
index 42cafd4..5a66e80 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ChangeAppRotationTest.java
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ChangeAppRotationTest.java
@@ -66,7 +66,7 @@
     @Parameters(name = "{0}-{1}")
     public static Collection<Object[]> getParams() {
         int[] supportedRotations =
-                {Surface.ROTATION_0, Surface.ROTATION_90, Surface.ROTATION_270};
+                {Surface.ROTATION_0, Surface.ROTATION_90};
         Collection<Object[]> params = new ArrayList<>();
         for (int begin : supportedRotations) {
             for (int end : supportedRotations) {
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/CloseImeWindowToHomeTest.java b/tests/FlickerTests/src/com/android/server/wm/flicker/CloseImeWindowToHomeTest.java
index fc6719e..f740af9 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/CloseImeWindowToHomeTest.java
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/CloseImeWindowToHomeTest.java
@@ -25,6 +25,7 @@
 
 import org.junit.Before;
 import org.junit.FixMethodOrder;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.MethodSorters;
@@ -62,6 +63,7 @@
                 .forAllEntries());
     }
 
+    @Ignore("Flaky")
     @Test
     public void checkVisibility_imeLayerBecomesInvisible() {
         checkResults(result -> LayersTraceSubject.assertThat(result)
@@ -71,6 +73,7 @@
                 .forAllEntries());
     }
 
+    @Ignore("Flaky")
     @Test
     public void checkVisibility_imeAppLayerBecomesInvisible() {
         checkResults(result -> LayersTraceSubject.assertThat(result)
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/SeamlessAppRotationTest.java b/tests/FlickerTests/src/com/android/server/wm/flicker/SeamlessAppRotationTest.java
index 8559cb9..37d7c4c 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/SeamlessAppRotationTest.java
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/SeamlessAppRotationTest.java
@@ -69,7 +69,7 @@
     @Parameters(name = "{0}")
     public static Collection<Object[]> getParams() {
         int[] supportedRotations =
-                {Surface.ROTATION_0, Surface.ROTATION_90, Surface.ROTATION_270};
+                {Surface.ROTATION_0, Surface.ROTATION_90};
         Collection<Object[]> params = new ArrayList<>();
 
         ArrayList<Intent> testIntents = new ArrayList<>();
@@ -112,7 +112,7 @@
 
         super.runTransition(
                 changeAppRotation(mIntent, intentId, InstrumentationRegistry.getContext(),
-                        mUiDevice, mBeginRotation, mEndRotation).repeat(5).build());
+                        mUiDevice, mBeginRotation, mEndRotation).build());
     }
 
     @Test
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/AlphaLayersActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/AlphaLayersActivity.java
index 1a68a93..3766182 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/AlphaLayersActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/AlphaLayersActivity.java
@@ -50,7 +50,7 @@
 
         setContentView(container);
     }
-    
+
     @SuppressWarnings({"UnusedDeclaration"})
     static int dipToPx(Context c, int dip) {
         return (int) (c.getResources().getDisplayMetrics().density * dip + 0.5f);
@@ -86,30 +86,24 @@
             canvas.save();
             canvas.clipRect(20.0f, 0.0f, 40.0f, 20.0f);
             Log.d(LOG_TAG, "clipRect = " + canvas.getClipBounds());
-            Log.d(LOG_TAG, "rejected = " + canvas.quickReject(100.0f, 100.0f, 110.0f, 110.0f,
-                    Canvas.EdgeType.BW));
-            Log.d(LOG_TAG, "rejected = " + canvas.quickReject(25.0f, 5.0f, 30.0f, 10.0f,
-                    Canvas.EdgeType.BW));
+            Log.d(LOG_TAG, "rejected = " + canvas.quickReject(100.0f, 100.0f, 110.0f, 110.0f));
+            Log.d(LOG_TAG, "rejected = " + canvas.quickReject(25.0f, 5.0f, 30.0f, 10.0f));
             canvas.restore();
-            
+
             canvas.save();
             canvas.scale(2.0f, 2.0f);
             canvas.clipRect(20.0f, 0.0f, 40.0f, 20.0f);
             Log.d(LOG_TAG, "clipRect = " + canvas.getClipBounds());
-            Log.d(LOG_TAG, "rejected = " + canvas.quickReject(50.0f, 50.0f, 60.0f, 60.0f,
-                    Canvas.EdgeType.BW));
-            Log.d(LOG_TAG, "rejected = " + canvas.quickReject(25.0f, 5.0f, 30.0f, 10.0f,
-                    Canvas.EdgeType.BW));
+            Log.d(LOG_TAG, "rejected = " + canvas.quickReject(50.0f, 50.0f, 60.0f, 60.0f));
+            Log.d(LOG_TAG, "rejected = " + canvas.quickReject(25.0f, 5.0f, 30.0f, 10.0f));
             canvas.restore();
 
             canvas.save();
             canvas.translate(20.0f, 20.0f);
             canvas.clipRect(20.0f, 0.0f, 40.0f, 20.0f);
             Log.d(LOG_TAG, "clipRect = " + canvas.getClipBounds());
-            Log.d(LOG_TAG, "rejected = " + canvas.quickReject(80.0f, 80.0f, 90.0f, 90.0f,
-                    Canvas.EdgeType.BW));
-            Log.d(LOG_TAG, "rejected = " + canvas.quickReject(25.0f, 5.0f, 30.0f, 10.0f,
-                    Canvas.EdgeType.BW));
+            Log.d(LOG_TAG, "rejected = " + canvas.quickReject(80.0f, 80.0f, 90.0f, 90.0f));
+            Log.d(LOG_TAG, "rejected = " + canvas.quickReject(25.0f, 5.0f, 30.0f, 10.0f));
             canvas.restore();
 
             canvas.save();
diff --git a/tests/PlatformCompatGating/Android.bp b/tests/PlatformCompatGating/Android.bp
index 5e9ef8e..609896e 100644
--- a/tests/PlatformCompatGating/Android.bp
+++ b/tests/PlatformCompatGating/Android.bp
@@ -18,7 +18,6 @@
     name: "PlatformCompatGating",
     // Only compile source java files in this apk.
     srcs: ["src/**/*.java"],
-    certificate: "platform",
     libs: [
         "android.test.runner",
         "android.test.base",
diff --git a/tests/PlatformCompatGating/test-rules/src/android/compat/testing/PlatformCompatChangeRule.java b/tests/PlatformCompatGating/test-rules/src/android/compat/testing/PlatformCompatChangeRule.java
index 932ec64..c00aa2a 100644
--- a/tests/PlatformCompatGating/test-rules/src/android/compat/testing/PlatformCompatChangeRule.java
+++ b/tests/PlatformCompatGating/test-rules/src/android/compat/testing/PlatformCompatChangeRule.java
@@ -16,7 +16,9 @@
 
 package android.compat.testing;
 
+import android.Manifest;
 import android.app.Instrumentation;
+import android.app.UiAutomation;
 import android.compat.Compatibility;
 import android.compat.Compatibility.ChangeConfig;
 import android.content.Context;
@@ -83,12 +85,16 @@
         @Override
         public void evaluate() throws Throwable {
             Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
+            UiAutomation uiAutomation = instrumentation.getUiAutomation();
             String packageName = instrumentation.getTargetContext().getPackageName();
             IPlatformCompat platformCompat = IPlatformCompat.Stub
                     .asInterface(ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
             if (platformCompat == null) {
                 throw new IllegalStateException("Could not get IPlatformCompat service!");
             }
+            uiAutomation.adoptShellPermissionIdentity(
+                    Manifest.permission.READ_COMPAT_CHANGE_CONFIG,
+                    Manifest.permission.OVERRIDE_COMPAT_CHANGE_CONFIG);
             Compatibility.setOverrides(mConfig);
             try {
                 platformCompat.setOverridesForTest(new CompatibilityChangeConfig(mConfig),
@@ -101,6 +107,7 @@
             } catch (RemoteException e) {
                 throw new RuntimeException("Could not call IPlatformCompat binder method!", e);
             } finally {
+                uiAutomation.dropShellPermissionIdentity();
                 Compatibility.clearOverrides();
             }
         }
diff --git a/tools/stats_log_api_gen/java_writer_q.cpp b/tools/stats_log_api_gen/java_writer_q.cpp
index f866129..1259a68 100644
--- a/tools/stats_log_api_gen/java_writer_q.cpp
+++ b/tools/stats_log_api_gen/java_writer_q.cpp
@@ -75,9 +75,7 @@
                         java_type_name(chainField.javaType), chainField.name.c_str());
                 }
             } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
-                // Module logging does not yet support key value pair.
-                fprintf(stderr, "Module logging does not yet support key value pair.\n");
-                continue;
+                fprintf(out, ", android.util.SparseArray<Object> valueMap");
             } else {
                 fprintf(out, ", %s arg%d", java_type_name(*arg), argIndex);
             }
@@ -161,9 +159,114 @@
                 fprintf(out, "%s    needed += attrSize;\n", indent.c_str());
                 break;
             }
+            case JAVA_TYPE_KEY_VALUE_PAIR:
+            {
+                fprintf(out,
+                        "%s    // Calculate bytes needed by Key Value Pairs.\n",
+                        indent.c_str());
+                fprintf(out,
+                        "%s    final int count = valueMap.size();\n", indent.c_str());
+                fprintf(out,
+                        "%s    android.util.SparseIntArray intMap = null;\n", indent.c_str());
+                fprintf(out,
+                        "%s    android.util.SparseLongArray longMap = null;\n", indent.c_str());
+                fprintf(out,
+                        "%s    android.util.SparseArray<String> stringMap = null;\n",
+                        indent.c_str());
+                fprintf(out,
+                        "%s    android.util.SparseArray<Float> floatMap = null;\n", indent.c_str());
+                fprintf(out,
+                        "%s    int keyValuePairSize = LIST_TYPE_OVERHEAD * 5;\n",
+                        indent.c_str());
+                fprintf(out,
+                        "%s    for (int i = 0; i < count; i++) {\n", indent.c_str());
+                fprintf(out,
+                        "%s        final int key = valueMap.keyAt(i);\n", indent.c_str());
+                fprintf(out,
+                        "%s        final Object value = valueMap.valueAt(i);\n",
+                        indent.c_str());
+                fprintf(out,
+                        "%s        if (value instanceof Integer) {\n", indent.c_str());
+                fprintf(out,
+                        "%s            keyValuePairSize += LIST_TYPE_OVERHEAD\n",
+                        indent.c_str());
+                fprintf(out,
+                        "%s                    + INT_TYPE_SIZE + INT_TYPE_SIZE;\n",
+                        indent.c_str());
+                fprintf(out,
+                        "%s            if (null == intMap) {\n", indent.c_str());
+                fprintf(out,
+                        "%s                intMap = new android.util.SparseIntArray();\n", indent.c_str());
+                fprintf(out,
+                        "%s            }\n", indent.c_str());
+                fprintf(out,
+                        "%s            intMap.put(key, (Integer) value);\n", indent.c_str());
+                fprintf(out,
+                        "%s        } else if (value instanceof Long) {\n", indent.c_str());
+                fprintf(out,
+                        "%s            keyValuePairSize += LIST_TYPE_OVERHEAD\n",
+                        indent.c_str());
+                fprintf(out,
+                        "%s                    + INT_TYPE_SIZE + LONG_TYPE_SIZE;\n",
+                        indent.c_str());
+                fprintf(out,
+                        "%s            if (null == longMap) {\n", indent.c_str());
+                fprintf(out,
+                        "%s                longMap = new android.util.SparseLongArray();\n", indent.c_str());
+                fprintf(out,
+                        "%s            }\n", indent.c_str());
+                fprintf(out,
+                        "%s            longMap.put(key, (Long) value);\n", indent.c_str());
+                fprintf(out,
+                        "%s        } else if (value instanceof String) {\n", indent.c_str());
+                fprintf(out,
+                        "%s            final String str = (value == null) ? \"\" : "
+                        "(String) value;\n",
+                        indent.c_str());
+                fprintf(out,
+                        "%s            final int len = "
+                        "str.getBytes(java.nio.charset.StandardCharsets.UTF_8).length;\n",
+                        indent.c_str());
+                fprintf(out,
+                        "%s            keyValuePairSize += LIST_TYPE_OVERHEAD + INT_TYPE_SIZE\n",
+                        indent.c_str());
+                fprintf(out,
+                        "%s                    + STRING_TYPE_OVERHEAD + len;\n",
+                        indent.c_str());
+                fprintf(out,
+                        "%s            if (null == stringMap) {\n", indent.c_str());
+                fprintf(out,
+                        "%s                stringMap = new android.util.SparseArray<>();\n", indent.c_str());
+                fprintf(out,
+                        "%s            }\n", indent.c_str());
+                fprintf(out,
+                        "%s            stringMap.put(key, str);\n", indent.c_str());
+                fprintf(out,
+                        "%s        } else if (value instanceof Float) {\n", indent.c_str());
+                fprintf(out,
+                        "%s            keyValuePairSize += LIST_TYPE_OVERHEAD\n",
+                        indent.c_str());
+                fprintf(out,
+                        "%s                    + INT_TYPE_SIZE + FLOAT_TYPE_SIZE;\n",
+                        indent.c_str());
+                fprintf(out,
+                        "%s            if (null == floatMap) {\n", indent.c_str());
+                fprintf(out,
+                        "%s                floatMap = new android.util.SparseArray<>();\n", indent.c_str());
+                fprintf(out,
+                        "%s            }\n", indent.c_str());
+                fprintf(out,
+                        "%s            floatMap.put(key, (Float) value);\n", indent.c_str());
+                fprintf(out,
+                        "%s        }\n", indent.c_str());
+                fprintf(out,
+                        "%s    }\n", indent.c_str());
+                fprintf(out, "%s    needed += keyValuePairSize;\n", indent.c_str());
+                break;
+            }
             default:
-                // Unsupported types: OBJECT, DOUBLE, KEY_VALUE_PAIR.
-                fprintf(stderr, "Module logging does not yet support key value pair.\n");
+                // Unsupported types: OBJECT, DOUBLE.
+                fprintf(stderr, "Module logging does not yet support Object and Double.\n");
                 return 1;
             }
             argIndex++;
@@ -253,10 +356,18 @@
                 fprintf(out, "%s    pos += attrSize;\n", indent.c_str());
                 break;
             }
+            case JAVA_TYPE_KEY_VALUE_PAIR:
+                requiredHelpers |= JAVA_MODULE_REQUIRES_FLOAT;
+                requiredHelpers |= JAVA_MODULE_REQUIRES_KEY_VALUE_PAIRS;
+                fprintf(out,
+                        "%s    writeKeyValuePairs(buff, pos, intMap, longMap, stringMap, "
+                        "floatMap);\n", indent.c_str());
+                fprintf(out, "%s    pos += keyValuePairSize;\n", indent.c_str());
+                break;
             default:
-                // Unsupported types: OBJECT, DOUBLE, KEY_VALUE_PAIR.
+                // Unsupported types: OBJECT, DOUBLE.
                 fprintf(stderr,
-                        "Object, Double, and KeyValuePairs are not supported in module logging");
+                        "Object and Double are not supported in module logging");
                 return 1;
             }
             argIndex++;
@@ -359,6 +470,111 @@
         fprintf(out, "%s}\n", indent.c_str());
         fprintf(out, "\n");
     }
+
+    if (requiredHelpers & JAVA_MODULE_REQUIRES_KEY_VALUE_PAIRS) {
+        fprintf(out, "%sprivate static void writeKeyValuePairs(byte[] buff, int pos,\n",
+                indent.c_str());
+        fprintf(out, "%s        final android.util.SparseIntArray intMap,\n", indent.c_str());
+        fprintf(out, "%s        final android.util.SparseLongArray longMap,\n", indent.c_str());
+        fprintf(out, "%s        final android.util.SparseArray<String> stringMap,\n",
+                indent.c_str());
+        fprintf(out, "%s        final android.util.SparseArray<Float> floatMap) {\n",
+                indent.c_str());
+
+        // Start list of lists.
+        fprintf(out, "%s    buff[pos] = LIST_TYPE;\n", indent.c_str());
+        fprintf(out, "%s    buff[pos + 1] = (byte) 4;\n", indent.c_str());
+        fprintf(out, "%s    pos += LIST_TYPE_OVERHEAD;\n", indent.c_str());
+
+        // Write integers.
+        fprintf(out, "%s    final int intMapSize = null == intMap ? 0 : intMap.size();\n",
+                indent.c_str());
+        fprintf(out, "%s    buff[pos] = LIST_TYPE;\n", indent.c_str());
+        fprintf(out, "%s    buff[pos + 1] = (byte) intMapSize;\n", indent.c_str());
+        fprintf(out, "%s    pos += LIST_TYPE_OVERHEAD;\n", indent.c_str());
+        fprintf(out, "%s    for (int i = 0; i < intMapSize; i++) {\n", indent.c_str());
+        fprintf(out, "%s        buff[pos] = LIST_TYPE;\n", indent.c_str());
+        fprintf(out, "%s        buff[pos + 1] = (byte) 2;\n", indent.c_str());
+        fprintf(out, "%s        pos += LIST_TYPE_OVERHEAD;\n", indent.c_str());
+        fprintf(out, "%s        final int key = intMap.keyAt(i);\n", indent.c_str());
+        fprintf(out, "%s        final int value = intMap.valueAt(i);\n", indent.c_str());
+        fprintf(out, "%s        buff[pos] = INT_TYPE;\n", indent.c_str());
+        fprintf(out, "%s        copyInt(buff, pos + 1, key);\n", indent.c_str());
+        fprintf(out, "%s        pos += INT_TYPE_SIZE;\n", indent.c_str());
+        fprintf(out, "%s        buff[pos] = INT_TYPE;\n", indent.c_str());
+        fprintf(out, "%s        copyInt(buff, pos + 1, value);\n", indent.c_str());
+        fprintf(out, "%s        pos += INT_TYPE_SIZE;\n", indent.c_str());
+        fprintf(out, "%s    }\n", indent.c_str());
+
+        // Write longs.
+        fprintf(out, "%s    final int longMapSize = null == longMap ? 0 : longMap.size();\n",
+                indent.c_str());
+        fprintf(out, "%s    buff[pos] = LIST_TYPE;\n", indent.c_str());
+        fprintf(out, "%s    buff[pos + 1] = (byte) longMapSize;\n", indent.c_str());
+        fprintf(out, "%s    pos += LIST_TYPE_OVERHEAD;\n", indent.c_str());
+        fprintf(out, "%s    for (int i = 0; i < longMapSize; i++) {\n", indent.c_str());
+        fprintf(out, "%s        buff[pos] = LIST_TYPE;\n", indent.c_str());
+        fprintf(out, "%s        buff[pos + 1] = (byte) 2;\n", indent.c_str());
+        fprintf(out, "%s        pos += LIST_TYPE_OVERHEAD;\n", indent.c_str());
+        fprintf(out, "%s        final int key = longMap.keyAt(i);\n", indent.c_str());
+        fprintf(out, "%s        final long value = longMap.valueAt(i);\n", indent.c_str());
+        fprintf(out, "%s        buff[pos] = INT_TYPE;\n", indent.c_str());
+        fprintf(out, "%s        copyInt(buff, pos + 1, key);\n", indent.c_str());
+        fprintf(out, "%s        pos += INT_TYPE_SIZE;\n", indent.c_str());
+        fprintf(out, "%s        buff[pos] = LONG_TYPE;\n", indent.c_str());
+        fprintf(out, "%s        copyLong(buff, pos + 1, value);\n", indent.c_str());
+        fprintf(out, "%s        pos += LONG_TYPE_SIZE;\n", indent.c_str());
+        fprintf(out, "%s    }\n", indent.c_str());
+
+        // Write Strings.
+        fprintf(out, "%s    final int stringMapSize = null == stringMap ? 0 : stringMap.size();\n",
+                indent.c_str());
+        fprintf(out, "%s    buff[pos] = LIST_TYPE;\n", indent.c_str());
+        fprintf(out, "%s    buff[pos + 1] = (byte) stringMapSize;\n", indent.c_str());
+        fprintf(out, "%s    pos += LIST_TYPE_OVERHEAD;\n", indent.c_str());
+        fprintf(out, "%s    for (int i = 0; i < stringMapSize; i++) {\n", indent.c_str());
+        fprintf(out, "%s        buff[pos] = LIST_TYPE;\n", indent.c_str());
+        fprintf(out, "%s        buff[pos + 1] = (byte) 2;\n", indent.c_str());
+        fprintf(out, "%s        pos += LIST_TYPE_OVERHEAD;\n", indent.c_str());
+        fprintf(out, "%s        final int key = stringMap.keyAt(i);\n", indent.c_str());
+        fprintf(out, "%s        final String value = stringMap.valueAt(i);\n", indent.c_str());
+        fprintf(out, "%s        final byte[] valueBytes = "
+                "value.getBytes(java.nio.charset.StandardCharsets.UTF_8);\n",
+                indent.c_str());
+        fprintf(out, "%s        buff[pos] = INT_TYPE;\n", indent.c_str());
+        fprintf(out, "%s        copyInt(buff, pos + 1, key);\n", indent.c_str());
+        fprintf(out, "%s        pos += INT_TYPE_SIZE;\n", indent.c_str());
+        fprintf(out, "%s        buff[pos] = STRING_TYPE;\n", indent.c_str());
+        fprintf(out, "%s        copyInt(buff, pos + 1, valueBytes.length);\n", indent.c_str());
+        fprintf(out, "%s        System.arraycopy("
+                "valueBytes, 0, buff, pos + STRING_TYPE_OVERHEAD, valueBytes.length);\n",
+                indent.c_str());
+        fprintf(out, "%s        pos += STRING_TYPE_OVERHEAD + valueBytes.length;\n",
+                indent.c_str());
+        fprintf(out, "%s    }\n", indent.c_str());
+
+        // Write floats.
+        fprintf(out, "%s    final int floatMapSize = null == floatMap ? 0 : floatMap.size();\n",
+                indent.c_str());
+        fprintf(out, "%s    buff[pos] = LIST_TYPE;\n", indent.c_str());
+        fprintf(out, "%s    buff[pos + 1] = (byte) floatMapSize;\n", indent.c_str());
+        fprintf(out, "%s    pos += LIST_TYPE_OVERHEAD;\n", indent.c_str());
+        fprintf(out, "%s    for (int i = 0; i < floatMapSize; i++) {\n", indent.c_str());
+        fprintf(out, "%s        buff[pos] = LIST_TYPE;\n", indent.c_str());
+        fprintf(out, "%s        buff[pos + 1] = (byte) 2;\n", indent.c_str());
+        fprintf(out, "%s        pos += LIST_TYPE_OVERHEAD;\n", indent.c_str());
+        fprintf(out, "%s        final int key = floatMap.keyAt(i);\n", indent.c_str());
+        fprintf(out, "%s        final float value = floatMap.valueAt(i);\n", indent.c_str());
+        fprintf(out, "%s        buff[pos] = INT_TYPE;\n", indent.c_str());
+        fprintf(out, "%s        copyInt(buff, pos + 1, key);\n", indent.c_str());
+        fprintf(out, "%s        pos += INT_TYPE_SIZE;\n", indent.c_str());
+        fprintf(out, "%s        buff[pos] = FLOAT_TYPE;\n", indent.c_str());
+        fprintf(out, "%s        copyFloat(buff, pos + 1, value);\n", indent.c_str());
+        fprintf(out, "%s        pos += FLOAT_TYPE_SIZE;\n", indent.c_str());
+        fprintf(out, "%s    }\n", indent.c_str());
+        fprintf(out, "%s}\n", indent.c_str());
+        fprintf(out, "\n");
+    }
 }
 
 #if defined(STATS_SCHEMA_LEGACY)
@@ -382,7 +598,7 @@
                         java_type_name(chainField.javaType), chainField.name.c_str());
                 }
             } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
-                fprintf(out, ", android.util.SparseArray<Object> value_map");
+                fprintf(out, ", android.util.SparseArray<Object> valueMap");
             } else {
                 fprintf(out, ", %s arg%d", java_type_name(*arg), argIndex);
             }
diff --git a/tools/stats_log_api_gen/utils.h b/tools/stats_log_api_gen/utils.h
index 50737a6..cd602e5 100644
--- a/tools/stats_log_api_gen/utils.h
+++ b/tools/stats_log_api_gen/utils.h
@@ -39,6 +39,7 @@
 
 const int JAVA_MODULE_REQUIRES_FLOAT = 0x01;
 const int JAVA_MODULE_REQUIRES_ATTRIBUTION = 0x02;
+const int JAVA_MODULE_REQUIRES_KEY_VALUE_PAIRS = 0x04;
 
 string make_constant_name(const string& str);