Merge "Tell KeygaurdViewMediator about keyguard showing updates"
diff --git a/Android.bp b/Android.bp
index d94bd84..56d6557 100644
--- a/Android.bp
+++ b/Android.bp
@@ -103,6 +103,8 @@
         "core/java/android/app/backup/IRestoreObserver.aidl",
         "core/java/android/app/backup/IRestoreSession.aidl",
         "core/java/android/app/backup/ISelectBackupTransportCallback.aidl",
+        "core/java/android/app/role/IRoleManager.aidl",
+        "core/java/android/app/role/IRoleManagerCallback.aidl",
         "core/java/android/app/slice/ISliceManager.aidl",
         "core/java/android/app/slice/ISliceListener.aidl",
         "core/java/android/app/timedetector/ITimeDetectorService.aidl",
@@ -233,8 +235,7 @@
         "core/java/android/os/IDeviceIdentifiersPolicyService.aidl",
         "core/java/android/os/IDeviceIdleController.aidl",
         "core/java/android/os/IHardwarePropertiesManager.aidl",
-        "core/java/android/os/IIncidentManager.aidl",
-        "core/java/android/os/IIncidentReportStatusListener.aidl",
+        ":libincident_aidl",
         "core/java/android/os/IMaintenanceActivityListener.aidl",
         "core/java/android/os/IMessenger.aidl",
         "core/java/android/os/INetworkActivityListener.aidl",
@@ -247,8 +248,7 @@
         "core/java/android/os/IRecoverySystemProgressListener.aidl",
         "core/java/android/os/IRemoteCallback.aidl",
         "core/java/android/os/ISchedulingPolicyService.aidl",
-        "core/java/android/os/IStatsCompanionService.aidl",
-        "core/java/android/os/IStatsManager.aidl",
+        ":statsd_aidl",
         "core/java/android/os/ISystemUpdateManager.aidl",
         "core/java/android/os/IThermalEventListener.aidl",
         "core/java/android/os/IThermalService.aidl",
@@ -259,6 +259,7 @@
         "core/java/android/os/storage/IStorageEventListener.aidl",
         "core/java/android/os/storage/IStorageShutdownObserver.aidl",
         "core/java/android/os/storage/IObbActionListener.aidl",
+        "core/java/android/rolecontrollerservice/IRoleControllerService.aidl",
         ":keystore_aidl",
         "core/java/android/security/keymaster/IKeyAttestationApplicationIdProvider.aidl",
         "core/java/android/service/autofill/IAutoFillService.aidl",
@@ -721,6 +722,22 @@
 
 }
 
+filegroup {
+    name: "libincident_aidl",
+    srcs: [
+        "core/java/android/os/IIncidentManager.aidl",
+        "core/java/android/os/IIncidentReportStatusListener.aidl",
+    ],
+}
+
+filegroup {
+    name: "statsd_aidl",
+    srcs: [
+        "core/java/android/os/IStatsCompanionService.aidl",
+        "core/java/android/os/IStatsManager.aidl",
+    ],
+}
+
 java_library {
     name: "framework",
     defaults: ["framework-defaults"],
@@ -931,12 +948,14 @@
         "core/proto/android/os/batterytype.proto",
         "core/proto/android/os/cpufreq.proto",
         "core/proto/android/os/cpuinfo.proto",
+        "core/proto/android/os/data.proto",
         "core/proto/android/os/kernelwake.proto",
         "core/proto/android/os/pagetypeinfo.proto",
         "core/proto/android/os/procrank.proto",
         "core/proto/android/os/ps.proto",
         "core/proto/android/os/system_properties.proto",
         "core/proto/android/util/event_log_tags.proto",
+        "core/proto/android/util/log.proto",
     ],
 
     // Append protoc-gen-cppstream tool's PATH otherwise aprotoc can't find the plugin tool
diff --git a/apct-tests/perftests/core/src/android/graphics/perftests/RenderNodePerfTest.java b/apct-tests/perftests/core/src/android/graphics/perftests/RenderNodePerfTest.java
index d18aa51..62dd124 100644
--- a/apct-tests/perftests/core/src/android/graphics/perftests/RenderNodePerfTest.java
+++ b/apct-tests/perftests/core/src/android/graphics/perftests/RenderNodePerfTest.java
@@ -17,7 +17,6 @@
 package android.graphics.perftests;
 
 import android.graphics.Outline;
-import android.graphics.RecordingCanvas;
 import android.graphics.RenderNode;
 import android.perftests.utils.BenchmarkState;
 import android.perftests.utils.PerfStatusReporter;
@@ -62,7 +61,7 @@
         final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
         RenderNode node = RenderNode.create("LinearLayout", null);
         while (state.keepRunning()) {
-            node.isValid();
+            node.hasDisplayList();
         }
     }
 
@@ -71,8 +70,8 @@
         final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
         RenderNode node = RenderNode.create("LinearLayout", null);
         while (state.keepRunning()) {
-            RecordingCanvas canvas = node.start(100, 100);
-            node.end(canvas);
+            node.startRecording(100, 100);
+            node.endRecording();
         }
     }
 
@@ -80,17 +79,16 @@
     public void testStartEndDeepHierarchy() {
         final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
         RenderNode[] nodes = new RenderNode[30];
-        RecordingCanvas[] canvases = new RecordingCanvas[nodes.length];
         for (int i = 0; i < nodes.length; i++) {
             nodes[i] = RenderNode.create("LinearLayout", null);
         }
 
         while (state.keepRunning()) {
             for (int i = 0; i < nodes.length; i++) {
-                canvases[i] = nodes[i].start(100, 100);
+                nodes[i].startRecording(100, 100);
             }
             for (int i = nodes.length - 1; i >= 0; i--) {
-                nodes[i].end(canvases[i]);
+                nodes[i].endRecording();
             }
         }
     }
diff --git a/apct-tests/perftests/core/src/android/os/BinderCallsStatsPerfTest.java b/apct-tests/perftests/core/src/android/os/BinderCallsStatsPerfTest.java
index d8d4a6e..5be0cb0 100644
--- a/apct-tests/perftests/core/src/android/os/BinderCallsStatsPerfTest.java
+++ b/apct-tests/perftests/core/src/android/os/BinderCallsStatsPerfTest.java
@@ -38,6 +38,23 @@
 @RunWith(AndroidJUnit4.class)
 @LargeTest
 public class BinderCallsStatsPerfTest {
+    private static final int DEFAULT_BUCKET_SIZE = 1000;
+    static class FakeCpuTimeBinderCallsStats extends BinderCallsStats {
+        private int mTimeMs;
+
+        FakeCpuTimeBinderCallsStats() {
+            super(new BinderCallsStats.Injector());
+            setDeviceState(new CachedDeviceState(false, false).getReadonlyClient());
+        }
+
+        protected long getThreadTimeMicro() {
+            return mTimeMs++;
+        }
+
+        protected long getElapsedRealtimeMicro() {
+            return mTimeMs++;
+        }
+    }
 
     @Rule
     public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
@@ -57,28 +74,50 @@
     @Test
     public void timeCallSession() {
         mBinderCallsStats.setDetailedTracking(true);
-        runScenario();
+        runScenario(DEFAULT_BUCKET_SIZE);
     }
 
     @Test
     public void timeCallSessionOnePercentSampling() {
         mBinderCallsStats.setDetailedTracking(false);
         mBinderCallsStats.setSamplingInterval(100);
-        runScenario();
+        runScenario(DEFAULT_BUCKET_SIZE);
     }
 
     @Test
     public void timeCallSessionTrackingDisabled() {
         mBinderCallsStats.setDetailedTracking(false);
-        runScenario();
+        runScenario(DEFAULT_BUCKET_SIZE);
     }
 
-    private void runScenario() {
+    @Test
+    public void timeCallSession_1000_buckets_cpuNotRecorded() {
+        mBinderCallsStats = new FakeCpuTimeBinderCallsStats();
+        mBinderCallsStats.setSamplingInterval(1);
+        runScenario(/* max bucket size */ 1000);
+    }
+
+    @Test
+    public void timeCallSession_500_buckets_cpuNotRecorded() {
+        mBinderCallsStats = new FakeCpuTimeBinderCallsStats();
+        mBinderCallsStats.setSamplingInterval(1);
+        runScenario(/* max bucket size */ 500);
+    }
+
+    @Test
+    public void timeCallSession_100_buckets_cpuNotRecorded() {
+        mBinderCallsStats = new FakeCpuTimeBinderCallsStats();
+        mBinderCallsStats.setSamplingInterval(1);
+        runScenario(/* max bucket size */ 100);
+    }
+
+    // There will be a warmup time of maxBucketSize to initialize the map of CallStat.
+    private void runScenario(int maxBucketSize) {
         final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
         Binder b = new Binder();
         while (state.keepRunning()) {
-            for (int i = 0; i < 1000; i++) {
-                CallSession s = mBinderCallsStats.callStarted(b, i % 100);
+            for (int i = 0; i < 10000; i++) {
+                CallSession s = mBinderCallsStats.callStarted(b, i % maxBucketSize);
                 mBinderCallsStats.callEnded(s, 0, 0);
             }
         }
diff --git a/apct-tests/perftests/core/src/android/os/KernelCpuThreadReaderPerfTest.java b/apct-tests/perftests/core/src/android/os/KernelCpuThreadReaderPerfTest.java
new file mode 100644
index 0000000..9034034
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/os/KernelCpuThreadReaderPerfTest.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import static org.junit.Assert.assertNotNull;
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.support.test.filters.LargeTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.internal.os.KernelCpuThreadReader;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+
+/**
+ * Performance tests collecting per-thread CPU data.
+ */
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public class KernelCpuThreadReaderPerfTest {
+    @Rule
+    public final PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    private final KernelCpuThreadReader mKernelCpuThreadReader = KernelCpuThreadReader.create();
+
+    @Test
+    public void timeReadCurrentProcessCpuUsage() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        assertNotNull(mKernelCpuThreadReader);
+        while (state.keepRunning()) {
+            this.mKernelCpuThreadReader.getCurrentProcessCpuUsage();
+        }
+    }
+}
diff --git a/apct-tests/perftests/core/src/android/text/CanvasDrawTextTest.java b/apct-tests/perftests/core/src/android/text/CanvasDrawTextTest.java
new file mode 100644
index 0000000..ad9fb5f
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/text/CanvasDrawTextTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.text;
+
+import android.graphics.RecordingCanvas;
+import android.graphics.RenderNode;
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.support.test.filters.LargeTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Random;
+
+@LargeTest
+@RunWith(AndroidJUnit4.class)
+public class CanvasDrawTextTest {
+    private static final int WORD_LENGTH = 9;  // Random word has 9 characters.
+
+    private static final TextPaint PAINT = new TextPaint();
+
+    @Rule
+    public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    private TextPerfUtils mTextUtil = new TextPerfUtils();
+
+    @Before
+    public void setUp() {
+        mTextUtil.resetRandom(0 /* seed */);
+    }
+
+    @Test
+    public void drawText_LongText_SmallWindow() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        final String text = mTextUtil.nextRandomParagraph(
+                WORD_LENGTH, 4 * 1024 * 1024 /* 4mb text */).toString();
+        final RenderNode node = RenderNode.create("benchmark", null);
+        final RenderNode child = RenderNode.create("child", null);
+        child.setLeftTopRightBottom(50, 50, 100, 100);
+
+        RecordingCanvas canvas = node.start(100, 100);
+        node.end(canvas);
+        canvas = child.start(50, 50);
+        child.end(canvas);
+
+        final Random r = new Random(0);
+
+        while (state.keepRunning()) {
+            int start = r.nextInt(text.length() - 100);
+            canvas.drawText(text, start, start + 100, 0, 0, PAINT);
+        }
+    }
+}
diff --git a/apct-tests/perftests/core/src/android/text/StaticLayoutPerfTest.java b/apct-tests/perftests/core/src/android/text/StaticLayoutPerfTest.java
index e224fa3..35d3802 100644
--- a/apct-tests/perftests/core/src/android/text/StaticLayoutPerfTest.java
+++ b/apct-tests/perftests/core/src/android/text/StaticLayoutPerfTest.java
@@ -245,10 +245,11 @@
             state.pauseTiming();
             final StaticLayout layout =
                     StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH).build();
-            final RecordingCanvas c = node.start(1200, 200);
+            final RecordingCanvas c = node.startRecording(1200, 200);
             state.resumeTiming();
 
             layout.draw(c);
+            node.endRecording();
         }
     }
 
@@ -261,10 +262,11 @@
             final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, STYLE_TEXT);
             final StaticLayout layout =
                     StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH).build();
-            final RecordingCanvas c = node.start(1200, 200);
+            final RecordingCanvas c = node.startRecording(1200, 200);
             state.resumeTiming();
 
             layout.draw(c);
+            node.endRecording();
         }
     }
 
@@ -277,10 +279,11 @@
             final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT);
             final StaticLayout layout =
                     StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH).build();
-            final RecordingCanvas c = node.start(1200, 200);
+            final RecordingCanvas c = node.startRecording(1200, 200);
             state.resumeTiming();
 
             layout.draw(c);
+            node.endRecording();
         }
     }
 
@@ -293,11 +296,12 @@
             final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, STYLE_TEXT);
             final StaticLayout layout =
                     StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH).build();
-            final RecordingCanvas c = node.start(1200, 200);
+            final RecordingCanvas c = node.startRecording(1200, 200);
             Canvas.freeTextLayoutCaches();
             state.resumeTiming();
 
             layout.draw(c);
+            node.endRecording();
         }
     }
 
@@ -310,11 +314,12 @@
             final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT);
             final StaticLayout layout =
                     StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH).build();
-            final RecordingCanvas c = node.start(1200, 200);
+            final RecordingCanvas c = node.startRecording(1200, 200);
             Canvas.freeTextLayoutCaches();
             state.resumeTiming();
 
             layout.draw(c);
+            node.endRecording();
         }
     }
 
@@ -328,10 +333,11 @@
                     mTextUtil.nextRandomParagraph(WORD_LENGTH, STYLE_TEXT), PAINT);
             final StaticLayout layout =
                     StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH).build();
-            final RecordingCanvas c = node.start(1200, 200);
+            final RecordingCanvas c = node.startRecording(1200, 200);
             state.resumeTiming();
 
             layout.draw(c);
+            node.endRecording();
         }
     }
 
@@ -345,10 +351,11 @@
                     mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT);
             final StaticLayout layout =
                     StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH).build();
-            final RecordingCanvas c = node.start(1200, 200);
+            final RecordingCanvas c = node.startRecording(1200, 200);
             state.resumeTiming();
 
             layout.draw(c);
+            node.endRecording();
         }
     }
 
@@ -362,11 +369,12 @@
                     mTextUtil.nextRandomParagraph(WORD_LENGTH, STYLE_TEXT), PAINT);
             final StaticLayout layout =
                     StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH).build();
-            final RecordingCanvas c = node.start(1200, 200);
+            final RecordingCanvas c = node.startRecording(1200, 200);
             Canvas.freeTextLayoutCaches();
             state.resumeTiming();
 
             layout.draw(c);
+            node.endRecording();
         }
     }
 
@@ -380,11 +388,12 @@
                     mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT);
             final StaticLayout layout =
                     StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH).build();
-            final RecordingCanvas c = node.start(1200, 200);
+            final RecordingCanvas c = node.startRecording(1200, 200);
             Canvas.freeTextLayoutCaches();
             state.resumeTiming();
 
             layout.draw(c);
+            node.endRecording();
         }
     }
 
diff --git a/apct-tests/perftests/core/src/android/text/TextPerfUtils.java b/apct-tests/perftests/core/src/android/text/TextPerfUtils.java
index 22e516a..2a98ebf 100644
--- a/apct-tests/perftests/core/src/android/text/TextPerfUtils.java
+++ b/apct-tests/perftests/core/src/android/text/TextPerfUtils.java
@@ -65,18 +65,23 @@
     }
 
     public CharSequence nextRandomParagraph(int wordLen, boolean applyRandomStyle, String setStr) {
-        return nextRandomParagraph(wordLen, applyRandomStyle, UnicodeSetToArray(setStr));
+        return nextRandomParagraph(wordLen, PARA_LENGTH, applyRandomStyle,
+                UnicodeSetToArray(setStr));
     }
 
     public CharSequence nextRandomParagraph(int wordLen, boolean applyRandomStyle) {
-        return nextRandomParagraph(wordLen, applyRandomStyle, ALPHABET);
+        return nextRandomParagraph(wordLen, PARA_LENGTH, applyRandomStyle, ALPHABET);
     }
 
-    public CharSequence nextRandomParagraph(int wordLen, boolean applyRandomStyle,
+    public CharSequence nextRandomParagraph(int wordLen, int paraLength) {
+        return nextRandomParagraph(wordLen, paraLength, false /* no style */, ALPHABET);
+    }
+
+    public CharSequence nextRandomParagraph(int wordLen, int paraLength, boolean applyRandomStyle,
             String[] charSet) {
         ArrayList<Character> chars = new ArrayList<>();
         ArrayList<Integer> wordOffsets = new ArrayList<>();
-        for (int i = 0; i < PARA_LENGTH; i++) {
+        for (int i = 0; i < paraLength; i++) {
             if (i % (wordLen + 1) == wordLen) {
                 chars.add(' ');
                 wordOffsets.add(chars.size());
diff --git a/apct-tests/perftests/core/src/android/view/ViewShowHidePerfTest.java b/apct-tests/perftests/core/src/android/view/ViewShowHidePerfTest.java
index 6159da4..dc4d4bd 100644
--- a/apct-tests/perftests/core/src/android/view/ViewShowHidePerfTest.java
+++ b/apct-tests/perftests/core/src/android/view/ViewShowHidePerfTest.java
@@ -155,7 +155,7 @@
     }
 
     private void updateAndValidateDisplayList(View view) {
-        boolean hasDisplayList = view.updateDisplayListIfDirty().isValid();
+        boolean hasDisplayList = view.updateDisplayListIfDirty().hasDisplayList();
         assertTrue(hasDisplayList);
     }
 
diff --git a/api/current.txt b/api/current.txt
index 1c3ee82..f27e83c 100755
--- a/api/current.txt
+++ b/api/current.txt
@@ -283,7 +283,6 @@
     field public static final int allowBackup = 16843392; // 0x1010280
     field public static final int allowClearUserData = 16842757; // 0x1010005
     field public static final int allowEmbedded = 16843765; // 0x10103f5
-    field public static final int allowForceDark = 16844172; // 0x101058c
     field public static final int allowParallelSyncs = 16843570; // 0x1010332
     field public static final int allowSingleTap = 16843353; // 0x1010259
     field public static final int allowTaskReparenting = 16843268; // 0x1010204
@@ -638,6 +637,7 @@
     field public static final int fontVariationSettings = 16844144; // 0x1010570
     field public static final int fontWeight = 16844083; // 0x1010533
     field public static final int footerDividersEnabled = 16843311; // 0x101022f
+    field public static final int forceDarkAllowed = 16844172; // 0x101058c
     field public static final int forceHasOverlappingRendering = 16844065; // 0x1010521
     field public static final int foreground = 16843017; // 0x1010109
     field public static final int foregroundGravity = 16843264; // 0x1010200
@@ -5217,6 +5217,7 @@
     ctor public Notification(android.os.Parcel);
     method public android.app.Notification clone();
     method public int describeContents();
+    method public android.app.PendingIntent getAppOverlayIntent();
     method public int getBadgeIconType();
     method public java.lang.String getChannelId();
     method public java.lang.String getGroup();
@@ -5446,6 +5447,7 @@
     method public android.app.Notification.Style getStyle();
     method public static android.app.Notification.Builder recoverBuilder(android.content.Context, android.app.Notification);
     method public android.app.Notification.Builder setActions(android.app.Notification.Action...);
+    method public android.app.Notification.Builder setAppOverlayIntent(android.app.PendingIntent);
     method public android.app.Notification.Builder setAutoCancel(boolean);
     method public android.app.Notification.Builder setBadgeIconType(int);
     method public android.app.Notification.Builder setCategory(java.lang.String);
@@ -5663,6 +5665,7 @@
   public final class NotificationChannel implements android.os.Parcelable {
     ctor public NotificationChannel(java.lang.String, java.lang.CharSequence, int);
     method public boolean canBypassDnd();
+    method public boolean canOverlayApps();
     method public boolean canShowBadge();
     method public int describeContents();
     method public void enableLights(boolean);
@@ -5678,6 +5681,7 @@
     method public android.net.Uri getSound();
     method public long[] getVibrationPattern();
     method public boolean hasUserSetImportance();
+    method public void setAllowAppOverlay(boolean);
     method public void setBypassDnd(boolean);
     method public void setDescription(java.lang.String);
     method public void setGroup(java.lang.String);
@@ -5697,6 +5701,7 @@
 
   public final class NotificationChannelGroup implements android.os.Parcelable {
     ctor public NotificationChannelGroup(java.lang.String, java.lang.CharSequence);
+    method public boolean canOverlayApps();
     method public android.app.NotificationChannelGroup clone();
     method public int describeContents();
     method public java.util.List<android.app.NotificationChannel> getChannels();
@@ -5704,6 +5709,7 @@
     method public java.lang.String getId();
     method public java.lang.CharSequence getName();
     method public boolean isBlocked();
+    method public void setAllowAppOverlay(boolean);
     method public void setDescription(java.lang.String);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.app.NotificationChannelGroup> CREATOR;
@@ -7281,6 +7287,18 @@
 
 }
 
+package android.app.role {
+
+  public final class RoleManager {
+    method public android.content.Intent createRequestRoleIntent(java.lang.String);
+    method public boolean isRoleAvailable(java.lang.String);
+    method public boolean isRoleHeld(java.lang.String);
+    field public static final java.lang.String ROLE_DIALER = "android.app.role.DIALER";
+    field public static final java.lang.String ROLE_SMS = "android.app.role.SMS";
+  }
+
+}
+
 package android.app.slice {
 
   public final class Slice implements android.os.Parcelable {
@@ -9625,6 +9643,7 @@
     field public static final java.lang.String PRINT_SERVICE = "print";
     field public static final int RECEIVER_VISIBLE_TO_INSTANT_APPS = 1; // 0x1
     field public static final java.lang.String RESTRICTIONS_SERVICE = "restrictions";
+    field public static final java.lang.String ROLE_SERVICE = "role";
     field public static final java.lang.String SEARCH_SERVICE = "search";
     field public static final java.lang.String SENSOR_SERVICE = "sensor";
     field public static final java.lang.String SHORTCUT_SERVICE = "shortcut";
@@ -16068,10 +16087,10 @@
 
   public class BiometricManager {
     method public int canAuthenticate();
-    field public static final int ERROR_NONE = 0; // 0x0
-    field public static final int ERROR_NO_BIOMETRICS = 11; // 0xb
-    field public static final int ERROR_NO_HARDWARE = 12; // 0xc
-    field public static final int ERROR_UNAVAILABLE = 1; // 0x1
+    field public static final int BIOMETRIC_ERROR_NO_BIOMETRICS = 11; // 0xb
+    field public static final int BIOMETRIC_ERROR_NO_HARDWARE = 12; // 0xc
+    field public static final int BIOMETRIC_ERROR_UNAVAILABLE = 1; // 0x1
+    field public static final int BIOMETRIC_SUCCESS = 0; // 0x0
   }
 
   public class BiometricPrompt {
@@ -17382,6 +17401,63 @@
     field public static final int VOWEL_JAMO = 2; // 0x2
   }
 
+  public static abstract interface UCharacter.IndicPositionalCategory {
+    field public static final int BOTTOM = 1; // 0x1
+    field public static final int BOTTOM_AND_LEFT = 2; // 0x2
+    field public static final int BOTTOM_AND_RIGHT = 3; // 0x3
+    field public static final int LEFT = 4; // 0x4
+    field public static final int LEFT_AND_RIGHT = 5; // 0x5
+    field public static final int NA = 0; // 0x0
+    field public static final int OVERSTRUCK = 6; // 0x6
+    field public static final int RIGHT = 7; // 0x7
+    field public static final int TOP = 8; // 0x8
+    field public static final int TOP_AND_BOTTOM = 9; // 0x9
+    field public static final int TOP_AND_BOTTOM_AND_RIGHT = 10; // 0xa
+    field public static final int TOP_AND_LEFT = 11; // 0xb
+    field public static final int TOP_AND_LEFT_AND_RIGHT = 12; // 0xc
+    field public static final int TOP_AND_RIGHT = 13; // 0xd
+    field public static final int VISUAL_ORDER_LEFT = 14; // 0xe
+  }
+
+  public static abstract interface UCharacter.IndicSyllabicCategory {
+    field public static final int AVAGRAHA = 1; // 0x1
+    field public static final int BINDU = 2; // 0x2
+    field public static final int BRAHMI_JOINING_NUMBER = 3; // 0x3
+    field public static final int CANTILLATION_MARK = 4; // 0x4
+    field public static final int CONSONANT = 5; // 0x5
+    field public static final int CONSONANT_DEAD = 6; // 0x6
+    field public static final int CONSONANT_FINAL = 7; // 0x7
+    field public static final int CONSONANT_HEAD_LETTER = 8; // 0x8
+    field public static final int CONSONANT_INITIAL_POSTFIXED = 9; // 0x9
+    field public static final int CONSONANT_KILLER = 10; // 0xa
+    field public static final int CONSONANT_MEDIAL = 11; // 0xb
+    field public static final int CONSONANT_PLACEHOLDER = 12; // 0xc
+    field public static final int CONSONANT_PRECEDING_REPHA = 13; // 0xd
+    field public static final int CONSONANT_PREFIXED = 14; // 0xe
+    field public static final int CONSONANT_SUBJOINED = 15; // 0xf
+    field public static final int CONSONANT_SUCCEEDING_REPHA = 16; // 0x10
+    field public static final int CONSONANT_WITH_STACKER = 17; // 0x11
+    field public static final int GEMINATION_MARK = 18; // 0x12
+    field public static final int INVISIBLE_STACKER = 19; // 0x13
+    field public static final int JOINER = 20; // 0x14
+    field public static final int MODIFYING_LETTER = 21; // 0x15
+    field public static final int NON_JOINER = 22; // 0x16
+    field public static final int NUKTA = 23; // 0x17
+    field public static final int NUMBER = 24; // 0x18
+    field public static final int NUMBER_JOINER = 25; // 0x19
+    field public static final int OTHER = 0; // 0x0
+    field public static final int PURE_KILLER = 26; // 0x1a
+    field public static final int REGISTER_SHIFTER = 27; // 0x1b
+    field public static final int SYLLABLE_MODIFIER = 28; // 0x1c
+    field public static final int TONE_LETTER = 29; // 0x1d
+    field public static final int TONE_MARK = 30; // 0x1e
+    field public static final int VIRAMA = 31; // 0x1f
+    field public static final int VISARGA = 32; // 0x20
+    field public static final int VOWEL = 33; // 0x21
+    field public static final int VOWEL_DEPENDENT = 34; // 0x22
+    field public static final int VOWEL_INDEPENDENT = 35; // 0x23
+  }
+
   public static abstract interface UCharacter.JoiningGroup {
     field public static final int AFRICAN_FEH = 86; // 0x56
     field public static final int AFRICAN_NOON = 87; // 0x57
@@ -18165,6 +18241,13 @@
     field public static final int ZANABAZAR_SQUARE_ID = 280; // 0x118
   }
 
+  public static abstract interface UCharacter.VerticalOrientation {
+    field public static final int ROTATED = 0; // 0x0
+    field public static final int TRANSFORMED_ROTATED = 1; // 0x1
+    field public static final int TRANSFORMED_UPRIGHT = 2; // 0x2
+    field public static final int UPRIGHT = 3; // 0x3
+  }
+
   public static abstract interface UCharacter.WordBreak {
     field public static final int ALETTER = 1; // 0x1
     field public static final int CR = 8; // 0x8
@@ -18336,6 +18419,8 @@
     field public static final int IDS_TRINARY_OPERATOR = 19; // 0x13
     field public static final int ID_CONTINUE = 15; // 0xf
     field public static final int ID_START = 16; // 0x10
+    field public static final int INDIC_POSITIONAL_CATEGORY = 4118; // 0x1016
+    field public static final int INDIC_SYLLABIC_CATEGORY = 4119; // 0x1017
     field public static final int INT_START = 4096; // 0x1000
     field public static final int JOINING_GROUP = 4102; // 0x1006
     field public static final int JOINING_TYPE = 4103; // 0x1007
@@ -18389,6 +18474,7 @@
     field public static final int UPPERCASE = 30; // 0x1e
     field public static final int UPPERCASE_MAPPING = 16396; // 0x400c
     field public static final int VARIATION_SELECTOR = 36; // 0x24
+    field public static final int VERTICAL_ORIENTATION = 4120; // 0x1018
     field public static final int WHITE_SPACE = 31; // 0x1f
     field public static final int WORD_BREAK = 4116; // 0x1014
     field public static final int XID_CONTINUE = 32; // 0x20
@@ -18919,6 +19005,7 @@
     method public int preceding(int);
     method public abstract int previous();
     method public void setText(java.lang.String);
+    method public void setText(java.lang.CharSequence);
     method public abstract void setText(java.text.CharacterIterator);
     field public static final int DONE = -1; // 0xffffffff
     field public static final int KIND_CHARACTER = 0; // 0x0
@@ -18947,24 +19034,31 @@
   }
 
   public static final class CaseMap.Fold extends android.icu.text.CaseMap {
+    method public java.lang.String apply(java.lang.CharSequence);
     method public <A extends java.lang.Appendable> A apply(java.lang.CharSequence, A, android.icu.text.Edits);
     method public android.icu.text.CaseMap.Fold omitUnchangedText();
     method public android.icu.text.CaseMap.Fold turkic();
   }
 
   public static final class CaseMap.Lower extends android.icu.text.CaseMap {
+    method public java.lang.String apply(java.util.Locale, java.lang.CharSequence);
     method public <A extends java.lang.Appendable> A apply(java.util.Locale, java.lang.CharSequence, A, android.icu.text.Edits);
     method public android.icu.text.CaseMap.Lower omitUnchangedText();
   }
 
   public static final class CaseMap.Title extends android.icu.text.CaseMap {
+    method public android.icu.text.CaseMap.Title adjustToCased();
+    method public java.lang.String apply(java.util.Locale, android.icu.text.BreakIterator, java.lang.CharSequence);
     method public <A extends java.lang.Appendable> A apply(java.util.Locale, android.icu.text.BreakIterator, java.lang.CharSequence, A, android.icu.text.Edits);
     method public android.icu.text.CaseMap.Title noBreakAdjustment();
     method public android.icu.text.CaseMap.Title noLowercase();
     method public android.icu.text.CaseMap.Title omitUnchangedText();
+    method public android.icu.text.CaseMap.Title sentences();
+    method public android.icu.text.CaseMap.Title wholeString();
   }
 
   public static final class CaseMap.Upper extends android.icu.text.CaseMap {
+    method public java.lang.String apply(java.util.Locale, java.lang.CharSequence);
     method public <A extends java.lang.Appendable> A apply(java.util.Locale, java.lang.CharSequence, A, android.icu.text.Edits);
     method public android.icu.text.CaseMap.Upper omitUnchangedText();
   }
@@ -18972,7 +19066,6 @@
   public final class CollationElementIterator {
     method public int getMaxExpansion(int);
     method public int getOffset();
-    method public deprecated int hashCode();
     method public int next();
     method public int previous();
     method public static int primaryOrder(int);
@@ -19085,7 +19178,6 @@
     method public static android.icu.text.CurrencyPluralInfo getInstance(android.icu.util.ULocale);
     method public android.icu.util.ULocale getLocale();
     method public android.icu.text.PluralRules getPluralRules();
-    method public deprecated int hashCode();
     method public void setCurrencyPluralPattern(java.lang.String, java.lang.String);
     method public void setLocale(android.icu.util.ULocale);
     method public void setPluralRules(java.lang.String);
@@ -19375,7 +19467,6 @@
     method public boolean firstDateInPtnIsLaterDate();
     method public java.lang.String getFirstPart();
     method public java.lang.String getSecondPart();
-    method public deprecated java.lang.String toString();
   }
 
   public class DateTimePatternGenerator implements java.lang.Cloneable android.icu.util.Freezable {
@@ -19535,6 +19626,8 @@
     ctor public DecimalFormatSymbols(java.util.Locale);
     ctor public DecimalFormatSymbols(android.icu.util.ULocale);
     method public java.lang.Object clone();
+    method public static android.icu.text.DecimalFormatSymbols forNumberingSystem(java.util.Locale, android.icu.text.NumberingSystem);
+    method public static android.icu.text.DecimalFormatSymbols forNumberingSystem(android.icu.util.ULocale, android.icu.text.NumberingSystem);
     method public static java.util.Locale[] getAvailableLocales();
     method public android.icu.util.Currency getCurrency();
     method public java.lang.String getCurrencySymbol();
@@ -19644,11 +19737,15 @@
     method public android.icu.text.Edits.Iterator getFineIterator();
     method public boolean hasChanges();
     method public int lengthDelta();
+    method public android.icu.text.Edits mergeAndAppend(android.icu.text.Edits, android.icu.text.Edits);
+    method public int numberOfChanges();
     method public void reset();
   }
 
   public static final class Edits.Iterator {
     method public int destinationIndex();
+    method public int destinationIndexFromSourceIndex(int);
+    method public boolean findDestinationIndex(int);
     method public boolean findSourceIndex(int);
     method public boolean hasChange();
     method public int newLength();
@@ -19656,6 +19753,7 @@
     method public int oldLength();
     method public int replacementIndex();
     method public int sourceIndex();
+    method public int sourceIndexFromDestinationIndex(int);
   }
 
   public abstract class IDNA {
@@ -20058,6 +20156,7 @@
     method public int getRadix();
     method public boolean isAlgorithmic();
     method public static boolean isValidDigitString(java.lang.String);
+    field public static final android.icu.text.NumberingSystem LATIN;
   }
 
   public class PluralFormat extends android.icu.text.UFormat {
@@ -20095,7 +20194,6 @@
     method public java.util.Set<java.lang.String> getKeywords();
     method public java.util.Collection<java.lang.Double> getSamples(java.lang.String);
     method public double getUniqueKeywordValue(java.lang.String);
-    method public deprecated int hashCode();
     method public static android.icu.text.PluralRules parseDescription(java.lang.String) throws java.text.ParseException;
     method public java.lang.String select(double);
     field public static final android.icu.text.PluralRules DEFAULT;
@@ -20338,7 +20436,6 @@
     ctor public StringPrepParseException(java.lang.String, int, java.lang.String, int);
     ctor public StringPrepParseException(java.lang.String, int, java.lang.String, int, int);
     method public int getError();
-    method public deprecated int hashCode();
     field public static final int ACE_PREFIX_ERROR = 6; // 0x6
     field public static final int BUFFER_OVERFLOW_ERROR = 9; // 0x9
     field public static final int CHECK_BIDI_ERROR = 4; // 0x4
@@ -20969,6 +21066,7 @@
 
   public class Currency extends android.icu.util.MeasureUnit {
     ctor protected Currency(java.lang.String);
+    method public static android.icu.util.Currency fromJavaCurrency(java.util.Currency);
     method public static java.util.Set<android.icu.util.Currency> getAvailableCurrencies();
     method public static java.lang.String[] getAvailableCurrencyCodes(android.icu.util.ULocale, java.util.Date);
     method public static java.lang.String[] getAvailableCurrencyCodes(java.util.Locale, java.util.Date);
@@ -20994,6 +21092,7 @@
     method public java.lang.String getSymbol(java.util.Locale);
     method public java.lang.String getSymbol(android.icu.util.ULocale);
     method public static boolean isAvailable(java.lang.String, java.util.Date, java.util.Date);
+    method public java.util.Currency toJavaCurrency();
     field public static final int LONG_NAME = 1; // 0x1
     field public static final int PLURAL_LONG_NAME = 2; // 0x2
     field public static final int SYMBOL_NAME = 0; // 0x0
@@ -21009,6 +21108,8 @@
   public class CurrencyAmount extends android.icu.util.Measure {
     ctor public CurrencyAmount(java.lang.Number, android.icu.util.Currency);
     ctor public CurrencyAmount(double, android.icu.util.Currency);
+    ctor public CurrencyAmount(java.lang.Number, java.util.Currency);
+    ctor public CurrencyAmount(double, java.util.Currency);
     method public android.icu.util.Currency getCurrency();
   }
 
@@ -22662,6 +22763,7 @@
     method public boolean isBluetoothScoOn();
     method public boolean isMicrophoneMute();
     method public boolean isMusicActive();
+    method public static boolean isOffloadedPlaybackSupported(android.media.AudioFormat);
     method public boolean isSpeakerphoneOn();
     method public boolean isStreamMute(int);
     method public boolean isVolumeFixed();
@@ -22983,6 +23085,7 @@
     method public int getUnderrunCount();
     method public void pause() throws java.lang.IllegalStateException;
     method public void play() throws java.lang.IllegalStateException;
+    method public void registerStreamEventCallback(java.util.concurrent.Executor, android.media.AudioTrack.StreamEventCallback);
     method public void release();
     method public int reloadStaticData();
     method public void removeOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener);
@@ -23003,6 +23106,7 @@
     method public deprecated int setStereoVolume(float, float);
     method public int setVolume(float);
     method public void stop() throws java.lang.IllegalStateException;
+    method public void unregisterStreamEventCallback(android.media.AudioTrack.StreamEventCallback);
     method public int write(byte[], int, int);
     method public int write(byte[], int, int, int);
     method public int write(short[], int, int);
@@ -23036,6 +23140,7 @@
     method public android.media.AudioTrack.Builder setAudioAttributes(android.media.AudioAttributes) throws java.lang.IllegalArgumentException;
     method public android.media.AudioTrack.Builder setAudioFormat(android.media.AudioFormat) throws java.lang.IllegalArgumentException;
     method public android.media.AudioTrack.Builder setBufferSizeInBytes(int) throws java.lang.IllegalArgumentException;
+    method public android.media.AudioTrack.Builder setOffloadedPlayback(boolean);
     method public android.media.AudioTrack.Builder setPerformanceMode(int);
     method public android.media.AudioTrack.Builder setSessionId(int) throws java.lang.IllegalArgumentException;
     method public android.media.AudioTrack.Builder setTransferMode(int) throws java.lang.IllegalArgumentException;
@@ -23059,6 +23164,13 @@
     method public default void onRoutingChanged(android.media.AudioRouting);
   }
 
+  public static abstract class AudioTrack.StreamEventCallback {
+    ctor public AudioTrack.StreamEventCallback();
+    method public void onDataRequest(android.media.AudioTrack, int);
+    method public void onPresentationEnded(android.media.AudioTrack);
+    method public void onTearDown(android.media.AudioTrack);
+  }
+
   public class CamcorderProfile {
     method public static android.media.CamcorderProfile get(int);
     method public static android.media.CamcorderProfile get(int, int);
@@ -29742,8 +29854,7 @@
     field public static final int EGL_WINDOW_BIT = 4; // 0x4
   }
 
-  public class EGL15 {
-    ctor public EGL15();
+  public final class EGL15 {
     method public static int eglClientWaitSync(android.opengl.EGLDisplay, android.opengl.EGLSync, int, long);
     method public static android.opengl.EGLImage eglCreateImage(android.opengl.EGLDisplay, android.opengl.EGLContext, int, long, long[], int);
     method public static android.opengl.EGLSurface eglCreatePlatformPixmapSurface(android.opengl.EGLDisplay, android.opengl.EGLConfig, java.nio.Buffer, long[], int);
@@ -36791,11 +36902,14 @@
     ctor public MediaStore();
     method public static android.net.Uri getDocumentUri(android.content.Context, android.net.Uri);
     method public static android.net.Uri getMediaScannerUri();
+    method public static android.net.Uri getMediaUri(android.content.Context, android.net.Uri);
     method public static java.lang.String getVersion(android.content.Context);
+    method public static java.lang.String getVolumeName(android.net.Uri);
     field public static final java.lang.String ACTION_IMAGE_CAPTURE = "android.media.action.IMAGE_CAPTURE";
     field public static final java.lang.String ACTION_IMAGE_CAPTURE_SECURE = "android.media.action.IMAGE_CAPTURE_SECURE";
     field public static final java.lang.String ACTION_VIDEO_CAPTURE = "android.media.action.VIDEO_CAPTURE";
     field public static final java.lang.String AUTHORITY = "media";
+    field public static final android.net.Uri AUTHORITY_URI;
     field public static final java.lang.String EXTRA_DURATION_LIMIT = "android.intent.extra.durationLimit";
     field public static final java.lang.String EXTRA_FINISH_ON_COMPLETION = "android.intent.extra.finishOnCompletion";
     field public static final java.lang.String EXTRA_FULL_SCREEN = "android.intent.extra.fullScreen";
@@ -37586,6 +37700,7 @@
     field public static final java.lang.String AUTH_TYPE = "authtype";
     field public static final deprecated java.lang.String BEARER = "bearer";
     field public static final java.lang.String CARRIER_ENABLED = "carrier_enabled";
+    field public static final java.lang.String CARRIER_ID = "carrier_id";
     field public static final android.net.Uri CONTENT_URI;
     field public static final java.lang.String CURRENT = "current";
     field public static final java.lang.String DEFAULT_SORT_ORDER = "name ASC";
@@ -42376,6 +42491,7 @@
     field public static final java.lang.String KEY_CALL_BARRING_VISIBILITY_BOOL = "call_barring_visibility_bool";
     field public static final java.lang.String KEY_CALL_FORWARDING_BLOCKS_WHILE_ROAMING_STRING_ARRAY = "call_forwarding_blocks_while_roaming_string_array";
     field public static final java.lang.String KEY_CARRIER_ALLOW_TURNOFF_IMS_BOOL = "carrier_allow_turnoff_ims_bool";
+    field public static final java.lang.String KEY_CARRIER_CALL_SCREENING_APP_STRING = "call_screening_app";
     field public static final java.lang.String KEY_CARRIER_DATA_CALL_PERMANENT_FAILURE_STRINGS = "carrier_data_call_permanent_failure_strings";
     field public static final java.lang.String KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT = "carrier_default_wfc_ims_mode_int";
     field public static final java.lang.String KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_MODE_INT = "carrier_default_wfc_ims_roaming_mode_int";
@@ -42491,6 +42607,7 @@
     field public static final java.lang.String KEY_SIM_NETWORK_UNLOCK_ALLOW_DISMISS_BOOL = "sim_network_unlock_allow_dismiss_bool";
     field public static final java.lang.String KEY_SMS_REQUIRES_DESTINATION_NUMBER_CONVERSION_BOOL = "sms_requires_destination_number_conversion_bool";
     field public static final java.lang.String KEY_SUPPORT_3GPP_CALL_FORWARDING_WHILE_ROAMING_BOOL = "support_3gpp_call_forwarding_while_roaming_bool";
+    field public static final java.lang.String KEY_SUPPORT_CLIR_NETWORK_DEFAULT_BOOL = "support_clir_network_default_bool";
     field public static final java.lang.String KEY_SUPPORT_CONFERENCE_CALL_BOOL = "support_conference_call_bool";
     field public static final java.lang.String KEY_SUPPORT_EMERGENCY_SMS_OVER_IMS_BOOL = "support_emergency_sms_over_ims_bool";
     field public static final java.lang.String KEY_SUPPORT_PAUSE_IMS_VIDEO_CALLS_BOOL = "support_pause_ims_video_calls_bool";
@@ -42568,6 +42685,7 @@
     method public int getLac();
     method public java.lang.String getMccString();
     method public java.lang.String getMncString();
+    method public java.lang.String getMobileNetworkOperator();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.telephony.CellIdentityTdscdma> CREATOR;
   }
@@ -42596,6 +42714,7 @@
     field public static final int CONNECTION_SECONDARY_SERVING = 2; // 0x2
     field public static final int CONNECTION_UNKNOWN = 2147483647; // 0x7fffffff
     field public static final android.os.Parcelable.Creator<android.telephony.CellInfo> CREATOR;
+    field public static final int UNAVAILABLE = 2147483647; // 0x7fffffff
   }
 
   public final class CellInfoCdma extends android.telephony.CellInfo implements android.os.Parcelable {
@@ -43128,7 +43247,7 @@
     method public static int getDefaultSmsSubscriptionId();
     method public static int getDefaultSubscriptionId();
     method public static int getDefaultVoiceSubscriptionId();
-    method public java.util.List<android.telephony.SubscriptionInfo> getOpportunisticSubscriptions(int);
+    method public java.util.List<android.telephony.SubscriptionInfo> getOpportunisticSubscriptions();
     method public static int getSlotIndex(int);
     method public static int[] getSubscriptionIds(int);
     method public java.util.List<android.telephony.SubscriptionPlan> getSubscriptionPlans(int);
@@ -45873,7 +45992,8 @@
   }
 
   public class TransitionValues {
-    ctor public TransitionValues();
+    ctor public deprecated TransitionValues();
+    ctor public TransitionValues(android.view.View);
     field public final java.util.Map<java.lang.String, java.lang.Object> values;
     field public android.view.View view;
   }
@@ -48508,6 +48628,7 @@
     method public final boolean isFocusableInTouchMode();
     method public boolean isFocused();
     method public final boolean isFocusedByDefault();
+    method public boolean isForceDarkAllowed();
     method public boolean isHapticFeedbackEnabled();
     method public boolean isHardwareAccelerated();
     method public boolean isHorizontalFadingEdgeEnabled();
@@ -48694,6 +48815,7 @@
     method public void setFocusable(int);
     method public void setFocusableInTouchMode(boolean);
     method public void setFocusedByDefault(boolean);
+    method public void setForceDarkAllowed(boolean);
     method public void setForeground(android.graphics.drawable.Drawable);
     method public void setForegroundGravity(int);
     method public void setForegroundTintList(android.content.res.ColorStateList);
@@ -51307,6 +51429,99 @@
 
 package android.view.textclassifier {
 
+  public final class ConversationActions implements android.os.Parcelable {
+    ctor public ConversationActions(java.util.List<android.view.textclassifier.ConversationActions.ConversationAction>);
+    method public int describeContents();
+    method public java.util.List<android.view.textclassifier.ConversationActions.ConversationAction> getConversationActions();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.view.textclassifier.ConversationActions> CREATOR;
+    field public static final java.lang.String HINT_FOR_IN_APP = "in_app";
+    field public static final java.lang.String HINT_FOR_NOTIFICATION = "notification";
+    field public static final java.lang.String TYPE_CALL_PHONE = "call_phone";
+    field public static final java.lang.String TYPE_CREATE_REMINDER = "create_reminder";
+    field public static final java.lang.String TYPE_OPEN_URL = "open_url";
+    field public static final java.lang.String TYPE_SEND_EMAIL = "send_email";
+    field public static final java.lang.String TYPE_SEND_SMS = "send_sms";
+    field public static final java.lang.String TYPE_SHARE_LOCATION = "share_location";
+    field public static final java.lang.String TYPE_TEXT_REPLY = "text_reply";
+    field public static final java.lang.String TYPE_TRACK_FLIGHT = "track_flight";
+    field public static final java.lang.String TYPE_VIEW_CALENDAR = "view_calendar";
+    field public static final java.lang.String TYPE_VIEW_MAP = "view_map";
+  }
+
+  public static final class ConversationActions.ConversationAction implements android.os.Parcelable {
+    method public int describeContents();
+    method public android.app.RemoteAction getAction();
+    method public float getConfidenceScore();
+    method public android.os.Bundle getExtras();
+    method public java.lang.CharSequence getTextReply();
+    method public java.lang.String getType();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.view.textclassifier.ConversationActions.ConversationAction> CREATOR;
+  }
+
+  public static final class ConversationActions.ConversationAction.Builder {
+    ctor public ConversationActions.ConversationAction.Builder(java.lang.String);
+    method public android.view.textclassifier.ConversationActions.ConversationAction build();
+    method public android.view.textclassifier.ConversationActions.ConversationAction.Builder setAction(android.app.RemoteAction);
+    method public android.view.textclassifier.ConversationActions.ConversationAction.Builder setConfidenceScore(float);
+    method public android.view.textclassifier.ConversationActions.ConversationAction.Builder setExtras(android.os.Bundle);
+    method public android.view.textclassifier.ConversationActions.ConversationAction.Builder setTextReply(java.lang.CharSequence);
+  }
+
+  public static final class ConversationActions.Message implements android.os.Parcelable {
+    method public int describeContents();
+    method public android.app.Person getAuthor();
+    method public android.os.Bundle getExtras();
+    method public java.lang.CharSequence getText();
+    method public java.time.ZonedDateTime getTime();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.view.textclassifier.ConversationActions.Message> CREATOR;
+  }
+
+  public static final class ConversationActions.Message.Builder {
+    ctor public ConversationActions.Message.Builder();
+    method public android.view.textclassifier.ConversationActions.Message build();
+    method public android.view.textclassifier.ConversationActions.Message.Builder setAuthor(android.app.Person);
+    method public android.view.textclassifier.ConversationActions.Message.Builder setComposeTime(java.time.ZonedDateTime);
+    method public android.view.textclassifier.ConversationActions.Message.Builder setExtras(android.os.Bundle);
+    method public android.view.textclassifier.ConversationActions.Message.Builder setText(java.lang.CharSequence);
+  }
+
+  public static final class ConversationActions.Request implements android.os.Parcelable {
+    method public int describeContents();
+    method public java.util.List<android.view.textclassifier.ConversationActions.Message> getConversation();
+    method public java.util.List<java.lang.String> getHints();
+    method public int getMaxSuggestions();
+    method public android.view.textclassifier.ConversationActions.TypeConfig getTypeConfig();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.view.textclassifier.ConversationActions.Request> CREATOR;
+  }
+
+  public static final class ConversationActions.Request.Builder {
+    ctor public ConversationActions.Request.Builder(java.util.List<android.view.textclassifier.ConversationActions.Message>);
+    method public android.view.textclassifier.ConversationActions.Request build();
+    method public android.view.textclassifier.ConversationActions.Request.Builder setHints(java.util.List<java.lang.String>);
+    method public android.view.textclassifier.ConversationActions.Request.Builder setMaxSuggestions(int);
+    method public android.view.textclassifier.ConversationActions.Request.Builder setTypeConfig(android.view.textclassifier.ConversationActions.TypeConfig);
+  }
+
+  public static final class ConversationActions.TypeConfig implements android.os.Parcelable {
+    method public int describeContents();
+    method public java.util.Collection<java.lang.String> resolveTypes(java.util.Collection<java.lang.String>);
+    method public boolean shouldIncludeTypesFromTextClassifier();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.view.textclassifier.ConversationActions.TypeConfig> CREATOR;
+  }
+
+  public static final class ConversationActions.TypeConfig.Builder {
+    ctor public ConversationActions.TypeConfig.Builder();
+    method public android.view.textclassifier.ConversationActions.TypeConfig build();
+    method public android.view.textclassifier.ConversationActions.TypeConfig.Builder includeTypesFromTextClassifier(boolean);
+    method public android.view.textclassifier.ConversationActions.TypeConfig.Builder setExcludedTypes(java.util.Collection<java.lang.String>);
+    method public android.view.textclassifier.ConversationActions.TypeConfig.Builder setIncludedTypes(java.util.Collection<java.lang.String>);
+  }
+
   public final class SelectionEvent implements android.os.Parcelable {
     method public static android.view.textclassifier.SelectionEvent createSelectionActionEvent(int, int, int);
     method public static android.view.textclassifier.SelectionEvent createSelectionActionEvent(int, int, int, android.view.textclassifier.TextClassification);
@@ -51361,6 +51576,7 @@
     method public float getConfidenceScore(java.lang.String);
     method public java.lang.String getEntity(int);
     method public int getEntityCount();
+    method public android.os.Bundle getExtras();
     method public deprecated android.graphics.drawable.Drawable getIcon();
     method public java.lang.String getId();
     method public deprecated android.content.Intent getIntent();
@@ -51376,6 +51592,7 @@
     method public android.view.textclassifier.TextClassification.Builder addAction(android.app.RemoteAction);
     method public android.view.textclassifier.TextClassification build();
     method public android.view.textclassifier.TextClassification.Builder setEntityType(java.lang.String, float);
+    method public android.view.textclassifier.TextClassification.Builder setExtras(android.os.Bundle);
     method public deprecated android.view.textclassifier.TextClassification.Builder setIcon(android.graphics.drawable.Drawable);
     method public android.view.textclassifier.TextClassification.Builder setId(java.lang.String);
     method public deprecated android.view.textclassifier.TextClassification.Builder setIntent(android.content.Intent);
@@ -51388,6 +51605,7 @@
     method public int describeContents();
     method public android.os.LocaleList getDefaultLocales();
     method public int getEndIndex();
+    method public android.os.Bundle getExtras();
     method public java.time.ZonedDateTime getReferenceTime();
     method public int getStartIndex();
     method public java.lang.CharSequence getText();
@@ -51399,6 +51617,7 @@
     ctor public TextClassification.Request.Builder(java.lang.CharSequence, int, int);
     method public android.view.textclassifier.TextClassification.Request build();
     method public android.view.textclassifier.TextClassification.Request.Builder setDefaultLocales(android.os.LocaleList);
+    method public android.view.textclassifier.TextClassification.Request.Builder setExtras(android.os.Bundle);
     method public android.view.textclassifier.TextClassification.Request.Builder setReferenceTime(java.time.ZonedDateTime);
   }
 
@@ -51443,6 +51662,7 @@
     method public default int getMaxGenerateLinksTextLength();
     method public default boolean isDestroyed();
     method public default void onSelectionEvent(android.view.textclassifier.SelectionEvent);
+    method public default android.view.textclassifier.ConversationActions suggestConversationActions(android.view.textclassifier.ConversationActions.Request);
     method public default android.view.textclassifier.TextSelection suggestSelection(android.view.textclassifier.TextSelection.Request);
     method public default android.view.textclassifier.TextSelection suggestSelection(java.lang.CharSequence, int, int, android.os.LocaleList);
     field public static final java.lang.String HINT_TEXT_IS_EDITABLE = "android.text_is_editable";
diff --git a/api/system-current.txt b/api/system-current.txt
index 7e51082..b1cbfa6 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -93,6 +93,7 @@
     field public static final java.lang.String LOCATION_HARDWARE = "android.permission.LOCATION_HARDWARE";
     field public static final java.lang.String LOCK_DEVICE = "android.permission.LOCK_DEVICE";
     field public static final java.lang.String LOOP_RADIO = "android.permission.LOOP_RADIO";
+    field public static final java.lang.String MANAGE_ACCESSIBILITY = "android.permission.MANAGE_ACCESSIBILITY";
     field public static final java.lang.String MANAGE_ACTIVITY_STACKS = "android.permission.MANAGE_ACTIVITY_STACKS";
     field public static final java.lang.String MANAGE_APP_OPS_RESTRICTIONS = "android.permission.MANAGE_APP_OPS_RESTRICTIONS";
     field public static final java.lang.String MANAGE_APP_TOKENS = "android.permission.MANAGE_APP_TOKENS";
@@ -101,6 +102,7 @@
     field public static final java.lang.String MANAGE_CA_CERTIFICATES = "android.permission.MANAGE_CA_CERTIFICATES";
     field public static final java.lang.String MANAGE_DEVICE_ADMINS = "android.permission.MANAGE_DEVICE_ADMINS";
     field public static final java.lang.String MANAGE_IPSEC_TUNNELS = "android.permission.MANAGE_IPSEC_TUNNELS";
+    field public static final java.lang.String MANAGE_ROLE_HOLDERS = "android.permission.MANAGE_ROLE_HOLDERS";
     field public static final java.lang.String MANAGE_SOUND_TRIGGER = "android.permission.MANAGE_SOUND_TRIGGER";
     field public static final java.lang.String MANAGE_SUBSCRIPTION_PLANS = "android.permission.MANAGE_SUBSCRIPTION_PLANS";
     field public static final java.lang.String MANAGE_USB = "android.permission.MANAGE_USB";
@@ -293,6 +295,8 @@
   public class AppOpsManager {
     method public static java.lang.String[] getOpStrs();
     method public java.util.List<android.app.AppOpsManager.PackageOps> getOpsForPackage(int, java.lang.String, int[]);
+    method public static java.lang.String opToPermission(java.lang.String);
+    method public void resetUidMode(java.lang.String, int, boolean);
     method public void setMode(java.lang.String, int, java.lang.String, int);
     method public void setUidMode(java.lang.String, int, int);
     field public static final java.lang.String OPSTR_ACCEPT_HANDOVER = "android:accept_handover";
@@ -802,6 +806,23 @@
 
 }
 
+package android.app.role {
+
+  public final class RoleManager {
+    method public void addRoleHolderAsUser(java.lang.String, java.lang.String, android.os.UserHandle, java.util.concurrent.Executor, android.app.role.RoleManagerCallback);
+    method public void clearRoleHoldersAsUser(java.lang.String, android.os.UserHandle, java.util.concurrent.Executor, android.app.role.RoleManagerCallback);
+    method public java.util.Set<java.lang.String> getRoleHoldersAsUser(java.lang.String, android.os.UserHandle);
+    method public void removeRoleHolderAsUser(java.lang.String, java.lang.String, android.os.UserHandle, java.util.concurrent.Executor, android.app.role.RoleManagerCallback);
+    field public static final java.lang.String EXTRA_REQUEST_ROLE_NAME = "android.app.role.extra.REQUEST_ROLE_NAME";
+  }
+
+  public abstract interface RoleManagerCallback {
+    method public abstract void onFailure();
+    method public abstract void onSuccess();
+  }
+
+}
+
 package android.app.usage {
 
   public final class CacheQuotaHint implements android.os.Parcelable {
@@ -850,9 +871,11 @@
     method public int getAppStandbyBucket(java.lang.String);
     method public java.util.Map<java.lang.String, java.lang.Integer> getAppStandbyBuckets();
     method public void registerAppUsageObserver(int, java.lang.String[], long, java.util.concurrent.TimeUnit, android.app.PendingIntent);
+    method public void registerUsageSessionObserver(int, java.lang.String[], long, java.util.concurrent.TimeUnit, long, java.util.concurrent.TimeUnit, android.app.PendingIntent, android.app.PendingIntent);
     method public void setAppStandbyBucket(java.lang.String, int);
     method public void setAppStandbyBuckets(java.util.Map<java.lang.String, java.lang.Integer>);
     method public void unregisterAppUsageObserver(int);
+    method public void unregisterUsageSessionObserver(int);
     method public void whitelistAppTemporarily(java.lang.String, long, android.os.UserHandle);
     field public static final java.lang.String EXTRA_OBSERVER_ID = "android.app.usage.extra.OBSERVER_ID";
     field public static final java.lang.String EXTRA_TIME_LIMIT = "android.app.usage.extra.TIME_LIMIT";
@@ -987,8 +1010,8 @@
     field public static final java.lang.String ACTION_PRE_BOOT_COMPLETED = "android.intent.action.PRE_BOOT_COMPLETED";
     field public static final java.lang.String ACTION_QUERY_PACKAGE_RESTART = "android.intent.action.QUERY_PACKAGE_RESTART";
     field public static final java.lang.String ACTION_RESOLVE_INSTANT_APP_PACKAGE = "android.intent.action.RESOLVE_INSTANT_APP_PACKAGE";
-    field public static final java.lang.String ACTION_REVIEW_PERMISSION_USAGE = "android.intent.action.REVIEW_PERMISSION_USAGE";
     field public static final java.lang.String ACTION_REVIEW_PERMISSIONS = "android.intent.action.REVIEW_PERMISSIONS";
+    field public static final java.lang.String ACTION_REVIEW_PERMISSION_USAGE = "android.intent.action.REVIEW_PERMISSION_USAGE";
     field public static final java.lang.String ACTION_SHOW_SUSPENDED_APP_DETAILS = "android.intent.action.SHOW_SUSPENDED_APP_DETAILS";
     field public static final deprecated java.lang.String ACTION_SIM_STATE_CHANGED = "android.intent.action.SIM_STATE_CHANGED";
     field public static final java.lang.String ACTION_SPLIT_CONFIGURATION_CHANGED = "android.intent.action.SPLIT_CONFIGURATION_CHANGED";
@@ -1148,6 +1171,7 @@
     method public java.util.List<android.content.pm.ResolveInfo> queryBroadcastReceiversAsUser(android.content.Intent, int, android.os.UserHandle);
     method public abstract void registerDexModule(java.lang.String, android.content.pm.PackageManager.DexModuleRegisterCallback);
     method public abstract void removeOnPermissionsChangeListener(android.content.pm.PackageManager.OnPermissionsChangedListener);
+    method public void replacePreferredActivity(android.content.IntentFilter, int, java.util.List<android.content.ComponentName>, android.content.ComponentName);
     method public abstract void revokeRuntimePermission(java.lang.String, java.lang.String, android.os.UserHandle);
     method public abstract boolean setDefaultBrowserPackageNameAsUser(java.lang.String, int);
     method public void setHarmfulAppWarning(java.lang.String, java.lang.CharSequence);
@@ -4154,8 +4178,11 @@
     method public deprecated int getUserRestrictionSource(java.lang.String, android.os.UserHandle);
     method public java.util.List<android.os.UserManager.EnforcingUser> getUserRestrictionSources(java.lang.String, android.os.UserHandle);
     method public boolean hasRestrictedProfiles();
+    method public boolean isAdminUser();
+    method public boolean isGuestUser();
     method public boolean isManagedProfile();
     method public boolean isManagedProfile(int);
+    method public boolean isPrimaryUser();
     method public boolean isRestrictedProfile();
     field public static final java.lang.String ACTION_USER_RESTRICTIONS_CHANGED = "android.os.action.USER_RESTRICTIONS_CHANGED";
     field public static final deprecated java.lang.String DISALLOW_OEM_UNLOCK = "no_oem_unlock";
@@ -4468,6 +4495,7 @@
     field public static final java.lang.String AUTOFILL_USER_DATA_MIN_VALUE_LENGTH = "autofill_user_data_min_value_length";
     field public static final java.lang.String HUSH_GESTURE_USED = "hush_gesture_used";
     field public static final java.lang.String INSTANT_APPS_ENABLED = "instant_apps_enabled";
+    field public static final java.lang.String LAST_SETUP_SHOWN = "last_setup_shown";
     field public static final java.lang.String MANUAL_RINGER_TOGGLE_COUNT = "manual_ringer_toggle_count";
     field public static final java.lang.String VOLUME_HUSH_GESTURE = "volume_hush_gesture";
   }
@@ -4507,6 +4535,19 @@
 
 }
 
+package android.rolecontrollerservice {
+
+  public abstract class RoleControllerService extends android.app.Service {
+    ctor public RoleControllerService();
+    method public abstract void onAddRoleHolder(java.lang.String, java.lang.String, android.app.role.RoleManagerCallback);
+    method public final android.os.IBinder onBind(android.content.Intent);
+    method public abstract void onClearRoleHolders(java.lang.String, android.app.role.RoleManagerCallback);
+    method public abstract void onRemoveRoleHolder(java.lang.String, java.lang.String, android.app.role.RoleManagerCallback);
+    field public static final java.lang.String SERVICE_INTERFACE = "android.rolecontrollerservice.RoleControllerService";
+  }
+
+}
+
 package android.security.keystore {
 
   public abstract class AttestationUtils {
@@ -5286,6 +5327,7 @@
 
   public class CarrierConfigManager {
     method public static android.os.PersistableBundle getDefaultConfig();
+    method public void overrideConfig(int, android.os.PersistableBundle);
     method public void updateConfigForPhoneId(int, java.lang.String);
     field public static final java.lang.String KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING = "config_plans_package_override_string";
   }
@@ -5492,6 +5534,7 @@
     method public int getRadioPowerState();
     method public int getSimApplicationState();
     method public int getSimCardState();
+    method public int getSupportedRadioAccessFamily();
     method public java.util.List<android.telephony.TelephonyHistogram> getTelephonyHistograms();
     method public android.telephony.UiccSlotInfo[] getUiccSlotsInfo();
     method public android.os.Bundle getVisualVoicemailSettings();
@@ -5499,7 +5542,10 @@
     method public boolean handlePinMmi(java.lang.String);
     method public boolean handlePinMmiForSubscriber(int, java.lang.String);
     method public boolean isDataConnectivityPossible();
+    method public deprecated boolean isIdle();
+    method public deprecated boolean isOffhook();
     method public deprecated boolean isRadioOn();
+    method public deprecated boolean isRinging();
     method public boolean isVideoCallingEnabled();
     method public deprecated boolean isVisualVoicemailEnabled(android.telecom.PhoneAccountHandle);
     method public boolean needsOtaServiceProvisioning();
@@ -5554,6 +5600,24 @@
     field public static final int NETWORK_MODE_TDSCDMA_WCDMA = 14; // 0xe
     field public static final int NETWORK_MODE_WCDMA_ONLY = 2; // 0x2
     field public static final int NETWORK_MODE_WCDMA_PREF = 0; // 0x0
+    field public static final int NETWORK_TYPE_BITMASK_1xRTT = 128; // 0x80
+    field public static final int NETWORK_TYPE_BITMASK_CDMA = 16; // 0x10
+    field public static final int NETWORK_TYPE_BITMASK_EDGE = 4; // 0x4
+    field public static final int NETWORK_TYPE_BITMASK_EHRPD = 16384; // 0x4000
+    field public static final int NETWORK_TYPE_BITMASK_EVDO_0 = 32; // 0x20
+    field public static final int NETWORK_TYPE_BITMASK_EVDO_A = 64; // 0x40
+    field public static final int NETWORK_TYPE_BITMASK_EVDO_B = 4096; // 0x1000
+    field public static final int NETWORK_TYPE_BITMASK_GPRS = 2; // 0x2
+    field public static final int NETWORK_TYPE_BITMASK_GSM = 65536; // 0x10000
+    field public static final int NETWORK_TYPE_BITMASK_HSDPA = 256; // 0x100
+    field public static final int NETWORK_TYPE_BITMASK_HSPA = 1024; // 0x400
+    field public static final int NETWORK_TYPE_BITMASK_HSPAP = 32768; // 0x8000
+    field public static final int NETWORK_TYPE_BITMASK_HSUPA = 512; // 0x200
+    field public static final int NETWORK_TYPE_BITMASK_LTE = 8192; // 0x2000
+    field public static final int NETWORK_TYPE_BITMASK_LTE_CA = 524288; // 0x80000
+    field public static final int NETWORK_TYPE_BITMASK_TD_SCDMA = 131072; // 0x20000
+    field public static final int NETWORK_TYPE_BITMASK_UMTS = 8; // 0x8
+    field public static final int NETWORK_TYPE_BITMASK_UNKNOWN = 1; // 0x1
     field public static final int RADIO_POWER_OFF = 0; // 0x0
     field public static final int RADIO_POWER_ON = 1; // 0x1
     field public static final int RADIO_POWER_UNAVAILABLE = 2; // 0x2
@@ -5828,7 +5892,18 @@
     method public int getTimeSeconds();
     method public int getToA();
     method public void writeToParcel(android.os.Parcel, int);
+    field public static final int CDIV_CF_REASON_ALL = 4; // 0x4
+    field public static final int CDIV_CF_REASON_ALL_CONDITIONAL = 5; // 0x5
+    field public static final int CDIV_CF_REASON_BUSY = 1; // 0x1
+    field public static final int CDIV_CF_REASON_NOT_LOGGED_IN = 6; // 0x6
+    field public static final int CDIV_CF_REASON_NOT_REACHABLE = 3; // 0x3
+    field public static final int CDIV_CF_REASON_NO_REPLY = 2; // 0x2
+    field public static final int CDIV_CF_REASON_UNCONDITIONAL = 0; // 0x0
     field public static final android.os.Parcelable.Creator<android.telephony.ims.ImsCallForwardInfo> CREATOR;
+    field public static final int STATUS_ACTIVE = 1; // 0x1
+    field public static final int STATUS_NOT_ACTIVE = 0; // 0x0
+    field public static final int TYPE_OF_ADDRESS_INTERNATIONAL = 145; // 0x91
+    field public static final int TYPE_OF_ADDRESS_UNKNOWN = 129; // 0x81
   }
 
   public final class ImsCallProfile implements android.os.Parcelable {
@@ -6164,6 +6239,13 @@
   public final class ImsSsData implements android.os.Parcelable {
     ctor public ImsSsData(int, int, int, int, int);
     method public int describeContents();
+    method public android.telephony.ims.ImsCallForwardInfo[] getCallForwardInfo();
+    method public int getRequestType();
+    method public int getResult();
+    method public int getServiceClass();
+    method public int getServiceType();
+    method public android.telephony.ims.ImsSsInfo[] getSuppServiceInfo();
+    method public int getTeleserviceType();
     method public boolean isTypeBarring();
     method public boolean isTypeCf();
     method public boolean isTypeClip();
@@ -6176,6 +6258,16 @@
     method public boolean isTypeUnConditional();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.telephony.ims.ImsSsData> CREATOR;
+    field public static final int RESULT_SUCCESS = 0; // 0x0
+    field public static final int SERVICE_CLASS_DATA = 2; // 0x2
+    field public static final int SERVICE_CLASS_DATA_CIRCUIT_ASYNC = 32; // 0x20
+    field public static final int SERVICE_CLASS_DATA_CIRCUIT_SYNC = 16; // 0x10
+    field public static final int SERVICE_CLASS_DATA_PACKET_ACCESS = 64; // 0x40
+    field public static final int SERVICE_CLASS_DATA_PAD = 128; // 0x80
+    field public static final int SERVICE_CLASS_FAX = 4; // 0x4
+    field public static final int SERVICE_CLASS_NONE = 0; // 0x0
+    field public static final int SERVICE_CLASS_SMS = 8; // 0x8
+    field public static final int SERVICE_CLASS_VOICE = 1; // 0x1
     field public static final int SS_ACTIVATION = 0; // 0x0
     field public static final int SS_ALL_BARRING = 18; // 0x12
     field public static final int SS_ALL_DATA_TELESERVICES = 3; // 0x3
@@ -6212,13 +6304,31 @@
     field public static final int SS_WAIT = 12; // 0xc
   }
 
+  public static class ImsSsData.Builder {
+    ctor public ImsSsData.Builder(int, int, int, int, int);
+    method public android.telephony.ims.ImsSsData build();
+    method public android.telephony.ims.ImsSsData.Builder setCallForwardingInfo(android.telephony.ims.ImsCallForwardInfo[]);
+    method public android.telephony.ims.ImsSsData.Builder setSuppServiceInfo(android.telephony.ims.ImsSsInfo[]);
+  }
+
   public final class ImsSsInfo implements android.os.Parcelable {
-    ctor public ImsSsInfo(int, java.lang.String);
+    ctor public deprecated ImsSsInfo(int, java.lang.String);
     method public int describeContents();
-    method public java.lang.String getIcbNum();
+    method public int getClirInterrogationStatus();
+    method public int getClirOutgoingState();
+    method public deprecated java.lang.String getIcbNum();
+    method public java.lang.String getIncomingCommunicationBarringNumber();
     method public int getProvisionStatus();
     method public int getStatus();
     method public void writeToParcel(android.os.Parcel, int);
+    field public static final int CLIR_OUTGOING_DEFAULT = 0; // 0x0
+    field public static final int CLIR_OUTGOING_INVOCATION = 1; // 0x1
+    field public static final int CLIR_OUTGOING_SUPPRESSION = 2; // 0x2
+    field public static final int CLIR_STATUS_NOT_PROVISIONED = 0; // 0x0
+    field public static final int CLIR_STATUS_PROVISIONED_PERMANENT = 1; // 0x1
+    field public static final int CLIR_STATUS_TEMPORARILY_ALLOWED = 4; // 0x4
+    field public static final int CLIR_STATUS_TEMPORARILY_RESTRICTED = 3; // 0x3
+    field public static final int CLIR_STATUS_UNKNOWN = 2; // 0x2
     field public static final android.os.Parcelable.Creator<android.telephony.ims.ImsSsInfo> CREATOR;
     field public static final int DISABLED = 0; // 0x0
     field public static final int ENABLED = 1; // 0x1
@@ -6228,6 +6338,21 @@
     field public static final int SERVICE_PROVISIONING_UNKNOWN = -1; // 0xffffffff
   }
 
+  public static class ImsSsInfo.Builder {
+    ctor public ImsSsInfo.Builder(int);
+    method public android.telephony.ims.ImsSsInfo build();
+    method public android.telephony.ims.ImsSsInfo.Builder setClirInterrogationStatus(int);
+    method public android.telephony.ims.ImsSsInfo.Builder setClirOutgoingState(int);
+    method public android.telephony.ims.ImsSsInfo.Builder setIncomingCommunicationBarringNumber(java.lang.String);
+    method public android.telephony.ims.ImsSsInfo.Builder setProvisionStatus(int);
+  }
+
+  public static abstract class ImsSsInfo.ClirInterrogationStatus implements java.lang.annotation.Annotation {
+  }
+
+  public static abstract class ImsSsInfo.ClirOutgoingState implements java.lang.annotation.Annotation {
+  }
+
   public final class ImsStreamMediaProfile implements android.os.Parcelable {
     ctor public ImsStreamMediaProfile(int, int, int, int, int);
     method public void copyFrom(android.telephony.ims.ImsStreamMediaProfile);
@@ -6708,6 +6833,14 @@
 
 }
 
+package android.view.accessibility {
+
+  public final class AccessibilityManager {
+    method public void performAccessibilityShortcut();
+  }
+
+}
+
 package android.webkit {
 
   public abstract class CookieManager {
diff --git a/api/system-removed.txt b/api/system-removed.txt
index 4e7a114..4beb699 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -116,9 +116,6 @@
   public class TelephonyManager {
     method public deprecated void answerRingingCall();
     method public deprecated boolean endCall();
-    method public deprecated boolean isIdle();
-    method public deprecated boolean isOffhook();
-    method public deprecated boolean isRinging();
     method public deprecated void silenceRinger();
   }
 
diff --git a/api/test-current.txt b/api/test-current.txt
index 463c9d3..d453395 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -140,7 +140,10 @@
   }
 
   public final class NotificationChannelGroup implements android.os.Parcelable {
+    method public int getUserLockedFields();
+    method public void lockFields(int);
     method public void setBlocked(boolean);
+    field public static final int USER_LOCKED_ALLOW_APP_OVERLAY = 2; // 0x2
   }
 
   public class NotificationManager {
@@ -957,6 +960,7 @@
 
   public static final class Settings.Secure extends android.provider.Settings.NameValueTable {
     field public static final java.lang.String ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED = "accessibility_display_magnification_enabled";
+    field public static final java.lang.String ACCESSIBILITY_SHORTCUT_TARGET_SERVICE = "accessibility_shortcut_target_service";
     field public static final java.lang.String AUTOFILL_FEATURE_FIELD_CLASSIFICATION = "autofill_field_classification";
     field public static final java.lang.String AUTOFILL_SERVICE = "autofill_service";
     field public static final java.lang.String AUTOFILL_USER_DATA_MAX_CATEGORY_COUNT = "autofill_user_data_max_category_count";
@@ -1183,6 +1187,10 @@
 
 package android.telephony {
 
+  public class CarrierConfigManager {
+    method public void overrideConfig(int, android.os.PersistableBundle);
+  }
+
   public class MbmsDownloadSession implements java.lang.AutoCloseable {
     field public static final java.lang.String MBMS_DOWNLOAD_SERVICE_OVERRIDE_METADATA = "mbms-download-service-override";
   }
@@ -1604,6 +1612,17 @@
 
 package android.view.accessibility {
 
+  public final class AccessibilityManager {
+    method public void addAccessibilityServicesStateChangeListener(android.view.accessibility.AccessibilityManager.AccessibilityServicesStateChangeListener, android.os.Handler);
+    method public java.lang.String getAccessibilityShortcutService();
+    method public void performAccessibilityShortcut();
+    method public void removeAccessibilityServicesStateChangeListener(android.view.accessibility.AccessibilityManager.AccessibilityServicesStateChangeListener);
+  }
+
+  public static abstract interface AccessibilityManager.AccessibilityServicesStateChangeListener {
+    method public abstract void onAccessibilityServicesStateChanged(android.view.accessibility.AccessibilityManager);
+  }
+
   public class AccessibilityNodeInfo implements android.os.Parcelable {
     method public static void setNumInstancesInUseCounter(java.util.concurrent.atomic.AtomicInteger);
     method public void writeToParcelNoRecycle(android.os.Parcel, int);
diff --git a/cmds/idmap2/.clang-format b/cmds/idmap2/.clang-format
new file mode 100644
index 0000000..c91502a
--- /dev/null
+++ b/cmds/idmap2/.clang-format
@@ -0,0 +1,7 @@
+BasedOnStyle: Google
+ColumnLimit: 100
+AllowShortBlocksOnASingleLine: false
+AllowShortFunctionsOnASingleLine: false
+CommentPragmas: NOLINT:.*
+DerivePointerAlignment: false
+PointerAlignment: Left
diff --git a/cmds/idmap2/Android.bp b/cmds/idmap2/Android.bp
new file mode 100644
index 0000000..5a6c813
--- /dev/null
+++ b/cmds/idmap2/Android.bp
@@ -0,0 +1,191 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+cc_library {
+    name: "libidmap2",
+    host_supported: true,
+    tidy: true,
+    tidy_flags: [
+        "-system-headers",
+        "-warnings-as-errors=*",
+    ],
+    srcs: [
+        "libidmap2/BinaryStreamVisitor.cpp",
+        "libidmap2/CommandLineOptions.cpp",
+        "libidmap2/FileUtils.cpp",
+        "libidmap2/Idmap.cpp",
+        "libidmap2/PrettyPrintVisitor.cpp",
+        "libidmap2/RawPrintVisitor.cpp",
+        "libidmap2/ResourceUtils.cpp",
+        "libidmap2/Xml.cpp",
+        "libidmap2/ZipFile.cpp",
+    ],
+    export_include_dirs: ["include"],
+    target: {
+        android: {
+            static: {
+                enabled: false,
+            },
+            shared_libs: [
+                "libandroidfw",
+                "libbase",
+                "libutils",
+                "libziparchive",
+            ],
+        },
+        host: {
+            shared: {
+                enabled: false,
+            },
+            static_libs: [
+                "libandroidfw",
+                "libbase",
+                "libutils",
+                "libziparchive",
+            ],
+        },
+    },
+}
+
+cc_test {
+    name: "idmap2_tests",
+    host_supported: true,
+    tidy: true,
+    tidy_flags: [
+        "-system-headers",
+        "-warnings-as-errors=*",
+    ],
+    srcs: [
+        "tests/BinaryStreamVisitorTests.cpp",
+        "tests/CommandLineOptionsTests.cpp",
+        "tests/FileUtilsTests.cpp",
+        "tests/Idmap2BinaryTests.cpp",
+        "tests/IdmapTests.cpp",
+        "tests/Main.cpp",
+        "tests/PrettyPrintVisitorTests.cpp",
+        "tests/RawPrintVisitorTests.cpp",
+        "tests/ResourceUtilsTests.cpp",
+        "tests/XmlTests.cpp",
+        "tests/ZipFileTests.cpp",
+    ],
+    required: [
+        "idmap2",
+    ],
+    static_libs: ["libgmock"],
+    target: {
+        android: {
+            shared_libs: [
+                "libandroidfw",
+                "libbase",
+                "libidmap2",
+                "liblog",
+                "libutils",
+                "libz",
+                "libziparchive",
+            ],
+        },
+        host: {
+            static_libs: [
+                "libandroidfw",
+                "libbase",
+                "libidmap2",
+                "liblog",
+                "libutils",
+                "libziparchive",
+            ],
+            shared_libs: [
+                "libz",
+            ],
+        },
+    },
+    data: ["tests/data/**/*.apk"],
+}
+
+cc_binary {
+    name: "idmap2",
+    host_supported: true,
+    tidy: true,
+    tidy_flags: [
+        "-system-headers",
+        "-warnings-as-errors=*",
+    ],
+    srcs: [
+        "idmap2/Create.cpp",
+        "idmap2/Dump.cpp",
+        "idmap2/Lookup.cpp",
+        "idmap2/Main.cpp",
+        "idmap2/Scan.cpp",
+        "idmap2/Verify.cpp",
+    ],
+    target: {
+        android: {
+            shared_libs: [
+                "libandroidfw",
+                "libbase",
+                "libidmap2",
+                "libutils",
+                "libziparchive",
+            ],
+        },
+        host: {
+            static_libs: [
+                "libandroidfw",
+                "libbase",
+                "libidmap2",
+                "liblog",
+                "libutils",
+                "libziparchive",
+            ],
+            shared_libs: [
+                "libz",
+            ],
+        },
+    },
+}
+
+cc_binary {
+    name: "idmap2d",
+    host_supported: false,
+    tidy: true,
+    tidy_checks: [
+        // remove google-default-arguments or clang-tidy will complain about
+        // the auto-generated file IIdmap2.cpp
+        "-google-default-arguments",
+    ],
+    tidy_flags: [
+        "-system-headers",
+        "-warnings-as-errors=*",
+    ],
+    srcs: [
+        ":idmap2_aidl",
+        "idmap2d/Idmap2Service.cpp",
+        "idmap2d/Main.cpp",
+    ],
+    shared_libs: [
+        "libandroidfw",
+        "libbase",
+        "libbinder",
+        "libcutils",
+        "libidmap2",
+        "libutils",
+        "libziparchive",
+    ],
+}
+
+filegroup {
+    name: "idmap2_aidl",
+    srcs: [
+        "idmap2d/aidl/android/os/IIdmap2.aidl",
+    ],
+}
diff --git a/cmds/idmap2/AndroidTest.xml b/cmds/idmap2/AndroidTest.xml
new file mode 100644
index 0000000..5147f4e
--- /dev/null
+++ b/cmds/idmap2/AndroidTest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Config for idmap2_tests">
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push" value="idmap2_tests->/data/local/tmp/idmap2_tests" />
+    </target_preparer>
+    <option name="test-suite-tag" value="idmap2_tests" />
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="idmap2_tests" />
+    </test>
+</configuration>
diff --git a/cmds/statsd/tools/Android.mk b/cmds/idmap2/CPPLINT.cfg
similarity index 74%
rename from cmds/statsd/tools/Android.mk
rename to cmds/idmap2/CPPLINT.cfg
index 7253c96..9dc6b4a 100644
--- a/cmds/statsd/tools/Android.mk
+++ b/cmds/idmap2/CPPLINT.cfg
@@ -1,4 +1,4 @@
-# Copyright (C) 2017 The Android Open Source Project
+# Copyright (C) 2018 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -11,10 +11,8 @@
 # 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.
-#
-#
 
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-#Include the sub-makefiles
-include $(call all-makefiles-under,$(LOCAL_PATH))
\ No newline at end of file
+set noparent
+linelength=100
+root=..
+filter=+build/include_alpha
diff --git a/cmds/idmap2/OWNERS b/cmds/idmap2/OWNERS
new file mode 100644
index 0000000..23ec5ab
--- /dev/null
+++ b/cmds/idmap2/OWNERS
@@ -0,0 +1,2 @@
+set noparent
+toddke@google.com
diff --git a/cmds/idmap2/TEST_MAPPING b/cmds/idmap2/TEST_MAPPING
new file mode 100644
index 0000000..26ccf03
--- /dev/null
+++ b/cmds/idmap2/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit" : [
+    {
+      "name" : "idmap2_tests"
+    }
+  ]
+}
diff --git a/cmds/idmap2/idmap2/Commands.h b/cmds/idmap2/idmap2/Commands.h
new file mode 100644
index 0000000..dcc69b3
--- /dev/null
+++ b/cmds/idmap2/idmap2/Commands.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef IDMAP2_IDMAP2_COMMANDS_H_
+#define IDMAP2_IDMAP2_COMMANDS_H_
+
+#include <string>
+#include <vector>
+
+bool Create(const std::vector<std::string>& args, std::ostream& out_error);
+bool Dump(const std::vector<std::string>& args, std::ostream& out_error);
+bool Lookup(const std::vector<std::string>& args, std::ostream& out_error);
+bool Scan(const std::vector<std::string>& args, std::ostream& out_error);
+bool Verify(const std::vector<std::string>& args, std::ostream& out_error);
+
+#endif  // IDMAP2_IDMAP2_COMMANDS_H_
diff --git a/cmds/idmap2/idmap2/Create.cpp b/cmds/idmap2/idmap2/Create.cpp
new file mode 100644
index 0000000..291eaeb
--- /dev/null
+++ b/cmds/idmap2/idmap2/Create.cpp
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <sys/stat.h>   // umask
+#include <sys/types.h>  // umask
+#include <fstream>
+#include <memory>
+#include <ostream>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "idmap2/BinaryStreamVisitor.h"
+#include "idmap2/CommandLineOptions.h"
+#include "idmap2/FileUtils.h"
+#include "idmap2/Idmap.h"
+
+using android::ApkAssets;
+using android::idmap2::BinaryStreamVisitor;
+using android::idmap2::CommandLineOptions;
+using android::idmap2::Idmap;
+
+bool Create(const std::vector<std::string>& args, std::ostream& out_error) {
+  std::string target_apk_path, overlay_apk_path, idmap_path;
+
+  const CommandLineOptions opts =
+      CommandLineOptions("idmap2 create")
+          .MandatoryOption("--target-apk-path",
+                           "input: path to apk which will have its resources overlaid",
+                           &target_apk_path)
+          .MandatoryOption("--overlay-apk-path",
+                           "input: path to apk which contains the new resource values",
+                           &overlay_apk_path)
+          .MandatoryOption("--idmap-path", "output: path to where to write idmap file",
+                           &idmap_path);
+  if (!opts.Parse(args, out_error)) {
+    return false;
+  }
+
+  const std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
+  if (!target_apk) {
+    out_error << "error: failed to load apk " << target_apk_path << std::endl;
+    return false;
+  }
+
+  const std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
+  if (!overlay_apk) {
+    out_error << "error: failed to load apk " << overlay_apk_path << std::endl;
+    return false;
+  }
+
+  const std::unique_ptr<const Idmap> idmap =
+      Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk, out_error);
+  if (!idmap) {
+    return false;
+  }
+
+  umask(0133);  // u=rw,g=r,o=r
+  std::ofstream fout(idmap_path);
+  if (fout.fail()) {
+    out_error << "failed to open idmap path " << idmap_path << std::endl;
+    return false;
+  }
+  BinaryStreamVisitor visitor(fout);
+  idmap->accept(&visitor);
+  fout.close();
+  if (fout.fail()) {
+    out_error << "failed to write to idmap path " << idmap_path << std::endl;
+    return false;
+  }
+
+  return true;
+}
diff --git a/cmds/idmap2/idmap2/Dump.cpp b/cmds/idmap2/idmap2/Dump.cpp
new file mode 100644
index 0000000..c8cdcfa
--- /dev/null
+++ b/cmds/idmap2/idmap2/Dump.cpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <fstream>
+#include <iostream>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "idmap2/CommandLineOptions.h"
+#include "idmap2/Idmap.h"
+#include "idmap2/PrettyPrintVisitor.h"
+#include "idmap2/RawPrintVisitor.h"
+
+using android::idmap2::CommandLineOptions;
+using android::idmap2::Idmap;
+using android::idmap2::PrettyPrintVisitor;
+using android::idmap2::RawPrintVisitor;
+
+bool Dump(const std::vector<std::string>& args, std::ostream& out_error) {
+  std::string idmap_path;
+  bool verbose;
+
+  const CommandLineOptions opts =
+      CommandLineOptions("idmap2 dump")
+          .MandatoryOption("--idmap-path", "input: path to idmap file to pretty-print", &idmap_path)
+          .OptionalFlag("--verbose", "annotate every byte of the idmap", &verbose);
+  if (!opts.Parse(args, out_error)) {
+    return false;
+  }
+  std::ifstream fin(idmap_path);
+  const std::unique_ptr<const Idmap> idmap = Idmap::FromBinaryStream(fin, out_error);
+  fin.close();
+  if (!idmap) {
+    return false;
+  }
+
+  if (verbose) {
+    RawPrintVisitor visitor(std::cout);
+    idmap->accept(&visitor);
+  } else {
+    PrettyPrintVisitor visitor(std::cout);
+    idmap->accept(&visitor);
+  }
+
+  return true;
+}
diff --git a/cmds/idmap2/idmap2/Lookup.cpp b/cmds/idmap2/idmap2/Lookup.cpp
new file mode 100644
index 0000000..1191e6a
--- /dev/null
+++ b/cmds/idmap2/idmap2/Lookup.cpp
@@ -0,0 +1,249 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <algorithm>
+#include <fstream>
+#include <iterator>
+#include <memory>
+#include <ostream>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "android-base/macros.h"
+#include "android-base/stringprintf.h"
+#include "androidfw/ApkAssets.h"
+#include "androidfw/AssetManager2.h"
+#include "androidfw/ConfigDescription.h"
+#include "androidfw/ResourceUtils.h"
+#include "androidfw/StringPiece.h"
+#include "androidfw/Util.h"
+#include "utils/String16.h"
+#include "utils/String8.h"
+
+#include "idmap2/CommandLineOptions.h"
+#include "idmap2/Idmap.h"
+#include "idmap2/Xml.h"
+#include "idmap2/ZipFile.h"
+
+using android::ApkAssets;
+using android::ApkAssetsCookie;
+using android::AssetManager2;
+using android::ConfigDescription;
+using android::is_valid_resid;
+using android::kInvalidCookie;
+using android::Res_value;
+using android::ResStringPool;
+using android::ResTable_config;
+using android::String16;
+using android::String8;
+using android::StringPiece16;
+using android::base::StringPrintf;
+using android::idmap2::CommandLineOptions;
+using android::idmap2::IdmapHeader;
+using android::idmap2::ResourceId;
+using android::idmap2::Xml;
+using android::idmap2::ZipFile;
+using android::util::Utf16ToUtf8;
+
+namespace {
+std::pair<bool, ResourceId> WARN_UNUSED ParseResReference(const AssetManager2& am,
+                                                          const std::string& res,
+                                                          const std::string& fallback_package) {
+  // first, try to parse as a hex number
+  char* endptr = nullptr;
+  ResourceId resid;
+  resid = strtol(res.c_str(), &endptr, 16);
+  if (*endptr == '\0') {
+    return std::make_pair(true, resid);
+  }
+
+  // next, try to parse as a package:type/name string
+  resid = am.GetResourceId(res, "", fallback_package);
+  if (is_valid_resid(resid)) {
+    return std::make_pair(true, resid);
+  }
+
+  // end of the road: res could not be parsed
+  return std::make_pair(false, 0);
+}
+
+std::pair<bool, std::string> WARN_UNUSED GetValue(const AssetManager2& am, ResourceId resid) {
+  Res_value value;
+  ResTable_config config;
+  uint32_t flags;
+  ApkAssetsCookie cookie = am.GetResource(resid, false, 0, &value, &config, &flags);
+  if (cookie == kInvalidCookie) {
+    return std::make_pair(false, "");
+  }
+
+  std::string out;
+
+  // TODO(martenkongstad): use optional parameter GetResource(..., std::string*
+  // stacktrace = NULL) instead
+  out.append(StringPrintf("cookie=%d ", cookie));
+
+  out.append("config='");
+  out.append(config.toString().c_str());
+  out.append("' value=");
+
+  switch (value.dataType) {
+    case Res_value::TYPE_INT_DEC:
+      out.append(StringPrintf("%d", value.data));
+      break;
+    case Res_value::TYPE_INT_HEX:
+      out.append(StringPrintf("0x%08x", value.data));
+      break;
+    case Res_value::TYPE_INT_BOOLEAN:
+      out.append(value.data != 0 ? "true" : "false");
+      break;
+    case Res_value::TYPE_STRING: {
+      const ResStringPool* pool = am.GetStringPoolForCookie(cookie);
+      size_t len;
+      if (pool->isUTF8()) {
+        const char* str = pool->string8At(value.data, &len);
+        out.append(str, len);
+      } else {
+        const char16_t* str16 = pool->stringAt(value.data, &len);
+        out += Utf16ToUtf8(StringPiece16(str16, len));
+      }
+    } break;
+    default:
+      out.append(StringPrintf("dataType=0x%02x data=0x%08x", value.dataType, value.data));
+      break;
+  }
+  return std::make_pair(true, out);
+}
+
+std::pair<bool, std::string> GetTargetPackageNameFromManifest(const std::string& apk_path) {
+  const auto zip = ZipFile::Open(apk_path);
+  if (!zip) {
+    return std::make_pair(false, "");
+  }
+  const auto entry = zip->Uncompress("AndroidManifest.xml");
+  if (!entry) {
+    return std::make_pair(false, "");
+  }
+  const auto xml = Xml::Create(entry->buf, entry->size);
+  if (!xml) {
+    return std::make_pair(false, "");
+  }
+  const auto tag = xml->FindTag("overlay");
+  if (!tag) {
+    return std::make_pair(false, "");
+  }
+  const auto iter = tag->find("targetPackage");
+  if (iter == tag->end()) {
+    return std::make_pair(false, "");
+  }
+  return std::make_pair(true, iter->second);
+}
+}  // namespace
+
+bool Lookup(const std::vector<std::string>& args, std::ostream& out_error) {
+  std::vector<std::string> idmap_paths;
+  std::string config_str, resid_str;
+  const CommandLineOptions opts =
+      CommandLineOptions("idmap2 lookup")
+          .MandatoryOption("--idmap-path", "input: path to idmap file to load", &idmap_paths)
+          .MandatoryOption("--config", "configuration to use", &config_str)
+          .MandatoryOption("--resid",
+                           "Resource ID (in the target package; '0xpptteeee' or "
+                           "'[package:]type/name') to look up",
+                           &resid_str);
+
+  if (!opts.Parse(args, out_error)) {
+    return false;
+  }
+
+  ConfigDescription config;
+  if (!ConfigDescription::Parse(config_str, &config)) {
+    out_error << "error: failed to parse config" << std::endl;
+    return false;
+  }
+
+  std::vector<std::unique_ptr<const ApkAssets>> apk_assets;
+  std::string target_path;
+  std::string target_package_name;
+  for (size_t i = 0; i < idmap_paths.size(); i++) {
+    const auto& idmap_path = idmap_paths[i];
+    std::fstream fin(idmap_path);
+    auto idmap_header = IdmapHeader::FromBinaryStream(fin);
+    fin.close();
+    if (!idmap_header) {
+      out_error << "error: failed to read idmap from " << idmap_path << std::endl;
+      return false;
+    }
+
+    if (i == 0) {
+      target_path = idmap_header->GetTargetPath().to_string();
+      auto target_apk = ApkAssets::Load(target_path);
+      if (!target_apk) {
+        out_error << "error: failed to read target apk from " << target_path << std::endl;
+        return false;
+      }
+      apk_assets.push_back(std::move(target_apk));
+
+      bool lookup_ok;
+      std::tie(lookup_ok, target_package_name) =
+          GetTargetPackageNameFromManifest(idmap_header->GetOverlayPath().to_string());
+      if (!lookup_ok) {
+        out_error << "error: failed to parse android:targetPackage from overlay manifest"
+                  << std::endl;
+        return false;
+      }
+    } else if (target_path != idmap_header->GetTargetPath()) {
+      out_error << "error: different target APKs (expected target APK " << target_path << " but "
+                << idmap_path << " has target APK " << idmap_header->GetTargetPath() << ")"
+                << std::endl;
+      return false;
+    }
+
+    auto overlay_apk = ApkAssets::LoadOverlay(idmap_path);
+    if (!overlay_apk) {
+      out_error << "error: failed to read overlay apk from " << idmap_header->GetOverlayPath()
+                << std::endl;
+      return false;
+    }
+    apk_assets.push_back(std::move(overlay_apk));
+  }
+
+  // AssetManager2::SetApkAssets requires raw ApkAssets pointers, not unique_ptrs
+  std::vector<const ApkAssets*> raw_pointer_apk_assets;
+  std::transform(apk_assets.cbegin(), apk_assets.cend(), std::back_inserter(raw_pointer_apk_assets),
+                 [](const auto& p) -> const ApkAssets* { return p.get(); });
+  AssetManager2 am;
+  am.SetApkAssets(raw_pointer_apk_assets);
+  am.SetConfiguration(config);
+
+  ResourceId resid;
+  bool lookup_ok;
+  std::tie(lookup_ok, resid) = ParseResReference(am, resid_str, target_package_name);
+  if (!lookup_ok) {
+    out_error << "error: failed to parse resource ID" << std::endl;
+    return false;
+  }
+
+  std::string value;
+  std::tie(lookup_ok, value) = GetValue(am, resid);
+  if (!lookup_ok) {
+    out_error << StringPrintf("error: resource 0x%08x not found", resid) << std::endl;
+    return false;
+  }
+  std::cout << value << std::endl;
+
+  return true;
+}
diff --git a/cmds/idmap2/idmap2/Main.cpp b/cmds/idmap2/idmap2/Main.cpp
new file mode 100644
index 0000000..5d9ea77
--- /dev/null
+++ b/cmds/idmap2/idmap2/Main.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cstdlib>  // EXIT_{FAILURE,SUCCESS}
+#include <functional>
+#include <iostream>
+#include <map>
+#include <memory>
+#include <ostream>
+#include <string>
+#include <vector>
+
+#include "idmap2/CommandLineOptions.h"
+
+#include "Commands.h"
+
+using android::idmap2::CommandLineOptions;
+
+typedef std::map<std::string, std::function<int(const std::vector<std::string>&, std::ostream&)>>
+    NameToFunctionMap;
+
+static void PrintUsage(const NameToFunctionMap& commands, std::ostream& out) {
+  out << "usage: idmap2 [";
+  for (auto iter = commands.cbegin(); iter != commands.cend(); iter++) {
+    if (iter != commands.cbegin()) {
+      out << "|";
+    }
+    out << iter->first;
+  }
+  out << "]" << std::endl;
+}
+
+int main(int argc, char** argv) {
+  const NameToFunctionMap commands = {
+      {"create", Create}, {"dump", Dump}, {"lookup", Lookup}, {"scan", Scan}, {"verify", Verify},
+  };
+  if (argc <= 1) {
+    PrintUsage(commands, std::cerr);
+    return EXIT_FAILURE;
+  }
+  const std::unique_ptr<std::vector<std::string>> args =
+      CommandLineOptions::ConvertArgvToVector(argc - 1, const_cast<const char**>(argv + 1));
+  if (!args) {
+    std::cerr << "error: failed to parse command line options" << std::endl;
+    return EXIT_FAILURE;
+  }
+  const auto iter = commands.find(argv[1]);
+  if (iter == commands.end()) {
+    std::cerr << argv[1] << ": command not found" << std::endl;
+    PrintUsage(commands, std::cerr);
+    return EXIT_FAILURE;
+  }
+  return iter->second(*args, std::cerr) ? EXIT_SUCCESS : EXIT_FAILURE;
+}
diff --git a/cmds/idmap2/idmap2/Scan.cpp b/cmds/idmap2/idmap2/Scan.cpp
new file mode 100644
index 0000000..33c274e
--- /dev/null
+++ b/cmds/idmap2/idmap2/Scan.cpp
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dirent.h>
+#include <fstream>
+#include <memory>
+#include <ostream>
+#include <set>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "idmap2/CommandLineOptions.h"
+#include "idmap2/FileUtils.h"
+#include "idmap2/Idmap.h"
+#include "idmap2/Xml.h"
+#include "idmap2/ZipFile.h"
+
+#include "Commands.h"
+
+using android::idmap2::CommandLineOptions;
+using android::idmap2::Idmap;
+using android::idmap2::MemoryChunk;
+using android::idmap2::Xml;
+using android::idmap2::ZipFile;
+using android::idmap2::utils::FindFiles;
+
+namespace {
+std::unique_ptr<std::vector<std::string>> FindApkFiles(const std::vector<std::string>& dirs,
+                                                       bool recursive, std::ostream& out_error) {
+  const auto predicate = [](unsigned char type, const std::string& path) -> bool {
+    static constexpr size_t kExtLen = 4;  // strlen(".apk")
+    return type == DT_REG && path.size() > kExtLen &&
+           !path.compare(path.size() - kExtLen, kExtLen, ".apk");
+  };
+  // pass apk paths through a set to filter out duplicates
+  std::set<std::string> paths;
+  for (const auto& dir : dirs) {
+    const auto apk_paths = FindFiles(dir, recursive, predicate);
+    if (!apk_paths) {
+      out_error << "error: failed to open directory " << dir << std::endl;
+      return nullptr;
+    }
+    paths.insert(apk_paths->cbegin(), apk_paths->cend());
+  }
+  return std::unique_ptr<std::vector<std::string>>(
+      new std::vector<std::string>(paths.cbegin(), paths.cend()));
+}
+}  // namespace
+
+bool Scan(const std::vector<std::string>& args, std::ostream& out_error) {
+  std::vector<std::string> input_directories;
+  std::string target_package_name, target_apk_path, output_directory;
+  bool recursive = false;
+
+  const CommandLineOptions opts =
+      CommandLineOptions("idmap2 scan")
+          .MandatoryOption("--input-directory", "directory containing overlay apks to scan",
+                           &input_directories)
+          .OptionalFlag("--recursive", "also scan subfolders of overlay-directory", &recursive)
+          .MandatoryOption("--target-package-name", "package name of target package",
+                           &target_package_name)
+          .MandatoryOption("--target-apk-path", "path to target apk", &target_apk_path)
+          .MandatoryOption("--output-directory",
+                           "directory in which to write artifacts (idmap files and overlays.list)",
+                           &output_directory);
+  if (!opts.Parse(args, out_error)) {
+    return false;
+  }
+
+  const auto apk_paths = FindApkFiles(input_directories, recursive, out_error);
+  if (!apk_paths) {
+    return false;
+  }
+
+  std::vector<std::string> interesting_apks;
+  for (const std::string& path : *apk_paths) {
+    std::unique_ptr<const ZipFile> zip = ZipFile::Open(path);
+    if (!zip) {
+      out_error << "error: failed to open " << path << " as a zip file" << std::endl;
+      return false;
+    }
+
+    std::unique_ptr<const MemoryChunk> entry = zip->Uncompress("AndroidManifest.xml");
+    if (!entry) {
+      out_error << "error: failed to uncompress AndroidManifest.xml from " << path << std::endl;
+      return false;
+    }
+
+    std::unique_ptr<const Xml> xml = Xml::Create(entry->buf, entry->size);
+    if (!xml) {
+      out_error << "error: failed to parse AndroidManifest.xml from " << path << std::endl;
+      continue;
+    }
+
+    const auto tag = xml->FindTag("overlay");
+    if (!tag) {
+      continue;
+    }
+
+    auto iter = tag->find("isStatic");
+    if (iter == tag->end() || std::stoul(iter->second) == 0u) {
+      continue;
+    }
+
+    iter = tag->find("targetPackage");
+    if (iter == tag->end() || iter->second != target_package_name) {
+      continue;
+    }
+
+    iter = tag->find("priority");
+    if (iter == tag->end()) {
+      continue;
+    }
+
+    const int priority = std::stoi(iter->second);
+    if (priority < 0) {
+      continue;
+    }
+
+    interesting_apks.insert(
+        std::lower_bound(interesting_apks.begin(), interesting_apks.end(), path), path);
+  }
+
+  std::stringstream stream;
+  for (auto iter = interesting_apks.cbegin(); iter != interesting_apks.cend(); ++iter) {
+    const std::string idmap_path = Idmap::CanonicalIdmapPathFor(output_directory, *iter);
+    if (!Verify(std::vector<std::string>({"--idmap-path", idmap_path}), out_error) &&
+        !Create(std::vector<std::string>({
+                    "--target-apk-path",
+                    target_apk_path,
+                    "--overlay-apk-path",
+                    *iter,
+                    "--idmap-path",
+                    idmap_path,
+                }),
+                out_error)) {
+      return false;
+    }
+    stream << idmap_path << std::endl;
+  }
+
+  std::cout << stream.str();
+
+  return true;
+}
diff --git a/cmds/idmap2/idmap2/Verify.cpp b/cmds/idmap2/idmap2/Verify.cpp
new file mode 100644
index 0000000..b5fa438
--- /dev/null
+++ b/cmds/idmap2/idmap2/Verify.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <fstream>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "idmap2/CommandLineOptions.h"
+#include "idmap2/Idmap.h"
+
+using android::idmap2::CommandLineOptions;
+using android::idmap2::IdmapHeader;
+
+bool Verify(const std::vector<std::string>& args, std::ostream& out_error) {
+  std::string idmap_path;
+  const CommandLineOptions opts =
+      CommandLineOptions("idmap2 verify")
+          .MandatoryOption("--idmap-path", "input: path to idmap file to verify", &idmap_path);
+  if (!opts.Parse(args, out_error)) {
+    return false;
+  }
+
+  std::ifstream fin(idmap_path);
+  const std::unique_ptr<const IdmapHeader> header = IdmapHeader::FromBinaryStream(fin);
+  fin.close();
+  if (!header) {
+    out_error << "error: failed to parse idmap header" << std::endl;
+    return false;
+  }
+
+  return header->IsUpToDate(out_error);
+}
diff --git a/cmds/idmap2/idmap2d/Idmap2Service.cpp b/cmds/idmap2/idmap2d/Idmap2Service.cpp
new file mode 100644
index 0000000..cf72cb9
--- /dev/null
+++ b/cmds/idmap2/idmap2d/Idmap2Service.cpp
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <sys/stat.h>   // umask
+#include <sys/types.h>  // umask
+#include <unistd.h>
+
+#include <cerrno>
+#include <cstring>
+#include <fstream>
+#include <memory>
+#include <ostream>
+#include <string>
+
+#include "android-base/macros.h"
+#include "utils/String8.h"
+#include "utils/Trace.h"
+
+#include "idmap2/BinaryStreamVisitor.h"
+#include "idmap2/FileUtils.h"
+#include "idmap2/Idmap.h"
+
+#include "idmap2d/Idmap2Service.h"
+
+using android::binder::Status;
+using android::idmap2::BinaryStreamVisitor;
+using android::idmap2::Idmap;
+using android::idmap2::IdmapHeader;
+
+namespace {
+
+static constexpr const char* kIdmapCacheDir = "/data/resource-cache";
+
+Status ok() {
+  return Status::ok();
+}
+
+Status error(const std::string& msg) {
+  LOG(ERROR) << msg;
+  return Status::fromExceptionCode(Status::EX_NONE, msg.c_str());
+}
+
+}  // namespace
+
+namespace android {
+namespace os {
+
+Status Idmap2Service::getIdmapPath(const std::string& overlay_apk_path,
+                                   int32_t user_id ATTRIBUTE_UNUSED, std::string* _aidl_return) {
+  assert(_aidl_return);
+  *_aidl_return = Idmap::CanonicalIdmapPathFor(kIdmapCacheDir, overlay_apk_path);
+  return ok();
+}
+
+Status Idmap2Service::removeIdmap(const std::string& overlay_apk_path,
+                                  int32_t user_id ATTRIBUTE_UNUSED, bool* _aidl_return) {
+  assert(_aidl_return);
+  const std::string idmap_path = Idmap::CanonicalIdmapPathFor(kIdmapCacheDir, overlay_apk_path);
+  if (unlink(idmap_path.c_str()) == 0) {
+    *_aidl_return = true;
+    return ok();
+  } else {
+    *_aidl_return = false;
+    return error("failed to unlink " + idmap_path + ": " + strerror(errno));
+  }
+}
+
+Status Idmap2Service::createIdmap(const std::string& target_apk_path,
+                                  const std::string& overlay_apk_path, int32_t user_id,
+                                  std::unique_ptr<std::string>* _aidl_return) {
+  assert(_aidl_return);
+  std::stringstream trace;
+  trace << __FUNCTION__ << " " << target_apk_path << " " << overlay_apk_path << " "
+        << std::to_string(user_id);
+  ATRACE_NAME(trace.str().c_str());
+  std::cout << trace.str() << std::endl;
+
+  _aidl_return->reset(nullptr);
+
+  const std::string idmap_path = Idmap::CanonicalIdmapPathFor(kIdmapCacheDir, overlay_apk_path);
+  std::ifstream fin(idmap_path);
+  const std::unique_ptr<const IdmapHeader> header = IdmapHeader::FromBinaryStream(fin);
+  fin.close();
+  // do not reuse error stream from IsUpToDate below, or error messages will be
+  // polluted with irrelevant data
+  std::stringstream dev_null;
+  if (header && header->IsUpToDate(dev_null)) {
+    return ok();
+  }
+
+  const std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
+  if (!target_apk) {
+    return error("failed to load apk " + target_apk_path);
+  }
+
+  const std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
+  if (!overlay_apk) {
+    return error("failed to load apk " + overlay_apk_path);
+  }
+
+  std::stringstream err;
+  const std::unique_ptr<const Idmap> idmap =
+      Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk, err);
+  if (!idmap) {
+    return error(err.str());
+  }
+
+  umask(0133);  // u=rw,g=r,o=r
+  std::ofstream fout(idmap_path);
+  if (fout.fail()) {
+    return error("failed to open idmap path " + idmap_path);
+  }
+  BinaryStreamVisitor visitor(fout);
+  idmap->accept(&visitor);
+  fout.close();
+  if (fout.fail()) {
+    return error("failed to write to idmap path " + idmap_path);
+  }
+
+  _aidl_return->reset(new std::string(idmap_path));
+  return ok();
+}
+
+}  // namespace os
+}  // namespace android
diff --git a/cmds/idmap2/idmap2d/Idmap2Service.h b/cmds/idmap2/idmap2d/Idmap2Service.h
new file mode 100644
index 0000000..2b32042
--- /dev/null
+++ b/cmds/idmap2/idmap2d/Idmap2Service.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef IDMAP2_IDMAP2D_IDMAP2SERVICE_H_
+#define IDMAP2_IDMAP2D_IDMAP2SERVICE_H_
+
+#include <android-base/unique_fd.h>
+#include <binder/BinderService.h>
+
+#include <memory>
+#include <string>
+
+#include "android/os/BnIdmap2.h"
+
+namespace android {
+namespace os {
+class Idmap2Service : public BinderService<Idmap2Service>, public BnIdmap2 {
+ public:
+  static char const* getServiceName() {
+    return "idmap";
+  }
+
+  binder::Status getIdmapPath(const std::string& overlay_apk_path, int32_t user_id,
+                              std::string* _aidl_return);
+
+  binder::Status removeIdmap(const std::string& overlay_apk_path, int32_t user_id,
+                             bool* _aidl_return);
+
+  binder::Status createIdmap(const std::string& target_apk_path,
+                             const std::string& overlay_apk_path, int32_t user_id,
+                             std::unique_ptr<std::string>* _aidl_return);
+};
+}  // namespace os
+}  // namespace android
+
+#endif  // IDMAP2_IDMAP2D_IDMAP2SERVICE_H_
diff --git a/cmds/idmap2/idmap2d/Main.cpp b/cmds/idmap2/idmap2d/Main.cpp
new file mode 100644
index 0000000..d64a87b
--- /dev/null
+++ b/cmds/idmap2/idmap2d/Main.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define ATRACE_TAG ATRACE_TAG_RESOURCES
+
+#include <binder/BinderService.h>
+#include <binder/IPCThreadState.h>
+#include <binder/ProcessState.h>
+
+#include <cstdlib>  // EXIT_{FAILURE,SUCCESS}
+
+#include <iostream>
+#include <sstream>
+
+#include "android-base/macros.h"
+
+#include "Idmap2Service.h"
+
+using android::BinderService;
+using android::IPCThreadState;
+using android::ProcessState;
+using android::sp;
+using android::status_t;
+using android::os::Idmap2Service;
+
+int main(int argc ATTRIBUTE_UNUSED, char** argv ATTRIBUTE_UNUSED) {
+  IPCThreadState::self()->disableBackgroundScheduling(true);
+  status_t ret = BinderService<Idmap2Service>::publish();
+  if (ret != android::OK) {
+    return EXIT_FAILURE;
+  }
+  sp<ProcessState> ps(ProcessState::self());
+  ps->startThreadPool();
+  ps->giveThreadPoolName();
+  IPCThreadState::self()->joinThreadPool();
+  return EXIT_SUCCESS;
+}
diff --git a/cmds/idmap2/idmap2d/aidl/android/os/IIdmap2.aidl b/cmds/idmap2/idmap2d/aidl/android/os/IIdmap2.aidl
new file mode 100644
index 0000000..5d19610
--- /dev/null
+++ b/cmds/idmap2/idmap2d/aidl/android/os/IIdmap2.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+/**
+ * @hide
+ */
+interface IIdmap2 {
+  @utf8InCpp String getIdmapPath(@utf8InCpp String overlayApkPath, int userId);
+  boolean removeIdmap(@utf8InCpp String overlayApkPath, int userId);
+  @nullable @utf8InCpp String createIdmap(@utf8InCpp String targetApkPath,
+                                          @utf8InCpp String overlayApkPath, int userId);
+}
diff --git a/cmds/idmap2/include/idmap2/BinaryStreamVisitor.h b/cmds/idmap2/include/idmap2/BinaryStreamVisitor.h
new file mode 100644
index 0000000..2368aea
--- /dev/null
+++ b/cmds/idmap2/include/idmap2/BinaryStreamVisitor.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef IDMAP2_INCLUDE_IDMAP2_BINARYSTREAMVISITOR_H_
+#define IDMAP2_INCLUDE_IDMAP2_BINARYSTREAMVISITOR_H_
+
+#include <cstdint>
+#include <iostream>
+#include <string>
+
+#include "idmap2/Idmap.h"
+
+namespace android {
+namespace idmap2 {
+
+class BinaryStreamVisitor : public Visitor {
+ public:
+  explicit BinaryStreamVisitor(std::ostream& stream) : stream_(stream) {
+  }
+  virtual void visit(const Idmap& idmap);
+  virtual void visit(const IdmapHeader& header);
+  virtual void visit(const IdmapData& data);
+  virtual void visit(const IdmapData::Header& header);
+  virtual void visit(const IdmapData::TypeEntry& type_entry);
+
+ private:
+  void Write16(uint16_t value);
+  void Write32(uint32_t value);
+  void WriteString(const StringPiece& value);
+  std::ostream& stream_;
+};
+
+}  // namespace idmap2
+}  // namespace android
+
+#endif  // IDMAP2_INCLUDE_IDMAP2_BINARYSTREAMVISITOR_H_
diff --git a/cmds/idmap2/include/idmap2/CommandLineOptions.h b/cmds/idmap2/include/idmap2/CommandLineOptions.h
new file mode 100644
index 0000000..f3aa68b
--- /dev/null
+++ b/cmds/idmap2/include/idmap2/CommandLineOptions.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef IDMAP2_INCLUDE_IDMAP2_COMMANDLINEOPTIONS_H_
+#define IDMAP2_INCLUDE_IDMAP2_COMMANDLINEOPTIONS_H_
+
+#include <functional>
+#include <memory>
+#include <ostream>
+#include <string>
+#include <vector>
+
+namespace android {
+namespace idmap2 {
+
+/*
+ * Utility class to convert a command line, including options (--path foo.txt),
+ * into data structures (options.path = "foo.txt").
+ */
+class CommandLineOptions {
+ public:
+  static std::unique_ptr<std::vector<std::string>> ConvertArgvToVector(int argc, const char** argv);
+
+  explicit CommandLineOptions(const std::string& name) : name_(name) {
+  }
+
+  CommandLineOptions& OptionalFlag(const std::string& name, const std::string& description,
+                                   bool* value);
+  CommandLineOptions& MandatoryOption(const std::string& name, const std::string& description,
+                                      std::string* value);
+  CommandLineOptions& MandatoryOption(const std::string& name, const std::string& description,
+                                      std::vector<std::string>* value);
+  CommandLineOptions& OptionalOption(const std::string& name, const std::string& description,
+                                     std::string* value);
+  bool Parse(const std::vector<std::string>& argv, std::ostream& outError) const;
+  void Usage(std::ostream& out) const;
+
+ private:
+  struct Option {
+    std::string name;
+    std::string description;
+    std::function<void(const std::string& value)> action;
+    enum {
+      COUNT_OPTIONAL,
+      COUNT_EXACTLY_ONCE,
+      COUNT_ONCE_OR_MORE,
+    } count;
+    bool argument;
+  };
+
+  mutable std::vector<Option> options_;
+  std::string name_;
+};
+
+}  // namespace idmap2
+}  // namespace android
+
+#endif  // IDMAP2_INCLUDE_IDMAP2_COMMANDLINEOPTIONS_H_
diff --git a/cmds/idmap2/include/idmap2/FileUtils.h b/cmds/idmap2/include/idmap2/FileUtils.h
new file mode 100644
index 0000000..05c6d31
--- /dev/null
+++ b/cmds/idmap2/include/idmap2/FileUtils.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef IDMAP2_INCLUDE_IDMAP2_FILEUTILS_H_
+#define IDMAP2_INCLUDE_IDMAP2_FILEUTILS_H_
+
+#include <functional>
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace android {
+namespace idmap2 {
+namespace utils {
+typedef std::function<bool(unsigned char type /* DT_* from dirent.h */, const std::string& path)>
+    FindFilesPredicate;
+std::unique_ptr<std::vector<std::string>> FindFiles(const std::string& root, bool recurse,
+                                                    const FindFilesPredicate& predicate);
+
+std::unique_ptr<std::string> ReadFile(int fd);
+
+std::unique_ptr<std::string> ReadFile(const std::string& path);
+
+}  // namespace utils
+}  // namespace idmap2
+}  // namespace android
+
+#endif  // IDMAP2_INCLUDE_IDMAP2_FILEUTILS_H_
diff --git a/cmds/idmap2/include/idmap2/Idmap.h b/cmds/idmap2/include/idmap2/Idmap.h
new file mode 100644
index 0000000..837b7c5
--- /dev/null
+++ b/cmds/idmap2/include/idmap2/Idmap.h
@@ -0,0 +1,277 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * # idmap file format (current version)
+ *
+ * idmap             := header data*
+ * header            := magic version target_crc overlay_crc target_path overlay_path
+ * data              := data_header data_block*
+ * data_header       := target_package_id types_count
+ * data_block        := target_type overlay_type entry_count entry_offset entry*
+ * overlay_path      := string
+ * target_path       := string
+ * entry             := <uint32_t>
+ * entry_count       := <uint16_t>
+ * entry_offset      := <uint16_t>
+ * magic             := <uint32_t>
+ * overlay_crc       := <uint32_t>
+ * overlay_type      := <uint16_t>
+ * string            := <uint8_t>[256]
+ * target_crc        := <uint32_t>
+ * target_package_id := <uint16_t>
+ * target_type       := <uint16_t>
+ * types_count       := <uint16_t>
+ * version           := <uint32_t>
+ *
+ *
+ * # idmap file format changelog
+ * ## v1
+ * - Identical to idmap v1.
+ */
+
+#ifndef IDMAP2_INCLUDE_IDMAP2_IDMAP_H_
+#define IDMAP2_INCLUDE_IDMAP2_IDMAP_H_
+
+#include <iostream>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "android-base/macros.h"
+
+#include "androidfw/ApkAssets.h"
+#include "androidfw/ResourceTypes.h"
+#include "androidfw/StringPiece.h"
+
+namespace android {
+namespace idmap2 {
+
+class Idmap;
+class Visitor;
+
+// use typedefs to let the compiler warn us about implicit casts
+typedef uint32_t ResourceId;  // 0xpptteeee
+typedef uint8_t PackageId;    // pp in 0xpptteeee
+typedef uint8_t TypeId;       // tt in 0xpptteeee
+typedef uint16_t EntryId;     // eeee in 0xpptteeee
+
+static constexpr const ResourceId kPadding = 0xffffffffu;
+
+static constexpr const EntryId kNoEntry = 0xffffu;
+
+// magic number: all idmap files start with this
+static constexpr const uint32_t kIdmapMagic = android::kIdmapMagic;
+
+// current version of the idmap binary format; must be incremented when the format is changed
+static constexpr const uint32_t kIdmapCurrentVersion = android::kIdmapCurrentVersion;
+
+// strings in the idmap are encoded char arrays of length 'kIdmapStringLength' (including mandatory
+// terminating null)
+static constexpr const size_t kIdmapStringLength = 256;
+
+class IdmapHeader {
+ public:
+  static std::unique_ptr<const IdmapHeader> FromBinaryStream(std::istream& stream);
+
+  inline uint32_t GetMagic() const {
+    return magic_;
+  }
+
+  inline uint32_t GetVersion() const {
+    return version_;
+  }
+
+  inline uint32_t GetTargetCrc() const {
+    return target_crc_;
+  }
+
+  inline uint32_t GetOverlayCrc() const {
+    return overlay_crc_;
+  }
+
+  inline StringPiece GetTargetPath() const {
+    return StringPiece(target_path_);
+  }
+
+  inline StringPiece GetOverlayPath() const {
+    return StringPiece(overlay_path_);
+  }
+
+  // Invariant: anytime the idmap data encoding is changed, the idmap version
+  // field *must* be incremented. Because of this, we know that if the idmap
+  // header is up-to-date the entire file is up-to-date.
+  bool IsUpToDate(std::ostream& out_error) const;
+
+  void accept(Visitor* v) const;
+
+ private:
+  IdmapHeader() {
+  }
+
+  uint32_t magic_;
+  uint32_t version_;
+  uint32_t target_crc_;
+  uint32_t overlay_crc_;
+  char target_path_[kIdmapStringLength];
+  char overlay_path_[kIdmapStringLength];
+
+  friend Idmap;
+  DISALLOW_COPY_AND_ASSIGN(IdmapHeader);
+};
+
+class IdmapData {
+ public:
+  class Header {
+   public:
+    static std::unique_ptr<const Header> FromBinaryStream(std::istream& stream);
+
+    inline PackageId GetTargetPackageId() const {
+      return target_package_id_;
+    }
+
+    inline uint16_t GetTypeCount() const {
+      return type_count_;
+    }
+
+    void accept(Visitor* v) const;
+
+   private:
+    Header() {
+    }
+
+    PackageId target_package_id_;
+    uint16_t type_count_;
+
+    friend Idmap;
+    DISALLOW_COPY_AND_ASSIGN(Header);
+  };
+
+  class TypeEntry {
+   public:
+    static std::unique_ptr<const TypeEntry> FromBinaryStream(std::istream& stream);
+
+    inline TypeId GetTargetTypeId() const {
+      return target_type_id_;
+    }
+
+    inline TypeId GetOverlayTypeId() const {
+      return overlay_type_id_;
+    }
+
+    inline uint16_t GetEntryCount() const {
+      return entries_.size();
+    }
+
+    inline uint16_t GetEntryOffset() const {
+      return entry_offset_;
+    }
+
+    inline EntryId GetEntry(size_t i) const {
+      return i < entries_.size() ? entries_[i] : 0xffffu;
+    }
+
+    void accept(Visitor* v) const;
+
+   private:
+    TypeEntry() {
+    }
+
+    TypeId target_type_id_;
+    TypeId overlay_type_id_;
+    uint16_t entry_offset_;
+    std::vector<EntryId> entries_;
+
+    friend Idmap;
+    DISALLOW_COPY_AND_ASSIGN(TypeEntry);
+  };
+
+  static std::unique_ptr<const IdmapData> FromBinaryStream(std::istream& stream);
+
+  inline const std::unique_ptr<const Header>& GetHeader() const {
+    return header_;
+  }
+
+  inline const std::vector<std::unique_ptr<const TypeEntry>>& GetTypeEntries() const {
+    return type_entries_;
+  }
+
+  void accept(Visitor* v) const;
+
+ private:
+  IdmapData() {
+  }
+
+  std::unique_ptr<const Header> header_;
+  std::vector<std::unique_ptr<const TypeEntry>> type_entries_;
+
+  friend Idmap;
+  DISALLOW_COPY_AND_ASSIGN(IdmapData);
+};
+
+class Idmap {
+ public:
+  static std::string CanonicalIdmapPathFor(const std::string& absolute_dir,
+                                           const std::string& absolute_apk_path);
+
+  static std::unique_ptr<const Idmap> FromBinaryStream(std::istream& stream,
+                                                       std::ostream& out_error);
+
+  // In the current version of idmap, the first package in each resources.arsc
+  // file is used; change this in the next version of idmap to use a named
+  // package instead; also update FromApkAssets to take additional parameters:
+  // the target and overlay package names
+  static std::unique_ptr<const Idmap> FromApkAssets(const std::string& target_apk_path,
+                                                    const ApkAssets& target_apk_assets,
+                                                    const std::string& overlay_apk_path,
+                                                    const ApkAssets& overlay_apk_assets,
+                                                    std::ostream& out_error);
+
+  inline const std::unique_ptr<const IdmapHeader>& GetHeader() const {
+    return header_;
+  }
+
+  inline const std::vector<std::unique_ptr<const IdmapData>>& GetData() const {
+    return data_;
+  }
+
+  void accept(Visitor* v) const;
+
+ private:
+  Idmap() {
+  }
+
+  std::unique_ptr<const IdmapHeader> header_;
+  std::vector<std::unique_ptr<const IdmapData>> data_;
+
+  DISALLOW_COPY_AND_ASSIGN(Idmap);
+};
+
+class Visitor {
+ public:
+  virtual ~Visitor() {
+  }
+  virtual void visit(const Idmap& idmap) = 0;
+  virtual void visit(const IdmapHeader& header) = 0;
+  virtual void visit(const IdmapData& data) = 0;
+  virtual void visit(const IdmapData::Header& header) = 0;
+  virtual void visit(const IdmapData::TypeEntry& type_entry) = 0;
+};
+
+}  // namespace idmap2
+}  // namespace android
+
+#endif  // IDMAP2_INCLUDE_IDMAP2_IDMAP_H_
diff --git a/cmds/idmap2/include/idmap2/PrettyPrintVisitor.h b/cmds/idmap2/include/idmap2/PrettyPrintVisitor.h
new file mode 100644
index 0000000..c388f4b
--- /dev/null
+++ b/cmds/idmap2/include/idmap2/PrettyPrintVisitor.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef IDMAP2_INCLUDE_IDMAP2_PRETTYPRINTVISITOR_H_
+#define IDMAP2_INCLUDE_IDMAP2_PRETTYPRINTVISITOR_H_
+
+#include <iostream>
+#include <memory>
+
+#include "androidfw/AssetManager2.h"
+
+#include "idmap2/Idmap.h"
+
+namespace android {
+
+class ApkAssets;
+
+namespace idmap2 {
+
+class PrettyPrintVisitor : public Visitor {
+ public:
+  explicit PrettyPrintVisitor(std::ostream& stream) : stream_(stream) {
+  }
+  virtual void visit(const Idmap& idmap);
+  virtual void visit(const IdmapHeader& header);
+  virtual void visit(const IdmapData& data);
+  virtual void visit(const IdmapData::Header& header);
+  virtual void visit(const IdmapData::TypeEntry& type_entry);
+
+ private:
+  std::ostream& stream_;
+  std::unique_ptr<const ApkAssets> target_apk_;
+  AssetManager2 target_am_;
+  PackageId last_seen_package_id_;
+};
+
+}  // namespace idmap2
+}  // namespace android
+
+#endif  // IDMAP2_INCLUDE_IDMAP2_PRETTYPRINTVISITOR_H_
diff --git a/cmds/idmap2/include/idmap2/RawPrintVisitor.h b/cmds/idmap2/include/idmap2/RawPrintVisitor.h
new file mode 100644
index 0000000..7e33b3b
--- /dev/null
+++ b/cmds/idmap2/include/idmap2/RawPrintVisitor.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef IDMAP2_INCLUDE_IDMAP2_RAWPRINTVISITOR_H_
+#define IDMAP2_INCLUDE_IDMAP2_RAWPRINTVISITOR_H_
+
+#include <iostream>
+#include <memory>
+#include <string>
+
+#include "androidfw/AssetManager2.h"
+
+#include "idmap2/Idmap.h"
+
+namespace android {
+
+class ApkAssets;
+
+namespace idmap2 {
+
+class RawPrintVisitor : public Visitor {
+ public:
+  explicit RawPrintVisitor(std::ostream& stream) : stream_(stream), offset_(0) {
+  }
+  virtual void visit(const Idmap& idmap);
+  virtual void visit(const IdmapHeader& header);
+  virtual void visit(const IdmapData& data);
+  virtual void visit(const IdmapData::Header& header);
+  virtual void visit(const IdmapData::TypeEntry& type_entry);
+
+ private:
+  void print(uint16_t value, const char* fmt, ...);
+  void print(uint32_t value, const char* fmt, ...);
+  void print(const std::string& value, const char* fmt, ...);
+
+  std::ostream& stream_;
+  std::unique_ptr<const ApkAssets> target_apk_;
+  AssetManager2 target_am_;
+  size_t offset_;
+  PackageId last_seen_package_id_;
+};
+
+}  // namespace idmap2
+}  // namespace android
+
+#endif  // IDMAP2_INCLUDE_IDMAP2_RAWPRINTVISITOR_H_
diff --git a/cmds/idmap2/include/idmap2/ResourceUtils.h b/cmds/idmap2/include/idmap2/ResourceUtils.h
new file mode 100644
index 0000000..88a835b
--- /dev/null
+++ b/cmds/idmap2/include/idmap2/ResourceUtils.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef IDMAP2_INCLUDE_IDMAP2_RESOURCEUTILS_H_
+#define IDMAP2_INCLUDE_IDMAP2_RESOURCEUTILS_H_
+
+#include <string>
+#include <utility>
+
+#include "android-base/macros.h"
+#include "androidfw/AssetManager2.h"
+
+#include "idmap2/Idmap.h"
+
+namespace android {
+namespace idmap2 {
+namespace utils {
+
+std::pair<bool, std::string> WARN_UNUSED ResToTypeEntryName(const AssetManager2& am,
+                                                            ResourceId resid);
+
+}  // namespace utils
+}  // namespace idmap2
+}  // namespace android
+
+#endif  // IDMAP2_INCLUDE_IDMAP2_RESOURCEUTILS_H_
diff --git a/cmds/idmap2/include/idmap2/Xml.h b/cmds/idmap2/include/idmap2/Xml.h
new file mode 100644
index 0000000..9ab5ec4
--- /dev/null
+++ b/cmds/idmap2/include/idmap2/Xml.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef IDMAP2_INCLUDE_IDMAP2_XML_H_
+#define IDMAP2_INCLUDE_IDMAP2_XML_H_
+
+#include <map>
+#include <memory>
+#include <string>
+
+#include "android-base/macros.h"
+#include "androidfw/ResourceTypes.h"
+#include "utils/String16.h"
+
+namespace android {
+namespace idmap2 {
+
+class Xml {
+ public:
+  static std::unique_ptr<const Xml> Create(const uint8_t* data, size_t size, bool copyData = false);
+
+  std::unique_ptr<std::map<std::string, std::string>> FindTag(const std::string& name) const;
+
+  ~Xml();
+
+ private:
+  Xml() {
+  }
+
+  mutable ResXMLTree xml_;
+
+  DISALLOW_COPY_AND_ASSIGN(Xml);
+};
+
+}  // namespace idmap2
+}  // namespace android
+
+#endif  // IDMAP2_INCLUDE_IDMAP2_XML_H_
diff --git a/cmds/idmap2/include/idmap2/ZipFile.h b/cmds/idmap2/include/idmap2/ZipFile.h
new file mode 100644
index 0000000..328bd36
--- /dev/null
+++ b/cmds/idmap2/include/idmap2/ZipFile.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef IDMAP2_INCLUDE_IDMAP2_ZIPFILE_H_
+#define IDMAP2_INCLUDE_IDMAP2_ZIPFILE_H_
+
+#include <memory>
+#include <string>
+#include <utility>
+
+#include "android-base/macros.h"
+#include "ziparchive/zip_archive.h"
+
+namespace android {
+namespace idmap2 {
+
+struct MemoryChunk {
+  size_t size;
+  uint8_t buf[0];
+
+  static std::unique_ptr<MemoryChunk> Allocate(size_t size);
+
+ private:
+  MemoryChunk() {
+  }
+};
+
+class ZipFile {
+ public:
+  static std::unique_ptr<const ZipFile> Open(const std::string& path);
+
+  std::unique_ptr<const MemoryChunk> Uncompress(const std::string& entryPath) const;
+  std::pair<bool, uint32_t> Crc(const std::string& entryPath) const;
+
+  ~ZipFile();
+
+ private:
+  explicit ZipFile(const ::ZipArchiveHandle handle) : handle_(handle) {
+  }
+
+  const ::ZipArchiveHandle handle_;
+
+  DISALLOW_COPY_AND_ASSIGN(ZipFile);
+};
+
+}  // namespace idmap2
+}  // namespace android
+
+#endif  // IDMAP2_INCLUDE_IDMAP2_ZIPFILE_H_
diff --git a/cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp b/cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp
new file mode 100644
index 0000000..29969a2
--- /dev/null
+++ b/cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <algorithm>
+#include <cstring>
+#include <string>
+
+#include "android-base/macros.h"
+
+#include "idmap2/BinaryStreamVisitor.h"
+
+namespace android {
+namespace idmap2 {
+
+void BinaryStreamVisitor::Write16(uint16_t value) {
+  uint16_t x = htodl(value);
+  stream_.write(reinterpret_cast<char*>(&x), sizeof(uint16_t));
+}
+
+void BinaryStreamVisitor::Write32(uint32_t value) {
+  uint32_t x = htodl(value);
+  stream_.write(reinterpret_cast<char*>(&x), sizeof(uint32_t));
+}
+
+void BinaryStreamVisitor::WriteString(const StringPiece& value) {
+  char buf[kIdmapStringLength];
+  memset(buf, 0, sizeof(buf));
+  memcpy(buf, value.data(), std::min(value.size(), sizeof(buf)));
+  stream_.write(buf, sizeof(buf));
+}
+
+void BinaryStreamVisitor::visit(const Idmap& idmap ATTRIBUTE_UNUSED) {
+  // nothing to do
+}
+
+void BinaryStreamVisitor::visit(const IdmapHeader& header) {
+  Write32(header.GetMagic());
+  Write32(header.GetVersion());
+  Write32(header.GetTargetCrc());
+  Write32(header.GetOverlayCrc());
+  WriteString(header.GetTargetPath());
+  WriteString(header.GetOverlayPath());
+}
+
+void BinaryStreamVisitor::visit(const IdmapData& data ATTRIBUTE_UNUSED) {
+  // nothing to do
+}
+
+void BinaryStreamVisitor::visit(const IdmapData::Header& header) {
+  Write16(header.GetTargetPackageId());
+  Write16(header.GetTypeCount());
+}
+
+void BinaryStreamVisitor::visit(const IdmapData::TypeEntry& te) {
+  const uint16_t entryCount = te.GetEntryCount();
+
+  Write16(te.GetTargetTypeId());
+  Write16(te.GetOverlayTypeId());
+  Write16(entryCount);
+  Write16(te.GetEntryOffset());
+  for (uint16_t i = 0; i < entryCount; i++) {
+    EntryId entry_id = te.GetEntry(i);
+    Write32(entry_id != kNoEntry ? static_cast<uint32_t>(entry_id) : kPadding);
+  }
+}
+
+}  // namespace idmap2
+}  // namespace android
diff --git a/cmds/idmap2/libidmap2/CommandLineOptions.cpp b/cmds/idmap2/libidmap2/CommandLineOptions.cpp
new file mode 100644
index 0000000..28c3797
--- /dev/null
+++ b/cmds/idmap2/libidmap2/CommandLineOptions.cpp
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <algorithm>
+#include <iomanip>
+#include <iostream>
+#include <memory>
+#include <set>
+#include <string>
+#include <vector>
+
+#include "android-base/macros.h"
+
+#include "idmap2/CommandLineOptions.h"
+
+namespace android {
+namespace idmap2 {
+
+std::unique_ptr<std::vector<std::string>> CommandLineOptions::ConvertArgvToVector(
+    int argc, const char** argv) {
+  return std::unique_ptr<std::vector<std::string>>(
+      new std::vector<std::string>(argv + 1, argv + argc));
+}
+
+CommandLineOptions& CommandLineOptions::OptionalFlag(const std::string& name,
+                                                     const std::string& description, bool* value) {
+  assert(value != nullptr);
+  auto func = [value](const std::string& arg ATTRIBUTE_UNUSED) -> void { *value = true; };
+  options_.push_back(Option{name, description, func, Option::COUNT_OPTIONAL, false});
+  return *this;
+}
+
+CommandLineOptions& CommandLineOptions::MandatoryOption(const std::string& name,
+                                                        const std::string& description,
+                                                        std::string* value) {
+  assert(value != nullptr);
+  auto func = [value](const std::string& arg) -> void { *value = arg; };
+  options_.push_back(Option{name, description, func, Option::COUNT_EXACTLY_ONCE, true});
+  return *this;
+}
+
+CommandLineOptions& CommandLineOptions::MandatoryOption(const std::string& name,
+                                                        const std::string& description,
+                                                        std::vector<std::string>* value) {
+  assert(value != nullptr);
+  auto func = [value](const std::string& arg) -> void { value->push_back(arg); };
+  options_.push_back(Option{name, description, func, Option::COUNT_ONCE_OR_MORE, true});
+  return *this;
+}
+
+CommandLineOptions& CommandLineOptions::OptionalOption(const std::string& name,
+                                                       const std::string& description,
+                                                       std::string* value) {
+  assert(value != nullptr);
+  auto func = [value](const std::string& arg) -> void { *value = arg; };
+  options_.push_back(Option{name, description, func, Option::COUNT_OPTIONAL, true});
+  return *this;
+}
+
+bool CommandLineOptions::Parse(const std::vector<std::string>& argv, std::ostream& outError) const {
+  const auto pivot = std::partition(options_.begin(), options_.end(), [](const Option& opt) {
+    return opt.count != Option::COUNT_OPTIONAL;
+  });
+  std::set<std::string> mandatory_opts;
+  std::transform(options_.begin(), pivot, std::inserter(mandatory_opts, mandatory_opts.end()),
+                 [](const Option& opt) -> std::string { return opt.name; });
+
+  const size_t argv_size = argv.size();
+  for (size_t i = 0; i < argv_size; i++) {
+    const std::string arg = argv[i];
+    if ("--help" == arg || "-h" == arg) {
+      Usage(outError);
+      return false;
+    }
+    bool match = false;
+    for (const Option& opt : options_) {
+      if (opt.name == arg) {
+        match = true;
+
+        if (opt.argument) {
+          i++;
+          if (i >= argv_size) {
+            outError << "error: " << opt.name << ": missing argument" << std::endl;
+            Usage(outError);
+            return false;
+          }
+        }
+        opt.action(argv[i]);
+        mandatory_opts.erase(opt.name);
+        break;
+      }
+    }
+    if (!match) {
+      outError << "error: " << arg << ": unknown option" << std::endl;
+      Usage(outError);
+      return false;
+    }
+  }
+
+  if (!mandatory_opts.empty()) {
+    for (auto iter = mandatory_opts.cbegin(); iter != mandatory_opts.cend(); ++iter) {
+      outError << "error: " << *iter << ": missing mandatory option" << std::endl;
+    }
+    Usage(outError);
+    return false;
+  }
+  return true;
+}
+
+void CommandLineOptions::Usage(std::ostream& out) const {
+  size_t maxLength = 0;
+  out << "usage: " << name_;
+  for (const Option& opt : options_) {
+    const bool mandatory = opt.count != Option::COUNT_OPTIONAL;
+    out << " ";
+    if (!mandatory) {
+      out << "[";
+    }
+    if (opt.argument) {
+      out << opt.name << " arg";
+      maxLength = std::max(maxLength, opt.name.size() + 4);
+    } else {
+      out << opt.name;
+      maxLength = std::max(maxLength, opt.name.size());
+    }
+    if (!mandatory) {
+      out << "]";
+    }
+    if (opt.count == Option::COUNT_ONCE_OR_MORE) {
+      out << " [" << opt.name << " arg [..]]";
+    }
+  }
+  out << std::endl << std::endl;
+  for (const Option& opt : options_) {
+    out << std::left << std::setw(maxLength);
+    if (opt.argument) {
+      out << (opt.name + " arg");
+    } else {
+      out << opt.name;
+    }
+    out << "    " << opt.description;
+    if (opt.count == Option::COUNT_ONCE_OR_MORE) {
+      out << " (can be provided multiple times)";
+    }
+    out << std::endl;
+  }
+}
+
+}  // namespace idmap2
+}  // namespace android
diff --git a/cmds/idmap2/libidmap2/FileUtils.cpp b/cmds/idmap2/libidmap2/FileUtils.cpp
new file mode 100644
index 0000000..4ac4c04
--- /dev/null
+++ b/cmds/idmap2/libidmap2/FileUtils.cpp
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dirent.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <fstream>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "idmap2/FileUtils.h"
+
+namespace android {
+namespace idmap2 {
+namespace utils {
+
+std::unique_ptr<std::vector<std::string>> FindFiles(const std::string& root, bool recurse,
+                                                    const FindFilesPredicate& predicate) {
+  DIR* dir = opendir(root.c_str());
+  if (!dir) {
+    return nullptr;
+  }
+  std::unique_ptr<std::vector<std::string>> vector(new std::vector<std::string>());
+  struct dirent* dirent;
+  while ((dirent = readdir(dir))) {
+    const std::string path = root + "/" + dirent->d_name;
+    if (predicate(dirent->d_type, path)) {
+      vector->push_back(path);
+    }
+    if (recurse && dirent->d_type == DT_DIR && strcmp(dirent->d_name, ".") != 0 &&
+        strcmp(dirent->d_name, "..") != 0) {
+      auto sub_vector = FindFiles(path, recurse, predicate);
+      if (!sub_vector) {
+        closedir(dir);
+        return nullptr;
+      }
+      vector->insert(vector->end(), sub_vector->begin(), sub_vector->end());
+    }
+  }
+  closedir(dir);
+
+  return vector;
+}
+
+std::unique_ptr<std::string> ReadFile(const std::string& path) {
+  std::unique_ptr<std::string> str(new std::string());
+  std::ifstream fin(path);
+  str->append({std::istreambuf_iterator<char>(fin), std::istreambuf_iterator<char>()});
+  fin.close();
+  return str;
+}
+
+std::unique_ptr<std::string> ReadFile(int fd) {
+  std::unique_ptr<std::string> str(new std::string());
+  char buf[1024];
+  ssize_t r;
+  while ((r = read(fd, buf, sizeof(buf))) > 0) {
+    str->append(buf, r);
+  }
+  return r == 0 ? std::move(str) : nullptr;
+}
+
+}  // namespace utils
+}  // namespace idmap2
+}  // namespace android
diff --git a/cmds/idmap2/libidmap2/Idmap.cpp b/cmds/idmap2/libidmap2/Idmap.cpp
new file mode 100644
index 0000000..5a47e30
--- /dev/null
+++ b/cmds/idmap2/libidmap2/Idmap.cpp
@@ -0,0 +1,443 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <algorithm>
+#include <iostream>
+#include <iterator>
+#include <limits>
+#include <map>
+#include <memory>
+#include <set>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "android-base/macros.h"
+#include "android-base/stringprintf.h"
+#include "androidfw/AssetManager2.h"
+#include "utils/String16.h"
+#include "utils/String8.h"
+
+#include "idmap2/Idmap.h"
+#include "idmap2/ResourceUtils.h"
+#include "idmap2/ZipFile.h"
+
+namespace android {
+namespace idmap2 {
+
+#define EXTRACT_TYPE(resid) ((0x00ff0000 & (resid)) >> 16)
+
+#define EXTRACT_ENTRY(resid) (0x0000ffff & (resid))
+
+struct MatchingResources {
+  void Add(ResourceId target_resid, ResourceId overlay_resid) {
+    TypeId target_typeid = EXTRACT_TYPE(target_resid);
+    if (map.find(target_typeid) == map.end()) {
+      map.emplace(target_typeid, std::set<std::pair<ResourceId, ResourceId>>());
+    }
+    map[target_typeid].insert(std::make_pair(target_resid, overlay_resid));
+  }
+
+  // target type id -> set { pair { overlay entry id, overlay entry id } }
+  std::map<TypeId, std::set<std::pair<ResourceId, ResourceId>>> map;
+};
+
+static bool WARN_UNUSED Read16(std::istream& stream, uint16_t* out) {
+  uint16_t value;
+  if (stream.read(reinterpret_cast<char*>(&value), sizeof(uint16_t))) {
+    *out = dtohl(value);
+    return true;
+  }
+  return false;
+}
+
+static bool WARN_UNUSED Read32(std::istream& stream, uint32_t* out) {
+  uint32_t value;
+  if (stream.read(reinterpret_cast<char*>(&value), sizeof(uint32_t))) {
+    *out = dtohl(value);
+    return true;
+  }
+  return false;
+}
+
+// a string is encoded as a kIdmapStringLength char array; the array is always null-terminated
+static bool WARN_UNUSED ReadString(std::istream& stream, char out[kIdmapStringLength]) {
+  char buf[kIdmapStringLength];
+  memset(buf, 0, sizeof(buf));
+  if (!stream.read(buf, sizeof(buf))) {
+    return false;
+  }
+  if (buf[sizeof(buf) - 1] != '\0') {
+    return false;
+  }
+  memcpy(out, buf, sizeof(buf));
+  return true;
+}
+
+static ResourceId NameToResid(const AssetManager2& am, const std::string& name) {
+  return am.GetResourceId(name);
+}
+
+// TODO(martenkongstad): scan for package name instead of assuming package at index 0
+//
+// idmap version 0x01 naively assumes that the package to use is always the first ResTable_package
+// in the resources.arsc blob. In most cases, there is only a single ResTable_package anyway, so
+// this assumption tends to work out. That said, the correct thing to do is to scan
+// resources.arsc for a package with a given name as read from the package manifest instead of
+// relying on a hard-coded index. This however requires storing the package name in the idmap
+// header, which in turn requires incrementing the idmap version. Because the initial version of
+// idmap2 is compatible with idmap, this will have to wait for now.
+static const LoadedPackage* GetPackageAtIndex0(const LoadedArsc& loaded_arsc) {
+  const std::vector<std::unique_ptr<const LoadedPackage>>& packages = loaded_arsc.GetPackages();
+  if (packages.empty()) {
+    return nullptr;
+  }
+  int id = packages[0]->GetPackageId();
+  return loaded_arsc.GetPackageById(id);
+}
+
+std::unique_ptr<const IdmapHeader> IdmapHeader::FromBinaryStream(std::istream& stream) {
+  std::unique_ptr<IdmapHeader> idmap_header(new IdmapHeader());
+
+  if (!Read32(stream, &idmap_header->magic_) || !Read32(stream, &idmap_header->version_) ||
+      !Read32(stream, &idmap_header->target_crc_) || !Read32(stream, &idmap_header->overlay_crc_) ||
+      !ReadString(stream, idmap_header->target_path_) ||
+      !ReadString(stream, idmap_header->overlay_path_)) {
+    return nullptr;
+  }
+
+  return std::move(idmap_header);
+}
+
+bool IdmapHeader::IsUpToDate(std::ostream& out_error) const {
+  if (magic_ != kIdmapMagic) {
+    out_error << base::StringPrintf("error: bad magic: actual 0x%08x, expected 0x%08x", magic_,
+                                    kIdmapMagic)
+              << std::endl;
+    return false;
+  }
+
+  if (version_ != kIdmapCurrentVersion) {
+    out_error << base::StringPrintf("error: bad version: actual 0x%08x, expected 0x%08x", version_,
+                                    kIdmapCurrentVersion)
+              << std::endl;
+    return false;
+  }
+
+  const std::unique_ptr<const ZipFile> target_zip = ZipFile::Open(target_path_);
+  if (!target_zip) {
+    out_error << "error: failed to open target " << target_path_ << std::endl;
+    return false;
+  }
+
+  bool status;
+  uint32_t target_crc;
+  std::tie(status, target_crc) = target_zip->Crc("resources.arsc");
+  if (!status) {
+    out_error << "error: failed to get target crc" << std::endl;
+    return false;
+  }
+
+  if (target_crc_ != target_crc) {
+    out_error << base::StringPrintf(
+                     "error: bad target crc: idmap version 0x%08x, file system version 0x%08x",
+                     target_crc_, target_crc)
+              << std::endl;
+    return false;
+  }
+
+  const std::unique_ptr<const ZipFile> overlay_zip = ZipFile::Open(overlay_path_);
+  if (!overlay_zip) {
+    out_error << "error: failed to open overlay " << overlay_path_ << std::endl;
+    return false;
+  }
+
+  uint32_t overlay_crc;
+  std::tie(status, overlay_crc) = overlay_zip->Crc("resources.arsc");
+  if (!status) {
+    out_error << "error: failed to get overlay crc" << std::endl;
+    return false;
+  }
+
+  if (overlay_crc_ != overlay_crc) {
+    out_error << base::StringPrintf(
+                     "error: bad overlay crc: idmap version 0x%08x, file system version 0x%08x",
+                     overlay_crc_, overlay_crc)
+              << std::endl;
+    return false;
+  }
+
+  return true;
+}
+
+std::unique_ptr<const IdmapData::Header> IdmapData::Header::FromBinaryStream(std::istream& stream) {
+  std::unique_ptr<IdmapData::Header> idmap_data_header(new IdmapData::Header());
+
+  uint16_t target_package_id16;
+  if (!Read16(stream, &target_package_id16) || !Read16(stream, &idmap_data_header->type_count_)) {
+    return nullptr;
+  }
+  idmap_data_header->target_package_id_ = target_package_id16;
+
+  return std::move(idmap_data_header);
+}
+
+std::unique_ptr<const IdmapData::TypeEntry> IdmapData::TypeEntry::FromBinaryStream(
+    std::istream& stream) {
+  std::unique_ptr<IdmapData::TypeEntry> data(new IdmapData::TypeEntry());
+
+  uint16_t target_type16, overlay_type16, entry_count;
+  if (!Read16(stream, &target_type16) || !Read16(stream, &overlay_type16) ||
+      !Read16(stream, &entry_count) || !Read16(stream, &data->entry_offset_)) {
+    return nullptr;
+  }
+  data->target_type_id_ = target_type16;
+  data->overlay_type_id_ = overlay_type16;
+  for (uint16_t i = 0; i < entry_count; i++) {
+    ResourceId resid;
+    if (!Read32(stream, &resid)) {
+      return nullptr;
+    }
+    data->entries_.push_back(resid);
+  }
+
+  return std::move(data);
+}
+
+std::unique_ptr<const IdmapData> IdmapData::FromBinaryStream(std::istream& stream) {
+  std::unique_ptr<IdmapData> data(new IdmapData());
+  data->header_ = IdmapData::Header::FromBinaryStream(stream);
+  if (!data->header_) {
+    return nullptr;
+  }
+  for (size_t type_count = 0; type_count < data->header_->GetTypeCount(); type_count++) {
+    std::unique_ptr<const TypeEntry> type = IdmapData::TypeEntry::FromBinaryStream(stream);
+    if (!type) {
+      return nullptr;
+    }
+    data->type_entries_.push_back(std::move(type));
+  }
+  return std::move(data);
+}
+
+std::string Idmap::CanonicalIdmapPathFor(const std::string& absolute_dir,
+                                         const std::string& absolute_apk_path) {
+  assert(absolute_dir.size() > 0 && absolute_dir[0] == "/");
+  assert(absolute_apk_path.size() > 0 && absolute_apk_path[0] == "/");
+  std::string copy(++absolute_apk_path.cbegin(), absolute_apk_path.cend());
+  replace(copy.begin(), copy.end(), '/', '@');
+  return absolute_dir + "/" + copy + "@idmap";
+}
+
+std::unique_ptr<const Idmap> Idmap::FromBinaryStream(std::istream& stream,
+                                                     std::ostream& out_error) {
+  std::unique_ptr<Idmap> idmap(new Idmap());
+
+  idmap->header_ = IdmapHeader::FromBinaryStream(stream);
+  if (!idmap->header_) {
+    out_error << "error: failed to parse idmap header" << std::endl;
+    return nullptr;
+  }
+
+  // idmap version 0x01 does not specify the number of data blocks that follow
+  // the idmap header; assume exactly one data block
+  for (int i = 0; i < 1; i++) {
+    std::unique_ptr<const IdmapData> data = IdmapData::FromBinaryStream(stream);
+    if (!data) {
+      out_error << "error: failed to parse data block " << i << std::endl;
+      return nullptr;
+    }
+    idmap->data_.push_back(std::move(data));
+  }
+
+  return std::move(idmap);
+}
+
+std::unique_ptr<const Idmap> Idmap::FromApkAssets(const std::string& target_apk_path,
+                                                  const ApkAssets& target_apk_assets,
+                                                  const std::string& overlay_apk_path,
+                                                  const ApkAssets& overlay_apk_assets,
+                                                  std::ostream& out_error) {
+  AssetManager2 target_asset_manager;
+  if (!target_asset_manager.SetApkAssets({&target_apk_assets}, true, false)) {
+    out_error << "error: failed to create target asset manager" << std::endl;
+    return nullptr;
+  }
+
+  AssetManager2 overlay_asset_manager;
+  if (!overlay_asset_manager.SetApkAssets({&overlay_apk_assets}, true, false)) {
+    out_error << "error: failed to create overlay asset manager" << std::endl;
+    return nullptr;
+  }
+
+  const LoadedArsc* target_arsc = target_apk_assets.GetLoadedArsc();
+  if (!target_arsc) {
+    out_error << "error: failed to load target resources.arsc" << std::endl;
+    return nullptr;
+  }
+
+  const LoadedArsc* overlay_arsc = overlay_apk_assets.GetLoadedArsc();
+  if (!overlay_arsc) {
+    out_error << "error: failed to load overlay resources.arsc" << std::endl;
+    return nullptr;
+  }
+
+  const LoadedPackage* target_pkg = GetPackageAtIndex0(*target_arsc);
+  if (!target_pkg) {
+    out_error << "error: failed to load target package from resources.arsc" << std::endl;
+    return nullptr;
+  }
+
+  const LoadedPackage* overlay_pkg = GetPackageAtIndex0(*overlay_arsc);
+  if (!overlay_pkg) {
+    out_error << "error: failed to load overlay package from resources.arsc" << std::endl;
+    return nullptr;
+  }
+
+  const std::unique_ptr<const ZipFile> target_zip = ZipFile::Open(target_apk_path);
+  if (!target_zip) {
+    out_error << "error: failed to open target as zip" << std::endl;
+    return nullptr;
+  }
+
+  const std::unique_ptr<const ZipFile> overlay_zip = ZipFile::Open(overlay_apk_path);
+  if (!overlay_zip) {
+    out_error << "error: failed to open overlay as zip" << std::endl;
+    return nullptr;
+  }
+
+  std::unique_ptr<IdmapHeader> header(new IdmapHeader());
+  header->magic_ = kIdmapMagic;
+  header->version_ = kIdmapCurrentVersion;
+  bool crc_status;
+  std::tie(crc_status, header->target_crc_) = target_zip->Crc("resources.arsc");
+  if (!crc_status) {
+    out_error << "error: failed to get zip crc for target" << std::endl;
+    return nullptr;
+  }
+  std::tie(crc_status, header->overlay_crc_) = overlay_zip->Crc("resources.arsc");
+  if (!crc_status) {
+    out_error << "error: failed to get zip crc for overlay" << std::endl;
+    return nullptr;
+  }
+
+  if (target_apk_path.size() > sizeof(header->target_path_)) {
+    out_error << "error: target apk path \"" << target_apk_path << "\" longer that maximum size "
+              << sizeof(header->target_path_) << std::endl;
+    return nullptr;
+  }
+  memset(header->target_path_, 0, sizeof(header->target_path_));
+  memcpy(header->target_path_, target_apk_path.data(), target_apk_path.size());
+
+  if (overlay_apk_path.size() > sizeof(header->overlay_path_)) {
+    out_error << "error: overlay apk path \"" << overlay_apk_path << "\" longer that maximum size "
+              << sizeof(header->overlay_path_) << std::endl;
+    return nullptr;
+  }
+  memset(header->overlay_path_, 0, sizeof(header->overlay_path_));
+  memcpy(header->overlay_path_, overlay_apk_path.data(), overlay_apk_path.size());
+
+  std::unique_ptr<Idmap> idmap(new Idmap());
+  idmap->header_ = std::move(header);
+
+  // find the resources that exist in both packages
+  MatchingResources matching_resources;
+  const auto end = overlay_pkg->end();
+  for (auto iter = overlay_pkg->begin(); iter != end; ++iter) {
+    const ResourceId overlay_resid = *iter;
+    bool lookup_ok;
+    std::string name;
+    std::tie(lookup_ok, name) = utils::ResToTypeEntryName(overlay_asset_manager, overlay_resid);
+    if (!lookup_ok) {
+      continue;
+    }
+    // prepend "<package>:" to turn name into "<package>:<type>/<name>"
+    name = base::StringPrintf("%s:%s", target_pkg->GetPackageName().c_str(), name.c_str());
+    const ResourceId target_resid = NameToResid(target_asset_manager, name);
+    if (target_resid == 0) {
+      continue;
+    }
+    matching_resources.Add(target_resid, overlay_resid);
+  }
+
+  // encode idmap data
+  std::unique_ptr<IdmapData> data(new IdmapData());
+  const auto types_end = matching_resources.map.cend();
+  for (auto ti = matching_resources.map.cbegin(); ti != types_end; ++ti) {
+    auto ei = ti->second.cbegin();
+    std::unique_ptr<IdmapData::TypeEntry> type(new IdmapData::TypeEntry());
+    type->target_type_id_ = EXTRACT_TYPE(ei->first);
+    type->overlay_type_id_ = EXTRACT_TYPE(ei->second);
+    type->entry_offset_ = EXTRACT_ENTRY(ei->first);
+    EntryId last_target_entry = kNoEntry;
+    for (; ei != ti->second.cend(); ++ei) {
+      if (last_target_entry != kNoEntry) {
+        int count = EXTRACT_ENTRY(ei->first) - last_target_entry - 1;
+        type->entries_.insert(type->entries_.end(), count, kNoEntry);
+      }
+      type->entries_.push_back(EXTRACT_ENTRY(ei->second));
+      last_target_entry = EXTRACT_ENTRY(ei->first);
+    }
+    data->type_entries_.push_back(std::move(type));
+  }
+
+  std::unique_ptr<IdmapData::Header> data_header(new IdmapData::Header());
+  data_header->target_package_id_ = target_pkg->GetPackageId();
+  data_header->type_count_ = data->type_entries_.size();
+  data->header_ = std::move(data_header);
+
+  idmap->data_.push_back(std::move(data));
+
+  return std::move(idmap);
+}
+
+void IdmapHeader::accept(Visitor* v) const {
+  assert(v != nullptr);
+  v->visit(*this);
+}
+
+void IdmapData::Header::accept(Visitor* v) const {
+  assert(v != nullptr);
+  v->visit(*this);
+}
+
+void IdmapData::TypeEntry::accept(Visitor* v) const {
+  assert(v != nullptr);
+  v->visit(*this);
+}
+
+void IdmapData::accept(Visitor* v) const {
+  assert(v != nullptr);
+  v->visit(*this);
+  header_->accept(v);
+  auto end = type_entries_.cend();
+  for (auto iter = type_entries_.cbegin(); iter != end; ++iter) {
+    (*iter)->accept(v);
+  }
+}
+
+void Idmap::accept(Visitor* v) const {
+  assert(v != nullptr);
+  v->visit(*this);
+  header_->accept(v);
+  auto end = data_.cend();
+  for (auto iter = data_.cbegin(); iter != end; ++iter) {
+    (*iter)->accept(v);
+  }
+}
+
+}  // namespace idmap2
+}  // namespace android
diff --git a/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp b/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp
new file mode 100644
index 0000000..492e6f0
--- /dev/null
+++ b/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <string>
+#include <utility>
+
+#include "android-base/macros.h"
+#include "android-base/stringprintf.h"
+#include "androidfw/ApkAssets.h"
+
+#include "idmap2/PrettyPrintVisitor.h"
+#include "idmap2/ResourceUtils.h"
+
+namespace android {
+namespace idmap2 {
+
+#define RESID(pkg, type, entry) (((pkg) << 24) | ((type) << 16) | (entry))
+
+void PrettyPrintVisitor::visit(const Idmap& idmap ATTRIBUTE_UNUSED) {
+}
+
+void PrettyPrintVisitor::visit(const IdmapHeader& header) {
+  stream_ << "target apk path  : " << header.GetTargetPath() << std::endl
+          << "overlay apk path : " << header.GetOverlayPath() << std::endl;
+
+  target_apk_ = ApkAssets::Load(header.GetTargetPath().to_string());
+  if (target_apk_) {
+    target_am_.SetApkAssets({target_apk_.get()});
+  }
+}
+
+void PrettyPrintVisitor::visit(const IdmapData& data ATTRIBUTE_UNUSED) {
+}
+
+void PrettyPrintVisitor::visit(const IdmapData::Header& header ATTRIBUTE_UNUSED) {
+  last_seen_package_id_ = header.GetTargetPackageId();
+}
+
+void PrettyPrintVisitor::visit(const IdmapData::TypeEntry& te) {
+  const bool target_package_loaded = !target_am_.GetApkAssets().empty();
+  for (uint16_t i = 0; i < te.GetEntryCount(); i++) {
+    const EntryId entry = te.GetEntry(i);
+    if (entry == kNoEntry) {
+      continue;
+    }
+
+    const ResourceId target_resid =
+        RESID(last_seen_package_id_, te.GetTargetTypeId(), te.GetEntryOffset() + i);
+    const ResourceId overlay_resid = RESID(last_seen_package_id_, te.GetOverlayTypeId(), entry);
+
+    stream_ << base::StringPrintf("0x%08x -> 0x%08x", target_resid, overlay_resid);
+    if (target_package_loaded) {
+      bool lookup_ok;
+      std::string name;
+      std::tie(lookup_ok, name) = utils::ResToTypeEntryName(target_am_, target_resid);
+      if (lookup_ok) {
+        stream_ << " " << name;
+      }
+    }
+    stream_ << std::endl;
+  }
+}
+
+}  // namespace idmap2
+}  // namespace android
diff --git a/cmds/idmap2/libidmap2/RawPrintVisitor.cpp b/cmds/idmap2/libidmap2/RawPrintVisitor.cpp
new file mode 100644
index 0000000..57cfc8e
--- /dev/null
+++ b/cmds/idmap2/libidmap2/RawPrintVisitor.cpp
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cstdarg>
+#include <string>
+#include <utility>
+
+#include "android-base/macros.h"
+#include "android-base/stringprintf.h"
+#include "androidfw/ApkAssets.h"
+
+#include "idmap2/RawPrintVisitor.h"
+#include "idmap2/ResourceUtils.h"
+
+using android::ApkAssets;
+
+namespace android {
+namespace idmap2 {
+
+// verbatim copy fomr PrettyPrintVisitor.cpp, move to common utils
+#define RESID(pkg, type, entry) (((pkg) << 24) | ((type) << 16) | (entry))
+
+void RawPrintVisitor::visit(const Idmap& idmap ATTRIBUTE_UNUSED) {
+}
+
+void RawPrintVisitor::visit(const IdmapHeader& header) {
+  print(header.GetMagic(), "magic");
+  print(header.GetVersion(), "version");
+  print(header.GetTargetCrc(), "target crc");
+  print(header.GetOverlayCrc(), "overlay crc");
+  print(header.GetTargetPath().to_string(), "target path");
+  print(header.GetOverlayPath().to_string(), "overlay path");
+
+  target_apk_ = ApkAssets::Load(header.GetTargetPath().to_string());
+  if (target_apk_) {
+    target_am_.SetApkAssets({target_apk_.get()});
+  }
+}
+
+void RawPrintVisitor::visit(const IdmapData& data ATTRIBUTE_UNUSED) {
+}
+
+void RawPrintVisitor::visit(const IdmapData::Header& header) {
+  print(static_cast<uint16_t>(header.GetTargetPackageId()), "target package id");
+  print(header.GetTypeCount(), "type count");
+  last_seen_package_id_ = header.GetTargetPackageId();
+}
+
+void RawPrintVisitor::visit(const IdmapData::TypeEntry& te) {
+  const bool target_package_loaded = !target_am_.GetApkAssets().empty();
+
+  print(static_cast<uint16_t>(te.GetTargetTypeId()), "target type");
+  print(static_cast<uint16_t>(te.GetOverlayTypeId()), "overlay type");
+  print(static_cast<uint16_t>(te.GetEntryCount()), "entry count");
+  print(static_cast<uint16_t>(te.GetEntryOffset()), "entry offset");
+
+  for (uint16_t i = 0; i < te.GetEntryCount(); i++) {
+    const EntryId entry = te.GetEntry(i);
+    if (entry == kNoEntry) {
+      print(kPadding, "no entry");
+    } else {
+      const ResourceId target_resid =
+          RESID(last_seen_package_id_, te.GetTargetTypeId(), te.GetEntryOffset() + i);
+      const ResourceId overlay_resid = RESID(last_seen_package_id_, te.GetOverlayTypeId(), entry);
+      bool lookup_ok = false;
+      std::string name;
+      if (target_package_loaded) {
+        std::tie(lookup_ok, name) = utils::ResToTypeEntryName(target_am_, target_resid);
+      }
+      if (lookup_ok) {
+        print(static_cast<uint32_t>(entry), "0x%08x -> 0x%08x %s", target_resid, overlay_resid,
+              name.c_str());
+      } else {
+        print(static_cast<uint32_t>(entry), "0x%08x -> 0x%08x", target_resid, overlay_resid);
+      }
+    }
+  }
+}
+
+void RawPrintVisitor::print(uint16_t value, const char* fmt, ...) {
+  va_list ap;
+  va_start(ap, fmt);
+  std::string comment;
+  base::StringAppendV(&comment, fmt, ap);
+  va_end(ap);
+
+  stream_ << base::StringPrintf("%08zx:     %04x", offset_, value) << "  " << comment << std::endl;
+
+  offset_ += sizeof(uint16_t);
+}
+
+void RawPrintVisitor::print(uint32_t value, const char* fmt, ...) {
+  va_list ap;
+  va_start(ap, fmt);
+  std::string comment;
+  base::StringAppendV(&comment, fmt, ap);
+  va_end(ap);
+
+  stream_ << base::StringPrintf("%08zx: %08x", offset_, value) << "  " << comment << std::endl;
+
+  offset_ += sizeof(uint32_t);
+}
+
+void RawPrintVisitor::print(const std::string& value, const char* fmt, ...) {
+  va_list ap;
+  va_start(ap, fmt);
+  std::string comment;
+  base::StringAppendV(&comment, fmt, ap);
+  va_end(ap);
+
+  stream_ << base::StringPrintf("%08zx: ", offset_) << "........ " << comment << ": " << value
+          << std::endl;
+
+  offset_ += kIdmapStringLength;
+}
+
+}  // namespace idmap2
+}  // namespace android
diff --git a/cmds/idmap2/libidmap2/ResourceUtils.cpp b/cmds/idmap2/libidmap2/ResourceUtils.cpp
new file mode 100644
index 0000000..e98f843
--- /dev/null
+++ b/cmds/idmap2/libidmap2/ResourceUtils.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <string>
+#include <utility>
+
+#include "androidfw/StringPiece.h"
+#include "androidfw/Util.h"
+
+#include "idmap2/ResourceUtils.h"
+
+using android::StringPiece16;
+using android::util::Utf16ToUtf8;
+
+namespace android {
+namespace idmap2 {
+namespace utils {
+
+std::pair<bool, std::string> WARN_UNUSED ResToTypeEntryName(const AssetManager2& am,
+                                                            ResourceId resid) {
+  AssetManager2::ResourceName name;
+  if (!am.GetResourceName(resid, &name)) {
+    return std::make_pair(false, "");
+  }
+  std::string out;
+  if (name.type != nullptr) {
+    out.append(name.type, name.type_len);
+  } else {
+    out += Utf16ToUtf8(StringPiece16(name.type16, name.type_len));
+  }
+  out.append("/");
+  if (name.entry != nullptr) {
+    out.append(name.entry, name.entry_len);
+  } else {
+    out += Utf16ToUtf8(StringPiece16(name.entry16, name.entry_len));
+  }
+  return std::make_pair(true, out);
+}
+
+}  // namespace utils
+}  // namespace idmap2
+}  // namespace android
diff --git a/cmds/idmap2/libidmap2/Xml.cpp b/cmds/idmap2/libidmap2/Xml.cpp
new file mode 100644
index 0000000..5543722
--- /dev/null
+++ b/cmds/idmap2/libidmap2/Xml.cpp
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <map>
+#include <memory>
+#include <string>
+#include <utility>
+
+#include "idmap2/Xml.h"
+
+namespace android {
+namespace idmap2 {
+
+std::unique_ptr<const Xml> Xml::Create(const uint8_t* data, size_t size, bool copyData) {
+  std::unique_ptr<Xml> xml(new Xml());
+  if (xml->xml_.setTo(data, size, copyData) != NO_ERROR) {
+    return nullptr;
+  }
+  return xml;
+}
+
+std::unique_ptr<std::map<std::string, std::string>> Xml::FindTag(const std::string& name) const {
+  const String16 tag_to_find(name.c_str(), name.size());
+  xml_.restart();
+  ResXMLParser::event_code_t type;
+  do {
+    type = xml_.next();
+    if (type == ResXMLParser::START_TAG) {
+      size_t len;
+      const String16 tag(xml_.getElementName(&len));
+      if (tag == tag_to_find) {
+        std::unique_ptr<std::map<std::string, std::string>> map(
+            new std::map<std::string, std::string>());
+        for (size_t i = 0; i < xml_.getAttributeCount(); i++) {
+          const String16 key16(xml_.getAttributeName(i, &len));
+          std::string key = String8(key16).c_str();
+
+          std::string value;
+          switch (xml_.getAttributeDataType(i)) {
+            case Res_value::TYPE_STRING: {
+              const String16 value16(xml_.getAttributeStringValue(i, &len));
+              value = String8(value16).c_str();
+            } break;
+            case Res_value::TYPE_INT_DEC:
+            case Res_value::TYPE_INT_HEX:
+            case Res_value::TYPE_INT_BOOLEAN: {
+              Res_value resValue;
+              xml_.getAttributeValue(i, &resValue);
+              value = std::to_string(resValue.data);
+            } break;
+            default:
+              return nullptr;
+          }
+
+          map->emplace(std::make_pair(key, value));
+        }
+        return map;
+      }
+    }
+  } while (type != ResXMLParser::BAD_DOCUMENT && type != ResXMLParser::END_DOCUMENT);
+  return nullptr;
+}
+
+Xml::~Xml() {
+  xml_.uninit();
+}
+
+}  // namespace idmap2
+}  // namespace android
diff --git a/cmds/idmap2/libidmap2/ZipFile.cpp b/cmds/idmap2/libidmap2/ZipFile.cpp
new file mode 100644
index 0000000..3f2079a
--- /dev/null
+++ b/cmds/idmap2/libidmap2/ZipFile.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <memory>
+#include <string>
+#include <utility>
+
+#include "idmap2/ZipFile.h"
+
+namespace android {
+namespace idmap2 {
+
+std::unique_ptr<MemoryChunk> MemoryChunk::Allocate(size_t size) {
+  void* ptr = ::operator new(sizeof(MemoryChunk) + size);
+  std::unique_ptr<MemoryChunk> chunk(reinterpret_cast<MemoryChunk*>(ptr));
+  chunk->size = size;
+  return chunk;
+}
+
+std::unique_ptr<const ZipFile> ZipFile::Open(const std::string& path) {
+  ::ZipArchiveHandle handle;
+  int32_t status = ::OpenArchive(path.c_str(), &handle);
+  if (status != 0) {
+    return nullptr;
+  }
+  return std::unique_ptr<ZipFile>(new ZipFile(handle));
+}
+
+ZipFile::~ZipFile() {
+  ::CloseArchive(handle_);
+}
+
+std::unique_ptr<const MemoryChunk> ZipFile::Uncompress(const std::string& entryPath) const {
+  ::ZipEntry entry;
+  int32_t status = ::FindEntry(handle_, ::ZipString(entryPath.c_str()), &entry);
+  if (status != 0) {
+    return nullptr;
+  }
+  std::unique_ptr<MemoryChunk> chunk = MemoryChunk::Allocate(entry.uncompressed_length);
+  status = ::ExtractToMemory(handle_, &entry, chunk->buf, chunk->size);
+  if (status != 0) {
+    return nullptr;
+  }
+  return chunk;
+}
+
+std::pair<bool, uint32_t> ZipFile::Crc(const std::string& entryPath) const {
+  ::ZipEntry entry;
+  int32_t status = ::FindEntry(handle_, ::ZipString(entryPath.c_str()), &entry);
+  return std::make_pair(status == 0, entry.crc32);
+}
+
+}  // namespace idmap2
+}  // namespace android
diff --git a/cmds/idmap2/static-checks.sh b/cmds/idmap2/static-checks.sh
new file mode 100755
index 0000000..560ccb6
--- /dev/null
+++ b/cmds/idmap2/static-checks.sh
@@ -0,0 +1,121 @@
+#!/bin/bash
+#
+# Copyright (C) 2018 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+function _log()
+{
+    echo -e "$*" >&2
+}
+
+function _eval()
+{
+    local label="$1"
+    local cmd="$2"
+    local red="\e[31m"
+    local green="\e[32m"
+    local reset="\e[0m"
+
+    _log "${green}[ RUN      ]${reset} ${label}"
+    local output="$(eval "$cmd")"
+    if [[ -z "${output}" ]]; then
+        _log "${green}[       OK ]${reset} ${label}"
+        return 0
+    else
+        echo "${output}"
+        _log "${red}[  FAILED  ]${reset} ${label}"
+        errors=$((errors + 1))
+        return 1
+    fi
+}
+
+function _clang_format()
+{
+    local path
+    local errors=0
+
+    for path in $cpp_files; do
+        local output="$(clang-format -style=file "$path" | diff $path -)"
+        if [[ "$output" ]]; then
+            echo "$path"
+            echo "$output"
+            errors=1
+        fi
+    done
+    return $errors
+}
+
+function _bpfmt()
+{
+    local output="$(bpfmt -s -d $bp_files)"
+    if [[ "$output" ]]; then
+        echo "$output"
+        return 1
+    fi
+    return 0
+}
+
+function _cpplint()
+{
+    local cpplint="${ANDROID_BUILD_TOP}/tools/repohooks/tools/cpplint.py"
+    $cpplint --quiet $cpp_files
+}
+
+function _parse_args()
+{
+    local opts
+
+    opts="$(getopt -o cfh --long check,fix,help -- "$@")"
+    if [[ $? -ne 0 ]]; then
+        exit 1
+    fi
+    eval set -- "$opts"
+    while true; do
+        case "$1" in
+            -c|--check) opt_mode="check"; shift ;;
+            -f|--fix) opt_mode="fix"; shift ;;
+            -h|--help) opt_mode="help"; shift ;;
+            *) break ;;
+        esac
+    done
+}
+
+errors=0
+script="$(readlink -f "$BASH_SOURCE")"
+prefix="$(dirname "$script")"
+cpp_files="$(find "$prefix" -name '*.cpp' -or -name '*.h')"
+bp_files="$(find "$prefix" -name 'Android.bp')"
+opt_mode="check"
+
+_parse_args "$@"
+if [[ $opt_mode == "check" ]]; then
+    _eval "clang-format" "_clang_format"
+    _eval "bpfmt" "_bpfmt"
+    _eval "cpplint" "_cpplint"
+    exit $errors
+elif [[ $opt_mode == "fix" ]]; then
+    clang-format -style=file -i $cpp_files
+    bpfmt -s -w $bp_files
+    exit 0
+elif [[ $opt_mode == "help" ]]; then
+    echo "Run static analysis tools such as clang-format and cpplint on the idmap2"
+    echo "module. Optionally fix some of the issues found (--fix). Intended to be run"
+    echo "before merging any changes."
+    echo
+    echo "usage: $(basename $script) [--check|--fix|--help]"
+    exit 0
+else
+    exit 1
+fi
diff --git a/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp b/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp
new file mode 100644
index 0000000..8b552dc
--- /dev/null
+++ b/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <memory>
+#include <sstream>
+#include <string>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#include "androidfw/ApkAssets.h"
+#include "androidfw/Idmap.h"
+
+#include "idmap2/BinaryStreamVisitor.h"
+#include "idmap2/Idmap.h"
+
+#include "TestHelpers.h"
+
+using ::testing::IsNull;
+using ::testing::NotNull;
+
+namespace android {
+namespace idmap2 {
+
+TEST(BinaryStreamVisitorTests, CreateBinaryStreamViaBinaryStreamVisitor) {
+  std::string raw(reinterpret_cast<const char*>(idmap_raw_data), idmap_raw_data_len);
+  std::istringstream raw_stream(raw);
+
+  std::stringstream error;
+  std::unique_ptr<const Idmap> idmap1 = Idmap::FromBinaryStream(raw_stream, error);
+  ASSERT_THAT(idmap1, NotNull());
+
+  std::stringstream stream;
+  BinaryStreamVisitor visitor(stream);
+  idmap1->accept(&visitor);
+
+  std::unique_ptr<const Idmap> idmap2 = Idmap::FromBinaryStream(stream, error);
+  ASSERT_THAT(idmap2, NotNull());
+
+  ASSERT_EQ(idmap1->GetHeader()->GetTargetCrc(), idmap2->GetHeader()->GetTargetCrc());
+  ASSERT_EQ(idmap1->GetHeader()->GetTargetPath(), idmap2->GetHeader()->GetTargetPath());
+  ASSERT_EQ(idmap1->GetData().size(), 1u);
+  ASSERT_EQ(idmap1->GetData().size(), idmap2->GetData().size());
+
+  const auto& data1 = idmap1->GetData()[0];
+  const auto& data2 = idmap2->GetData()[0];
+
+  ASSERT_EQ(data1->GetHeader()->GetTargetPackageId(), data2->GetHeader()->GetTargetPackageId());
+  ASSERT_EQ(data1->GetTypeEntries().size(), 2u);
+  ASSERT_EQ(data1->GetTypeEntries().size(), data2->GetTypeEntries().size());
+  ASSERT_EQ(data1->GetTypeEntries()[0]->GetEntry(0), data2->GetTypeEntries()[0]->GetEntry(0));
+  ASSERT_EQ(data1->GetTypeEntries()[0]->GetEntry(1), data2->GetTypeEntries()[0]->GetEntry(1));
+  ASSERT_EQ(data1->GetTypeEntries()[0]->GetEntry(2), data2->GetTypeEntries()[0]->GetEntry(2));
+  ASSERT_EQ(data1->GetTypeEntries()[1]->GetEntry(0), data2->GetTypeEntries()[1]->GetEntry(0));
+  ASSERT_EQ(data1->GetTypeEntries()[1]->GetEntry(1), data2->GetTypeEntries()[1]->GetEntry(1));
+  ASSERT_EQ(data1->GetTypeEntries()[1]->GetEntry(2), data2->GetTypeEntries()[1]->GetEntry(2));
+}
+
+TEST(BinaryStreamVisitorTests, CreateIdmapFromApkAssetsInteropWithLoadedIdmap) {
+  const std::string target_apk_path(GetTestDataPath() + "/target/target.apk");
+  std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
+  ASSERT_THAT(target_apk, NotNull());
+
+  const std::string overlay_apk_path(GetTestDataPath() + "/overlay/overlay.apk");
+  std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
+  ASSERT_THAT(overlay_apk, NotNull());
+
+  std::stringstream error;
+  std::unique_ptr<const Idmap> idmap =
+      Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk, error);
+  ASSERT_THAT(idmap, NotNull());
+
+  std::stringstream stream;
+  BinaryStreamVisitor visitor(stream);
+  idmap->accept(&visitor);
+  const std::string str = stream.str();
+  const StringPiece data(str);
+  std::unique_ptr<const LoadedIdmap> loaded_idmap = LoadedIdmap::Load(data);
+  ASSERT_THAT(loaded_idmap, NotNull());
+  ASSERT_EQ(loaded_idmap->TargetPackageId(), 0x7f);
+
+  const IdmapEntry_header* header = loaded_idmap->GetEntryMapForType(0x01);
+  ASSERT_THAT(header, NotNull());
+
+  EntryId entry;
+  bool success = LoadedIdmap::Lookup(header, 0x0000, &entry);
+  ASSERT_TRUE(success);
+  ASSERT_EQ(entry, 0x0000);
+
+  header = loaded_idmap->GetEntryMapForType(0x02);
+  ASSERT_THAT(header, NotNull());
+
+  success = LoadedIdmap::Lookup(header, 0x0002, &entry);
+  ASSERT_FALSE(success);
+
+  success = LoadedIdmap::Lookup(header, 0x0003, &entry);
+  ASSERT_TRUE(success);
+  ASSERT_EQ(entry, 0x0000);
+
+  success = LoadedIdmap::Lookup(header, 0x0004, &entry);
+  ASSERT_FALSE(success);
+
+  success = LoadedIdmap::Lookup(header, 0x0005, &entry);
+  ASSERT_TRUE(success);
+  ASSERT_EQ(entry, 0x0001);
+
+  success = LoadedIdmap::Lookup(header, 0x0006, &entry);
+  ASSERT_TRUE(success);
+  ASSERT_EQ(entry, 0x0002);
+
+  success = LoadedIdmap::Lookup(header, 0x0007, &entry);
+  ASSERT_FALSE(success);
+}
+
+}  // namespace idmap2
+}  // namespace android
diff --git a/cmds/idmap2/tests/CommandLineOptionsTests.cpp b/cmds/idmap2/tests/CommandLineOptionsTests.cpp
new file mode 100644
index 0000000..b04b256
--- /dev/null
+++ b/cmds/idmap2/tests/CommandLineOptionsTests.cpp
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <fstream>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#include "android-base/file.h"
+#include "androidfw/ApkAssets.h"
+#include "androidfw/Idmap.h"
+#include "androidfw/LoadedArsc.h"
+
+#include "idmap2/CommandLineOptions.h"
+#include "idmap2/Idmap.h"
+
+#include "TestHelpers.h"
+
+using ::testing::NotNull;
+
+namespace android {
+namespace idmap2 {
+
+TEST(CommandLineOptionsTests, Flag) {
+  bool foo = true, bar = false;
+
+  CommandLineOptions opts =
+      CommandLineOptions("test").OptionalFlag("--foo", "", &foo).OptionalFlag("--bar", "", &bar);
+
+  std::ostream fakeStdErr(nullptr);
+  bool success = opts.Parse({"--foo", "--bar"}, fakeStdErr);
+  ASSERT_TRUE(success);
+  ASSERT_TRUE(foo);
+  ASSERT_TRUE(bar);
+
+  foo = bar = false;
+  success = opts.Parse({"--foo"}, fakeStdErr);
+  ASSERT_TRUE(success);
+  ASSERT_TRUE(foo);
+  ASSERT_FALSE(bar);
+}
+
+TEST(CommandLineOptionsTests, MandatoryOption) {
+  std::string foo, bar;
+  CommandLineOptions opts = CommandLineOptions("test")
+                                .MandatoryOption("--foo", "", &foo)
+                                .MandatoryOption("--bar", "", &bar);
+  std::ostream fakeStdErr(nullptr);
+  bool success = opts.Parse({"--foo", "FOO", "--bar", "BAR"}, fakeStdErr);
+  ASSERT_TRUE(success);
+  ASSERT_EQ(foo, "FOO");
+  ASSERT_EQ(bar, "BAR");
+
+  success = opts.Parse({"--foo"}, fakeStdErr);
+  ASSERT_FALSE(success);
+}
+
+TEST(CommandLineOptionsTests, MandatoryOptionMultipleArgsButExpectedOnce) {
+  std::string foo;
+  CommandLineOptions opts = CommandLineOptions("test").MandatoryOption("--foo", "", &foo);
+  std::ostream fakeStdErr(nullptr);
+  bool success = opts.Parse({"--foo", "FIRST", "--foo", "SECOND"}, fakeStdErr);
+  ASSERT_TRUE(success);
+  ASSERT_EQ(foo, "SECOND");
+}
+
+TEST(CommandLineOptionsTests, MandatoryOptionMultipleArgsAndExpectedOnceOrMore) {
+  std::vector<std::string> args;
+  CommandLineOptions opts = CommandLineOptions("test").MandatoryOption("--foo", "", &args);
+  std::ostream fakeStdErr(nullptr);
+  bool success = opts.Parse({"--foo", "FOO", "--foo", "BAR"}, fakeStdErr);
+  ASSERT_TRUE(success);
+  ASSERT_EQ(args.size(), 2u);
+  ASSERT_EQ(args[0], "FOO");
+  ASSERT_EQ(args[1], "BAR");
+}
+
+TEST(CommandLineOptionsTests, OptionalOption) {
+  std::string foo, bar;
+  CommandLineOptions opts = CommandLineOptions("test")
+                                .OptionalOption("--foo", "", &foo)
+                                .OptionalOption("--bar", "", &bar);
+  std::ostream fakeStdErr(nullptr);
+  bool success = opts.Parse({"--foo", "FOO", "--bar", "BAR"}, fakeStdErr);
+  ASSERT_TRUE(success);
+  ASSERT_EQ(foo, "FOO");
+  ASSERT_EQ(bar, "BAR");
+
+  success = opts.Parse({"--foo", "BAZ"}, fakeStdErr);
+  ASSERT_TRUE(success);
+  ASSERT_EQ(foo, "BAZ");
+
+  success = opts.Parse({"--foo"}, fakeStdErr);
+  ASSERT_FALSE(success);
+
+  success = opts.Parse({"--foo", "--bar", "BAR"}, fakeStdErr);
+  ASSERT_FALSE(success);
+
+  success = opts.Parse({"--foo", "FOO", "--bar"}, fakeStdErr);
+  ASSERT_FALSE(success);
+}
+
+TEST(CommandLineOptionsTests, CornerCases) {
+  std::string foo, bar;
+  bool baz = false;
+  CommandLineOptions opts = CommandLineOptions("test")
+                                .MandatoryOption("--foo", "", &foo)
+                                .OptionalFlag("--baz", "", &baz)
+                                .OptionalOption("--bar", "", &bar);
+  std::ostream fakeStdErr(nullptr);
+  bool success = opts.Parse({"--unexpected"}, fakeStdErr);
+  ASSERT_FALSE(success);
+
+  success = opts.Parse({"--bar", "BAR"}, fakeStdErr);
+  ASSERT_FALSE(success);
+
+  success = opts.Parse({"--baz", "--foo", "FOO"}, fakeStdErr);
+  ASSERT_TRUE(success);
+  ASSERT_TRUE(baz);
+  ASSERT_EQ(foo, "FOO");
+}
+
+TEST(CommandLineOptionsTests, ConvertArgvToVector) {
+  const char* argv[] = {
+      "program-name",
+      "--foo",
+      "FOO",
+      nullptr,
+  };
+  std::unique_ptr<std::vector<std::string>> v = CommandLineOptions::ConvertArgvToVector(3, argv);
+  ASSERT_EQ(v->size(), 2ul);
+  ASSERT_EQ((*v)[0], "--foo");
+  ASSERT_EQ((*v)[1], "FOO");
+}
+
+TEST(CommandLineOptionsTests, ConvertArgvToVectorNoArgs) {
+  const char* argv[] = {
+      "program-name",
+      nullptr,
+  };
+  std::unique_ptr<std::vector<std::string>> v = CommandLineOptions::ConvertArgvToVector(1, argv);
+  ASSERT_EQ(v->size(), 0ul);
+}
+
+TEST(CommandLineOptionsTests, Usage) {
+  std::string arg1, arg2, arg3, arg4;
+  bool arg5 = false, arg6 = false;
+  std::vector<std::string> arg7;
+  CommandLineOptions opts = CommandLineOptions("test")
+                                .MandatoryOption("--aa", "description-aa", &arg1)
+                                .OptionalFlag("--bb", "description-bb", &arg5)
+                                .OptionalOption("--cc", "description-cc", &arg2)
+                                .OptionalOption("--dd", "description-dd", &arg3)
+                                .MandatoryOption("--ee", "description-ee", &arg4)
+                                .OptionalFlag("--ff", "description-ff", &arg6)
+                                .MandatoryOption("--gg", "description-gg", &arg7);
+  std::stringstream stream;
+  opts.Usage(stream);
+  const std::string s = stream.str();
+  ASSERT_NE(s.find("usage: test --aa arg [--bb] [--cc arg] [--dd arg] --ee arg [--ff] --gg arg "
+                   "[--gg arg [..]]"),
+            std::string::npos);
+  ASSERT_NE(s.find("--aa arg    description-aa"), std::string::npos);
+  ASSERT_NE(s.find("--ff        description-ff"), std::string::npos);
+  ASSERT_NE(s.find("--gg arg    description-gg (can be provided multiple times)"),
+            std::string::npos);
+}
+
+}  // namespace idmap2
+}  // namespace android
diff --git a/cmds/idmap2/tests/FileUtilsTests.cpp b/cmds/idmap2/tests/FileUtilsTests.cpp
new file mode 100644
index 0000000..0c6439a
--- /dev/null
+++ b/cmds/idmap2/tests/FileUtilsTests.cpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dirent.h>
+#include <set>
+#include <string>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#include "android-base/macros.h"
+
+#include "idmap2/FileUtils.h"
+
+#include "TestHelpers.h"
+
+using ::testing::NotNull;
+
+namespace android {
+namespace idmap2 {
+namespace utils {
+
+TEST(FileUtilsTests, FindFilesFindEverythingNonRecursive) {
+  const auto& root = GetTestDataPath();
+  auto v = utils::FindFiles(root, false,
+                            [](unsigned char type ATTRIBUTE_UNUSED,
+                               const std::string& path ATTRIBUTE_UNUSED) -> bool { return true; });
+  ASSERT_THAT(v, NotNull());
+  ASSERT_EQ(v->size(), 4u);
+  ASSERT_EQ(
+      std::set<std::string>(v->begin(), v->end()),
+      std::set<std::string>({root + "/.", root + "/..", root + "/overlay", root + "/target"}));
+}
+
+TEST(FileUtilsTests, FindFilesFindApkFilesRecursive) {
+  const auto& root = GetTestDataPath();
+  auto v = utils::FindFiles(root, true, [](unsigned char type, const std::string& path) -> bool {
+    return type == DT_REG && path.size() > 4 && !path.compare(path.size() - 4, 4, ".apk");
+  });
+  ASSERT_THAT(v, NotNull());
+  ASSERT_EQ(v->size(), 4u);
+  ASSERT_EQ(std::set<std::string>(v->begin(), v->end()),
+            std::set<std::string>({root + "/target/target.apk", root + "/overlay/overlay.apk",
+                                   root + "/overlay/overlay-static-1.apk",
+                                   root + "/overlay/overlay-static-2.apk"}));
+}
+
+TEST(FileUtilsTests, ReadFile) {
+  int pipefd[2];
+  ASSERT_EQ(pipe(pipefd), 0);
+
+  ASSERT_EQ(write(pipefd[1], "foobar", 6), 6);
+  close(pipefd[1]);
+
+  auto data = ReadFile(pipefd[0]);
+  ASSERT_THAT(data, NotNull());
+  ASSERT_EQ(*data, "foobar");
+  close(pipefd[0]);
+}
+
+}  // namespace utils
+}  // namespace idmap2
+}  // namespace android
diff --git a/cmds/idmap2/tests/Idmap2BinaryTests.cpp b/cmds/idmap2/tests/Idmap2BinaryTests.cpp
new file mode 100644
index 0000000..5c4e857
--- /dev/null
+++ b/cmds/idmap2/tests/Idmap2BinaryTests.cpp
@@ -0,0 +1,313 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * The tests in this file operate on a higher level than the tests in the other
+ * files. Here, all tests execute the idmap2 binary and only depend on
+ * libidmap2 to verify the output of idmap2.
+ */
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <cerrno>
+#include <cstdlib>
+#include <cstring>  // strerror
+#include <fstream>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#include "androidfw/PosixUtils.h"
+#include "idmap2/FileUtils.h"
+#include "idmap2/Idmap.h"
+
+#include "TestHelpers.h"
+
+using ::android::util::ExecuteBinary;
+using ::testing::NotNull;
+
+namespace android {
+namespace idmap2 {
+
+class Idmap2BinaryTests : public Idmap2Tests {};
+
+static void AssertIdmap(const Idmap& idmap, const std::string& target_apk_path,
+                        const std::string& overlay_apk_path) {
+  // check that the idmap file looks reasonable (IdmapTests is responsible for
+  // more in-depth verification)
+  ASSERT_EQ(idmap.GetHeader()->GetMagic(), kIdmapMagic);
+  ASSERT_EQ(idmap.GetHeader()->GetVersion(), kIdmapCurrentVersion);
+  ASSERT_EQ(idmap.GetHeader()->GetTargetPath(), target_apk_path);
+  ASSERT_EQ(idmap.GetHeader()->GetOverlayPath(), overlay_apk_path);
+  ASSERT_EQ(idmap.GetData().size(), 1u);
+}
+
+#define ASSERT_IDMAP(idmap_ref, target_apk_path, overlay_apk_path)                      \
+  do {                                                                                  \
+    ASSERT_NO_FATAL_FAILURE(AssertIdmap(idmap_ref, target_apk_path, overlay_apk_path)); \
+  } while (0)
+
+TEST_F(Idmap2BinaryTests, Create) {
+  // clang-format off
+  auto result = ExecuteBinary({"idmap2",
+                               "create",
+                               "--target-apk-path", GetTargetApkPath(),
+                               "--overlay-apk-path", GetOverlayApkPath(),
+                               "--idmap-path", GetIdmapPath()});
+  // clang-format on
+  ASSERT_THAT(result, NotNull());
+  ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
+
+  struct stat st;
+  ASSERT_EQ(stat(GetIdmapPath().c_str(), &st), 0);
+
+  std::stringstream error;
+  std::ifstream fin(GetIdmapPath());
+  std::unique_ptr<const Idmap> idmap = Idmap::FromBinaryStream(fin, error);
+  fin.close();
+
+  ASSERT_THAT(idmap, NotNull());
+  ASSERT_IDMAP(*idmap, GetTargetApkPath(), GetOverlayApkPath());
+
+  unlink(GetIdmapPath().c_str());
+}
+
+TEST_F(Idmap2BinaryTests, Dump) {
+  // clang-format off
+  auto result = ExecuteBinary({"idmap2",
+                               "create",
+                               "--target-apk-path", GetTargetApkPath(),
+                               "--overlay-apk-path", GetOverlayApkPath(),
+                               "--idmap-path", GetIdmapPath()});
+  // clang-format on
+  ASSERT_THAT(result, NotNull());
+  ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
+
+  // clang-format off
+  result = ExecuteBinary({"idmap2",
+                          "dump",
+                          "--idmap-path", GetIdmapPath()});
+  // clang-format on
+  ASSERT_THAT(result, NotNull());
+  ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
+  ASSERT_NE(result->stdout.find("0x7f010000 -> 0x7f010000 integer/int1"), std::string::npos);
+  ASSERT_NE(result->stdout.find("0x7f020003 -> 0x7f020000 string/str1"), std::string::npos);
+  ASSERT_NE(result->stdout.find("0x7f020005 -> 0x7f020001 string/str3"), std::string::npos);
+  ASSERT_EQ(result->stdout.find("00000210:     007f  target package id"), std::string::npos);
+
+  // clang-format off
+  result = ExecuteBinary({"idmap2",
+                          "dump",
+                          "--verbose",
+                          "--idmap-path", GetIdmapPath()});
+  // clang-format on
+  ASSERT_THAT(result, NotNull());
+  ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
+  ASSERT_NE(result->stdout.find("00000000: 504d4449  magic"), std::string::npos);
+  ASSERT_NE(result->stdout.find("00000210:     007f  target package id"), std::string::npos);
+
+  // clang-format off
+  result = ExecuteBinary({"idmap2",
+                          "dump",
+                          "--verbose",
+                          "--idmap-path", GetTestDataPath() + "/DOES-NOT-EXIST"});
+  // clang-format on
+  ASSERT_THAT(result, NotNull());
+  ASSERT_NE(result->status, EXIT_SUCCESS);
+
+  unlink(GetIdmapPath().c_str());
+}
+
+TEST_F(Idmap2BinaryTests, Scan) {
+  const std::string overlay_static_1_apk_path = GetTestDataPath() + "/overlay/overlay-static-1.apk";
+  const std::string overlay_static_2_apk_path = GetTestDataPath() + "/overlay/overlay-static-2.apk";
+  const std::string idmap_static_1_path =
+      Idmap::CanonicalIdmapPathFor(GetTempDirPath(), overlay_static_1_apk_path);
+  const std::string idmap_static_2_path =
+      Idmap::CanonicalIdmapPathFor(GetTempDirPath(), overlay_static_2_apk_path);
+
+  // single input directory, recursive
+  // clang-format off
+  auto result = ExecuteBinary({"idmap2",
+                               "scan",
+                               "--input-directory", GetTestDataPath(),
+                               "--recursive",
+                               "--target-package-name", "test.target",
+                               "--target-apk-path", GetTargetApkPath(),
+                               "--output-directory", GetTempDirPath()});
+  // clang-format on
+  ASSERT_THAT(result, NotNull());
+  ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
+  std::stringstream expected;
+  expected << idmap_static_1_path << std::endl;
+  expected << idmap_static_2_path << std::endl;
+  ASSERT_EQ(result->stdout, expected.str());
+
+  std::stringstream error;
+  auto idmap_static_1_raw_string = utils::ReadFile(idmap_static_1_path);
+  auto idmap_static_1_raw_stream = std::istringstream(*idmap_static_1_raw_string);
+  auto idmap_static_1 = Idmap::FromBinaryStream(idmap_static_1_raw_stream, error);
+  ASSERT_THAT(idmap_static_1, NotNull());
+  ASSERT_IDMAP(*idmap_static_1, GetTargetApkPath(), overlay_static_1_apk_path);
+
+  auto idmap_static_2_raw_string = utils::ReadFile(idmap_static_2_path);
+  auto idmap_static_2_raw_stream = std::istringstream(*idmap_static_2_raw_string);
+  auto idmap_static_2 = Idmap::FromBinaryStream(idmap_static_2_raw_stream, error);
+  ASSERT_THAT(idmap_static_2, NotNull());
+  ASSERT_IDMAP(*idmap_static_2, GetTargetApkPath(), overlay_static_2_apk_path);
+
+  unlink(idmap_static_2_path.c_str());
+  unlink(idmap_static_1_path.c_str());
+
+  // multiple input directories, non-recursive
+  // clang-format off
+  result = ExecuteBinary({"idmap2",
+                          "scan",
+                          "--input-directory", GetTestDataPath() + "/target",
+                          "--input-directory", GetTestDataPath() + "/overlay",
+                          "--target-package-name", "test.target",
+                          "--target-apk-path", GetTargetApkPath(),
+                          "--output-directory", GetTempDirPath()});
+  // clang-format on
+  ASSERT_THAT(result, NotNull());
+  ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
+  ASSERT_EQ(result->stdout, expected.str());
+  unlink(idmap_static_2_path.c_str());
+  unlink(idmap_static_1_path.c_str());
+
+  // the same input directory given twice, but no duplicate entries
+  // clang-format off
+  result = ExecuteBinary({"idmap2",
+                          "scan",
+                          "--input-directory", GetTestDataPath(),
+                          "--input-directory", GetTestDataPath(),
+                          "--recursive",
+                          "--target-package-name", "test.target",
+                          "--target-apk-path", GetTargetApkPath(),
+                          "--output-directory", GetTempDirPath()});
+  // clang-format on
+  ASSERT_THAT(result, NotNull());
+  ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
+  ASSERT_EQ(result->stdout, expected.str());
+  unlink(idmap_static_2_path.c_str());
+  unlink(idmap_static_1_path.c_str());
+
+  // no APKs in input-directory: ok, but no output
+  // clang-format off
+  result = ExecuteBinary({"idmap2",
+                          "scan",
+                          "--input-directory", GetTempDirPath(),
+                          "--target-package-name", "test.target",
+                          "--target-apk-path", GetTargetApkPath(),
+                          "--output-directory", GetTempDirPath()});
+  // clang-format on
+  ASSERT_THAT(result, NotNull());
+  ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
+  ASSERT_EQ(result->stdout, "");
+}
+
+TEST_F(Idmap2BinaryTests, Lookup) {
+  // clang-format off
+  auto result = ExecuteBinary({"idmap2",
+                               "create",
+                               "--target-apk-path", GetTargetApkPath(),
+                               "--overlay-apk-path", GetOverlayApkPath(),
+                               "--idmap-path", GetIdmapPath()});
+  // clang-format on
+  ASSERT_THAT(result, NotNull());
+  ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
+
+  // clang-format off
+  result = ExecuteBinary({"idmap2",
+                          "lookup",
+                          "--idmap-path", GetIdmapPath(),
+                          "--config", "",
+                          "--resid", "0x7f020003"});  // string/str1
+  // clang-format on
+  ASSERT_THAT(result, NotNull());
+  ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
+  ASSERT_NE(result->stdout.find("overlay-1"), std::string::npos);
+  ASSERT_EQ(result->stdout.find("overlay-1-sv"), std::string::npos);
+
+  // clang-format off
+  result = ExecuteBinary({"idmap2",
+                          "lookup",
+                          "--idmap-path", GetIdmapPath(),
+                          "--config", "",
+                          "--resid", "test.target:string/str1"});
+  // clang-format on
+  ASSERT_THAT(result, NotNull());
+  ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
+  ASSERT_NE(result->stdout.find("overlay-1"), std::string::npos);
+  ASSERT_EQ(result->stdout.find("overlay-1-sv"), std::string::npos);
+
+  // clang-format off
+  result = ExecuteBinary({"idmap2",
+                          "lookup",
+                          "--idmap-path", GetIdmapPath(),
+                          "--config", "sv",
+                          "--resid", "test.target:string/str1"});
+  // clang-format on
+  ASSERT_THAT(result, NotNull());
+  ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
+  ASSERT_NE(result->stdout.find("overlay-1-sv"), std::string::npos);
+
+  unlink(GetIdmapPath().c_str());
+}
+
+TEST_F(Idmap2BinaryTests, InvalidCommandLineOptions) {
+  const std::string invalid_target_apk_path = GetTestDataPath() + "/DOES-NOT-EXIST";
+
+  // missing mandatory options
+  // clang-format off
+  auto result = ExecuteBinary({"idmap2",
+                               "create"});
+  // clang-format on
+  ASSERT_THAT(result, NotNull());
+  ASSERT_NE(result->status, EXIT_SUCCESS);
+
+  // missing argument to option
+  // clang-format off
+  result = ExecuteBinary({"idmap2",
+                          "create",
+                          "--target-apk-path", GetTargetApkPath(),
+                          "--overlay-apk-path", GetOverlayApkPath(),
+                          "--idmap-path"});
+  // clang-format on
+  ASSERT_THAT(result, NotNull());
+  ASSERT_NE(result->status, EXIT_SUCCESS);
+
+  // invalid target apk path
+  // clang-format off
+  result = ExecuteBinary({"idmap2",
+                          "create",
+                          "--target-apk-path", invalid_target_apk_path,
+                          "--overlay-apk-path", GetOverlayApkPath(),
+                          "--idmap-path", GetIdmapPath()});
+  // clang-format on
+  ASSERT_THAT(result, NotNull());
+  ASSERT_NE(result->status, EXIT_SUCCESS);
+}
+
+}  // namespace idmap2
+}  // namespace android
diff --git a/cmds/idmap2/tests/IdmapTests.cpp b/cmds/idmap2/tests/IdmapTests.cpp
new file mode 100644
index 0000000..0379aa4
--- /dev/null
+++ b/cmds/idmap2/tests/IdmapTests.cpp
@@ -0,0 +1,395 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cstdio>  // fclose
+
+#include <fstream>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#include "android-base/macros.h"
+#include "androidfw/ApkAssets.h"
+
+#include "idmap2/BinaryStreamVisitor.h"
+#include "idmap2/CommandLineOptions.h"
+#include "idmap2/Idmap.h"
+
+#include "TestHelpers.h"
+
+using ::testing::IsNull;
+using ::testing::NotNull;
+
+namespace android {
+namespace idmap2 {
+
+TEST(IdmapTests, TestCanonicalIdmapPathFor) {
+  ASSERT_EQ(Idmap::CanonicalIdmapPathFor("/foo", "/vendor/overlay/bar.apk"),
+            "/foo/vendor@overlay@bar.apk@idmap");
+}
+
+TEST(IdmapTests, CreateIdmapHeaderFromBinaryStream) {
+  std::string raw(reinterpret_cast<const char*>(idmap_raw_data), idmap_raw_data_len);
+  std::istringstream stream(raw);
+  std::unique_ptr<const IdmapHeader> header = IdmapHeader::FromBinaryStream(stream);
+  ASSERT_THAT(header, NotNull());
+  ASSERT_EQ(header->GetMagic(), 0x504d4449u);
+  ASSERT_EQ(header->GetVersion(), 0x01u);
+  ASSERT_EQ(header->GetTargetCrc(), 0x1234u);
+  ASSERT_EQ(header->GetOverlayCrc(), 0x5678u);
+  ASSERT_EQ(header->GetTargetPath().to_string(), "target.apk");
+  ASSERT_EQ(header->GetOverlayPath().to_string(), "overlay.apk");
+}
+
+TEST(IdmapTests, FailToCreateIdmapHeaderFromBinaryStreamIfPathTooLong) {
+  std::string raw(reinterpret_cast<const char*>(idmap_raw_data), idmap_raw_data_len);
+  // overwrite the target path string, including the terminating null, with '.'
+  for (size_t i = 0x10; i < 0x110; i++) {
+    raw[i] = '.';
+  }
+  std::istringstream stream(raw);
+  std::unique_ptr<const IdmapHeader> header = IdmapHeader::FromBinaryStream(stream);
+  ASSERT_THAT(header, IsNull());
+}
+
+TEST(IdmapTests, CreateIdmapDataHeaderFromBinaryStream) {
+  const size_t offset = 0x210;
+  std::string raw(reinterpret_cast<const char*>(idmap_raw_data + offset),
+                  idmap_raw_data_len - offset);
+  std::istringstream stream(raw);
+
+  std::unique_ptr<const IdmapData::Header> header = IdmapData::Header::FromBinaryStream(stream);
+  ASSERT_THAT(header, NotNull());
+  ASSERT_EQ(header->GetTargetPackageId(), 0x7fu);
+  ASSERT_EQ(header->GetTypeCount(), 2u);
+}
+
+TEST(IdmapTests, CreateIdmapDataResourceTypeFromBinaryStream) {
+  const size_t offset = 0x214;
+  std::string raw(reinterpret_cast<const char*>(idmap_raw_data + offset),
+                  idmap_raw_data_len - offset);
+  std::istringstream stream(raw);
+
+  std::unique_ptr<const IdmapData::TypeEntry> data = IdmapData::TypeEntry::FromBinaryStream(stream);
+  ASSERT_THAT(data, NotNull());
+  ASSERT_EQ(data->GetTargetTypeId(), 0x02u);
+  ASSERT_EQ(data->GetOverlayTypeId(), 0x02u);
+  ASSERT_EQ(data->GetEntryCount(), 1u);
+  ASSERT_EQ(data->GetEntryOffset(), 0u);
+  ASSERT_EQ(data->GetEntry(0), 0u);
+}
+
+TEST(IdmapTests, CreateIdmapDataFromBinaryStream) {
+  const size_t offset = 0x210;
+  std::string raw(reinterpret_cast<const char*>(idmap_raw_data + offset),
+                  idmap_raw_data_len - offset);
+  std::istringstream stream(raw);
+
+  std::unique_ptr<const IdmapData> data = IdmapData::FromBinaryStream(stream);
+  ASSERT_THAT(data, NotNull());
+  ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fu);
+  ASSERT_EQ(data->GetHeader()->GetTypeCount(), 2u);
+  const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
+  ASSERT_EQ(types.size(), 2u);
+
+  ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02u);
+  ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x02u);
+  ASSERT_EQ(types[0]->GetEntryCount(), 1u);
+  ASSERT_EQ(types[0]->GetEntryOffset(), 0u);
+  ASSERT_EQ(types[0]->GetEntry(0), 0x0000u);
+
+  ASSERT_EQ(types[1]->GetTargetTypeId(), 0x03u);
+  ASSERT_EQ(types[1]->GetOverlayTypeId(), 0x03u);
+  ASSERT_EQ(types[1]->GetEntryCount(), 3u);
+  ASSERT_EQ(types[1]->GetEntryOffset(), 3u);
+  ASSERT_EQ(types[1]->GetEntry(0), 0x0000u);
+  ASSERT_EQ(types[1]->GetEntry(1), kNoEntry);
+  ASSERT_EQ(types[1]->GetEntry(2), 0x0001u);
+}
+
+TEST(IdmapTests, CreateIdmapFromBinaryStream) {
+  std::string raw(reinterpret_cast<const char*>(idmap_raw_data), idmap_raw_data_len);
+  std::istringstream stream(raw);
+
+  std::stringstream error;
+  std::unique_ptr<const Idmap> idmap = Idmap::FromBinaryStream(stream, error);
+  ASSERT_THAT(idmap, NotNull());
+
+  ASSERT_THAT(idmap->GetHeader(), NotNull());
+  ASSERT_EQ(idmap->GetHeader()->GetMagic(), 0x504d4449u);
+  ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x01u);
+  ASSERT_EQ(idmap->GetHeader()->GetTargetCrc(), 0x1234u);
+  ASSERT_EQ(idmap->GetHeader()->GetOverlayCrc(), 0x5678u);
+  ASSERT_EQ(idmap->GetHeader()->GetTargetPath().to_string(), "target.apk");
+  ASSERT_EQ(idmap->GetHeader()->GetOverlayPath().to_string(), "overlay.apk");
+
+  const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
+  ASSERT_EQ(dataBlocks.size(), 1u);
+
+  const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
+  ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fu);
+  ASSERT_EQ(data->GetHeader()->GetTypeCount(), 2u);
+  const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
+  ASSERT_EQ(types.size(), 2u);
+
+  ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02u);
+  ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x02u);
+  ASSERT_EQ(types[0]->GetEntryCount(), 1u);
+  ASSERT_EQ(types[0]->GetEntryOffset(), 0u);
+  ASSERT_EQ(types[0]->GetEntry(0), 0x0000u);
+
+  ASSERT_EQ(types[1]->GetTargetTypeId(), 0x03u);
+  ASSERT_EQ(types[1]->GetOverlayTypeId(), 0x03u);
+  ASSERT_EQ(types[1]->GetEntryCount(), 3u);
+  ASSERT_EQ(types[1]->GetEntryOffset(), 3u);
+  ASSERT_EQ(types[1]->GetEntry(0), 0x0000u);
+  ASSERT_EQ(types[1]->GetEntry(1), kNoEntry);
+  ASSERT_EQ(types[1]->GetEntry(2), 0x0001u);
+}
+
+TEST(IdmapTests, GracefullyFailToCreateIdmapFromCorruptBinaryStream) {
+  std::string raw(reinterpret_cast<const char*>(idmap_raw_data),
+                  10);  // data too small
+  std::istringstream stream(raw);
+
+  std::stringstream error;
+  std::unique_ptr<const Idmap> idmap = Idmap::FromBinaryStream(stream, error);
+  ASSERT_THAT(idmap, IsNull());
+}
+
+TEST(IdmapTests, CreateIdmapFromApkAssets) {
+  const std::string target_apk_path(GetTestDataPath() + "/target/target.apk");
+  std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
+  ASSERT_THAT(target_apk, NotNull());
+
+  const std::string overlay_apk_path(GetTestDataPath() + "/overlay/overlay.apk");
+  std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
+  ASSERT_THAT(overlay_apk, NotNull());
+
+  std::stringstream error;
+  std::unique_ptr<const Idmap> idmap =
+      Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk, error);
+  ASSERT_THAT(idmap, NotNull());
+
+  ASSERT_THAT(idmap->GetHeader(), NotNull());
+  ASSERT_EQ(idmap->GetHeader()->GetMagic(), 0x504d4449u);
+  ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x01u);
+  ASSERT_EQ(idmap->GetHeader()->GetTargetCrc(), 0xf5ad1d1d);
+  ASSERT_EQ(idmap->GetHeader()->GetOverlayCrc(), 0xd470336b);
+  ASSERT_EQ(idmap->GetHeader()->GetTargetPath().to_string(), target_apk_path);
+  ASSERT_EQ(idmap->GetHeader()->GetOverlayPath(), overlay_apk_path);
+  ASSERT_EQ(idmap->GetHeader()->GetOverlayPath(), overlay_apk_path);
+
+  const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
+  ASSERT_EQ(dataBlocks.size(), 1u);
+
+  const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
+
+  ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fu);
+  ASSERT_EQ(data->GetHeader()->GetTypeCount(), 2u);
+
+  const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
+  ASSERT_EQ(types.size(), 2u);
+
+  ASSERT_EQ(types[0]->GetTargetTypeId(), 0x01u);
+  ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01u);
+  ASSERT_EQ(types[0]->GetEntryCount(), 1u);
+  ASSERT_EQ(types[0]->GetEntryOffset(), 0u);
+  ASSERT_EQ(types[0]->GetEntry(0), 0x0000u);
+
+  ASSERT_EQ(types[1]->GetTargetTypeId(), 0x02u);
+  ASSERT_EQ(types[1]->GetOverlayTypeId(), 0x02u);
+  ASSERT_EQ(types[1]->GetEntryCount(), 4u);
+  ASSERT_EQ(types[1]->GetEntryOffset(), 3u);
+  ASSERT_EQ(types[1]->GetEntry(0), 0x0000u);
+  ASSERT_EQ(types[1]->GetEntry(1), kNoEntry);
+  ASSERT_EQ(types[1]->GetEntry(2), 0x0001u);
+  ASSERT_EQ(types[1]->GetEntry(3), 0x0002u);
+}
+
+TEST(IdmapTests, FailToCreateIdmapFromApkAssetsIfPathTooLong) {
+  std::string target_apk_path(GetTestDataPath());
+  for (int i = 0; i < 32; i++) {
+    target_apk_path += "/target/../";
+  }
+  target_apk_path += "/target/target.apk";
+  ASSERT_GT(target_apk_path.size(), kIdmapStringLength);
+  std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
+  ASSERT_THAT(target_apk, NotNull());
+
+  const std::string overlay_apk_path(GetTestDataPath() + "/overlay/overlay.apk");
+  std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
+  ASSERT_THAT(overlay_apk, NotNull());
+
+  std::stringstream error;
+  std::unique_ptr<const Idmap> idmap =
+      Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk, error);
+  ASSERT_THAT(idmap, IsNull());
+}
+
+TEST(IdmapTests, IdmapHeaderIsUpToDate) {
+  fclose(stderr);  // silence expected warnings from libandroidfw
+
+  const std::string target_apk_path(GetTestDataPath() + "/target/target.apk");
+  std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
+  ASSERT_THAT(target_apk, NotNull());
+
+  const std::string overlay_apk_path(GetTestDataPath() + "/overlay/overlay.apk");
+  std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
+  ASSERT_THAT(overlay_apk, NotNull());
+
+  std::stringstream error;
+  std::unique_ptr<const Idmap> idmap =
+      Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk, error);
+  ASSERT_THAT(idmap, NotNull());
+
+  std::stringstream stream;
+  BinaryStreamVisitor visitor(stream);
+  idmap->accept(&visitor);
+
+  std::unique_ptr<const IdmapHeader> header = IdmapHeader::FromBinaryStream(stream);
+  ASSERT_THAT(header, NotNull());
+  ASSERT_TRUE(header->IsUpToDate(error)) << error.str();
+
+  // magic: bytes (0x0, 0x03)
+  std::string bad_magic_string(stream.str());
+  bad_magic_string[0x0] = '.';
+  bad_magic_string[0x1] = '.';
+  bad_magic_string[0x2] = '.';
+  bad_magic_string[0x3] = '.';
+  std::stringstream bad_magic_stream(bad_magic_string);
+  std::unique_ptr<const IdmapHeader> bad_magic_header =
+      IdmapHeader::FromBinaryStream(bad_magic_stream);
+  ASSERT_THAT(bad_magic_header, NotNull());
+  ASSERT_NE(header->GetMagic(), bad_magic_header->GetMagic());
+  ASSERT_FALSE(bad_magic_header->IsUpToDate(error));
+
+  // version: bytes (0x4, 0x07)
+  std::string bad_version_string(stream.str());
+  bad_version_string[0x4] = '.';
+  bad_version_string[0x5] = '.';
+  bad_version_string[0x6] = '.';
+  bad_version_string[0x7] = '.';
+  std::stringstream bad_version_stream(bad_version_string);
+  std::unique_ptr<const IdmapHeader> bad_version_header =
+      IdmapHeader::FromBinaryStream(bad_version_stream);
+  ASSERT_THAT(bad_version_header, NotNull());
+  ASSERT_NE(header->GetVersion(), bad_version_header->GetVersion());
+  ASSERT_FALSE(bad_version_header->IsUpToDate(error));
+
+  // target crc: bytes (0x8, 0xb)
+  std::string bad_target_crc_string(stream.str());
+  bad_target_crc_string[0x8] = '.';
+  bad_target_crc_string[0x9] = '.';
+  bad_target_crc_string[0xa] = '.';
+  bad_target_crc_string[0xb] = '.';
+  std::stringstream bad_target_crc_stream(bad_target_crc_string);
+  std::unique_ptr<const IdmapHeader> bad_target_crc_header =
+      IdmapHeader::FromBinaryStream(bad_target_crc_stream);
+  ASSERT_THAT(bad_target_crc_header, NotNull());
+  ASSERT_NE(header->GetTargetCrc(), bad_target_crc_header->GetTargetCrc());
+  ASSERT_FALSE(bad_target_crc_header->IsUpToDate(error));
+
+  // overlay crc: bytes (0xc, 0xf)
+  std::string bad_overlay_crc_string(stream.str());
+  bad_overlay_crc_string[0xc] = '.';
+  bad_overlay_crc_string[0xd] = '.';
+  bad_overlay_crc_string[0xe] = '.';
+  bad_overlay_crc_string[0xf] = '.';
+  std::stringstream bad_overlay_crc_stream(bad_overlay_crc_string);
+  std::unique_ptr<const IdmapHeader> bad_overlay_crc_header =
+      IdmapHeader::FromBinaryStream(bad_overlay_crc_stream);
+  ASSERT_THAT(bad_overlay_crc_header, NotNull());
+  ASSERT_NE(header->GetOverlayCrc(), bad_overlay_crc_header->GetOverlayCrc());
+  ASSERT_FALSE(bad_overlay_crc_header->IsUpToDate(error));
+
+  // target path: bytes (0x10, 0x10f)
+  std::string bad_target_path_string(stream.str());
+  bad_target_path_string[0x10] = '\0';
+  std::stringstream bad_target_path_stream(bad_target_path_string);
+  std::unique_ptr<const IdmapHeader> bad_target_path_header =
+      IdmapHeader::FromBinaryStream(bad_target_path_stream);
+  ASSERT_THAT(bad_target_path_header, NotNull());
+  ASSERT_NE(header->GetTargetPath(), bad_target_path_header->GetTargetPath());
+  ASSERT_FALSE(bad_target_path_header->IsUpToDate(error));
+
+  // overlay path: bytes (0x110, 0x20f)
+  std::string bad_overlay_path_string(stream.str());
+  bad_overlay_path_string[0x110] = '\0';
+  std::stringstream bad_overlay_path_stream(bad_overlay_path_string);
+  std::unique_ptr<const IdmapHeader> bad_overlay_path_header =
+      IdmapHeader::FromBinaryStream(bad_overlay_path_stream);
+  ASSERT_THAT(bad_overlay_path_header, NotNull());
+  ASSERT_NE(header->GetOverlayPath(), bad_overlay_path_header->GetOverlayPath());
+  ASSERT_FALSE(bad_overlay_path_header->IsUpToDate(error));
+}
+
+class TestVisitor : public Visitor {
+ public:
+  explicit TestVisitor(std::ostream& stream) : stream_(stream) {
+  }
+
+  void visit(const Idmap& idmap ATTRIBUTE_UNUSED) {
+    stream_ << "TestVisitor::visit(Idmap)" << std::endl;
+  }
+
+  void visit(const IdmapHeader& idmap ATTRIBUTE_UNUSED) {
+    stream_ << "TestVisitor::visit(IdmapHeader)" << std::endl;
+  }
+
+  void visit(const IdmapData& idmap ATTRIBUTE_UNUSED) {
+    stream_ << "TestVisitor::visit(IdmapData)" << std::endl;
+  }
+
+  void visit(const IdmapData::Header& idmap ATTRIBUTE_UNUSED) {
+    stream_ << "TestVisitor::visit(IdmapData::Header)" << std::endl;
+  }
+
+  void visit(const IdmapData::TypeEntry& idmap ATTRIBUTE_UNUSED) {
+    stream_ << "TestVisitor::visit(IdmapData::TypeEntry)" << std::endl;
+  }
+
+ private:
+  std::ostream& stream_;
+};
+
+TEST(IdmapTests, TestVisitor) {
+  std::string raw(reinterpret_cast<const char*>(idmap_raw_data), idmap_raw_data_len);
+  std::istringstream stream(raw);
+
+  std::stringstream error;
+  std::unique_ptr<const Idmap> idmap = Idmap::FromBinaryStream(stream, error);
+  ASSERT_THAT(idmap, NotNull());
+
+  std::stringstream test_stream;
+  TestVisitor visitor(test_stream);
+  idmap->accept(&visitor);
+
+  ASSERT_EQ(test_stream.str(),
+            "TestVisitor::visit(Idmap)\n"
+            "TestVisitor::visit(IdmapHeader)\n"
+            "TestVisitor::visit(IdmapData)\n"
+            "TestVisitor::visit(IdmapData::Header)\n"
+            "TestVisitor::visit(IdmapData::TypeEntry)\n"
+            "TestVisitor::visit(IdmapData::TypeEntry)\n");
+}
+
+}  // namespace idmap2
+}  // namespace android
diff --git a/cmds/idmap2/tests/Main.cpp b/cmds/idmap2/tests/Main.cpp
new file mode 100644
index 0000000..f2469ea
--- /dev/null
+++ b/cmds/idmap2/tests/Main.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <string>
+
+#include "android-base/file.h"
+
+#include "gtest/gtest.h"
+
+#include "TestHelpers.h"
+
+namespace android {
+namespace idmap2 {
+
+const std::string GetTestDataPath() {
+  return base::GetExecutableDirectory() + "/tests/data";
+}
+
+}  // namespace idmap2
+}  // namespace android
+
+int main(int argc, char** argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
diff --git a/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp b/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp
new file mode 100644
index 0000000..da97792
--- /dev/null
+++ b/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <memory>
+#include <sstream>
+#include <string>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#include "androidfw/ApkAssets.h"
+#include "androidfw/Idmap.h"
+
+#include "idmap2/Idmap.h"
+#include "idmap2/PrettyPrintVisitor.h"
+
+#include "TestHelpers.h"
+
+using ::testing::IsNull;
+using ::testing::NotNull;
+
+using android::ApkAssets;
+
+namespace android {
+namespace idmap2 {
+
+TEST(PrettyPrintVisitorTests, CreatePrettyPrintVisitor) {
+  const std::string target_apk_path(GetTestDataPath() + "/target/target.apk");
+  std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
+  ASSERT_THAT(target_apk, NotNull());
+
+  const std::string overlay_apk_path(GetTestDataPath() + "/overlay/overlay.apk");
+  std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
+  ASSERT_THAT(overlay_apk, NotNull());
+
+  std::stringstream error;
+  std::unique_ptr<const Idmap> idmap =
+      Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk, error);
+  ASSERT_THAT(idmap, NotNull());
+
+  std::stringstream stream;
+  PrettyPrintVisitor visitor(stream);
+  idmap->accept(&visitor);
+
+  ASSERT_NE(stream.str().find("target apk path  : "), std::string::npos);
+  ASSERT_NE(stream.str().find("overlay apk path : "), std::string::npos);
+  ASSERT_NE(stream.str().find("0x7f010000 -> 0x7f010000 integer/int1\n"), std::string::npos);
+}
+
+TEST(PrettyPrintVisitorTests, CreatePrettyPrintVisitorWithoutAccessToApks) {
+  fclose(stderr);  // silence expected warnings from libandroidfw
+
+  std::string raw(reinterpret_cast<const char*>(idmap_raw_data), idmap_raw_data_len);
+  std::istringstream raw_stream(raw);
+
+  std::stringstream error;
+  std::unique_ptr<const Idmap> idmap = Idmap::FromBinaryStream(raw_stream, error);
+  ASSERT_THAT(idmap, NotNull());
+
+  std::stringstream stream;
+  PrettyPrintVisitor visitor(stream);
+  idmap->accept(&visitor);
+
+  ASSERT_NE(stream.str().find("target apk path  : "), std::string::npos);
+  ASSERT_NE(stream.str().find("overlay apk path : "), std::string::npos);
+  ASSERT_NE(stream.str().find("0x7f020000 -> 0x7f020000\n"), std::string::npos);
+}
+
+}  // namespace idmap2
+}  // namespace android
diff --git a/cmds/idmap2/tests/RawPrintVisitorTests.cpp b/cmds/idmap2/tests/RawPrintVisitorTests.cpp
new file mode 100644
index 0000000..c28ce2e
--- /dev/null
+++ b/cmds/idmap2/tests/RawPrintVisitorTests.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cstdio>  // fclose
+#include <memory>
+#include <sstream>
+#include <string>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#include "idmap2/Idmap.h"
+#include "idmap2/RawPrintVisitor.h"
+
+#include "TestHelpers.h"
+
+using ::testing::IsNull;
+using ::testing::NotNull;
+
+namespace android {
+namespace idmap2 {
+
+TEST(RawPrintVisitorTests, CreateRawPrintVisitor) {
+  const std::string target_apk_path(GetTestDataPath() + "/target/target.apk");
+  std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
+  ASSERT_THAT(target_apk, NotNull());
+
+  const std::string overlay_apk_path(GetTestDataPath() + "/overlay/overlay.apk");
+  std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
+  ASSERT_THAT(overlay_apk, NotNull());
+
+  std::stringstream error;
+  std::unique_ptr<const Idmap> idmap =
+      Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk, error);
+  ASSERT_THAT(idmap, NotNull());
+
+  std::stringstream stream;
+  RawPrintVisitor visitor(stream);
+  idmap->accept(&visitor);
+
+  ASSERT_NE(stream.str().find("00000000: 504d4449  magic\n"), std::string::npos);
+  ASSERT_NE(stream.str().find("00000004: 00000001  version\n"), std::string::npos);
+  ASSERT_NE(stream.str().find("00000008: f5ad1d1d  target crc\n"), std::string::npos);
+  ASSERT_NE(stream.str().find("0000000c: d470336b  overlay crc\n"), std::string::npos);
+  ASSERT_NE(stream.str().find("0000021c: 00000000  0x7f010000 -> 0x7f010000 integer/int1\n"),
+            std::string::npos);
+}
+
+TEST(RawPrintVisitorTests, CreateRawPrintVisitorWithoutAccessToApks) {
+  fclose(stderr);  // silence expected warnings from libandroidfw
+
+  std::string raw(reinterpret_cast<const char*>(idmap_raw_data), idmap_raw_data_len);
+  std::istringstream raw_stream(raw);
+
+  std::stringstream error;
+  std::unique_ptr<const Idmap> idmap = Idmap::FromBinaryStream(raw_stream, error);
+  ASSERT_THAT(idmap, NotNull());
+
+  std::stringstream stream;
+  RawPrintVisitor visitor(stream);
+  idmap->accept(&visitor);
+
+  ASSERT_NE(stream.str().find("00000000: 504d4449  magic\n"), std::string::npos);
+  ASSERT_NE(stream.str().find("00000004: 00000001  version\n"), std::string::npos);
+  ASSERT_NE(stream.str().find("00000008: 00001234  target crc\n"), std::string::npos);
+  ASSERT_NE(stream.str().find("0000000c: 00005678  overlay crc\n"), std::string::npos);
+  ASSERT_NE(stream.str().find("0000021c: 00000000  0x7f020000 -> 0x7f020000\n"), std::string::npos);
+}
+
+}  // namespace idmap2
+}  // namespace android
diff --git a/cmds/idmap2/tests/ResourceUtilsTests.cpp b/cmds/idmap2/tests/ResourceUtilsTests.cpp
new file mode 100644
index 0000000..0547fa0
--- /dev/null
+++ b/cmds/idmap2/tests/ResourceUtilsTests.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <memory>
+#include <string>
+#include <utility>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#include "androidfw/ApkAssets.h"
+#include "idmap2/ResourceUtils.h"
+
+#include "TestHelpers.h"
+
+using ::testing::NotNull;
+
+namespace android {
+namespace idmap2 {
+
+class ResourceUtilsTests : public Idmap2Tests {
+ protected:
+  void SetUp() override {
+    Idmap2Tests::SetUp();
+
+    apk_assets_ = ApkAssets::Load(GetTargetApkPath());
+    ASSERT_THAT(apk_assets_, NotNull());
+
+    am_.SetApkAssets({apk_assets_.get()});
+  }
+
+  const AssetManager2& GetAssetManager() {
+    return am_;
+  }
+
+ private:
+  AssetManager2 am_;
+  std::unique_ptr<const ApkAssets> apk_assets_;
+};
+
+TEST_F(ResourceUtilsTests, ResToTypeEntryName) {
+  bool lookup_ok;
+  std::string name;
+  std::tie(lookup_ok, name) = utils::ResToTypeEntryName(GetAssetManager(), 0x7f010000u);
+  ASSERT_TRUE(lookup_ok);
+  ASSERT_EQ(name, "integer/int1");
+}
+
+TEST_F(ResourceUtilsTests, ResToTypeEntryNameNoSuchResourceId) {
+  bool lookup_ok;
+  std::tie(lookup_ok, std::ignore) = utils::ResToTypeEntryName(GetAssetManager(), 0x7f123456u);
+  ASSERT_FALSE(lookup_ok);
+}
+
+}  // namespace idmap2
+}  // namespace android
diff --git a/cmds/idmap2/tests/TestHelpers.h b/cmds/idmap2/tests/TestHelpers.h
new file mode 100644
index 0000000..18dc541
--- /dev/null
+++ b/cmds/idmap2/tests/TestHelpers.h
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef IDMAP2_TESTS_TESTHELPERS_H_
+#define IDMAP2_TESTS_TESTHELPERS_H_
+
+#include <string>
+
+namespace android {
+namespace idmap2 {
+
+const unsigned char idmap_raw_data[] = {
+    // IDMAP HEADER
+    // 0x0: magic
+    0x49, 0x44, 0x4d, 0x50,
+
+    // 0x4: version
+    0x01, 0x00, 0x00, 0x00,
+
+    // 0x8: target crc
+    0x34, 0x12, 0x00, 0x00,
+
+    // 0xc: overlay crc
+    0x78, 0x56, 0x00, 0x00,
+
+    // 0x10: target path "target.apk"
+    0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x2e, 0x61, 0x70, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+    // 0x110: overlay path "overlay.apk"
+    0x6f, 0x76, 0x65, 0x72, 0x6c, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+    // DATA HEADER
+    // 0x210: target package id
+    0x7f, 0x00,
+
+    // 0x212: types count
+    0x02, 0x00,
+
+    // DATA BLOCK
+    // 0x214: target type
+    0x02, 0x00,
+
+    // 0x216: overlay type
+    0x02, 0x00,
+
+    // 0x218: entry count
+    0x01, 0x00,
+
+    // 0x21a: entry offset
+    0x00, 0x00,
+
+    // 0x21c: entries
+    0x00, 0x00, 0x00, 0x00,
+
+    // DATA BLOCK
+    // 0x220: target type
+    0x03, 0x00,
+
+    // 0x222: overlay type
+    0x03, 0x00,
+
+    // 0x224: entry count
+    0x03, 0x00,
+
+    // 0x226: entry offset
+    0x03, 0x00,
+
+    // 0x228, 0x22c, 0x230: entries
+    0x00, 0x00, 0x00, 0x00,
+
+    0xff, 0xff, 0xff, 0xff,
+
+    0x01, 0x00, 0x00, 0x00};
+
+const unsigned int idmap_raw_data_len = 565;
+
+const std::string GetTestDataPath();
+
+class Idmap2Tests : public testing::Test {
+ protected:
+  virtual void SetUp() {
+#ifdef __ANDROID__
+    tmp_dir_path_ = "/data/local/tmp/idmap2-tests-XXXXXX";
+#else
+    tmp_dir_path_ = "/tmp/idmap2-tests-XXXXXX";
+#endif
+    EXPECT_NE(mkdtemp(const_cast<char*>(tmp_dir_path_.c_str())), nullptr)
+        << "Failed to create temporary directory: " << strerror(errno);
+    target_apk_path_ = GetTestDataPath() + "/target/target.apk";
+    overlay_apk_path_ = GetTestDataPath() + "/overlay/overlay.apk";
+    idmap_path_ = tmp_dir_path_ + "/a.idmap";
+  }
+
+  virtual void TearDown() {
+    EXPECT_EQ(rmdir(tmp_dir_path_.c_str()), 0)
+        << "Failed to remove temporary directory " << tmp_dir_path_ << ": " << strerror(errno);
+  }
+
+  const std::string& GetTempDirPath() {
+    return tmp_dir_path_;
+  }
+
+  const std::string& GetTargetApkPath() {
+    return target_apk_path_;
+  }
+
+  const std::string& GetOverlayApkPath() {
+    return overlay_apk_path_;
+  }
+
+  const std::string& GetIdmapPath() {
+    return idmap_path_;
+  }
+
+ private:
+  std::string tmp_dir_path_;
+  std::string target_apk_path_;
+  std::string overlay_apk_path_;
+  std::string idmap_path_;
+};
+
+}  // namespace idmap2
+}  // namespace android
+
+#endif  // IDMAP2_TESTS_TESTHELPERS_H_
diff --git a/cmds/idmap2/tests/XmlTests.cpp b/cmds/idmap2/tests/XmlTests.cpp
new file mode 100644
index 0000000..97ff03e
--- /dev/null
+++ b/cmds/idmap2/tests/XmlTests.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cstdio>  // fclose
+
+#include "idmap2/Xml.h"
+#include "idmap2/ZipFile.h"
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#include "TestHelpers.h"
+
+using ::testing::IsNull;
+using ::testing::NotNull;
+
+namespace android {
+namespace idmap2 {
+
+TEST(XmlTests, Create) {
+  auto zip = ZipFile::Open(GetTestDataPath() + "/target/target.apk");
+  ASSERT_THAT(zip, NotNull());
+
+  auto data = zip->Uncompress("AndroidManifest.xml");
+  ASSERT_THAT(data, NotNull());
+
+  auto xml = Xml::Create(data->buf, data->size);
+  ASSERT_THAT(xml, NotNull());
+
+  fclose(stderr);  // silence expected warnings from libandroidfw
+  const char* not_xml = "foo";
+  auto fail = Xml::Create(reinterpret_cast<const uint8_t*>(not_xml), strlen(not_xml));
+  ASSERT_THAT(fail, IsNull());
+}
+
+TEST(XmlTests, FindTag) {
+  auto zip = ZipFile::Open(GetTestDataPath() + "/target/target.apk");
+  ASSERT_THAT(zip, NotNull());
+
+  auto data = zip->Uncompress("res/xml/test.xml");
+  ASSERT_THAT(data, NotNull());
+
+  auto xml = Xml::Create(data->buf, data->size);
+  ASSERT_THAT(xml, NotNull());
+
+  auto attrs = xml->FindTag("c");
+  ASSERT_THAT(attrs, NotNull());
+  ASSERT_EQ(attrs->size(), 4u);
+  ASSERT_EQ(attrs->at("type_string"), "fortytwo");
+  ASSERT_EQ(std::stoi(attrs->at("type_int_dec")), 42);
+  ASSERT_EQ(std::stoi(attrs->at("type_int_hex")), 42);
+  ASSERT_NE(std::stoul(attrs->at("type_int_boolean")), 0u);
+
+  auto fail = xml->FindTag("does-not-exist");
+  ASSERT_THAT(fail, IsNull());
+}
+
+}  // namespace idmap2
+}  // namespace android
diff --git a/cmds/idmap2/tests/ZipFileTests.cpp b/cmds/idmap2/tests/ZipFileTests.cpp
new file mode 100644
index 0000000..a504d31
--- /dev/null
+++ b/cmds/idmap2/tests/ZipFileTests.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cstdio>  // fclose
+#include <string>
+#include <utility>
+
+#include "idmap2/ZipFile.h"
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#include "TestHelpers.h"
+
+using ::testing::IsNull;
+using ::testing::NotNull;
+
+namespace android {
+namespace idmap2 {
+
+TEST(ZipFileTests, BasicOpen) {
+  auto zip = ZipFile::Open(GetTestDataPath() + "/target/target.apk");
+  ASSERT_THAT(zip, NotNull());
+
+  fclose(stderr);  // silence expected warnings from libziparchive
+  auto fail = ZipFile::Open(GetTestDataPath() + "/does-not-exist");
+  ASSERT_THAT(fail, IsNull());
+}
+
+TEST(ZipFileTests, Crc) {
+  auto zip = ZipFile::Open(GetTestDataPath() + "/target/target.apk");
+  ASSERT_THAT(zip, NotNull());
+
+  bool status;
+  uint32_t crc;
+  std::tie(status, crc) = zip->Crc("AndroidManifest.xml");
+  ASSERT_TRUE(status);
+  ASSERT_EQ(crc, 0x762f3d24);
+
+  std::tie(status, std::ignore) = zip->Crc("does-not-exist");
+  ASSERT_FALSE(status);
+}
+
+TEST(ZipFileTests, Uncompress) {
+  auto zip = ZipFile::Open(GetTestDataPath() + "/target/target.apk");
+  ASSERT_THAT(zip, NotNull());
+
+  auto data = zip->Uncompress("assets/lorem-ipsum.txt");
+  ASSERT_THAT(data, NotNull());
+  const std::string lorem_ipsum("Lorem ipsum dolor sit amet.\n");
+  ASSERT_THAT(data->size, lorem_ipsum.size());
+  ASSERT_THAT(std::string(reinterpret_cast<const char*>(data->buf), data->size), lorem_ipsum);
+
+  auto fail = zip->Uncompress("does-not-exist");
+  ASSERT_THAT(fail, IsNull());
+}
+
+}  // namespace idmap2
+}  // namespace android
diff --git a/cmds/idmap2/tests/data/overlay/AndroidManifest.xml b/cmds/idmap2/tests/data/overlay/AndroidManifest.xml
new file mode 100644
index 0000000..9f89d31
--- /dev/null
+++ b/cmds/idmap2/tests/data/overlay/AndroidManifest.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="test.overlay">
+    <overlay
+        android:targetPackage="test.target" />
+</manifest>
diff --git a/cmds/idmap2/tests/data/overlay/AndroidManifestStatic1.xml b/cmds/idmap2/tests/data/overlay/AndroidManifestStatic1.xml
new file mode 100644
index 0000000..39336cc
--- /dev/null
+++ b/cmds/idmap2/tests/data/overlay/AndroidManifestStatic1.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="test.overlay.static1">
+    <overlay
+        android:targetPackage="test.target"
+        android:isStatic="true"
+        android:priority="1" />
+</manifest>
diff --git a/cmds/idmap2/tests/data/overlay/AndroidManifestStatic2.xml b/cmds/idmap2/tests/data/overlay/AndroidManifestStatic2.xml
new file mode 100644
index 0000000..e1cc175
--- /dev/null
+++ b/cmds/idmap2/tests/data/overlay/AndroidManifestStatic2.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="test.overlay.static2">
+    <overlay
+        android:targetPackage="test.target"
+        android:isStatic="true"
+        android:priority="2" />
+</manifest>
diff --git a/cmds/idmap2/tests/data/overlay/build b/cmds/idmap2/tests/data/overlay/build
new file mode 100644
index 0000000..cba1086
--- /dev/null
+++ b/cmds/idmap2/tests/data/overlay/build
@@ -0,0 +1,40 @@
+# Copyright (C) 2018 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+FRAMEWORK_RES_APK="$(gettop)/out/target/common/obj/APPS/framework-res_intermediates/package-export.apk"
+
+aapt2 compile --dir res -o compiled.flata
+
+aapt2 link \
+    --no-resource-removal \
+    -I "$FRAMEWORK_RES_APK" \
+    --manifest AndroidManifest.xml \
+    -o overlay.apk \
+    compiled.flata
+
+aapt2 link \
+    --no-resource-removal \
+    -I "$FRAMEWORK_RES_APK" \
+    --manifest AndroidManifestStatic1.xml \
+    -o overlay-static-1.apk \
+    compiled.flata
+
+aapt2 link \
+    --no-resource-removal \
+    -I "$FRAMEWORK_RES_APK" \
+    --manifest AndroidManifestStatic2.xml \
+    -o overlay-static-2.apk \
+    compiled.flata
+
+rm compiled.flata
diff --git a/cmds/idmap2/tests/data/overlay/overlay-static-1.apk b/cmds/idmap2/tests/data/overlay/overlay-static-1.apk
new file mode 100644
index 0000000..9a0f487
--- /dev/null
+++ b/cmds/idmap2/tests/data/overlay/overlay-static-1.apk
Binary files differ
diff --git a/cmds/idmap2/tests/data/overlay/overlay-static-2.apk b/cmds/idmap2/tests/data/overlay/overlay-static-2.apk
new file mode 100644
index 0000000..3fc31c7
--- /dev/null
+++ b/cmds/idmap2/tests/data/overlay/overlay-static-2.apk
Binary files differ
diff --git a/cmds/idmap2/tests/data/overlay/overlay.apk b/cmds/idmap2/tests/data/overlay/overlay.apk
new file mode 100644
index 0000000..b4cd7cf
--- /dev/null
+++ b/cmds/idmap2/tests/data/overlay/overlay.apk
Binary files differ
diff --git a/cmds/idmap2/tests/data/overlay/res/values-sv/values.xml b/cmds/idmap2/tests/data/overlay/res/values-sv/values.xml
new file mode 100644
index 0000000..eed0b3d
--- /dev/null
+++ b/cmds/idmap2/tests/data/overlay/res/values-sv/values.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<resources>
+    <string name="str1">overlay-1-sv</string>
+    <string name="str4">overlay-4-sv</string>
+</resources>
diff --git a/cmds/idmap2/tests/data/overlay/res/values/values.xml b/cmds/idmap2/tests/data/overlay/res/values/values.xml
new file mode 100644
index 0000000..815d1a8
--- /dev/null
+++ b/cmds/idmap2/tests/data/overlay/res/values/values.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<resources>
+    <string name="str1">overlay-1</string>
+    <string name="str3">overlay-3</string>
+    <integer name="int1">-1</integer>
+    <integer name="not_in_target">-1</integer>
+</resources>
diff --git a/cmds/idmap2/tests/data/target/AndroidManifest.xml b/cmds/idmap2/tests/data/target/AndroidManifest.xml
new file mode 100644
index 0000000..3a861b4
--- /dev/null
+++ b/cmds/idmap2/tests/data/target/AndroidManifest.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="test.target">
+</manifest>
diff --git a/cmds/idmap2/tests/data/target/assets/lorem-ipsum.txt b/cmds/idmap2/tests/data/target/assets/lorem-ipsum.txt
new file mode 100644
index 0000000..d2cf010
--- /dev/null
+++ b/cmds/idmap2/tests/data/target/assets/lorem-ipsum.txt
@@ -0,0 +1 @@
+Lorem ipsum dolor sit amet.
diff --git a/cmds/statsd/tools/Android.mk b/cmds/idmap2/tests/data/target/build
similarity index 73%
copy from cmds/statsd/tools/Android.mk
copy to cmds/idmap2/tests/data/target/build
index 7253c96..8569c4f 100644
--- a/cmds/statsd/tools/Android.mk
+++ b/cmds/idmap2/tests/data/target/build
@@ -1,4 +1,4 @@
-# Copyright (C) 2017 The Android Open Source Project
+# Copyright (C) 2018 The Android Open Source Project
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -11,10 +11,7 @@
 # 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.
-#
-#
 
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-#Include the sub-makefiles
-include $(call all-makefiles-under,$(LOCAL_PATH))
\ No newline at end of file
+aapt2 compile --dir res -o compiled.flata
+aapt2 link --manifest AndroidManifest.xml -A assets -o target.apk compiled.flata
+rm compiled.flata
diff --git a/cmds/idmap2/tests/data/target/res/values/values.xml b/cmds/idmap2/tests/data/target/res/values/values.xml
new file mode 100644
index 0000000..56bf0d6
--- /dev/null
+++ b/cmds/idmap2/tests/data/target/res/values/values.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<resources>
+    <string name="a">a</string>
+    <string name="b">b</string>
+    <string name="c">c</string>
+    <string name="str1">target-1</string>
+    <string name="str2">target-2</string>
+    <string name="str3">target-3</string>
+    <string name="str4">target-4</string>
+    <string name="x">x</string>
+    <string name="y">y</string>
+    <string name="z">z</string>
+    <integer name="int1">1</integer>
+</resources>
diff --git a/cmds/idmap2/tests/data/target/res/xml/test.xml b/cmds/idmap2/tests/data/target/res/xml/test.xml
new file mode 100644
index 0000000..0fe21c6
--- /dev/null
+++ b/cmds/idmap2/tests/data/target/res/xml/test.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<a>
+    <b>
+        <c
+            type_string="fortytwo"
+            type_int_dec="42"
+            type_int_hex="0x2a"
+            type_int_boolean="true"
+            />
+    </b>
+</a>
diff --git a/cmds/idmap2/tests/data/target/target.apk b/cmds/idmap2/tests/data/target/target.apk
new file mode 100644
index 0000000..18ecc27
--- /dev/null
+++ b/cmds/idmap2/tests/data/target/target.apk
Binary files differ
diff --git a/cmds/incident/Android.bp b/cmds/incident/Android.bp
new file mode 100644
index 0000000..2a5ec5b
--- /dev/null
+++ b/cmds/incident/Android.bp
@@ -0,0 +1,46 @@
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+cc_binary {
+    name: "incident",
+
+    srcs: [
+        "main.cpp",
+        ":incident_sections",
+    ],
+
+    shared_libs: [
+        "libbase",
+        "libbinder",
+        "libcutils",
+        "liblog",
+        "libutils",
+        "libincident",
+    ],
+
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wno-missing-field-initializers",
+        "-Wno-unused-variable",
+        "-Wunused-parameter",
+    ],
+}
+
+genrule {
+    name: "incident_sections",
+    tools: ["incident-section-gen"],
+    out: ["incident_sections.cpp"],
+    cmd: "$(location incident-section-gen) incident > $(out)",
+}
diff --git a/cmds/incident/Android.mk b/cmds/incident/Android.mk
deleted file mode 100644
index 8615f9b..0000000
--- a/cmds/incident/Android.mk
+++ /dev/null
@@ -1,48 +0,0 @@
-# Copyright (C) 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
-        main.cpp
-
-LOCAL_MODULE := incident
-
-LOCAL_SHARED_LIBRARIES := \
-        libbase \
-        libbinder \
-        libcutils \
-        liblog \
-        libutils \
-        libincident
-
-LOCAL_CFLAGS += \
-        -Wall -Werror -Wno-missing-field-initializers -Wno-unused-variable -Wunused-parameter
-
-LOCAL_MODULE_CLASS := EXECUTABLES
-gen_src_dir := $(local-generated-sources-dir)
-
-gen := $(gen_src_dir)/incident_sections.cpp
-$(gen): $(HOST_OUT_EXECUTABLES)/incident-section-gen
-$(gen): PRIVATE_CUSTOM_TOOL = \
-    $(HOST_OUT_EXECUTABLES)/incident-section-gen incident > $@
-$(gen): $(HOST_OUT_EXECUTABLES)/incident-section-gen
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(gen)
-
-gen_src_dir:=
-gen:=
-
-include $(BUILD_EXECUTABLE)
diff --git a/cmds/incidentd/Android.bp b/cmds/incidentd/Android.bp
new file mode 100644
index 0000000..1e970f4
--- /dev/null
+++ b/cmds/incidentd/Android.bp
@@ -0,0 +1,117 @@
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// =========
+// incidentd
+// =========
+
+cc_binary {
+    name: "incidentd",
+
+    srcs: [
+        "src/**/*.cpp",
+        ":incidentd_section_list",
+    ],
+
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wno-missing-field-initializers",
+        "-Wno-unused-variable",
+        "-Wunused-parameter",
+
+        // Allow implicit fallthrough in IncidentService.cpp:85 until it is fixed.
+        "-Wno-error=implicit-fallthrough",
+
+        // optimize for size (protobuf glop can get big)
+        "-Os",
+        //"-g",
+        //"-O0",
+    ],
+
+    local_include_dirs: ["src"],
+    generated_headers: ["gen-platform-proto-constants"],
+
+    shared_libs: [
+        "libbase",
+        "libbinder",
+        "libdebuggerd_client",
+        "libdumputils",
+        "libincident",
+        "liblog",
+        "libprotoutil",
+        "libservices",
+        "libutils",
+    ],
+
+    init_rc: ["incidentd.rc"],
+}
+
+// ==============
+// incidentd_test
+// ==============
+
+cc_test {
+    name: "incidentd_test",
+    test_suites: ["device-tests"],
+
+    cflags: [
+        "-Werror",
+        "-Wall",
+        "-Wno-unused-variable",
+        "-Wunused-parameter",
+
+        // Allow implicit fallthrough in IncidentService.cpp:85 until it is fixed.
+        "-Wno-error=implicit-fallthrough",
+    ],
+
+    local_include_dirs: ["src"],
+    generated_headers: ["gen-platform-proto-constants"],
+
+    srcs: [
+        "tests/**/*.cpp",
+        "src/PrivacyBuffer.cpp",
+        "src/FdBuffer.cpp",
+        "src/Privacy.cpp",
+        "src/Reporter.cpp",
+        "src/Section.cpp",
+        "src/Throttler.cpp",
+        "src/incidentd_util.cpp",
+        "src/report_directory.cpp",
+    ],
+
+    data: ["testdata/**/*"],
+
+    static_libs: ["libgmock"],
+
+    shared_libs: [
+        "libbase",
+        "libbinder",
+        "libdebuggerd_client",
+        "libdumputils",
+        "libincident",
+        "liblog",
+        "libprotobuf-cpp-lite",
+        "libprotoutil",
+        "libservices",
+        "libutils",
+    ],
+}
+
+genrule {
+    name: "incidentd_section_list",
+    tools: ["incident-section-gen"],
+    out: ["section_list.cpp"],
+    cmd: "$(location incident-section-gen) incidentd > $(out)",
+}
diff --git a/cmds/incidentd/Android.mk b/cmds/incidentd/Android.mk
deleted file mode 100644
index eba5586..0000000
--- a/cmds/incidentd/Android.mk
+++ /dev/null
@@ -1,156 +0,0 @@
-# Copyright (C) 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-
-# proto files used in incidentd to generate cppstream proto headers.
-PROTO_FILES:= \
-        frameworks/base/core/proto/android/os/backtrace.proto \
-        frameworks/base/core/proto/android/os/data.proto \
-        frameworks/base/core/proto/android/util/log.proto
-
-# ========= #
-# incidentd #
-# ========= #
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := incidentd
-
-LOCAL_SRC_FILES := $(call all-cpp-files-under, src) \
-
-LOCAL_CFLAGS += \
-        -Wall -Werror -Wno-missing-field-initializers -Wno-unused-variable -Wunused-parameter
-
-# Allow implicit fallthrough in IncidentService.cpp:85 until it is fixed.
-LOCAL_CFLAGS += -Wno-error=implicit-fallthrough
-
-ifeq (debug,)
-    LOCAL_CFLAGS += \
-            -g -O0
-else
-    # optimize for size (protobuf glop can get big)
-    LOCAL_CFLAGS += \
-            -Os
-endif
-LOCAL_C_INCLUDES += $(LOCAL_PATH)/src
-
-LOCAL_SHARED_LIBRARIES := \
-        libbase \
-        libbinder \
-        libdebuggerd_client \
-        libdumputils \
-        libincident \
-        liblog \
-        libprotoutil \
-        libservices \
-        libutils
-
-LOCAL_MODULE_CLASS := EXECUTABLES
-
-gen_src_dir := $(local-generated-sources-dir)
-
-# generate section_list.cpp
-GEN_LIST := $(gen_src_dir)/src/section_list.cpp
-$(GEN_LIST): $(HOST_OUT_EXECUTABLES)/incident-section-gen
-$(GEN_LIST): PRIVATE_CUSTOM_TOOL = \
-    $(HOST_OUT_EXECUTABLES)/incident-section-gen incidentd > $@
-$(GEN_LIST): $(HOST_OUT_EXECUTABLES)/incident-section-gen
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN_LIST)
-GEN_LIST:=
-
-# generate cppstream proto, add proto files to PROTO_FILES
-GEN_PROTO := $(gen_src_dir)/proto.timestamp
-$(GEN_PROTO): $(HOST_OUT_EXECUTABLES)/aprotoc $(HOST_OUT_EXECUTABLES)/protoc-gen-cppstream $(PROTO_FILES)
-$(GEN_PROTO): PRIVATE_GEN_SRC_DIR := $(gen_src_dir)
-$(GEN_PROTO): PRIVATE_CUSTOM_TOOL = \
-    $(HOST_OUT_EXECUTABLES)/aprotoc --plugin=protoc-gen-cppstream=$(HOST_OUT_EXECUTABLES)/protoc-gen-cppstream \
-        --cppstream_out=$(PRIVATE_GEN_SRC_DIR) -Iexternal/protobuf/src -I . \
-        $(PROTO_FILES) \
-    && touch $@
-$(GEN_PROTO): $(HOST_OUT_EXECUTABLES)/aprotoc
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN_PROTO)
-GEN_PROTO:=
-
-gen_src_dir:=
-
-LOCAL_INIT_RC := incidentd.rc
-
-include $(BUILD_EXECUTABLE)
-
-# ============== #
-# incidentd_test #
-# ============== #
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := incidentd_test
-LOCAL_COMPATIBILITY_SUITE := device-tests
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_CFLAGS := -Werror -Wall -Wno-unused-variable -Wunused-parameter
-
-# Allow implicit fallthrough in IncidentService.cpp:85 until it is fixed.
-LOCAL_CFLAGS += -Wno-error=implicit-fallthrough
-
-LOCAL_C_INCLUDES += $(LOCAL_PATH)/src
-
-LOCAL_SRC_FILES := $(call all-cpp-files-under, tests) \
-    src/PrivacyBuffer.cpp \
-    src/FdBuffer.cpp \
-    src/Privacy.cpp \
-    src/Reporter.cpp \
-    src/Section.cpp \
-    src/Throttler.cpp \
-    src/incidentd_util.cpp \
-    src/report_directory.cpp \
-
-LOCAL_STATIC_LIBRARIES := \
-    libgmock \
-
-LOCAL_SHARED_LIBRARIES := \
-    libbase \
-    libbinder \
-    libdebuggerd_client \
-    libdumputils \
-    libincident \
-    liblog \
-    libprotobuf-cpp-lite \
-    libprotoutil \
-    libservices \
-    libutils \
-
-LOCAL_TEST_DATA := $(call find-test-data-in-subdirs, $(LOCAL_PATH), *, testdata)
-
-LOCAL_MODULE_CLASS := NATIVE_TESTS
-gen_src_dir := $(local-generated-sources-dir)
-# generate cppstream proto for testing
-GEN_PROTO := $(gen_src_dir)/test.proto.timestamp
-$(GEN_PROTO): $(HOST_OUT_EXECUTABLES)/aprotoc $(HOST_OUT_EXECUTABLES)/protoc-gen-cppstream $(PROTO_FILES)
-$(GEN_PROTO): PRIVATE_GEN_SRC_DIR := $(gen_src_dir)
-$(GEN_PROTO): PRIVATE_CUSTOM_TOOL = \
-    $(HOST_OUT_EXECUTABLES)/aprotoc --plugin=protoc-gen-cppstream=$(HOST_OUT_EXECUTABLES)/protoc-gen-cppstream \
-        --cppstream_out=$(PRIVATE_GEN_SRC_DIR) -Iexternal/protobuf/src -I . \
-        $(PROTO_FILES) \
-    && touch $@
-$(GEN_PROTO): $(HOST_OUT_EXECUTABLES)/aprotoc
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN_PROTO)
-GEN_PROTO:=
-
-gen_src_dir:=
-
-include $(BUILD_NATIVE_TEST)
diff --git a/cmds/statsd/Android.bp b/cmds/statsd/Android.bp
index 94203f4f..02dde5a 100644
--- a/cmds/statsd/Android.bp
+++ b/cmds/statsd/Android.bp
@@ -1,5 +1,5 @@
 //
-// Copyright (C) 2015 The Android Open Source Project
+// 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.
@@ -42,6 +42,277 @@
 
 }
 
+cc_defaults {
+    name: "statsd_defaults",
+    aidl: {
+        include_dirs: ["frameworks/base/core/java"],
+    },
+
+    srcs: [
+        ":statsd_aidl",
+        "src/statsd_config.proto",
+        "src/FieldValue.cpp",
+        "src/hash.cpp",
+        "src/stats_log_util.cpp",
+        "src/anomaly/AlarmMonitor.cpp",
+        "src/anomaly/AlarmTracker.cpp",
+        "src/anomaly/AnomalyTracker.cpp",
+        "src/anomaly/DurationAnomalyTracker.cpp",
+        "src/anomaly/subscriber_util.cpp",
+        "src/condition/CombinationConditionTracker.cpp",
+        "src/condition/condition_util.cpp",
+        "src/condition/SimpleConditionTracker.cpp",
+        "src/condition/ConditionWizard.cpp",
+        "src/condition/StateTracker.cpp",
+        "src/config/ConfigKey.cpp",
+        "src/config/ConfigListener.cpp",
+        "src/config/ConfigManager.cpp",
+        "src/external/Perfetto.cpp",
+        "src/external/Perfprofd.cpp",
+        "src/external/StatsPuller.cpp",
+        "src/external/StatsCompanionServicePuller.cpp",
+        "src/external/SubsystemSleepStatePuller.cpp",
+        "src/external/ResourceHealthManagerPuller.cpp",
+        "src/external/ResourceThermalManagerPuller.cpp",
+        "src/external/StatsPullerManager.cpp",
+        "src/external/puller_util.cpp",
+        "src/logd/LogEvent.cpp",
+        "src/logd/LogListener.cpp",
+        "src/matchers/CombinationLogMatchingTracker.cpp",
+        "src/matchers/EventMatcherWizard.cpp",
+        "src/matchers/matcher_util.cpp",
+        "src/matchers/SimpleLogMatchingTracker.cpp",
+        "src/metrics/MetricProducer.cpp",
+        "src/metrics/EventMetricProducer.cpp",
+        "src/metrics/CountMetricProducer.cpp",
+        "src/metrics/DurationMetricProducer.cpp",
+        "src/metrics/duration_helper/OringDurationTracker.cpp",
+        "src/metrics/duration_helper/MaxDurationTracker.cpp",
+        "src/metrics/ValueMetricProducer.cpp",
+        "src/metrics/GaugeMetricProducer.cpp",
+        "src/metrics/MetricsManager.cpp",
+        "src/metrics/metrics_manager_util.cpp",
+        "src/packages/UidMap.cpp",
+        "src/storage/StorageManager.cpp",
+        "src/StatsLogProcessor.cpp",
+        "src/StatsService.cpp",
+        "src/statscompanion_util.cpp",
+        "src/subscriber/IncidentdReporter.cpp",
+        "src/subscriber/SubscriberReporter.cpp",
+        "src/HashableDimensionKey.cpp",
+        "src/guardrail/StatsdStats.cpp",
+        "src/socket/StatsSocketListener.cpp",
+        "src/shell/ShellSubscriber.cpp",
+        "src/shell/shell_config.proto",
+
+        ":perfprofd_aidl",
+    ],
+
+    local_include_dirs: [
+        "src",
+    ],
+
+    static_libs: [
+        "libhealthhalutils",
+    ],
+
+    shared_libs: [
+        "libbase",
+        "libbinder",
+        "libincident",
+        "liblog",
+        "libutils",
+        "libservices",
+        "libprotoutil",
+        "libstatslog",
+        "libhardware",
+        "libhardware_legacy",
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "android.frameworks.stats@1.0",
+        "android.hardware.health@2.0",
+        "android.hardware.power@1.0",
+        "android.hardware.power@1.1",
+        "android.hardware.thermal@1.0",
+        "libpackagelistparser",
+        "libsysutils",
+        "libcutils",
+    ],
+}
+
+// =========
+// statsd
+// =========
+
+cc_binary {
+    name: "statsd",
+    defaults: ["statsd_defaults"],
+
+    srcs: ["src/main.cpp"],
+
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+        "-Wno-unused-parameter",
+        // optimize for size (protobuf glop can get big)
+        "-Os",
+        // "-g",
+        // "-O0",
+    ],
+
+    product_variables: {
+        eng: {
+            // Enable sanitizer ONLY on eng builds
+            //sanitize: {
+            //    address: true,
+            //},
+        },
+        debuggable: {
+            // Add a flag to enable stats log printing from statsd on debug builds.
+            cflags: ["-DVERY_VERBOSE_PRINTING"],
+        },
+    },
+
+    proto: {
+        type: "lite",
+    },
+
+    shared_libs: ["libgtest_prod"],
+
+    init_rc: ["statsd.rc"],
+}
+
+// ==============
+// statsd_test
+// ==============
+
+cc_test {
+    name: "statsd_test",
+    defaults: ["statsd_defaults"],
+    test_suites: ["device-tests"],
+
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wno-missing-field-initializers",
+        "-Wno-unused-variable",
+        "-Wno-unused-function",
+        "-Wno-unused-parameter",
+    ],
+
+    srcs: [
+        "src/atom_field_options.proto",
+        "src/atoms.proto",
+        "src/stats_log.proto",
+        "src/shell/shell_data.proto",
+        "tests/AlarmMonitor_test.cpp",
+        "tests/anomaly/AlarmTracker_test.cpp",
+        "tests/anomaly/AnomalyTracker_test.cpp",
+        "tests/ConfigManager_test.cpp",
+        "tests/external/puller_util_test.cpp",
+        "tests/indexed_priority_queue_test.cpp",
+        "tests/LogEntryMatcher_test.cpp",
+        "tests/LogEvent_test.cpp",
+        "tests/MetricsManager_test.cpp",
+        "tests/StatsLogProcessor_test.cpp",
+        "tests/StatsService_test.cpp",
+        "tests/UidMap_test.cpp",
+        "tests/FieldValue_test.cpp",
+        "tests/condition/CombinationConditionTracker_test.cpp",
+        "tests/condition/SimpleConditionTracker_test.cpp",
+        "tests/condition/StateTracker_test.cpp",
+        "tests/metrics/OringDurationTracker_test.cpp",
+        "tests/metrics/MaxDurationTracker_test.cpp",
+        "tests/metrics/CountMetricProducer_test.cpp",
+        "tests/metrics/DurationMetricProducer_test.cpp",
+        "tests/metrics/EventMetricProducer_test.cpp",
+        "tests/metrics/ValueMetricProducer_test.cpp",
+        "tests/metrics/GaugeMetricProducer_test.cpp",
+        "tests/guardrail/StatsdStats_test.cpp",
+        "tests/metrics/metrics_test_helper.cpp",
+        "tests/statsd_test_util.cpp",
+        "tests/e2e/WakelockDuration_e2e_test.cpp",
+        "tests/e2e/MetricActivation_e2e_test.cpp",
+        "tests/e2e/MetricConditionLink_e2e_test.cpp",
+        "tests/e2e/Alarm_e2e_test.cpp",
+        "tests/e2e/Attribution_e2e_test.cpp",
+        "tests/e2e/GaugeMetric_e2e_push_test.cpp",
+        "tests/e2e/GaugeMetric_e2e_pull_test.cpp",
+        "tests/e2e/ValueMetric_pull_e2e_test.cpp",
+        "tests/e2e/DimensionInCondition_e2e_combination_AND_cond_test.cpp",
+        "tests/e2e/DimensionInCondition_e2e_combination_OR_cond_test.cpp",
+        "tests/e2e/DimensionInCondition_e2e_simple_cond_test.cpp",
+        "tests/e2e/Anomaly_count_e2e_test.cpp",
+        "tests/e2e/Anomaly_duration_sum_e2e_test.cpp",
+        "tests/e2e/ConfigTtl_e2e_test.cpp",
+        "tests/e2e/PartialBucket_e2e_test.cpp",
+        "tests/shell/ShellSubscriber_test.cpp",
+    ],
+
+    static_libs: [
+        "libgmock",
+        "libplatformprotos",
+    ],
+
+    proto: {
+        type: "full",
+        include_dirs: ["external/protobuf/src"],
+    },
+
+    shared_libs: ["libprotobuf-cpp-full"],
+
+}
+
+//#############################
+// statsd micro benchmark
+//#############################
+
+cc_benchmark {
+    name: "statsd_benchmark",
+    defaults: ["statsd_defaults"],
+
+    srcs: [
+        "src/atom_field_options.proto",
+        "src/atoms.proto",
+        "src/stats_log.proto",
+        "benchmark/main.cpp",
+        "benchmark/hello_world_benchmark.cpp",
+        "benchmark/log_event_benchmark.cpp",
+        "benchmark/stats_write_benchmark.cpp",
+        "benchmark/filter_value_benchmark.cpp",
+        "benchmark/get_dimensions_for_condition_benchmark.cpp",
+        "benchmark/metric_util.cpp",
+        "benchmark/duration_metric_benchmark.cpp",
+    ],
+
+    proto: {
+        type: "full",
+        include_dirs: ["external/protobuf/src"],
+    },
+
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wno-unused-parameter",
+        "-Wno-unused-variable",
+        "-Wno-unused-function",
+
+        // Bug: http://b/29823425 Disable -Wvarargs for Clang update to r271374
+        "-Wno-varargs"
+    ],
+
+    static_libs: [
+        "libplatformprotos",
+    ],
+
+    shared_libs: [
+        "libgtest_prod",
+        "libstatslog",
+        "libprotobuf-cpp-full",
+    ],
+}
 
 // ====  java proto device library (for test only)  ==============================
 java_library {
diff --git a/cmds/statsd/Android.mk b/cmds/statsd/Android.mk
deleted file mode 100644
index 5818f5d..0000000
--- a/cmds/statsd/Android.mk
+++ /dev/null
@@ -1,319 +0,0 @@
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-
-statsd_common_src := \
-    ../../core/java/android/os/IStatsCompanionService.aidl \
-    ../../core/java/android/os/IStatsManager.aidl \
-    src/statsd_config.proto \
-    src/FieldValue.cpp \
-    src/hash.cpp \
-    src/stats_log_util.cpp \
-    src/anomaly/AlarmMonitor.cpp \
-    src/anomaly/AlarmTracker.cpp \
-    src/anomaly/AnomalyTracker.cpp \
-    src/anomaly/DurationAnomalyTracker.cpp \
-    src/anomaly/subscriber_util.cpp \
-    src/condition/CombinationConditionTracker.cpp \
-    src/condition/condition_util.cpp \
-    src/condition/SimpleConditionTracker.cpp \
-    src/condition/ConditionWizard.cpp \
-    src/condition/StateTracker.cpp \
-    src/config/ConfigKey.cpp \
-    src/config/ConfigListener.cpp \
-    src/config/ConfigManager.cpp \
-    src/external/Perfetto.cpp \
-    src/external/Perfprofd.cpp \
-    src/external/StatsPuller.cpp \
-    src/external/StatsCompanionServicePuller.cpp \
-    src/external/SubsystemSleepStatePuller.cpp \
-    src/external/ResourceHealthManagerPuller.cpp \
-    src/external/ResourceThermalManagerPuller.cpp \
-    src/external/StatsPullerManager.cpp \
-    src/external/puller_util.cpp \
-    src/logd/LogEvent.cpp \
-    src/logd/LogListener.cpp \
-    src/matchers/CombinationLogMatchingTracker.cpp \
-    src/matchers/EventMatcherWizard.cpp \
-    src/matchers/matcher_util.cpp \
-    src/matchers/SimpleLogMatchingTracker.cpp \
-    src/metrics/MetricProducer.cpp \
-    src/metrics/EventMetricProducer.cpp \
-    src/metrics/CountMetricProducer.cpp \
-    src/metrics/DurationMetricProducer.cpp \
-    src/metrics/duration_helper/OringDurationTracker.cpp \
-    src/metrics/duration_helper/MaxDurationTracker.cpp \
-    src/metrics/ValueMetricProducer.cpp \
-    src/metrics/GaugeMetricProducer.cpp \
-    src/metrics/MetricsManager.cpp \
-    src/metrics/metrics_manager_util.cpp \
-    src/packages/UidMap.cpp \
-    src/storage/StorageManager.cpp \
-    src/StatsLogProcessor.cpp \
-    src/StatsService.cpp \
-    src/statscompanion_util.cpp \
-    src/subscriber/IncidentdReporter.cpp \
-    src/subscriber/SubscriberReporter.cpp \
-    src/HashableDimensionKey.cpp \
-    src/guardrail/StatsdStats.cpp \
-    src/socket/StatsSocketListener.cpp \
-    src/shell/ShellSubscriber.cpp \
-    src/shell/shell_config.proto
-
-# TODO(b/110563449): Once statsd is using a blueprint file, migrate to the proper filegroups.
-statsd_common_src += \
-    ../../../../system/extras/perfprofd/binder_interface/aidl/android/os/IPerfProfd.aidl
-
-statsd_common_c_includes := \
-    $(LOCAL_PATH)/src \
-    $(LOCAL_PATH)/../../libs/services/include
-
-statsd_common_aidl_includes := \
-    $(LOCAL_PATH)/../../core/java
-
-statsd_common_static_libraries := \
-    libhealthhalutils
-
-statsd_common_shared_libraries := \
-    libbase \
-    libbinder \
-    libincident \
-    liblog \
-    libutils \
-    libservices \
-    libprotoutil \
-    libstatslog \
-    libhardware \
-    libhardware_legacy \
-    libhidlbase \
-    libhidltransport \
-    libhwbinder \
-    android.frameworks.stats@1.0 \
-    android.hardware.health@2.0 \
-    android.hardware.power@1.0 \
-    android.hardware.power@1.1 \
-    android.hardware.thermal@1.0 \
-    libpackagelistparser \
-    libsysutils \
-    libcutils
-
-# =========
-# statsd
-# =========
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := statsd
-
-LOCAL_SRC_FILES := \
-    $(statsd_common_src) \
-    src/main.cpp
-
-LOCAL_CFLAGS += \
-    -Wall \
-    -Wextra \
-    -Werror \
-    -Wno-unused-parameter
-
-ifeq (debug,)
-    LOCAL_CFLAGS += \
-            -g -O0
-else
-    # optimize for size (protobuf glop can get big)
-    LOCAL_CFLAGS += \
-            -Os
-endif
-LOCAL_PROTOC_OPTIMIZE_TYPE := lite
-
-LOCAL_AIDL_INCLUDES := $(statsd_common_aidl_includes)
-LOCAL_C_INCLUDES += $(statsd_common_c_includes)
-
-LOCAL_STATIC_LIBRARIES := $(statsd_common_static_libraries)
-
-LOCAL_SHARED_LIBRARIES := $(statsd_common_shared_libraries) \
-    libgtest_prod
-
-LOCAL_MODULE_CLASS := EXECUTABLES
-
-# Enable sanitizer ONLY on eng builds.
-#ifeq ($(TARGET_BUILD_VARIANT),eng)
-#    LOCAL_CLANG := true
-#    LOCAL_SANITIZE := address
-#endif
-
-# Add a flag to enable stats log printing from statsd on debug builds.
-ifneq (,$(filter userdebug eng, $(TARGET_BUILD_VARIANT)))
-    LOCAL_CFLAGS += \
-        -DVERY_VERBOSE_PRINTING
-endif
-
-LOCAL_INIT_RC := statsd.rc
-
-include $(BUILD_EXECUTABLE)
-
-
-# ==============
-# statsd_test
-# ==============
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := statsd_test
-LOCAL_COMPATIBILITY_SUITE := device-tests
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_AIDL_INCLUDES := $(statsd_common_aidl_includes)
-LOCAL_C_INCLUDES += $(statsd_common_c_includes)
-
-LOCAL_CFLAGS += \
-    -Wall \
-    -Werror \
-    -Wno-missing-field-initializers \
-    -Wno-unused-variable \
-    -Wno-unused-function \
-    -Wno-unused-parameter
-
-LOCAL_SRC_FILES := \
-    $(statsd_common_src) \
-    src/atom_field_options.proto \
-    src/atoms.proto \
-    src/stats_log.proto \
-    src/shell/shell_data.proto \
-    tests/AlarmMonitor_test.cpp \
-    tests/anomaly/AlarmTracker_test.cpp \
-    tests/anomaly/AnomalyTracker_test.cpp \
-    tests/ConfigManager_test.cpp \
-    tests/external/puller_util_test.cpp \
-    tests/indexed_priority_queue_test.cpp \
-    tests/LogEntryMatcher_test.cpp \
-    tests/LogEvent_test.cpp \
-    tests/MetricsManager_test.cpp \
-    tests/StatsLogProcessor_test.cpp \
-    tests/StatsService_test.cpp \
-    tests/UidMap_test.cpp \
-    tests/FieldValue_test.cpp \
-    tests/condition/CombinationConditionTracker_test.cpp \
-    tests/condition/SimpleConditionTracker_test.cpp \
-    tests/condition/StateTracker_test.cpp \
-    tests/metrics/OringDurationTracker_test.cpp \
-    tests/metrics/MaxDurationTracker_test.cpp \
-    tests/metrics/CountMetricProducer_test.cpp \
-    tests/metrics/DurationMetricProducer_test.cpp \
-    tests/metrics/EventMetricProducer_test.cpp \
-    tests/metrics/ValueMetricProducer_test.cpp \
-    tests/metrics/GaugeMetricProducer_test.cpp \
-    tests/guardrail/StatsdStats_test.cpp \
-    tests/metrics/metrics_test_helper.cpp \
-    tests/statsd_test_util.cpp \
-    tests/e2e/WakelockDuration_e2e_test.cpp \
-    tests/e2e/MetricActivation_e2e_test.cpp \
-    tests/e2e/MetricConditionLink_e2e_test.cpp \
-    tests/e2e/Alarm_e2e_test.cpp \
-    tests/e2e/Attribution_e2e_test.cpp \
-    tests/e2e/GaugeMetric_e2e_push_test.cpp \
-    tests/e2e/GaugeMetric_e2e_pull_test.cpp \
-    tests/e2e/ValueMetric_pull_e2e_test.cpp \
-    tests/e2e/DimensionInCondition_e2e_combination_AND_cond_test.cpp \
-    tests/e2e/DimensionInCondition_e2e_combination_OR_cond_test.cpp \
-    tests/e2e/DimensionInCondition_e2e_simple_cond_test.cpp \
-    tests/e2e/Anomaly_count_e2e_test.cpp \
-    tests/e2e/Anomaly_duration_sum_e2e_test.cpp \
-    tests/e2e/ConfigTtl_e2e_test.cpp \
-    tests/e2e/PartialBucket_e2e_test.cpp \
-    tests/shell/ShellSubscriber_test.cpp
-
-LOCAL_STATIC_LIBRARIES := \
-    $(statsd_common_static_libraries) \
-    libgmock \
-    libplatformprotos
-
-LOCAL_PROTOC_OPTIMIZE_TYPE := full
-
-LOCAL_PROTOC_FLAGS := \
-    -Iexternal/protobuf/src
-
-LOCAL_SHARED_LIBRARIES := $(statsd_common_shared_libraries) \
-                        libprotobuf-cpp-full
-
-include $(BUILD_NATIVE_TEST)
-
-##############################
-# statsd micro benchmark
-##############################
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := statsd_benchmark
-
-LOCAL_SRC_FILES := $(statsd_common_src) \
-                    src/atom_field_options.proto \
-                    src/atoms.proto \
-                    src/stats_log.proto \
-                   benchmark/main.cpp \
-                   benchmark/hello_world_benchmark.cpp \
-                   benchmark/log_event_benchmark.cpp \
-                   benchmark/stats_write_benchmark.cpp \
-                   benchmark/filter_value_benchmark.cpp \
-                   benchmark/get_dimensions_for_condition_benchmark.cpp \
-                   benchmark/metric_util.cpp \
-                   benchmark/duration_metric_benchmark.cpp
-
-LOCAL_STATIC_LIBRARIES := \
-    $(statsd_common_static_libraries)
-
-LOCAL_PROTOC_OPTIMIZE_TYPE := full
-
-LOCAL_PROTOC_FLAGS := \
-    -Iexternal/protobuf/src
-
-LOCAL_SHARED_LIBRARIES := $(statsd_common_shared_libraries) \
-                        libprotobuf-cpp-full
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
-    platformprotoslite
-
-LOCAL_C_INCLUDES := $(statsd_common_c_includes)
-
-LOCAL_CFLAGS := -Wall \
-                -Werror \
-                -Wno-unused-parameter \
-                -Wno-unused-variable \
-                -Wno-unused-function \
-
-# Bug: http://b/29823425 Disable -Wvarargs for Clang update to r271374
-LOCAL_CFLAGS += -Wno-varargs
-
-LOCAL_AIDL_INCLUDES := $(statsd_common_aidl_includes)
-
-LOCAL_STATIC_LIBRARIES := \
-    $(statsd_common_static_libraries) \
-    libplatformprotos
-
-LOCAL_SHARED_LIBRARIES := $(statsd_common_shared_libraries) \
-    libgtest_prod \
-    libstatslog
-
-LOCAL_MODULE_TAGS := eng tests
-
-include $(BUILD_NATIVE_BENCHMARK)
-
-
-statsd_common_src:=
-statsd_common_aidl_includes:=
-statsd_common_c_includes:=
-statsd_common_static_libraries:=
-statsd_common_shared_libraries:=
-
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp
index f4c70be..12e2560a 100644
--- a/cmds/statsd/src/StatsLogProcessor.cpp
+++ b/cmds/statsd/src/StatsLogProcessor.cpp
@@ -442,7 +442,7 @@
     if (totalBytes >
         StatsdStats::kMaxMetricsBytesPerConfig) {  // Too late. We need to start clearing data.
         metricsManager.dropData(timestampNs);
-        StatsdStats::getInstance().noteDataDropped(key);
+        StatsdStats::getInstance().noteDataDropped(key, totalBytes);
         VLOG("StatsD had to toss out metrics for %s", key.ToString().c_str());
     } else if ((totalBytes > StatsdStats::kBytesPerConfigTriggerGetData) ||
                (mOnDiskDataConfigs.find(key) != mOnDiskDataConfigs.end())) {
diff --git a/cmds/statsd/src/atom_field_options.proto b/cmds/statsd/src/atom_field_options.proto
index 453bf7e..e33bd8c 100644
--- a/cmds/statsd/src/atom_field_options.proto
+++ b/cmds/statsd/src/atom_field_options.proto
@@ -64,10 +64,22 @@
     optional StateField option = 1 [default = STATE_FIELD_UNSET];
 }
 
+// Used to generate StatsLog.write APIs.
+enum LogMode {
+    MODE_UNSET = 0;
+    // Log fields as their actual types e.g., all primary data types.
+    // Or fields that are hardcoded in stats_log_api_gen tool e.g., AttributionNode
+    MODE_AUTOMATIC = 1;
+    // Log fields in their proto binary format. These fields will not be parsed in statsd
+    MODE_BYTES = 2;
+}
+
 extend google.protobuf.FieldOptions {
     // Flags to decorate an atom that presents a state change.
     optional StateAtomFieldOption state_field_option = 50000;
 
     // Flags to decorate the uid fields in an atom.
     optional bool is_uid = 50001 [default = false];
+
+    optional LogMode log_mode = 50002 [default = MODE_AUTOMATIC];
 }
\ No newline at end of file
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index d52dec1..51d05bb 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -29,6 +29,7 @@
 import "frameworks/base/core/proto/android/server/enums.proto";
 import "frameworks/base/core/proto/android/service/procstats_enum.proto";
 import "frameworks/base/core/proto/android/stats/enums.proto";
+import "frameworks/base/core/proto/android/stats/launcher/launcher.proto";
 import "frameworks/base/core/proto/android/telecomm/enums.proto";
 import "frameworks/base/core/proto/android/telephony/enums.proto";
 import "frameworks/base/core/proto/android/view/enums.proto";
@@ -67,7 +68,7 @@
         ExcessiveCpuUsageReported excessive_cpu_usage_reported = 16;
         CachedKillReported cached_kill_reported = 17;
         ProcessMemoryStatReported process_memory_stat_reported = 18;
-        // 19 is available
+        LauncherUIChanged launcher_event = 19;
         BatterySaverModeStateChanged battery_saver_mode_state_changed = 20;
         DeviceIdleModeStateChanged device_idle_mode_state_changed = 21;
         DeviceIdlingModeStateChanged device_idling_mode_state_changed = 22;
@@ -149,7 +150,7 @@
     }
 
     // Pulled events will start at field 10000.
-    // Next: 10037
+    // Next: 10038
     oneof pulled {
         WifiBytesTransfer wifi_bytes_transfer = 10000;
         WifiBytesTransferByFgBg wifi_bytes_transfer_by_fg_bg = 10001;
@@ -188,6 +189,7 @@
         ProcStats proc_stats_pkg_proc = 10034;
         ProcessCpuTime process_cpu_time = 10035;
         NativeProcessMemoryState native_process_memory_state = 10036;
+        CpuTimePerThreadFreq cpu_time_per_thread_freq = 10037;
     }
 
     // DO NOT USE field numbers above 100,000 in AOSP.
@@ -1439,6 +1441,14 @@
     optional State state = 1;
 }
 
+message LauncherUIChanged {
+    optional android.stats.launcher.LauncherAction action = 1;
+    optional android.stats.launcher.LauncherState src_state = 2;
+    optional android.stats.launcher.LauncherState dst_state = 3;
+    optional android.stats.launcher.LauncherExtension extension = 4 [(log_mode) = MODE_BYTES];
+    optional bool is_swipe_up_enabled = 5;
+}
+
 /**
  * Logs when Settings UI has changed.
  *
@@ -2395,25 +2405,28 @@
  * Logs the memory stats for a native process (from procfs).
  */
 message NativeProcessMemoryState {
-  // The uid if available. -1 means not available.
-  optional int32 uid = 1 [(is_uid) = true];
+    // The uid if available. -1 means not available.
+    optional int32 uid = 1 [(is_uid) = true];
 
-  // The process name.
-  optional string process_name = 2;
+    // The process name.
+    optional string process_name = 2;
 
-  // # of page-faults
-  optional int64 page_fault = 3;
+    // # of page-faults
+    optional int64 page_fault = 3;
 
-  // # of major page-faults
-  optional int64 page_major_fault = 4;
+    // # of major page-faults
+    optional int64 page_major_fault = 4;
 
-  // RSS
-  optional int64 rss_in_bytes = 5;
+    // RSS
+    optional int64 rss_in_bytes = 5;
 
-  // RSS high watermark.
-  // Peak RSS usage of the process. Value is read from the VmHWM field in /proc/PID/status or
-  // from memory.max_usage_in_bytes under /dev/memcg if the device uses per-app memory cgroups.
-  optional int64 rss_high_watermark_in_bytes = 6;
+    // RSS high watermark.
+    // Peak RSS usage of the process. Value is read from the VmHWM field in /proc/PID/status.
+    optional int64 rss_high_watermark_in_bytes = 6;
+
+    // Elapsed real time when the process started.
+    // Value is read from /proc/PID/stat, field 22.
+    optional int64 start_time_nanos = 7;
 }
 
 /*
@@ -3108,4 +3121,30 @@
     optional int64 user_time_millis = 3;
     // Process cpu time in system space, cumulative from boot/process start
     optional int64 system_time_millis = 4;
-}
\ No newline at end of file
+}
+
+/**
+ * Pulls the CPU usage for each thread.
+ *
+ * Read from /proc/$PID/task/$TID/time_in_state files.
+ *
+ * TODO(mishaw): This is an experimental atom. Issues with big/little CPU frequencies, and
+ * time_in_state files not being present on some phones, have not been addressed. These should be
+ * considered before a public release.
+ */
+message CpuTimePerThreadFreq {
+    // UID that owns the process.
+    optional int32 uid = 1 [(is_uid) = true];
+    // ID of the process.
+    optional uint32 process_id = 2;
+    // ID of the thread.
+    optional uint32 thread_id = 3;
+    // Name of the process taken from `/proc/$PID/cmdline`.
+    optional string process_name = 4;
+    // Name of the thread taken from `/proc/$PID/task/$TID/comm`
+    optional string thread_name = 5;
+    // What frequency the CPU was running at, in KHz
+    optional uint32 frequency_khz = 6;
+    // Time spent in frequency in milliseconds, since thread start.
+    optional uint32 time_millis = 7;
+}
diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp
index ba626f8..c9b361d 100644
--- a/cmds/statsd/src/external/StatsPullerManager.cpp
+++ b/cmds/statsd/src/external/StatsPullerManager.cpp
@@ -172,7 +172,7 @@
           new StatsCompanionServicePuller(android::util::PROCESS_MEMORY_STATE)}},
         // native_process_memory_state
         {android::util::NATIVE_PROCESS_MEMORY_STATE,
-         {{3, 4, 5, 6},
+         {{3, 4, 5, 6, 7},
           {2},
           1 * NS_PER_SEC,
           new StatsCompanionServicePuller(android::util::NATIVE_PROCESS_MEMORY_STATE)}},
@@ -234,6 +234,11 @@
             {{} /* additive fields */, {} /* non additive fields */,
              5 * NS_PER_SEC /* min cool-down in seconds*/,
              new StatsCompanionServicePuller(android::util::PROCESS_CPU_TIME)}},
+        {android::util::CPU_TIME_PER_THREAD_FREQ,
+         {{7},
+          {2, 3, 4, 5, 6},
+          1 * NS_PER_SEC,
+          new StatsCompanionServicePuller(android::util::CPU_TIME_PER_THREAD_FREQ)}},
 };
 
 StatsPullerManager::StatsPullerManager() : mNextPullTimeNs(NO_ALARM_UPDATE) {
diff --git a/cmds/statsd/src/guardrail/StatsdStats.cpp b/cmds/statsd/src/guardrail/StatsdStats.cpp
index bf0bfec..023d835 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.cpp
+++ b/cmds/statsd/src/guardrail/StatsdStats.cpp
@@ -73,7 +73,8 @@
 const int FIELD_ID_CONFIG_STATS_ALERT_COUNT = 8;
 const int FIELD_ID_CONFIG_STATS_VALID = 9;
 const int FIELD_ID_CONFIG_STATS_BROADCAST = 10;
-const int FIELD_ID_CONFIG_STATS_DATA_DROP = 11;
+const int FIELD_ID_CONFIG_STATS_DATA_DROP_TIME = 11;
+const int FIELD_ID_CONFIG_STATS_DATA_DROP_BYTES = 21;
 const int FIELD_ID_CONFIG_STATS_DUMP_REPORT_TIME = 12;
 const int FIELD_ID_CONFIG_STATS_DUMP_REPORT_BYTES = 20;
 const int FIELD_ID_CONFIG_STATS_MATCHER_STATS = 13;
@@ -205,11 +206,11 @@
     it->second->broadcast_sent_time_sec.push_back(timeSec);
 }
 
-void StatsdStats::noteDataDropped(const ConfigKey& key) {
-    noteDataDropped(key, getWallClockSec());
+void StatsdStats::noteDataDropped(const ConfigKey& key, const size_t totalBytes) {
+    noteDataDropped(key, totalBytes, getWallClockSec());
 }
 
-void StatsdStats::noteDataDropped(const ConfigKey& key, int32_t timeSec) {
+void StatsdStats::noteDataDropped(const ConfigKey& key, const size_t totalBytes, int32_t timeSec) {
     lock_guard<std::mutex> lock(mLock);
     auto it = mConfigStats.find(key);
     if (it == mConfigStats.end()) {
@@ -218,8 +219,10 @@
     }
     if (it->second->data_drop_time_sec.size() == kMaxTimestampCount) {
         it->second->data_drop_time_sec.pop_front();
+        it->second->data_drop_bytes.pop_front();
     }
     it->second->data_drop_time_sec.push_back(timeSec);
+    it->second->data_drop_bytes.push_back(totalBytes);
 }
 
 void StatsdStats::noteMetricsReportSent(const ConfigKey& key, const size_t num_bytes) {
@@ -382,6 +385,7 @@
     for (auto& config : mConfigStats) {
         config.second->broadcast_sent_time_sec.clear();
         config.second->data_drop_time_sec.clear();
+        config.second->data_drop_bytes.clear();
         config.second->dump_report_stats.clear();
         config.second->annotations.clear();
         config.second->matcher_stats.clear();
@@ -421,8 +425,12 @@
             dprintf(out, "\tbroadcast time: %d\n", broadcastTime);
         }
 
-        for (const auto& dataDropTime : configStats->data_drop_time_sec) {
-            dprintf(out, "\tdata drop time: %d\n", dataDropTime);
+        auto dropTimePtr = configStats->data_drop_time_sec.begin();
+        auto dropBytesPtr = configStats->data_drop_bytes.begin();
+        for (int i = 0; i < (int)configStats->data_drop_time_sec.size();
+             i++, dropTimePtr++, dropBytesPtr++) {
+            dprintf(out, "\tdata drop time: %d with size %lld", *dropTimePtr,
+                    (long long)*dropBytesPtr);
         }
     }
     dprintf(out, "%lu Active Configs\n", (unsigned long)mConfigStats.size());
@@ -445,9 +453,13 @@
                     (long long)broadcastTime);
         }
 
-        for (const auto& dataDropTime : configStats->data_drop_time_sec) {
-            dprintf(out, "\tdata drop time: %s(%lld)\n", buildTimeString(dataDropTime).c_str(),
-                    (long long)dataDropTime);
+        auto dropTimePtr = configStats->data_drop_time_sec.begin();
+        auto dropBytesPtr = configStats->data_drop_bytes.begin();
+        for (int i = 0; i < (int)configStats->data_drop_time_sec.size();
+             i++, dropTimePtr++, dropBytesPtr++) {
+            dprintf(out, "\tdata drop time: %s(%lld) with %lld bytes\n",
+                    buildTimeString(*dropTimePtr).c_str(), (long long)*dropTimePtr,
+                    (long long)*dropBytesPtr);
         }
 
         for (const auto& dump : configStats->dump_report_stats) {
@@ -540,9 +552,15 @@
                      broadcast);
     }
 
-    for (const auto& drop : configStats.data_drop_time_sec) {
-        proto->write(FIELD_TYPE_INT32 | FIELD_ID_CONFIG_STATS_DATA_DROP | FIELD_COUNT_REPEATED,
-                     drop);
+    for (const auto& drop_time : configStats.data_drop_time_sec) {
+        proto->write(FIELD_TYPE_INT32 | FIELD_ID_CONFIG_STATS_DATA_DROP_TIME | FIELD_COUNT_REPEATED,
+                     drop_time);
+    }
+
+    for (const auto& drop_bytes : configStats.data_drop_bytes) {
+        proto->write(
+                FIELD_TYPE_INT64 | FIELD_ID_CONFIG_STATS_DATA_DROP_BYTES | FIELD_COUNT_REPEATED,
+                (long long)drop_bytes);
     }
 
     for (const auto& dump : configStats.dump_report_stats) {
diff --git a/cmds/statsd/src/guardrail/StatsdStats.h b/cmds/statsd/src/guardrail/StatsdStats.h
index a8188c8..7d95b54 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.h
+++ b/cmds/statsd/src/guardrail/StatsdStats.h
@@ -43,6 +43,8 @@
 
     std::list<int32_t> broadcast_sent_time_sec;
     std::list<int32_t> data_drop_time_sec;
+    // Number of bytes dropped at corresponding time.
+    std::list<int64_t> data_drop_bytes;
     std::list<std::pair<int32_t, int64_t>> dump_report_stats;
 
     // Stores how many times a matcher have been matched. The map size is capped by kMaxConfigCount.
@@ -169,7 +171,7 @@
     /**
      * Report a config's metrics data has been dropped.
      */
-    void noteDataDropped(const ConfigKey& key);
+    void noteDataDropped(const ConfigKey& key, const size_t totalBytes);
 
     /**
      * Report metrics data report has been sent.
@@ -350,7 +352,7 @@
 
     void resetInternalLocked();
 
-    void noteDataDropped(const ConfigKey& key, int32_t timeSec);
+    void noteDataDropped(const ConfigKey& key, const size_t totalBytes, int32_t timeSec);
 
     void noteMetricsReportSent(const ConfigKey& key, const size_t num_bytes, int32_t timeSec);
 
diff --git a/cmds/statsd/src/logd/LogEvent.cpp b/cmds/statsd/src/logd/LogEvent.cpp
index 4bbcfd5..febb922 100644
--- a/cmds/statsd/src/logd/LogEvent.cpp
+++ b/cmds/statsd/src/logd/LogEvent.cpp
@@ -267,10 +267,12 @@
     }
 }
 
-LogEvent::LogEvent(int32_t tagId, int64_t timestampNs) {
+LogEvent::LogEvent(int32_t tagId, int64_t timestampNs) : LogEvent(tagId, timestampNs, 0) {}
+
+LogEvent::LogEvent(int32_t tagId, int64_t timestampNs, int32_t uid) {
     mLogdTimestampNs = timestampNs;
     mTagId = tagId;
-    mLogUid = 0;
+    mLogUid = uid;
     mContext = create_android_logger(1937006964); // the event tag shared by all stats logs
     if (mContext) {
         android_log_write_int64(mContext, timestampNs);
@@ -344,7 +346,8 @@
     return false;
 }
 
-bool LogEvent::writeKeyValuePairs(const std::map<int32_t, int32_t>& int_map,
+bool LogEvent::writeKeyValuePairs(int32_t uid,
+                                  const std::map<int32_t, int32_t>& int_map,
                                   const std::map<int32_t, int64_t>& long_map,
                                   const std::map<int32_t, std::string>& string_map,
                                   const std::map<int32_t, float>& float_map) {
@@ -352,6 +355,7 @@
          if (android_log_write_list_begin(mContext) < 0) {
             return false;
          }
+         write(uid);
          for (const auto& itr : int_map) {
              if (android_log_write_list_begin(mContext) < 0) {
                 return false;
@@ -561,6 +565,10 @@
         }
         i++;
     } while ((elem.type != EVENT_TYPE_UNKNOWN) && !elem.complete);
+    if (isKeyValuePairAtom && mValues.size() > 0) {
+        mValues[0] = FieldValue(Field(android::util::KEY_VALUE_PAIRS_ATOM, getSimpleField(1)),
+                                Value((int32_t)mLogUid));
+    }
 }
 
 int64_t LogEvent::GetLong(size_t key, status_t* err) const {
diff --git a/cmds/statsd/src/logd/LogEvent.h b/cmds/statsd/src/logd/LogEvent.h
index c7e2a8c..3d5b2ab 100644
--- a/cmds/statsd/src/logd/LogEvent.h
+++ b/cmds/statsd/src/logd/LogEvent.h
@@ -75,6 +75,9 @@
     // For testing. The timestamp is used as both elapsed real time and logd timestamp.
     explicit LogEvent(int32_t tagId, int64_t timestampNs);
 
+    // For testing. The timestamp is used as both elapsed real time and logd timestamp.
+    explicit LogEvent(int32_t tagId, int64_t timestampNs, int32_t uid);
+
     /**
      * Constructs a KeyValuePairsAtom LogEvent from value maps.
      */
@@ -147,7 +150,8 @@
     bool write(float value);
     bool write(const std::vector<AttributionNodeInternal>& nodes);
     bool write(const AttributionNodeInternal& node);
-    bool writeKeyValuePairs(const std::map<int32_t, int32_t>& int_map,
+    bool writeKeyValuePairs(int32_t uid,
+                            const std::map<int32_t, int32_t>& int_map,
                             const std::map<int32_t, int64_t>& long_map,
                             const std::map<int32_t, std::string>& string_map,
                             const std::map<int32_t, float>& float_map);
diff --git a/cmds/statsd/src/stats_log.proto b/cmds/statsd/src/stats_log.proto
index 10ed7f3..e8f74d3 100644
--- a/cmds/statsd/src/stats_log.proto
+++ b/cmds/statsd/src/stats_log.proto
@@ -328,6 +328,7 @@
         optional bool is_valid = 9;
         repeated int32 broadcast_sent_time_sec = 10;
         repeated int32 data_drop_time_sec = 11;
+        repeated int64 data_drop_bytes = 21;
         repeated int32 dump_report_time_sec = 12;
         repeated int32 dump_report_data_size = 20;
         repeated MatcherStats matcher_stats = 13;
diff --git a/cmds/statsd/src/stats_log_util.cpp b/cmds/statsd/src/stats_log_util.cpp
index 805e583..2498d9f 100644
--- a/cmds/statsd/src/stats_log_util.cpp
+++ b/cmds/statsd/src/stats_log_util.cpp
@@ -25,15 +25,16 @@
 #include <utils/Log.h>
 #include <utils/SystemClock.h>
 
+using android::util::AtomsInfo;
 using android::util::FIELD_COUNT_REPEATED;
 using android::util::FIELD_TYPE_BOOL;
+using android::util::FIELD_TYPE_FIXED64;
 using android::util::FIELD_TYPE_FLOAT;
 using android::util::FIELD_TYPE_INT32;
 using android::util::FIELD_TYPE_INT64;
-using android::util::FIELD_TYPE_UINT64;
-using android::util::FIELD_TYPE_FIXED64;
 using android::util::FIELD_TYPE_MESSAGE;
 using android::util::FIELD_TYPE_STRING;
+using android::util::FIELD_TYPE_UINT64;
 using android::util::ProtoOutputStream;
 
 namespace android {
@@ -294,8 +295,9 @@
 // }
 //
 //
-void writeFieldValueTreeToStreamHelper(const std::vector<FieldValue>& dims, size_t* index,
-                                       int depth, int prefix, ProtoOutputStream* protoOutput) {
+void writeFieldValueTreeToStreamHelper(int tagId, const std::vector<FieldValue>& dims,
+                                       size_t* index, int depth, int prefix,
+                                       ProtoOutputStream* protoOutput) {
     size_t count = dims.size();
     while (*index < count) {
         const auto& dim = dims[*index];
@@ -319,9 +321,31 @@
                 case FLOAT:
                     protoOutput->write(FIELD_TYPE_FLOAT | fieldNum, dim.mValue.float_value);
                     break;
-                case STRING:
-                    protoOutput->write(FIELD_TYPE_STRING | fieldNum, dim.mValue.str_value);
+                case STRING: {
+                    bool isBytesField = false;
+                    // Bytes field is logged via string format in log_msg format. So here we check
+                    // if this string field is a byte field.
+                    std::map<int, std::vector<int>>::const_iterator itr;
+                    if (depth == 0 && (itr = AtomsInfo::kBytesFieldAtoms.find(tagId)) !=
+                                              AtomsInfo::kBytesFieldAtoms.end()) {
+                        const std::vector<int>& bytesFields = itr->second;
+                        for (int bytesField : bytesFields) {
+                            if (bytesField == fieldNum) {
+                                // This is a bytes field
+                                isBytesField = true;
+                                break;
+                            }
+                        }
+                    }
+                    if (isBytesField) {
+                        protoOutput->write(FIELD_TYPE_MESSAGE | fieldNum,
+                                           (const char*)dim.mValue.str_value.c_str(),
+                                           dim.mValue.str_value.length());
+                    } else {
+                        protoOutput->write(FIELD_TYPE_STRING | fieldNum, dim.mValue.str_value);
+                    }
                     break;
+                }
                 case STORAGE:
                     protoOutput->write(FIELD_TYPE_MESSAGE | fieldNum,
                                        (const char*)dim.mValue.storage_value.data(),
@@ -342,7 +366,7 @@
             }
             // Directly jump to the leaf value because the repeated position field is implied
             // by the position of the sub msg in the parent field.
-            writeFieldValueTreeToStreamHelper(dims, index, valueDepth,
+            writeFieldValueTreeToStreamHelper(tagId, dims, index, valueDepth,
                                               dim.mField.getPrefix(valueDepth), protoOutput);
             if (msg_token != 0) {
                 protoOutput->end(msg_token);
@@ -359,7 +383,7 @@
     uint64_t atomToken = protoOutput->start(FIELD_TYPE_MESSAGE | tagId);
 
     size_t index = 0;
-    writeFieldValueTreeToStreamHelper(values, &index, 0, 0, protoOutput);
+    writeFieldValueTreeToStreamHelper(tagId, values, &index, 0, 0, protoOutput);
     protoOutput->end(atomToken);
 }
 
diff --git a/cmds/statsd/tests/LogEvent_test.cpp b/cmds/statsd/tests/LogEvent_test.cpp
index ced65f2..6384757 100644
--- a/cmds/statsd/tests/LogEvent_test.cpp
+++ b/cmds/statsd/tests/LogEvent_test.cpp
@@ -12,9 +12,11 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+#include "src/logd/LogEvent.h"
 #include <gtest/gtest.h>
 #include <log/log_event_list.h>
-#include "src/logd/LogEvent.h"
+#include "frameworks/base/cmds/statsd/src/atoms.pb.h"
+#include "frameworks/base/core/proto/android/stats/launcher/launcher.pb.h"
 
 #ifdef __ANDROID__
 
@@ -22,6 +24,9 @@
 namespace os {
 namespace statsd {
 
+using std::string;
+using util::ProtoOutputStream;
+
 TEST(LogEventTest, TestLogParsing) {
     LogEvent event1(1, 2000);
 
@@ -90,7 +95,7 @@
 }
 
 TEST(LogEventTest, TestKeyValuePairsAtomParsing) {
-    LogEvent event1(83, 2000);
+    LogEvent event1(83, 2000, 1000);
     std::map<int32_t, int32_t> int_map;
     std::map<int32_t, int64_t> long_map;
     std::map<int32_t, std::string> string_map;
@@ -108,7 +113,8 @@
     float_map[111] = 2.2f;
     float_map[222] = 1.1f;
 
-    EXPECT_TRUE(event1.writeKeyValuePairs(int_map,
+    EXPECT_TRUE(event1.writeKeyValuePairs(0, // Logging side logs 0 uid.
+                                          int_map,
                                           long_map,
                                           string_map,
                                           float_map));
@@ -116,87 +122,92 @@
 
     EXPECT_EQ(83, event1.GetTagId());
     const auto& items = event1.getValues();
-    EXPECT_EQ((size_t)16, items.size());
+    EXPECT_EQ((size_t)17, items.size());
 
     const FieldValue& item0 = event1.getValues()[0];
-    EXPECT_EQ(0x2010101, item0.mField.getField());
+    EXPECT_EQ(0x10000, item0.mField.getField());
     EXPECT_EQ(Type::INT, item0.mValue.getType());
-    EXPECT_EQ(11, item0.mValue.int_value);
+    EXPECT_EQ(1000, item0.mValue.int_value);
 
     const FieldValue& item1 = event1.getValues()[1];
-    EXPECT_EQ(0x2010182, item1.mField.getField());
+    EXPECT_EQ(0x2010201, item1.mField.getField());
     EXPECT_EQ(Type::INT, item1.mValue.getType());
-    EXPECT_EQ(123, item1.mValue.int_value);
+    EXPECT_EQ(11, item1.mValue.int_value);
 
     const FieldValue& item2 = event1.getValues()[2];
-    EXPECT_EQ(0x2010201, item2.mField.getField());
+    EXPECT_EQ(0x2010282, item2.mField.getField());
     EXPECT_EQ(Type::INT, item2.mValue.getType());
-    EXPECT_EQ(22, item2.mValue.int_value);
+    EXPECT_EQ(123, item2.mValue.int_value);
 
     const FieldValue& item3 = event1.getValues()[3];
-    EXPECT_EQ(0x2010282, item3.mField.getField());
+    EXPECT_EQ(0x2010301, item3.mField.getField());
     EXPECT_EQ(Type::INT, item3.mValue.getType());
-    EXPECT_EQ(345, item3.mValue.int_value);
+    EXPECT_EQ(22, item3.mValue.int_value);
 
     const FieldValue& item4 = event1.getValues()[4];
-    EXPECT_EQ(0x2010301, item4.mField.getField());
+    EXPECT_EQ(0x2010382, item4.mField.getField());
     EXPECT_EQ(Type::INT, item4.mValue.getType());
-    EXPECT_EQ(33, item4.mValue.int_value);
+    EXPECT_EQ(345, item4.mValue.int_value);
 
     const FieldValue& item5 = event1.getValues()[5];
-    EXPECT_EQ(0x2010382, item5.mField.getField());
-    EXPECT_EQ(Type::LONG, item5.mValue.getType());
-    EXPECT_EQ(678L, item5.mValue.int_value);
+    EXPECT_EQ(0x2010401, item5.mField.getField());
+    EXPECT_EQ(Type::INT, item5.mValue.getType());
+    EXPECT_EQ(33, item5.mValue.int_value);
 
     const FieldValue& item6 = event1.getValues()[6];
-    EXPECT_EQ(0x2010401, item6.mField.getField());
-    EXPECT_EQ(Type::INT, item6.mValue.getType());
-    EXPECT_EQ(44, item6.mValue.int_value);
+    EXPECT_EQ(0x2010482, item6.mField.getField());
+    EXPECT_EQ(Type::LONG, item6.mValue.getType());
+    EXPECT_EQ(678L, item6.mValue.int_value);
 
     const FieldValue& item7 = event1.getValues()[7];
-    EXPECT_EQ(0x2010482, item7.mField.getField());
-    EXPECT_EQ(Type::LONG, item7.mValue.getType());
-    EXPECT_EQ(890L, item7.mValue.int_value);
+    EXPECT_EQ(0x2010501, item7.mField.getField());
+    EXPECT_EQ(Type::INT, item7.mValue.getType());
+    EXPECT_EQ(44, item7.mValue.int_value);
 
     const FieldValue& item8 = event1.getValues()[8];
-    EXPECT_EQ(0x2010501, item8.mField.getField());
-    EXPECT_EQ(Type::INT, item8.mValue.getType());
-    EXPECT_EQ(1, item8.mValue.int_value);
+    EXPECT_EQ(0x2010582, item8.mField.getField());
+    EXPECT_EQ(Type::LONG, item8.mValue.getType());
+    EXPECT_EQ(890L, item8.mValue.int_value);
 
     const FieldValue& item9 = event1.getValues()[9];
-    EXPECT_EQ(0x2010583, item9.mField.getField());
-    EXPECT_EQ(Type::STRING, item9.mValue.getType());
-    EXPECT_EQ("test2", item9.mValue.str_value);
+    EXPECT_EQ(0x2010601, item9.mField.getField());
+    EXPECT_EQ(Type::INT, item9.mValue.getType());
+    EXPECT_EQ(1, item9.mValue.int_value);
 
     const FieldValue& item10 = event1.getValues()[10];
-    EXPECT_EQ(0x2010601, item10.mField.getField());
-    EXPECT_EQ(Type::INT, item10.mValue.getType());
-    EXPECT_EQ(2, item10.mValue.int_value);
+    EXPECT_EQ(0x2010683, item10.mField.getField());
+    EXPECT_EQ(Type::STRING, item10.mValue.getType());
+    EXPECT_EQ("test2", item10.mValue.str_value);
 
     const FieldValue& item11 = event1.getValues()[11];
-    EXPECT_EQ(0x2010683, item11.mField.getField());
-    EXPECT_EQ(Type::STRING, item11.mValue.getType());
-    EXPECT_EQ("test1", item11.mValue.str_value);
+    EXPECT_EQ(0x2010701, item11.mField.getField());
+    EXPECT_EQ(Type::INT, item11.mValue.getType());
+    EXPECT_EQ(2, item11.mValue.int_value);
 
     const FieldValue& item12 = event1.getValues()[12];
-    EXPECT_EQ(0x2010701, item12.mField.getField());
-    EXPECT_EQ(Type::INT, item12.mValue.getType());
-    EXPECT_EQ(111, item12.mValue.int_value);
+    EXPECT_EQ(0x2010783, item12.mField.getField());
+    EXPECT_EQ(Type::STRING, item12.mValue.getType());
+    EXPECT_EQ("test1", item12.mValue.str_value);
 
     const FieldValue& item13 = event1.getValues()[13];
-    EXPECT_EQ(0x2010784, item13.mField.getField());
-    EXPECT_EQ(Type::FLOAT, item13.mValue.getType());
-    EXPECT_EQ(2.2f, item13.mValue.float_value);
+    EXPECT_EQ(0x2010801, item13.mField.getField());
+    EXPECT_EQ(Type::INT, item13.mValue.getType());
+    EXPECT_EQ(111, item13.mValue.int_value);
 
     const FieldValue& item14 = event1.getValues()[14];
-    EXPECT_EQ(0x2018801, item14.mField.getField());
-    EXPECT_EQ(Type::INT, item14.mValue.getType());
-    EXPECT_EQ(222, item14.mValue.int_value);
+    EXPECT_EQ(0x2010884, item14.mField.getField());
+    EXPECT_EQ(Type::FLOAT, item14.mValue.getType());
+    EXPECT_EQ(2.2f, item14.mValue.float_value);
 
     const FieldValue& item15 = event1.getValues()[15];
-    EXPECT_EQ(0x2018884, item15.mField.getField());
-    EXPECT_EQ(Type::FLOAT, item15.mValue.getType());
-    EXPECT_EQ(1.1f, item15.mValue.float_value);
+    EXPECT_EQ(0x2018901, item15.mField.getField());
+    EXPECT_EQ(Type::INT, item15.mValue.getType());
+    EXPECT_EQ(222, item15.mValue.int_value);
+
+    const FieldValue& item16 = event1.getValues()[16];
+    EXPECT_EQ(0x2018984, item16.mField.getField());
+    EXPECT_EQ(Type::FLOAT, item16.mValue.getType());
+    EXPECT_EQ(1.1f, item16.mValue.float_value);
 }
 
 TEST(LogEventTest, TestLogParsing2) {
@@ -292,6 +303,7 @@
     EXPECT_EQ(83, event1.GetTagId());
     EXPECT_EQ((int64_t)2000, event1.GetLogdTimestampNs());
     EXPECT_EQ((int64_t)2001, event1.GetElapsedTimestampNs());
+    EXPECT_EQ((int64_t)10001, event1.GetUid());
 
     const auto& items = event1.getValues();
     EXPECT_EQ((size_t)17, items.size());
@@ -383,6 +395,57 @@
 }
 
 
+TEST(LogEventTest, TestBinaryFieldAtom) {
+    Atom launcherAtom;
+    auto launcher_event = launcherAtom.mutable_launcher_event();
+    launcher_event->set_action(stats::launcher::LauncherAction::LONGPRESS);
+    launcher_event->set_src_state(stats::launcher::LauncherState::OVERVIEW);
+    launcher_event->set_dst_state(stats::launcher::LauncherState::ALLAPPS);
+
+    auto extension = launcher_event->mutable_extension();
+
+    auto src_target = extension->add_src_target();
+    src_target->set_type(stats::launcher::LauncherTarget_Type_ITEM_TYPE);
+    src_target->set_item(stats::launcher::LauncherTarget_Item_FOLDER_ICON);
+
+    auto dst_target = extension->add_dst_target();
+    dst_target->set_type(stats::launcher::LauncherTarget_Type_ITEM_TYPE);
+    dst_target->set_item(stats::launcher::LauncherTarget_Item_WIDGET);
+
+    string extension_str;
+    extension->SerializeToString(&extension_str);
+
+    LogEvent event1(Atom::kLauncherEventFieldNumber, 1000);
+
+    event1.write((int32_t)stats::launcher::LauncherAction::LONGPRESS);
+    event1.write((int32_t)stats::launcher::LauncherState::OVERVIEW);
+    event1.write((int64_t)stats::launcher::LauncherState::ALLAPPS);
+    event1.write(extension_str);
+    event1.init();
+
+    ProtoOutputStream proto;
+    event1.ToProto(proto);
+
+    std::vector<uint8_t> outData;
+    outData.resize(proto.size());
+    size_t pos = 0;
+    auto iter = proto.data();
+    while (iter.readBuffer() != NULL) {
+        size_t toRead = iter.currentToRead();
+        std::memcpy(&(outData[pos]), iter.readBuffer(), toRead);
+        pos += toRead;
+        iter.rp()->move(toRead);
+    }
+
+    std::string result_str(outData.begin(), outData.end());
+    std::string orig_str;
+    launcherAtom.SerializeToString(&orig_str);
+
+    EXPECT_EQ(orig_str, result_str);
+}
+
+
+
 }  // namespace statsd
 }  // namespace os
 }  // namespace android
diff --git a/cmds/statsd/tests/guardrail/StatsdStats_test.cpp b/cmds/statsd/tests/guardrail/StatsdStats_test.cpp
index 967ef3c..f37f908 100644
--- a/cmds/statsd/tests/guardrail/StatsdStats_test.cpp
+++ b/cmds/statsd/tests/guardrail/StatsdStats_test.cpp
@@ -126,7 +126,7 @@
     stats.noteBroadcastSent(key);
 
     // data drop -> 1
-    stats.noteDataDropped(key);
+    stats.noteDataDropped(key, 123);
 
     // dump report -> 3
     stats.noteMetricsReportSent(key, 0);
@@ -142,6 +142,8 @@
     const auto& configReport = report.config_stats(0);
     EXPECT_EQ(2, configReport.broadcast_sent_time_sec_size());
     EXPECT_EQ(1, configReport.data_drop_time_sec_size());
+    EXPECT_EQ(1, configReport.data_drop_bytes_size());
+    EXPECT_EQ(123, configReport.data_drop_bytes(0));
     EXPECT_EQ(3, configReport.dump_report_time_sec_size());
     EXPECT_EQ(3, configReport.dump_report_data_size_size());
     EXPECT_EQ(1, configReport.annotation_size());
@@ -275,7 +277,7 @@
     int32_t newTimestamp = 10000;
 
     // now it should trigger removing oldest timestamp
-    stats.noteDataDropped(key, 10000);
+    stats.noteDataDropped(key, 123, 10000);
     stats.noteBroadcastSent(key, 10000);
     stats.noteMetricsReportSent(key, 0, 10000);
 
@@ -295,6 +297,7 @@
     // the last timestamp is the newest timestamp.
     EXPECT_EQ(newTimestamp, configStats->broadcast_sent_time_sec.back());
     EXPECT_EQ(newTimestamp, configStats->data_drop_time_sec.back());
+    EXPECT_EQ(123, configStats->data_drop_bytes.back());
     EXPECT_EQ(newTimestamp, configStats->dump_report_stats.back().first);
 }
 
diff --git a/cmds/statsd/tools/dogfood/Android.bp b/cmds/statsd/tools/dogfood/Android.bp
new file mode 100644
index 0000000..bb494a6
--- /dev/null
+++ b/cmds/statsd/tools/dogfood/Android.bp
@@ -0,0 +1,37 @@
+// 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.
+//
+//
+
+android_app {
+    name: "StatsdDogfood",
+    platform_apis: true,
+
+    srcs: ["src/**/*.java"],
+
+    resource_dirs: ["res"],
+    static_libs: [
+        "platformprotoslite",
+        "statsdprotolite",
+    ],
+
+    privileged: true,
+    dex_preopt: {
+        enabled: false,
+    },
+    certificate: "platform",
+    optimize: {
+        enabled: false,
+    },
+}
diff --git a/cmds/statsd/tools/dogfood/Android.mk b/cmds/statsd/tools/dogfood/Android.mk
deleted file mode 100644
index baf235b..0000000
--- a/cmds/statsd/tools/dogfood/Android.mk
+++ /dev/null
@@ -1,33 +0,0 @@
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-#
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_PACKAGE_NAME := StatsdDogfood
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-LOCAL_STATIC_JAVA_LIBRARIES := platformprotoslite \
-                               statsdprotolite
-
-LOCAL_PRIVILEGED_MODULE := true
-LOCAL_DEX_PREOPT := false
-LOCAL_CERTIFICATE := platform
-LOCAL_PROGUARD_ENABLED := disabled
-
-include $(BUILD_PACKAGE)
diff --git a/cmds/statsd/tools/loadtest/Android.bp b/cmds/statsd/tools/loadtest/Android.bp
new file mode 100644
index 0000000..bf87fc5
--- /dev/null
+++ b/cmds/statsd/tools/loadtest/Android.bp
@@ -0,0 +1,37 @@
+// 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.
+//
+//
+
+android_app {
+    name: "StatsdLoadtest",
+    platform_apis: true,
+
+    srcs: ["src/**/*.java"],
+
+    resource_dirs: ["res"],
+    static_libs: [
+        "platformprotoslite",
+        "statsdprotolite",
+    ],
+
+    certificate: "platform",
+    privileged: true,
+    dex_preopt: {
+        enabled: false,
+    },
+    optimize: {
+        enabled: false,
+    },
+}
diff --git a/cmds/statsd/tools/loadtest/Android.mk b/cmds/statsd/tools/loadtest/Android.mk
deleted file mode 100644
index 219cd95..0000000
--- a/cmds/statsd/tools/loadtest/Android.mk
+++ /dev/null
@@ -1,33 +0,0 @@
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-#
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_PACKAGE_NAME := StatsdLoadtest
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-LOCAL_STATIC_JAVA_LIBRARIES := platformprotoslite \
-                               statsdprotolite
-
-LOCAL_CERTIFICATE := platform
-LOCAL_PRIVILEGED_MODULE := true
-LOCAL_DEX_PREOPT := false
-LOCAL_PROGUARD_ENABLED := disabled
-
-include $(BUILD_PACKAGE)
diff --git a/config/hiddenapi-vendor-list.txt b/config/hiddenapi-vendor-list.txt
index e5e64d3..4275bd4 100644
--- a/config/hiddenapi-vendor-list.txt
+++ b/config/hiddenapi-vendor-list.txt
@@ -120,7 +120,6 @@
 Landroid/os/SystemVibrator;-><init>()V
 Landroid/os/UserHandle;->isSameApp(II)Z
 Landroid/os/UserManager;->hasUserRestriction(Ljava/lang/String;Landroid/os/UserHandle;)Z
-Landroid/os/UserManager;->isAdminUser()Z
 Landroid/R$styleable;->CheckBoxPreference:[I
 Landroid/telephony/ims/compat/feature/MMTelFeature;-><init>()V
 Landroid/telephony/ims/compat/ImsService;-><init>()V
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 9d3c5c6..3b2a21e 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -23,6 +23,8 @@
 import static android.app.servertransaction.ActivityLifecycleItem.ON_START;
 import static android.app.servertransaction.ActivityLifecycleItem.ON_STOP;
 import static android.app.servertransaction.ActivityLifecycleItem.PRE_ON_CREATE;
+import static android.content.ContentResolver.DEPRECATE_DATA_COLUMNS;
+import static android.content.ContentResolver.DEPRECATE_DATA_PREFIX;
 import static android.view.Display.INVALID_DISPLAY;
 
 import android.annotation.NonNull;
@@ -45,6 +47,7 @@
 import android.content.ComponentCallbacks2;
 import android.content.ComponentName;
 import android.content.ContentProvider;
+import android.content.ContentResolver;
 import android.content.Context;
 import android.content.IContentProvider;
 import android.content.IIntentReceiver;
@@ -84,6 +87,7 @@
 import android.os.Debug;
 import android.os.DropBoxManager;
 import android.os.Environment;
+import android.os.FileUtils;
 import android.os.GraphicsEnvironment;
 import android.os.Handler;
 import android.os.HandlerExecutor;
@@ -114,6 +118,9 @@
 import android.renderscript.RenderScriptCacheDir;
 import android.security.NetworkSecurityPolicy;
 import android.security.net.config.NetworkSecurityConfigProvider;
+import android.system.ErrnoException;
+import android.system.OsConstants;
+import android.system.StructStat;
 import android.util.AndroidRuntimeException;
 import android.util.ArrayMap;
 import android.util.DisplayMetrics;
@@ -162,13 +169,16 @@
 
 import libcore.io.DropBox;
 import libcore.io.EventLogger;
+import libcore.io.ForwardingOs;
 import libcore.io.IoUtils;
+import libcore.io.Os;
 import libcore.net.event.NetworkEventDispatcher;
 
 import org.apache.harmony.dalvik.ddmc.DdmVmInternal;
 
 import java.io.File;
 import java.io.FileDescriptor;
+import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.PrintWriter;
@@ -392,6 +402,9 @@
         = new ArrayMap<Activity, ArrayList<OnActivityPausedListener>>();
 
     final GcIdler mGcIdler = new GcIdler();
+    final PurgeIdler mPurgeIdler = new PurgeIdler();
+
+    boolean mPurgeIdlerScheduled = false;
     boolean mGcIdlerScheduled = false;
 
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
@@ -1425,60 +1438,10 @@
             PrintWriter pw = new FastPrintWriter(
                     new FileOutputStream(pfd.getFileDescriptor()));
             PrintWriterPrinter printer = new PrintWriterPrinter(pw);
-            SQLiteDebug.dump(printer, args);
-
-            if (isSystem) {
-                dumpDatabaseFileSizes(pw, Environment.getDataSystemDirectory(), true);
-                dumpDatabaseFileSizes(pw, Environment.getDataSystemDeDirectory(), true);
-                dumpDatabaseFileSizes(pw, Environment.getDataSystemCeDirectory(), true);
-            } else {
-                Context context = getApplication();
-                if (context != null) {
-                    dumpDatabaseFileSizes(pw,
-                            getDatabasesDir(context.createDeviceProtectedStorageContext()),
-                            false);
-                    dumpDatabaseFileSizes(pw,
-                            getDatabasesDir(context.createCredentialProtectedStorageContext()),
-                            false);
-                }
-            }
+            SQLiteDebug.dump(printer, args, isSystem);
             pw.flush();
         }
 
-        private void dumpDatabaseFileSizes(PrintWriter pw, File dir, boolean isSystem) {
-            final File[] files = dir.listFiles();
-            if (files == null || files.length == 0) {
-                return;
-            }
-            Arrays.sort(files, (a, b) -> a.getName().compareTo(b.getName()));
-
-            boolean needHeader = true;
-            for (File f : files) {
-                if (isSystem) {
-                    // If it's the system server, the directory contains other files too, so
-                    // filter by file extensions.
-                    // (If it's an app, just print all files because they may not use *.db
-                    // extension.)
-                    final String name = f.getName();
-                    if (!(name.endsWith(".db") || name.endsWith(".db-wal")
-                            || name.endsWith(".db-journal"))) {
-                        continue;
-                    }
-                }
-                if (needHeader) {
-                    pw.println();
-                    pw.println("Database files in " + dir.getAbsolutePath() + ":");
-                    needHeader = false;
-                }
-
-                pw.print("  ");
-                pw.print(f.getName());
-                pw.print("  ");
-                pw.print(f.length());
-                pw.println(" bytes");
-            }
-        }
-
         @Override
         public void dumpDbInfo(final ParcelFileDescriptor pfd, final String[] args) {
             if (mSystemThread) {
@@ -1731,6 +1694,7 @@
         public static final int RUN_ISOLATED_ENTRY_POINT = 158;
         public static final int EXECUTE_TRANSACTION = 159;
         public static final int RELAUNCH_ACTIVITY = 160;
+        public static final int PURGE_RESOURCES = 161;
 
         String codeToString(int code) {
             if (DEBUG_MESSAGES) {
@@ -1774,6 +1738,7 @@
                     case RUN_ISOLATED_ENTRY_POINT: return "RUN_ISOLATED_ENTRY_POINT";
                     case EXECUTE_TRANSACTION: return "EXECUTE_TRANSACTION";
                     case RELAUNCH_ACTIVITY: return "RELAUNCH_ACTIVITY";
+                    case PURGE_RESOURCES: return "PURGE_RESOURCES";
                 }
             }
             return Integer.toString(code);
@@ -1811,6 +1776,7 @@
                 case UNBIND_SERVICE:
                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceUnbind");
                     handleUnbindService((BindServiceData)msg.obj);
+                    schedulePurgeIdler();
                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                     break;
                 case SERVICE_ARGS:
@@ -1821,6 +1787,7 @@
                 case STOP_SERVICE:
                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceStop");
                     handleStopService((IBinder)msg.obj);
+                    schedulePurgeIdler();
                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                     break;
                 case CONFIGURATION_CHANGED:
@@ -1954,6 +1921,9 @@
                 case RELAUNCH_ACTIVITY:
                     handleRelaunchActivityLocally((IBinder) msg.obj);
                     break;
+                case PURGE_RESOURCES:
+                    schedulePurgeIdler();
+                    break;
             }
             Object obj = msg.obj;
             if (obj instanceof SomeArgs) {
@@ -2006,6 +1976,17 @@
         @Override
         public final boolean queueIdle() {
             doGcIfNeeded();
+            nPurgePendingResources();
+            return false;
+        }
+    }
+
+    final class PurgeIdler implements MessageQueue.IdleHandler {
+        @Override
+        public boolean queueIdle() {
+            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "purgePendingResources");
+            nPurgePendingResources();
+            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
             return false;
         }
     }
@@ -2335,6 +2316,22 @@
         mH.removeMessages(H.GC_WHEN_IDLE);
     }
 
+    void schedulePurgeIdler() {
+        if (!mPurgeIdlerScheduled) {
+            mPurgeIdlerScheduled = true;
+            Looper.myQueue().addIdleHandler(mPurgeIdler);
+        }
+        mH.removeMessages(H.PURGE_RESOURCES);
+    }
+
+    void unschedulePurgeIdler() {
+        if (mPurgeIdlerScheduled) {
+            mPurgeIdlerScheduled = false;
+            Looper.myQueue().removeIdleHandler(mPurgeIdler);
+        }
+        mH.removeMessages(H.PURGE_RESOURCES);
+    }
+
     void doGcIfNeeded() {
         mGcIdlerScheduled = false;
         final long now = SystemClock.uptimeMillis();
@@ -4636,6 +4633,7 @@
             }
             r.setState(ON_DESTROY);
         }
+        schedulePurgeIdler();
         mActivities.remove(token);
         StrictMode.decrementExpectedActivityCount(activityClass);
         return r;
@@ -6799,7 +6797,7 @@
         }
     }
 
-    private class DropBoxReporter implements DropBox.Reporter {
+    private static class DropBoxReporter implements DropBox.Reporter {
 
         private DropBoxManager dropBox;
 
@@ -6819,7 +6817,84 @@
 
         private synchronized void ensureInitialized() {
             if (dropBox == null) {
-                dropBox = (DropBoxManager) getSystemContext().getSystemService(Context.DROPBOX_SERVICE);
+                dropBox = currentActivityThread().getApplication()
+                        .getSystemService(DropBoxManager.class);
+            }
+        }
+    }
+
+    private static class AndroidOs extends ForwardingOs {
+        /**
+         * Install selective syscall interception. For example, this is used to
+         * implement special filesystem paths that will be redirected to
+         * {@link ContentResolver#openFileDescriptor(Uri, String)}.
+         */
+        public static void install() {
+            // If feature is disabled, we don't need to install
+            if (!DEPRECATE_DATA_COLUMNS) return;
+
+            // If app is modern enough, we don't need to install
+            if (VMRuntime.getRuntime().getTargetSdkVersion() >= Build.VERSION_CODES.Q) return;
+
+            // Install interception and make sure it sticks!
+            Os def = null;
+            do {
+                def = Os.getDefault();
+            } while (!Os.compareAndSetDefault(def, new AndroidOs(def)));
+        }
+
+        private AndroidOs(Os os) {
+            super(os);
+        }
+
+        private FileDescriptor openDeprecatedDataPath(String path, int mode) throws ErrnoException {
+            final Uri uri = ContentResolver.translateDeprecatedDataPath(path);
+            Log.v(TAG, "Redirecting " + path + " to " + uri);
+
+            final ContentResolver cr = currentActivityThread().getApplication()
+                    .getContentResolver();
+            try {
+                final FileDescriptor fd = new FileDescriptor();
+                fd.setInt$(cr.openFileDescriptor(uri,
+                        FileUtils.translateModePosixToString(mode)).detachFd());
+                return fd;
+            } catch (FileNotFoundException e) {
+                throw new ErrnoException(e.getMessage(), OsConstants.ENOENT);
+            }
+        }
+
+        @Override
+        public boolean access(String path, int mode) throws ErrnoException {
+            if (path != null && path.startsWith(DEPRECATE_DATA_PREFIX)) {
+                // If we opened it okay, then access check succeeded
+                IoUtils.closeQuietly(
+                        openDeprecatedDataPath(path, FileUtils.translateModeAccessToPosix(mode)));
+                return true;
+            } else {
+                return super.access(path, mode);
+            }
+        }
+
+        @Override
+        public FileDescriptor open(String path, int flags, int mode) throws ErrnoException {
+            if (path != null && path.startsWith(DEPRECATE_DATA_PREFIX)) {
+                return openDeprecatedDataPath(path, mode);
+            } else {
+                return super.open(path, flags, mode);
+            }
+        }
+
+        @Override
+        public StructStat stat(String path) throws ErrnoException {
+            if (path != null && path.startsWith(DEPRECATE_DATA_PREFIX)) {
+                final FileDescriptor fd = openDeprecatedDataPath(path, OsConstants.O_RDONLY);
+                try {
+                    return android.system.Os.fstat(fd);
+                } finally {
+                    IoUtils.closeQuietly(fd);
+                }
+            } else {
+                return super.stat(path);
             }
         }
     }
@@ -6827,6 +6902,9 @@
     public static void main(String[] args) {
         Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
 
+        // Install selective syscall interception
+        AndroidOs.install();
+
         // CloseGuard defaults to true and can be quite spammy.  We
         // disable it here, but selectively enable it later (via
         // StrictMode) on debug builds, but using DropBox, not logs.
@@ -6876,6 +6954,6 @@
     }
 
     // ------------------ Regular JNI ------------------------
-
+    private native void nPurgePendingResources();
     private native void nDumpGraphicsInfo(FileDescriptor fd);
 }
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 3b05566..a4f1db3 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -18,6 +18,7 @@
 
 import android.Manifest;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
@@ -33,6 +34,7 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.UserManager;
+import android.provider.Settings;
 import android.util.ArrayMap;
 
 import com.android.internal.app.IAppOpsActiveCallback;
@@ -1283,8 +1285,8 @@
             AppOpsManager.MODE_ALLOWED, // POST_NOTIFICATION
             AppOpsManager.MODE_ALLOWED, // NEIGHBORING_CELLS
             AppOpsManager.MODE_ALLOWED, // CALL_PHONE
-            AppOpsManager.MODE_ALLOWED, // READ_SMS
-            AppOpsManager.MODE_IGNORED, // WRITE_SMS
+            AppOpsManager.MODE_DEFAULT, // READ_SMS
+            AppOpsManager.MODE_DEFAULT, // WRITE_SMS
             AppOpsManager.MODE_DEFAULT, // RECEIVE_SMS
             AppOpsManager.MODE_ALLOWED, // RECEIVE_EMERGENCY_BROADCAST
             AppOpsManager.MODE_ALLOWED, // RECEIVE_MMS
@@ -1537,6 +1539,19 @@
     }
 
     /**
+     * Retrieve the permission associated with an operation, or null if there is not one.
+     *
+     * @param op The operation name.
+     *
+     * @hide
+     */
+    @Nullable
+    @SystemApi
+    public static String opToPermission(@NonNull String op) {
+        return opToPermission(strOpToOp(op));
+    }
+
+    /**
      * Retrieve the user restriction associated with an operation, or null if there is not one.
      * @hide
      */
@@ -1570,6 +1585,26 @@
      * @hide
      */
     public static int opToDefaultMode(int op) {
+        // STOPSHIP b/118520006: Hardcode the default values once the feature is stable.
+        switch (op) {
+            // SMS permissions
+            case AppOpsManager.OP_SEND_SMS:
+            case AppOpsManager.OP_RECEIVE_SMS:
+            case AppOpsManager.OP_READ_SMS:
+            case AppOpsManager.OP_RECEIVE_WAP_PUSH:
+            case AppOpsManager.OP_RECEIVE_MMS:
+            case AppOpsManager.OP_READ_CELL_BROADCASTS:
+            // CallLog permissions
+            case AppOpsManager.OP_READ_CALL_LOG:
+            case AppOpsManager.OP_WRITE_CALL_LOG:
+            case AppOpsManager.OP_PROCESS_OUTGOING_CALLS: {
+                // ActivityThread.currentApplication() is never null
+                if (Settings.Global.getInt(ActivityThread.currentApplication().getContentResolver(),
+                        Settings.Global.SMS_ACCESS_RESTRICTION_ENABLED, 0) == 1) {
+                    return AppOpsManager.MODE_DEFAULT;
+                }
+            }
+        }
         return sOpDefaultMode[op];
     }
 
@@ -1982,6 +2017,26 @@
         }
     }
 
+    /**
+     * Resets given app op in its default mode for app ops in the UID.
+     * This applies to all apps currently in the UID or installed in this UID in the future.
+     *
+     * @param appOp The app op.
+     * @param uid The UID for which to set the app.
+     *
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES)
+    @SystemApi
+    public void resetUidMode(String appOp, int uid, boolean force) {
+        int code = strOpToOp(appOp);
+        if (!(opAllowsReset(code) || force)) {
+            return;
+        }
+        int mode = opToDefaultMode(code);
+        setUidMode(code, uid, mode);
+    }
+
     /** @hide */
     public void setUserRestriction(int code, boolean restricted, IBinder token) {
         setUserRestriction(code, restricted, token, /*exceptionPackages*/null);
diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl
index b7b6352..fcfcc21 100644
--- a/core/java/android/app/IActivityTaskManager.aidl
+++ b/core/java/android/app/IActivityTaskManager.aidl
@@ -177,6 +177,7 @@
     void cancelRecentsAnimation(boolean restoreHomeStackPosition);
     void startLockTaskModeByToken(in IBinder token);
     void stopLockTaskModeByToken(in IBinder token);
+    void updateLockTaskPackages(int userId, in String[] packages);
     boolean isInLockTaskMode();
     int getLockTaskModeState();
     void setTaskDescription(in IBinder token, in ActivityManager.TaskDescription values);
diff --git a/core/java/android/app/InstantAppResolverService.java b/core/java/android/app/InstantAppResolverService.java
index 8f83ee3..b1541c6 100644
--- a/core/java/android/app/InstantAppResolverService.java
+++ b/core/java/android/app/InstantAppResolverService.java
@@ -240,7 +240,7 @@
                 args.arg4 = token;
                 args.arg5 = sanitizedIntent;
                 mHandler.obtainMessage(ServiceHandler.MSG_GET_INSTANT_APP_INTENT_FILTER,
-                        callback).sendToTarget();
+                        args).sendToTarget();
             }
         };
     }
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 4f41da6..6d464fb 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -1275,6 +1275,8 @@
     private String mShortcutId;
     private CharSequence mSettingsText;
 
+    private PendingIntent mAppOverlayIntent;
+
     /** @hide */
     @IntDef(prefix = { "GROUP_ALERT_" }, value = {
             GROUP_ALERT_ALL, GROUP_ALERT_CHILDREN, GROUP_ALERT_SUMMARY
@@ -2225,6 +2227,9 @@
         }
 
         mGroupAlertBehavior = parcel.readInt();
+        if (parcel.readInt() != 0) {
+            mAppOverlayIntent = PendingIntent.CREATOR.createFromParcel(parcel);
+        }
     }
 
     @Override
@@ -2339,6 +2344,7 @@
         that.mBadgeIcon = this.mBadgeIcon;
         that.mSettingsText = this.mSettingsText;
         that.mGroupAlertBehavior = this.mGroupAlertBehavior;
+        that.mAppOverlayIntent = this.mAppOverlayIntent;
 
         if (!heavy) {
             that.lightenPayload(); // will clean out extras
@@ -2660,6 +2666,13 @@
 
         parcel.writeInt(mGroupAlertBehavior);
 
+        if (mAppOverlayIntent != null) {
+            parcel.writeInt(1);
+            mAppOverlayIntent.writeToParcel(parcel, 0);
+        } else {
+            parcel.writeInt(0);
+        }
+
         // mUsesStandardHeader is not written because it should be recomputed in listeners
     }
 
@@ -3073,6 +3086,14 @@
     }
 
     /**
+     * Returns the intent that will be used to display app content in a floating window over the
+     * existing foreground activity.
+     */
+    public PendingIntent getAppOverlayIntent() {
+        return mAppOverlayIntent;
+    }
+
+    /**
      * The small icon representing this notification in the status bar and content view.
      *
      * @return the small icon representing this notification.
@@ -3406,6 +3427,23 @@
             return this;
         }
 
+        /**
+         * Sets the intent that will be used to display app content in a floating window
+         * over the existing foreground activity.
+         *
+         * <p>This intent will be ignored unless this notification is posted to a channel that
+         * allows {@link NotificationChannel#canOverlayApps() app overlays}.</p>
+         *
+         * <p>Notifications with a valid and allowed app overlay intent will be displayed as
+         * floating windows outside of the notification shade on unlocked devices. When a user
+         * interacts with one of these windows, this app overlay intent will be invoked and
+         * displayed.</p>
+         */
+        public Builder setAppOverlayIntent(PendingIntent intent) {
+            mN.mAppOverlayIntent = intent;
+            return this;
+        }
+
         /** @removed */
         @Deprecated
         public Builder setChannel(String channelId) {
diff --git a/core/java/android/app/NotificationChannel.java b/core/java/android/app/NotificationChannel.java
index 9f93e17..41ceaaf 100644
--- a/core/java/android/app/NotificationChannel.java
+++ b/core/java/android/app/NotificationChannel.java
@@ -15,6 +15,8 @@
  */
 package android.app;
 
+import static android.app.NotificationManager.IMPORTANCE_HIGH;
+
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.annotation.UnsupportedAppUsage;
@@ -41,6 +43,7 @@
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.Arrays;
+import java.util.Objects;
 
 /**
  * A representation of settings that apply to a collection of similarly themed notifications.
@@ -81,6 +84,7 @@
     private static final String ATT_FG_SERVICE_SHOWN = "fgservice";
     private static final String ATT_GROUP = "group";
     private static final String ATT_BLOCKABLE_SYSTEM = "blockable_system";
+    private static final String ATT_ALLOW_APP_OVERLAY = "app_overlay";
     private static final String DELIMITER = ",";
 
     /**
@@ -116,6 +120,11 @@
     /**
      * @hide
      */
+    public static final int USER_LOCKED_ALLOW_APP_OVERLAY = 0x00000100;
+
+    /**
+     * @hide
+     */
     public static final int[] LOCKABLE_FIELDS = new int[] {
             USER_LOCKED_PRIORITY,
             USER_LOCKED_VISIBILITY,
@@ -124,6 +133,7 @@
             USER_LOCKED_VIBRATION,
             USER_LOCKED_SOUND,
             USER_LOCKED_SHOW_BADGE,
+            USER_LOCKED_ALLOW_APP_OVERLAY
     };
 
     private static final int DEFAULT_LIGHT_COLOR = 0;
@@ -133,6 +143,7 @@
             NotificationManager.IMPORTANCE_UNSPECIFIED;
     private static final boolean DEFAULT_DELETED = false;
     private static final boolean DEFAULT_SHOW_BADGE = true;
+    private static final boolean DEFAULT_ALLOW_APP_OVERLAY = true;
 
     @UnsupportedAppUsage
     private final String mId;
@@ -156,6 +167,7 @@
     private AudioAttributes mAudioAttributes = Notification.AUDIO_ATTRIBUTES_DEFAULT;
     // If this is a blockable system notification channel.
     private boolean mBlockableSystem = false;
+    private boolean mAllowAppOverlay = DEFAULT_ALLOW_APP_OVERLAY;
 
     /**
      * Creates a notification channel.
@@ -217,6 +229,7 @@
         mAudioAttributes = in.readInt() > 0 ? AudioAttributes.CREATOR.createFromParcel(in) : null;
         mLightColor = in.readInt();
         mBlockableSystem = in.readBoolean();
+        mAllowAppOverlay = in.readBoolean();
     }
 
     @Override
@@ -269,6 +282,7 @@
         }
         dest.writeInt(mLightColor);
         dest.writeBoolean(mBlockableSystem);
+        dest.writeBoolean(mAllowAppOverlay);
     }
 
     /**
@@ -461,6 +475,22 @@
     }
 
     /**
+     * Sets whether notifications posted to this channel can appear outside of the notification
+     * shade, floating over other apps' content.
+     *
+     * <p>This value will be ignored for channels that aren't allowed to pop on screen (that is,
+     * channels whose {@link #getImportance() importance} is <
+     * {@link NotificationManager#IMPORTANCE_HIGH}.</p>
+     *
+     * <p>Only modifiable before the channel is submitted to
+     *      * {@link NotificationManager#createNotificationChannel(NotificationChannel)}.</p>
+     * @see Notification#getAppOverlayIntent()
+     */
+    public void setAllowAppOverlay(boolean allowAppOverlay) {
+        mAllowAppOverlay = allowAppOverlay;
+    }
+
+    /**
      * Returns the id of this channel.
      */
     public String getId() {
@@ -573,6 +603,22 @@
     }
 
     /**
+     * Returns whether notifications posted to this channel can display outside of the notification
+     * shade, in a floating window on top of other apps.
+     */
+    public boolean canOverlayApps() {
+        return isAppOverlayAllowed() && getImportance() >= IMPORTANCE_HIGH;
+    }
+
+    /**
+     * Like {@link #canOverlayApps()}, but only checks the permission, not the importance.
+     * @hide
+     */
+    public boolean isAppOverlayAllowed() {
+        return mAllowAppOverlay;
+    }
+
+    /**
      * @hide
      */
     @SystemApi
@@ -605,6 +651,7 @@
     /**
      * Returns whether the user has chosen the importance of this channel, either to affirm the
      * initial selection from the app, or changed it to be higher or lower.
+     * @see #getImportance()
      */
     public boolean hasUserSetImportance() {
         return (mUserLockedFields & USER_LOCKED_IMPORTANCE) != 0;
@@ -652,6 +699,7 @@
         lockFields(safeInt(parser, ATT_USER_LOCKED, 0));
         setFgServiceShown(safeBool(parser, ATT_FG_SERVICE_SHOWN, false));
         setBlockableSystem(safeBool(parser, ATT_BLOCKABLE_SYSTEM, false));
+        setAllowAppOverlay(safeBool(parser, ATT_ALLOW_APP_OVERLAY, DEFAULT_ALLOW_APP_OVERLAY));
     }
 
     @Nullable
@@ -770,6 +818,9 @@
         if (isBlockableSystem()) {
             out.attribute(null, ATT_BLOCKABLE_SYSTEM, Boolean.toString(isBlockableSystem()));
         }
+        if (canOverlayApps() != DEFAULT_ALLOW_APP_OVERLAY) {
+            out.attribute(null, ATT_ALLOW_APP_OVERLAY, Boolean.toString(canOverlayApps()));
+        }
 
         out.endTag(null, TAG_CHANNEL);
     }
@@ -812,6 +863,7 @@
         record.put(ATT_DELETED, Boolean.toString(isDeleted()));
         record.put(ATT_GROUP, getGroup());
         record.put(ATT_BLOCKABLE_SYSTEM, isBlockableSystem());
+        record.put(ATT_ALLOW_APP_OVERLAY, canOverlayApps());
         return record;
     }
 
@@ -899,58 +951,36 @@
     public boolean equals(Object o) {
         if (this == o) return true;
         if (o == null || getClass() != o.getClass()) return false;
-
         NotificationChannel that = (NotificationChannel) o;
-
-        if (getImportance() != that.getImportance()) return false;
-        if (mBypassDnd != that.mBypassDnd) return false;
-        if (getLockscreenVisibility() != that.getLockscreenVisibility()) return false;
-        if (mLights != that.mLights) return false;
-        if (getLightColor() != that.getLightColor()) return false;
-        if (getUserLockedFields() != that.getUserLockedFields()) return false;
-        if (mVibrationEnabled != that.mVibrationEnabled) return false;
-        if (mShowBadge != that.mShowBadge) return false;
-        if (isDeleted() != that.isDeleted()) return false;
-        if (isBlockableSystem() != that.isBlockableSystem()) return false;
-        if (getId() != null ? !getId().equals(that.getId()) : that.getId() != null) return false;
-        if (getName() != null ? !getName().equals(that.getName()) : that.getName() != null) {
-            return false;
-        }
-        if (getDescription() != null ? !getDescription().equals(that.getDescription())
-                : that.getDescription() != null) {
-            return false;
-        }
-        if (getSound() != null ? !getSound().equals(that.getSound()) : that.getSound() != null) {
-            return false;
-        }
-        if (!Arrays.equals(mVibration, that.mVibration)) return false;
-        if (getGroup() != null ? !getGroup().equals(that.getGroup()) : that.getGroup() != null) {
-            return false;
-        }
-        return getAudioAttributes() != null ? getAudioAttributes().equals(that.getAudioAttributes())
-                : that.getAudioAttributes() == null;
-
+        return getImportance() == that.getImportance() &&
+                mBypassDnd == that.mBypassDnd &&
+                getLockscreenVisibility() == that.getLockscreenVisibility() &&
+                mLights == that.mLights &&
+                getLightColor() == that.getLightColor() &&
+                getUserLockedFields() == that.getUserLockedFields() &&
+                isFgServiceShown() == that.isFgServiceShown() &&
+                mVibrationEnabled == that.mVibrationEnabled &&
+                mShowBadge == that.mShowBadge &&
+                isDeleted() == that.isDeleted() &&
+                isBlockableSystem() == that.isBlockableSystem() &&
+                mAllowAppOverlay == that.mAllowAppOverlay &&
+                Objects.equals(getId(), that.getId()) &&
+                Objects.equals(getName(), that.getName()) &&
+                Objects.equals(mDesc, that.mDesc) &&
+                Objects.equals(getSound(), that.getSound()) &&
+                Arrays.equals(mVibration, that.mVibration) &&
+                Objects.equals(getGroup(), that.getGroup()) &&
+                Objects.equals(getAudioAttributes(), that.getAudioAttributes());
     }
 
     @Override
     public int hashCode() {
-        int result = getId() != null ? getId().hashCode() : 0;
-        result = 31 * result + (getName() != null ? getName().hashCode() : 0);
-        result = 31 * result + (getDescription() != null ? getDescription().hashCode() : 0);
-        result = 31 * result + getImportance();
-        result = 31 * result + (mBypassDnd ? 1 : 0);
-        result = 31 * result + getLockscreenVisibility();
-        result = 31 * result + (getSound() != null ? getSound().hashCode() : 0);
-        result = 31 * result + (mLights ? 1 : 0);
-        result = 31 * result + getLightColor();
+        int result = Objects.hash(getId(), getName(), mDesc, getImportance(), mBypassDnd,
+                getLockscreenVisibility(), getSound(), mLights, getLightColor(),
+                getUserLockedFields(),
+                isFgServiceShown(), mVibrationEnabled, mShowBadge, isDeleted(), getGroup(),
+                getAudioAttributes(), isBlockableSystem(), mAllowAppOverlay);
         result = 31 * result + Arrays.hashCode(mVibration);
-        result = 31 * result + getUserLockedFields();
-        result = 31 * result + (mVibrationEnabled ? 1 : 0);
-        result = 31 * result + (mShowBadge ? 1 : 0);
-        result = 31 * result + (isDeleted() ? 1 : 0);
-        result = 31 * result + (getGroup() != null ? getGroup().hashCode() : 0);
-        result = 31 * result + (getAudioAttributes() != null ? getAudioAttributes().hashCode() : 0);
-        result = 31 * result + (isBlockableSystem() ? 1 : 0);
         return result;
     }
 
@@ -976,6 +1006,7 @@
                 + ", mGroup='" + mGroup + '\''
                 + ", mAudioAttributes=" + mAudioAttributes
                 + ", mBlockableSystem=" + mBlockableSystem
+                + ", mAllowAppOverlay=" + mAllowAppOverlay
                 + '}';
         pw.println(prefix + output);
     }
@@ -1001,6 +1032,7 @@
                 + ", mGroup='" + mGroup + '\''
                 + ", mAudioAttributes=" + mAudioAttributes
                 + ", mBlockableSystem=" + mBlockableSystem
+                + ", mAllowAppOverlay=" + mAllowAppOverlay
                 + '}';
     }
 
@@ -1034,6 +1066,7 @@
             mAudioAttributes.writeToProto(proto, NotificationChannelProto.AUDIO_ATTRIBUTES);
         }
         proto.write(NotificationChannelProto.IS_BLOCKABLE_SYSTEM, mBlockableSystem);
+        proto.write(NotificationChannelProto.ALLOW_APP_OVERLAY, mAllowAppOverlay);
 
         proto.end(token);
     }
diff --git a/core/java/android/app/NotificationChannelGroup.java b/core/java/android/app/NotificationChannelGroup.java
index 17c5cba..2322a42 100644
--- a/core/java/android/app/NotificationChannelGroup.java
+++ b/core/java/android/app/NotificationChannelGroup.java
@@ -32,6 +32,7 @@
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Objects;
 
 /**
  * A grouping of related notification channels. e.g., channels that all belong to a single account.
@@ -49,13 +50,33 @@
     private static final String ATT_DESC = "desc";
     private static final String ATT_ID = "id";
     private static final String ATT_BLOCKED = "blocked";
+    private static final String ATT_ALLOW_APP_OVERLAY = "app_overlay";
+    private static final String ATT_USER_LOCKED = "locked";
 
+    private static final boolean DEFAULT_ALLOW_APP_OVERLAY = true;
+
+    /**
+     * @hide
+     */
+    public static final int USER_LOCKED_BLOCKED_STATE = 0x00000001;
+    /**
+     * @hide
+     */
+    @TestApi
+    public static final int USER_LOCKED_ALLOW_APP_OVERLAY = 0x00000002;
+
+    /**
+     * @see #getId()
+     */
     @UnsupportedAppUsage
     private final String mId;
     private CharSequence mName;
     private String mDescription;
     private boolean mBlocked;
     private List<NotificationChannel> mChannels = new ArrayList<>();
+    private boolean mAllowAppOverlay = DEFAULT_ALLOW_APP_OVERLAY;
+    // Bitwise representation of fields that have been changed by the user
+    private int mUserLockedFields;
 
     /**
      * Creates a notification channel group.
@@ -89,6 +110,8 @@
         }
         in.readParcelableList(mChannels, NotificationChannel.class.getClassLoader());
         mBlocked = in.readBoolean();
+        mAllowAppOverlay = in.readBoolean();
+        mUserLockedFields = in.readInt();
     }
 
     private String getTrimmedString(String input) {
@@ -115,6 +138,8 @@
         }
         dest.writeParcelableList(mChannels, flags);
         dest.writeBoolean(mBlocked);
+        dest.writeBoolean(mAllowAppOverlay);
+        dest.writeInt(mUserLockedFields);
     }
 
     /**
@@ -156,6 +181,15 @@
     }
 
     /**
+     * Returns whether notifications posted to this channel group can display outside of the
+     * notification shade, in a floating window on top of other apps. These may additionally be
+     * blocked at the notification channel level, see {@link NotificationChannel#canOverlayApps()}.
+     */
+    public boolean canOverlayApps() {
+        return mAllowAppOverlay;
+    }
+
+    /**
      * Sets the user visible description of this group.
      *
      * <p>The recommended maximum length is 300 characters; the value may be truncated if it is too
@@ -166,6 +200,21 @@
     }
 
     /**
+     * Sets whether notifications posted to this channel group can appear outside of the
+     * notification shade, floating over other apps' content.
+     *
+     * <p>This value will be ignored for notifications that are posted to channels that do not
+     * allow app overlays ({@link NotificationChannel#canOverlayApps()}.
+     *
+     * <p>Only modifiable before the channel is submitted to
+     * {@link NotificationManager#createNotificationChannelGroup(NotificationChannelGroup)}.</p>
+     * @see Notification#getAppOverlayIntent()
+     */
+    public void setAllowAppOverlay(boolean allowAppOverlay) {
+        mAllowAppOverlay = allowAppOverlay;
+    }
+
+    /**
      * @hide
      */
     @TestApi
@@ -190,10 +239,34 @@
     /**
      * @hide
      */
+    @TestApi
+    public void lockFields(int field) {
+        mUserLockedFields |= field;
+    }
+
+    /**
+     * @hide
+     */
+    public void unlockFields(int field) {
+        mUserLockedFields &= ~field;
+    }
+
+    /**
+     * @hide
+     */
+    @TestApi
+    public int getUserLockedFields() {
+        return mUserLockedFields;
+    }
+
+    /**
+     * @hide
+     */
     public void populateFromXml(XmlPullParser parser) {
         // Name, id, and importance are set in the constructor.
         setDescription(parser.getAttributeValue(null, ATT_DESC));
         setBlocked(safeBool(parser, ATT_BLOCKED, false));
+        setAllowAppOverlay(safeBool(parser, ATT_ALLOW_APP_OVERLAY, DEFAULT_ALLOW_APP_OVERLAY));
     }
 
     private static boolean safeBool(XmlPullParser parser, String att, boolean defValue) {
@@ -216,6 +289,10 @@
             out.attribute(null, ATT_DESC, getDescription().toString());
         }
         out.attribute(null, ATT_BLOCKED, Boolean.toString(isBlocked()));
+        if (canOverlayApps() != DEFAULT_ALLOW_APP_OVERLAY) {
+            out.attribute(null, ATT_ALLOW_APP_OVERLAY, Boolean.toString(canOverlayApps()));
+        }
+        out.attribute(null, ATT_USER_LOCKED, Integer.toString(mUserLockedFields));
 
         out.endTag(null, TAG_GROUP);
     }
@@ -230,6 +307,8 @@
         record.put(ATT_NAME, getName());
         record.put(ATT_DESC, getDescription());
         record.put(ATT_BLOCKED, isBlocked());
+        record.put(ATT_ALLOW_APP_OVERLAY, canOverlayApps());
+        record.put(ATT_USER_LOCKED, mUserLockedFields);
         return record;
     }
 
@@ -255,30 +334,20 @@
     public boolean equals(Object o) {
         if (this == o) return true;
         if (o == null || getClass() != o.getClass()) return false;
-
         NotificationChannelGroup that = (NotificationChannelGroup) o;
-
-        if (isBlocked() != that.isBlocked()) return false;
-        if (getId() != null ? !getId().equals(that.getId()) : that.getId() != null) return false;
-        if (getName() != null ? !getName().equals(that.getName()) : that.getName() != null) {
-            return false;
-        }
-        if (getDescription() != null ? !getDescription().equals(that.getDescription())
-                : that.getDescription() != null) {
-            return false;
-        }
-        return getChannels() != null ? getChannels().equals(that.getChannels())
-                : that.getChannels() == null;
+        return isBlocked() == that.isBlocked() &&
+                mAllowAppOverlay == that.mAllowAppOverlay &&
+                mUserLockedFields == that.mUserLockedFields &&
+                Objects.equals(getId(), that.getId()) &&
+                Objects.equals(getName(), that.getName()) &&
+                Objects.equals(getDescription(), that.getDescription()) &&
+                Objects.equals(getChannels(), that.getChannels());
     }
 
     @Override
     public int hashCode() {
-        int result = getId() != null ? getId().hashCode() : 0;
-        result = 31 * result + (getName() != null ? getName().hashCode() : 0);
-        result = 31 * result + (getDescription() != null ? getDescription().hashCode() : 0);
-        result = 31 * result + (isBlocked() ? 1 : 0);
-        result = 31 * result + (getChannels() != null ? getChannels().hashCode() : 0);
-        return result;
+        return Objects.hash(getId(), getName(), getDescription(), isBlocked(), getChannels(),
+                mAllowAppOverlay, mUserLockedFields);
     }
 
     @Override
@@ -287,6 +356,8 @@
         cloned.setDescription(getDescription());
         cloned.setBlocked(isBlocked());
         cloned.setChannels(getChannels());
+        cloned.setAllowAppOverlay(canOverlayApps());
+        cloned.lockFields(mUserLockedFields);
         return cloned;
     }
 
@@ -298,6 +369,8 @@
                 + ", mDescription=" + (!TextUtils.isEmpty(mDescription) ? "hasDescription " : "")
                 + ", mBlocked=" + mBlocked
                 + ", mChannels=" + mChannels
+                + ", mAllowAppOverlay=" + mAllowAppOverlay
+                + ", mUserLockedFields=" + mUserLockedFields
                 + '}';
     }
 
@@ -312,7 +385,7 @@
         for (NotificationChannel channel : mChannels) {
             channel.writeToProto(proto, NotificationChannelGroupProto.CHANNELS);
         }
-
+        proto.write(NotificationChannelGroupProto.ALLOW_APP_OVERLAY, mAllowAppOverlay);
         proto.end(token);
     }
 }
diff --git a/core/java/android/app/ProcessMemoryState.java b/core/java/android/app/ProcessMemoryState.java
index 9bfdae0..d149243 100644
--- a/core/java/android/app/ProcessMemoryState.java
+++ b/core/java/android/app/ProcessMemoryState.java
@@ -33,10 +33,11 @@
     public final long cacheInBytes;
     public final long swapInBytes;
     public final long rssHighWatermarkInBytes;
+    public final long startTimeNanos;
 
     public ProcessMemoryState(int uid, String processName, int oomScore, long pgfault,
                               long pgmajfault, long rssInBytes, long cacheInBytes,
-                              long swapInBytes, long rssHighWatermarkInBytes) {
+                              long swapInBytes, long rssHighWatermarkInBytes, long startTimeNanos) {
         this.uid = uid;
         this.processName = processName;
         this.oomScore = oomScore;
@@ -46,6 +47,7 @@
         this.cacheInBytes = cacheInBytes;
         this.swapInBytes = swapInBytes;
         this.rssHighWatermarkInBytes = rssHighWatermarkInBytes;
+        this.startTimeNanos = startTimeNanos;
     }
 
     private ProcessMemoryState(Parcel in) {
@@ -58,6 +60,7 @@
         cacheInBytes = in.readLong();
         swapInBytes = in.readLong();
         rssHighWatermarkInBytes = in.readLong();
+        startTimeNanos = in.readLong();
     }
 
     public static final Creator<ProcessMemoryState> CREATOR = new Creator<ProcessMemoryState>() {
@@ -88,5 +91,6 @@
         parcel.writeLong(cacheInBytes);
         parcel.writeLong(swapInBytes);
         parcel.writeLong(rssHighWatermarkInBytes);
+        parcel.writeLong(startTimeNanos);
     }
 }
diff --git a/core/java/android/app/role/IRoleManager.aidl b/core/java/android/app/role/IRoleManager.aidl
new file mode 100644
index 0000000..64f69c1
--- /dev/null
+++ b/core/java/android/app/role/IRoleManager.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.role;
+
+import android.app.role.IRoleManagerCallback;
+
+/**
+ * @hide
+ */
+interface IRoleManager {
+
+    boolean isRoleAvailable(in String roleName);
+
+    boolean isRoleHeld(in String roleName, in String packageName);
+
+    List<String> getRoleHoldersAsUser(in String roleName, int userId);
+
+    void addRoleHolderAsUser(in String roleName, in String packageName, int userId,
+            in IRoleManagerCallback callback);
+
+    void removeRoleHolderAsUser(in String roleName, in String packageName, int userId,
+            in IRoleManagerCallback callback);
+
+    void clearRoleHoldersAsUser(in String roleName, int userId, in IRoleManagerCallback callback);
+}
diff --git a/core/java/android/app/role/IRoleManagerCallback.aidl b/core/java/android/app/role/IRoleManagerCallback.aidl
new file mode 100644
index 0000000..c0f8eea
--- /dev/null
+++ b/core/java/android/app/role/IRoleManagerCallback.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.role;
+
+/**
+ * @hide
+ */
+oneway interface IRoleManagerCallback {
+
+    void onSuccess();
+
+    void onFailure();
+}
diff --git a/core/java/android/app/role/RoleManager.java b/core/java/android/app/role/RoleManager.java
new file mode 100644
index 0000000..f7c6dea
--- /dev/null
+++ b/core/java/android/app/role/RoleManager.java
@@ -0,0 +1,348 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.role;
+
+import android.Manifest;
+import android.annotation.CallbackExecutor;
+import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
+import android.annotation.SystemService;
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Binder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.UserHandle;
+import android.util.ArraySet;
+
+import com.android.internal.util.Preconditions;
+
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.Executor;
+
+/**
+ * This class provides information about and manages roles.
+ * <p>
+ * A role is a unique name within the system associated with certain privileges. The list of
+ * available roles might change with a system app update, so apps should not make assumption about
+ * the availability of roles. Instead, they should always query if the role is available using
+ * {@link #isRoleAvailable(String)} before trying to do anything with it. Some predefined role names
+ * are available as constants in this class, and a list of possibly available roles can be found in
+ * the AndroidX Libraries.
+ * <p>
+ * There can be multiple applications qualifying for a role, but only a subset of them can become
+ * role holders. To qualify for a role, an application must meet certain requirements, including
+ * defining certain components in its manifest. These requirements can be found in the AndroidX
+ * Libraries. Then the application will need user consent to become a role holder, which can be
+ * requested using {@link Activity#startActivityForResult(Intent, int)} with the {@code Intent}
+ * obtained from {@link #createRequestRoleIntent(String)}.
+ * <p>
+ * Upon becoming a role holder, the application may be granted certain privileges that are role
+ * specific. When the application loses its role, these privileges will also be revoked.
+ */
+@SystemService(Context.ROLE_SERVICE)
+public final class RoleManager {
+
+    private static final String LOG_TAG = RoleManager.class.getSimpleName();
+
+    /**
+     * The name of the dialer role.
+     */
+    public static final String ROLE_DIALER = "android.app.role.DIALER";
+
+    /**
+     * The name of the SMS role.
+     */
+    public static final String ROLE_SMS = "android.app.role.SMS";
+
+    /**
+     * The action used to request user approval of a role for an application.
+     *
+     * @hide
+     */
+    public static final String ACTION_REQUEST_ROLE = "android.app.role.action.REQUEST_ROLE";
+
+    /**
+     * The name of the requested role.
+     * <p>
+     * <strong>Type:</strong> String
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final String EXTRA_REQUEST_ROLE_NAME = "android.app.role.extra.REQUEST_ROLE_NAME";
+
+    @NonNull
+    private final Context mContext;
+
+    @NonNull
+    private final IRoleManager mService;
+
+    /**
+     * @hide
+     */
+    public RoleManager(@NonNull Context context) throws ServiceManager.ServiceNotFoundException {
+        mContext = context;
+        mService = IRoleManager.Stub.asInterface(ServiceManager.getServiceOrThrow(
+                Context.ROLE_SERVICE));
+    }
+
+    /**
+     * Returns an {@code Intent} suitable for passing to {@link Activity#startActivityForResult(
+     * Intent, int)} which prompts the user to grant a role to this application.
+     * <p>
+     * If the role is granted, the {@code resultCode} will be {@link Activity#RESULT_OK}, otherwise
+     * it will be {@link Activity#RESULT_CANCELED}.
+     *
+     * @param roleName the name of requested role
+     *
+     * @return the {@code Intent} to prompt user to grant the role
+     *
+     * @throws IllegalArgumentException if {@code role} is {@code null} or empty
+     */
+    @NonNull
+    public Intent createRequestRoleIntent(@NonNull String roleName) {
+        Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
+        Intent intent = new Intent(ACTION_REQUEST_ROLE);
+        intent.setPackage(mContext.getPackageManager().getPermissionControllerPackageName());
+        intent.putExtra(EXTRA_REQUEST_ROLE_NAME, roleName);
+        return intent;
+    }
+
+    /**
+     * Check whether a role is available in the system.
+     *
+     * @param roleName the name of role to checking for
+     *
+     * @return whether the role is available in the system
+     *
+     * @throws IllegalArgumentException if the role name is {@code null} or empty
+     */
+    public boolean isRoleAvailable(@NonNull String roleName) {
+        Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
+        try {
+            return mService.isRoleAvailable(roleName);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Check whether the calling application is holding a particular role.
+     *
+     * @param roleName the name of the role to check for
+     *
+     * @return whether the calling application is holding the role
+     *
+     * @throws IllegalArgumentException if the role name is {@code null} or empty.
+     */
+    public boolean isRoleHeld(@NonNull String roleName) {
+        Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
+        try {
+            return mService.isRoleHeld(roleName, mContext.getPackageName());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Get package names of the applications holding the role.
+     * <p>
+     * <strong>Note: </strong>Using this API requires holding
+     * {@code android.permission.MANAGE_ROLE_HOLDERS} and if the user id is not the current user
+     * {@code android.permission.INTERACT_ACROSS_USERS_FULL}.
+     *
+     * @param roleName the name of the role to get the role holder for
+     * @param user the user to get the role holder for
+     *
+     * @return the package name of the role holder, or {@code null} if none.
+     *
+     * @throws IllegalArgumentException if the role name is {@code null} or empty.
+     *
+     * @see #addRoleHolderAsUser(String, String, UserHandle, Executor, RoleManagerCallback)
+     * @see #removeRoleHolderAsUser(String, String, UserHandle, Executor, RoleManagerCallback)
+     * @see #clearRoleHoldersAsUser(String, UserHandle, Executor, RoleManagerCallback)
+     *
+     * @hide
+     */
+    @NonNull
+    @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS)
+    @SystemApi
+    public Set<String> getRoleHoldersAsUser(@NonNull String roleName, @NonNull UserHandle user) {
+        Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
+        Preconditions.checkNotNull(user, "user cannot be null");
+        List<String> roleHolders;
+        try {
+            roleHolders = mService.getRoleHoldersAsUser(roleName, user.getIdentifier());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+        return new ArraySet<>(roleHolders);
+    }
+
+    /**
+     * Add a specific application to the holders of a role. If the role is exclusive, the previous
+     * holder will be replaced.
+     * <p>
+     * <strong>Note: </strong>Using this API requires holding
+     * {@code android.permission.MANAGE_ROLE_HOLDERS} and if the user id is not the current user
+     * {@code android.permission.INTERACT_ACROSS_USERS_FULL}.
+     *
+     * @param roleName the name of the role to add the role holder for
+     * @param packageName the package name of the application to add to the role holders
+     * @param user the user to add the role holder for
+     * @param executor the {@code Executor} to run the callback on.
+     * @param callback the callback for whether this call is successful
+     *
+     * @throws IllegalArgumentException if the role name or package name is {@code null} or empty.
+     *
+     * @see #getRoleHoldersAsUser(String, UserHandle)
+     * @see #removeRoleHolderAsUser(String, String, UserHandle, Executor, RoleManagerCallback)
+     * @see #clearRoleHoldersAsUser(String, UserHandle, Executor, RoleManagerCallback)
+     *
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS)
+    @SystemApi
+    public void addRoleHolderAsUser(@NonNull String roleName, @NonNull String packageName,
+            @NonNull UserHandle user, @CallbackExecutor @NonNull Executor executor,
+            @NonNull RoleManagerCallback callback) {
+        Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
+        Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
+        Preconditions.checkNotNull(user, "user cannot be null");
+        Preconditions.checkNotNull(executor, "executor cannot be null");
+        Preconditions.checkNotNull(callback, "callback cannot be null");
+        try {
+            mService.addRoleHolderAsUser(roleName, packageName, user.getIdentifier(),
+                    new RoleManagerCallbackDelegate(executor, callback));
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Remove a specific application from the holders of a role.
+     * <p>
+     * <strong>Note: </strong>Using this API requires holding
+     * {@code android.permission.MANAGE_ROLE_HOLDERS} and if the user id is not the current user
+     * {@code android.permission.INTERACT_ACROSS_USERS_FULL}.
+     *
+     * @param roleName the name of the role to remove the role holder for
+     * @param packageName the package name of the application to remove from the role holders
+     * @param user the user to remove the role holder for
+     * @param executor the {@code Executor} to run the callback on.
+     * @param callback the callback for whether this call is successful
+     *
+     * @throws IllegalArgumentException if the role name or package name is {@code null} or empty.
+     *
+     * @see #getRoleHoldersAsUser(String, UserHandle)
+     * @see #addRoleHolderAsUser(String, String, UserHandle, Executor, RoleManagerCallback)
+     * @see #clearRoleHoldersAsUser(String, UserHandle, Executor, RoleManagerCallback)
+     *
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS)
+    @SystemApi
+    public void removeRoleHolderAsUser(@NonNull String roleName, @NonNull String packageName,
+            @NonNull UserHandle user, @CallbackExecutor @NonNull Executor executor,
+            @NonNull RoleManagerCallback callback) {
+        Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
+        Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
+        Preconditions.checkNotNull(user, "user cannot be null");
+        Preconditions.checkNotNull(executor, "executor cannot be null");
+        Preconditions.checkNotNull(callback, "callback cannot be null");
+        try {
+            mService.removeRoleHolderAsUser(roleName, packageName, user.getIdentifier(),
+                    new RoleManagerCallbackDelegate(executor, callback));
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Remove all holders of a role.
+     * <p>
+     * <strong>Note: </strong>Using this API requires holding
+     * {@code android.permission.MANAGE_ROLE_HOLDERS} and if the user id is not the current user
+     * {@code android.permission.INTERACT_ACROSS_USERS_FULL}.
+     *
+     * @param roleName the name of the role to remove role holders for
+     * @param user the user to remove role holders for
+     * @param executor the {@code Executor} to run the callback on.
+     * @param callback the callback for whether this call is successful
+     *
+     * @throws IllegalArgumentException if the role name is {@code null} or empty.
+     *
+     * @see #getRoleHoldersAsUser(String, UserHandle)
+     * @see #addRoleHolderAsUser(String, String, UserHandle, Executor, RoleManagerCallback)
+     * @see #removeRoleHolderAsUser(String, String, UserHandle, Executor, RoleManagerCallback)
+     *
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS)
+    @SystemApi
+    public void clearRoleHoldersAsUser(@NonNull String roleName, @NonNull UserHandle user,
+            @CallbackExecutor @NonNull Executor executor, @NonNull RoleManagerCallback callback) {
+        Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
+        Preconditions.checkNotNull(user, "user cannot be null");
+        Preconditions.checkNotNull(executor, "executor cannot be null");
+        Preconditions.checkNotNull(callback, "callback cannot be null");
+        try {
+            mService.clearRoleHoldersAsUser(roleName, user.getIdentifier(),
+                    new RoleManagerCallbackDelegate(executor, callback));
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    private static class RoleManagerCallbackDelegate extends IRoleManagerCallback.Stub {
+
+        @NonNull
+        private final Executor mExecutor;
+        @NonNull
+        private final RoleManagerCallback mCallback;
+
+        RoleManagerCallbackDelegate(@NonNull Executor executor,
+                @NonNull RoleManagerCallback callback) {
+            mExecutor = executor;
+            mCallback = callback;
+        }
+
+        @Override
+        public void onSuccess() {
+            long token = Binder.clearCallingIdentity();
+            try {
+                mExecutor.execute(mCallback::onSuccess);
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        @Override
+        public void onFailure() {
+            long token = Binder.clearCallingIdentity();
+            try {
+                mExecutor.execute(mCallback::onFailure);
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+    }
+}
diff --git a/core/java/android/app/role/RoleManagerCallback.java b/core/java/android/app/role/RoleManagerCallback.java
new file mode 100644
index 0000000..ca68ebc
--- /dev/null
+++ b/core/java/android/app/role/RoleManagerCallback.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.role;
+
+import android.annotation.SystemApi;
+
+/**
+ * Callback for a {@link RoleManager} request.
+ *
+ * @hide
+ */
+@SystemApi
+public interface RoleManagerCallback {
+
+    /**
+     * Signals a success.
+     */
+    void onSuccess();
+
+    /**
+     * Signals a failure.
+     */
+    void onFailure();
+}
diff --git a/core/java/android/app/usage/IUsageStatsManager.aidl b/core/java/android/app/usage/IUsageStatsManager.aidl
index 9713527..4d52263 100644
--- a/core/java/android/app/usage/IUsageStatsManager.aidl
+++ b/core/java/android/app/usage/IUsageStatsManager.aidl
@@ -51,4 +51,8 @@
     void registerAppUsageObserver(int observerId, in String[] packages, long timeLimitMs,
             in PendingIntent callback, String callingPackage);
     void unregisterAppUsageObserver(int observerId, String callingPackage);
+    void registerUsageSessionObserver(int sessionObserverId, in String[] observed, long timeLimitMs,
+            long sessionThresholdTimeMs, in PendingIntent limitReachedCallbackIntent,
+            in PendingIntent sessionEndCallbackIntent, String callingPackage);
+    void unregisterUsageSessionObserver(int sessionObserverId, String callingPackage);
 }
diff --git a/core/java/android/app/usage/UsageStatsManager.java b/core/java/android/app/usage/UsageStatsManager.java
index dbb00eb..6d7400e 100644
--- a/core/java/android/app/usage/UsageStatsManager.java
+++ b/core/java/android/app/usage/UsageStatsManager.java
@@ -18,6 +18,7 @@
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
@@ -595,7 +596,7 @@
      *                       exceeded by the group of apps. The delivered Intent will also contain
      *                       the extras {@link #EXTRA_OBSERVER_ID}, {@link #EXTRA_TIME_LIMIT} and
      *                       {@link #EXTRA_TIME_USED}. Cannot be null.
-     * @throws SecurityException if the caller doesn't have the OBSERVE_APP_USAGE permission or
+     * @throws SecurityException if the caller doesn't have the OBSERVE_APP_USAGE permission and
      *                           is not the profile owner of this user.
      */
     @SystemApi
@@ -616,7 +617,7 @@
      * to any observer registered by this application. Unregistering an observer that was already
      * unregistered or never registered will have no effect.
      * @param observerId The id of the observer that was previously registered.
-     * @throws SecurityException if the caller doesn't have the OBSERVE_APP_USAGE permission or is
+     * @throws SecurityException if the caller doesn't have the OBSERVE_APP_USAGE permission and is
      *                           not the profile owner of this user.
      */
     @SystemApi
@@ -629,6 +630,81 @@
         }
     }
 
+    /**
+     * Register a usage session observer that receives a callback on the provided {@code
+     * limitReachedCallbackIntent} when the sum of usages of apps in the packages array exceeds
+     * the {@code timeLimit} specified within a usage session. After the {@code timeLimit} has
+     * been reached, the usage session observer will receive a callback on the provided {@code
+     * sessionEndCallbackIntent} when the usage session ends. Registering another session
+     * observer against a {@code sessionObserverId} that has already been registered will
+     * override the previous session observer.
+     *
+     * @param sessionObserverId A unique id associated with the group of apps to be
+     *                          monitored. There can be multiple groups with common
+     *                          packages and different time limits.
+     * @param packages The list of packages to observe for foreground activity time. Cannot be null
+     *                 and must include at least one package.
+     * @param timeLimit The total time the set of apps can be used continuously before the {@code
+     *                  limitReachedCallbackIntent} is delivered. Must be at least one minute.
+     * @param timeUnit The unit for time specified in {@code timeLimit}. Cannot be null.
+     * @param sessionThresholdTime The time that can take place between usage sessions before the
+     *                             next session is considered a new session. Must be non-negative.
+     * @param sessionThresholdTimeUnit The unit for time specified in {@code sessionThreshold}.
+     *                                 Cannot be null.
+     * @param limitReachedCallbackIntent The {@link PendingIntent} that will be dispatched when the
+     *                                   time limit is exceeded by the group of apps. The delivered
+     *                                   Intent will also contain the extras {@link
+     *                                   #EXTRA_OBSERVER_ID}, {@link #EXTRA_TIME_LIMIT} and {@link
+     *                                   #EXTRA_TIME_USED}. Cannot be null.
+     * @param sessionEndCallbackIntent The {@link PendingIntent}  that will be dispatched when the
+     *                                 session has ended after the time limit has been exceeded. The
+     *                                 session is considered at its end after the {@code observed}
+     *                                 usage has stopped and an additional {@code
+     *                                 sessionThresholdTime} has passed. The delivered Intent will
+     *                                 also contain the extras {@link #EXTRA_OBSERVER_ID} and {@link
+     *                                 #EXTRA_TIME_USED}. Can be null.
+     * @throws SecurityException if the caller doesn't have the OBSERVE_APP_USAGE permission and
+     *                           is not the profile owner of this user.
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.OBSERVE_APP_USAGE)
+    public void registerUsageSessionObserver(int sessionObserverId, @NonNull String[] packages,
+            long timeLimit, @NonNull TimeUnit timeUnit, long sessionThresholdTime,
+            @NonNull TimeUnit sessionThresholdTimeUnit,
+            @NonNull PendingIntent limitReachedCallbackIntent,
+            @Nullable PendingIntent sessionEndCallbackIntent) {
+        try {
+            mService.registerUsageSessionObserver(sessionObserverId, packages,
+                    timeUnit.toMillis(timeLimit),
+                    sessionThresholdTimeUnit.toMillis(sessionThresholdTime),
+                    limitReachedCallbackIntent, sessionEndCallbackIntent,
+                    mContext.getOpPackageName());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Unregister the usage session observer specified by the {@code sessionObserverId}. This will
+     * only apply to any app session observer registered by this application. Unregistering an
+     * observer that was already unregistered or never registered will have no effect.
+     *
+     * @param sessionObserverId The id of the observer that was previously registered.
+     * @throws SecurityException if the caller doesn't have the OBSERVE_APP_USAGE permission and
+     *                           is not the profile owner of this user.
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.OBSERVE_APP_USAGE)
+    public void unregisterUsageSessionObserver(int sessionObserverId) {
+        try {
+            mService.unregisterUsageSessionObserver(sessionObserverId, mContext.getOpPackageName());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
     /** @hide */
     public static String reasonToString(int standbyReason) {
         StringBuilder sb = new StringBuilder();
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 599c2d2..4de1dfc 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -36,11 +36,9 @@
 import android.database.Cursor;
 import android.database.IContentObserver;
 import android.graphics.Bitmap;
-import android.graphics.Canvas;
 import android.graphics.ImageDecoder;
 import android.graphics.ImageDecoder.ImageInfo;
 import android.graphics.ImageDecoder.Source;
-import android.graphics.PixelFormat;
 import android.graphics.Point;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
@@ -54,8 +52,9 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemClock;
+import android.os.SystemProperties;
 import android.os.UserHandle;
-import android.provider.DocumentsContract;
+import android.os.storage.StorageManager;
 import android.text.TextUtils;
 import android.util.EventLog;
 import android.util.Log;
@@ -91,6 +90,30 @@
  */
 public abstract class ContentResolver {
     /**
+     * Enables logic that supports deprecation of {@code _data} columns,
+     * typically by replacing values with fake paths that the OS then offers to
+     * redirect to {@link #openFileDescriptor(Uri, String)}, which developers
+     * should be using directly.
+     *
+     * @hide
+     */
+    public static final boolean DEPRECATE_DATA_COLUMNS = SystemProperties
+            .getBoolean(StorageManager.PROP_ISOLATED_STORAGE, false);
+
+    /**
+     * Special filesystem path prefix which indicates that a path should be
+     * treated as a {@code content://} {@link Uri} when
+     * {@link #DEPRECATE_DATA_COLUMNS} is enabled.
+     * <p>
+     * The remainder of the path after this prefix is a
+     * {@link Uri#getSchemeSpecificPart()} value, which includes authority, path
+     * segments, and query parameters.
+     *
+     * @hide
+     */
+    public static final String DEPRECATE_DATA_PREFIX = "/mnt/content/";
+
+    /**
      * @deprecated instead use
      * {@link #requestSync(android.accounts.Account, String, android.os.Bundle)}
      */
@@ -3255,4 +3278,25 @@
             }
         });
     }
+
+    /** {@hide} */
+    public static void onDbCorruption(String tag, String message, Throwable stacktrace) {
+        try {
+            getContentService().onDbCorruption(tag, message, Log.getStackTraceString(stacktrace));
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+        }
+    }
+
+    /** {@hide} */
+    public static Uri translateDeprecatedDataPath(String path) {
+        final String ssp = "//" + path.substring(DEPRECATE_DATA_PREFIX.length());
+        return Uri.parse(new Uri.Builder().scheme(SCHEME_CONTENT)
+                .encodedOpaquePart(ssp).build().toString());
+    }
+
+    /** {@hide} */
+    public static String translateDeprecatedDataPath(Uri uri) {
+        return DEPRECATE_DATA_PREFIX + uri.getEncodedSchemeSpecificPart().substring(2);
+    }
 }
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 3197352..713cc8b 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3061,6 +3061,7 @@
             USER_SERVICE,
             RESTRICTIONS_SERVICE,
             APP_OPS_SERVICE,
+            ROLE_SERVICE,
             CAMERA_SERVICE,
             PRINT_SERVICE,
             CONSUMER_IR_SERVICE,
@@ -4044,6 +4045,15 @@
     public static final String APP_OPS_SERVICE = "appops";
 
     /**
+     * Use with {@link #getSystemService(String)} to retrieve a {@link android.app.role.RoleManager}
+     * for managing roles.
+     *
+     * @see #getSystemService(String)
+     * @see android.app.role.RoleManager
+     */
+    public static final String ROLE_SERVICE = "role";
+
+    /**
      * Use with {@link #getSystemService(String)} to retrieve a
      * {@link android.hardware.camera2.CameraManager} for interacting with
      * camera devices.
diff --git a/core/java/android/content/IContentService.aidl b/core/java/android/content/IContentService.aidl
index a55dd31..1d02375 100644
--- a/core/java/android/content/IContentService.aidl
+++ b/core/java/android/content/IContentService.aidl
@@ -185,4 +185,6 @@
     Bundle getCache(in String packageName, in Uri key, int userId);
 
     void resetTodayStats();
+
+    void onDbCorruption(String tag, String message, String stacktrace);
 }
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index ea1a2fe..5ab643c 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -5285,6 +5285,7 @@
             FLAG_RECEIVER_EXCLUDE_BACKGROUND,
             FLAG_RECEIVER_FROM_SHELL,
             FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS,
+            FLAG_RECEIVER_OFFLOAD,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface Flags {}
@@ -5329,6 +5330,7 @@
             FLAG_RECEIVER_EXCLUDE_BACKGROUND,
             FLAG_RECEIVER_FROM_SHELL,
             FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS,
+            FLAG_RECEIVER_OFFLOAD,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface MutableFlags {}
@@ -5755,6 +5757,12 @@
      */
     public static final int FLAG_RECEIVER_FOREGROUND = 0x10000000;
     /**
+     * If set, when sending a broadcast the recipient will be run on the offload queue.
+     *
+     * @hide
+     */
+    public static final int FLAG_RECEIVER_OFFLOAD = 0x80000000;
+    /**
      * If this is an ordered broadcast, don't allow receivers to abort the broadcast.
      * They can still propagate results through to later receivers, but they can not prevent
      * later receivers from seeing the broadcast.
diff --git a/core/java/android/content/pm/AndroidHidlUpdater.java b/core/java/android/content/pm/AndroidHidlUpdater.java
index 69cc94f..b7ae8f4 100644
--- a/core/java/android/content/pm/AndroidHidlUpdater.java
+++ b/core/java/android/content/pm/AndroidHidlUpdater.java
@@ -38,6 +38,9 @@
         if (pkg.applicationInfo.targetSdkVersion <= Build.VERSION_CODES.P) {
             prefixRequiredLibrary(pkg, ANDROID_HIDL_BASE);
             prefixRequiredLibrary(pkg, ANDROID_HIDL_MANAGER);
+        } else {
+            removeLibrary(pkg, ANDROID_HIDL_BASE);
+            removeLibrary(pkg, ANDROID_HIDL_MANAGER);
         }
     }
 }
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index dfb8128..1f700f7 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -5439,6 +5439,28 @@
             ComponentName[] set, ComponentName activity);
 
     /**
+     * Replaces an existing preferred activity mapping to the system, and if that were not present
+     * adds a new preferred activity.  This will be used to automatically select the given activity
+     * component when {@link Context#startActivity(Intent) Context.startActivity()} finds multiple
+     * matching activities and also matches the given filter.
+     *
+     * @param filter The set of intents under which this activity will be made preferred.
+     * @param match The IntentFilter match category that this preference applies to. Should be a
+     *              combination of {@link IntentFilter#MATCH_CATEGORY_MASK} and
+     *              {@link IntentFilter#MATCH_ADJUSTMENT_MASK}).
+     * @param set The set of activities that the user was picking from when this preference was
+     *            made.
+     * @param activity The component name of the activity that is to be preferred.
+     *
+     * @hide
+     */
+    @SystemApi
+    public void replacePreferredActivity(@NonNull IntentFilter filter, int match,
+            @NonNull List<ComponentName> set, @NonNull ComponentName activity) {
+        replacePreferredActivity(filter, match, set.toArray(new ComponentName[0]), activity);
+    }
+
+    /**
      * @hide
      */
     @Deprecated
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index 4f58321..6f49cc4 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -703,6 +703,18 @@
     public abstract SparseArray<String> getAppsWithSharedUserIds();
 
     /**
+     * Get the value of attribute android:sharedUserId for the given packageName if specified,
+     * otherwise {@code null}.
+     */
+    public abstract String getSharedUserIdForPackage(@NonNull String packageName);
+
+    /**
+     * Get all packages which specified the given sharedUserId as android:sharedUserId attribute
+     * or an empty array if no package specified it.
+     */
+    public abstract String[] getPackagesForSharedUserId(@NonNull String sharedUserId, int userId);
+
+    /**
      * Return if device is currently in a "core" boot environment, typically
      * used to support full-disk encryption. Only apps marked with
      * {@code coreApp} attribute are available.
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 046e9e7..4708ea4 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -228,6 +228,24 @@
         CHILD_PACKAGE_TAGS.add(TAG_EAT_COMMENT);
     }
 
+    // STOPSHIP(b/112545973): remove once feature enabled by default
+    private static final Set<String> FORCE_AUDIO_PACKAGES;
+    private static final Set<String> FORCE_VIDEO_PACKAGES;
+    private static final Set<String> FORCE_IMAGES_PACKAGES;
+    static {
+        FORCE_AUDIO_PACKAGES = parsePackageList(
+                SystemProperties.get(StorageManager.PROP_FORCE_AUDIO));
+        FORCE_VIDEO_PACKAGES = parsePackageList(
+                SystemProperties.get(StorageManager.PROP_FORCE_VIDEO));
+        FORCE_IMAGES_PACKAGES = parsePackageList(
+                SystemProperties.get(StorageManager.PROP_FORCE_IMAGES));
+    }
+
+    private static Set<String> parsePackageList(String pkgs) {
+        if (TextUtils.isEmpty(pkgs)) return Collections.emptySet();
+        return new ArraySet<String>(Arrays.asList(pkgs.split(",")));
+    }
+
     private static final boolean LOG_UNSAFE_BROADCASTS = false;
 
     /**
@@ -2534,6 +2552,34 @@
                     }
                 }
             }
+        } else {
+            if (FORCE_AUDIO_PACKAGES.contains(pkg.packageName)) {
+                pkg.requestedPermissions.add(android.Manifest.permission.READ_MEDIA_AUDIO);
+                pkg.requestedPermissions.add(android.Manifest.permission.WRITE_MEDIA_AUDIO);
+            }
+            if (FORCE_VIDEO_PACKAGES.contains(pkg.packageName)) {
+                pkg.requestedPermissions.add(android.Manifest.permission.READ_MEDIA_VIDEO);
+                pkg.requestedPermissions.add(android.Manifest.permission.WRITE_MEDIA_VIDEO);
+            }
+            if (FORCE_IMAGES_PACKAGES.contains(pkg.packageName)) {
+                pkg.requestedPermissions.add(android.Manifest.permission.READ_MEDIA_IMAGES);
+                pkg.requestedPermissions.add(android.Manifest.permission.WRITE_MEDIA_IMAGES);
+            }
+
+            if (SystemProperties.getBoolean(StorageManager.PROP_FORCE_LEGACY, false)) {
+                if (pkg.requestedPermissions
+                        .contains(android.Manifest.permission.READ_EXTERNAL_STORAGE)) {
+                    pkg.requestedPermissions.add(android.Manifest.permission.READ_MEDIA_AUDIO);
+                    pkg.requestedPermissions.add(android.Manifest.permission.READ_MEDIA_VIDEO);
+                    pkg.requestedPermissions.add(android.Manifest.permission.READ_MEDIA_IMAGES);
+                }
+                if (pkg.requestedPermissions
+                        .contains(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
+                    pkg.requestedPermissions.add(android.Manifest.permission.WRITE_MEDIA_AUDIO);
+                    pkg.requestedPermissions.add(android.Manifest.permission.WRITE_MEDIA_VIDEO);
+                    pkg.requestedPermissions.add(android.Manifest.permission.WRITE_MEDIA_IMAGES);
+                }
+            }
         }
 
         return pkg;
@@ -6353,6 +6399,7 @@
         public ArrayList<String> usesOptionalLibraries = null;
         @UnsupportedAppUsage
         public String[] usesLibraryFiles = null;
+        public ArrayList<SharedLibraryInfo> usesLibraryInfos = null;
 
         public ArrayList<ActivityIntentInfo> preferredActivityFilters = null;
 
@@ -6887,6 +6934,8 @@
             internStringArrayList(usesOptionalLibraries);
             usesLibraryFiles = dest.readStringArray();
 
+            usesLibraryInfos = dest.createTypedArrayList(SharedLibraryInfo.CREATOR);
+
             final int libCount = dest.readInt();
             if (libCount > 0) {
                 usesStaticLibraries = new ArrayList<>(libCount);
@@ -7037,6 +7086,7 @@
             dest.writeStringList(usesLibraries);
             dest.writeStringList(usesOptionalLibraries);
             dest.writeStringArray(usesLibraryFiles);
+            dest.writeTypedList(usesLibraryInfos);
 
             if (ArrayUtils.isEmpty(usesStaticLibraries)) {
                 dest.writeInt(-1);
@@ -7503,6 +7553,10 @@
                 && p.usesLibraryFiles != null) {
             return true;
         }
+        if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0
+                && p.usesLibraryInfos != null) {
+            return true;
+        }
         if (p.staticSharedLibName != null) {
             return true;
         }
diff --git a/core/java/android/content/pm/SharedLibraryInfo.java b/core/java/android/content/pm/SharedLibraryInfo.java
index 33bc951..a8bbeab 100644
--- a/core/java/android/content/pm/SharedLibraryInfo.java
+++ b/core/java/android/content/pm/SharedLibraryInfo.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.IntRange;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -69,6 +70,8 @@
      */
     public static final int VERSION_UNDEFINED = -1;
 
+    private final String mPath;
+    private final String mPackageName;
     private final String mName;
 
     private final long mVersion;
@@ -87,8 +90,10 @@
      *
      * @hide
      */
-    public SharedLibraryInfo(String name, long version, int type,
+    public SharedLibraryInfo(String path, String packageName, String name, long version, int type,
             VersionedPackage declaringPackage, List<VersionedPackage> dependentPackages) {
+        mPath = path;
+        mPackageName = packageName;
         mName = name;
         mVersion = version;
         mType = type;
@@ -97,8 +102,8 @@
     }
 
     private SharedLibraryInfo(Parcel parcel) {
-        this(parcel.readString(), parcel.readLong(), parcel.readInt(),
-                parcel.readParcelable(null), parcel.readArrayList(null));
+        this(parcel.readString(), parcel.readString(), parcel.readString(), parcel.readLong(),
+                parcel.readInt(), parcel.readParcelable(null), parcel.readArrayList(null));
     }
 
     /**
@@ -121,6 +126,30 @@
     }
 
     /**
+     * If the shared library is a jar file, returns the path of that jar. Null otherwise.
+     * Only libraries with TYPE_BUILTIN are in jar files.
+     *
+     * @return The path.
+     *
+     * @hide
+     */
+    public @Nullable String getPath() {
+        return mPath;
+    }
+
+    /**
+     * If the shared library is an apk, returns the package name. Null otherwise.
+     * Only libraries with TYPE_DYNAMIC or TYPE_STATIC are in apks.
+     *
+     * @return The package name.
+     *
+     * @hide
+     */
+    public @Nullable String getPackageName() {
+        return mPackageName;
+    }
+
+    /**
      * @deprecated Use {@link #getLongVersion()} instead.
      */
     @Deprecated
@@ -196,6 +225,8 @@
 
     @Override
     public void writeToParcel(Parcel parcel, int flags) {
+        parcel.writeString(mPath);
+        parcel.writeString(mPackageName);
         parcel.writeString(mName);
         parcel.writeLong(mVersion);
         parcel.writeInt(mType);
diff --git a/core/java/android/database/DefaultDatabaseErrorHandler.java b/core/java/android/database/DefaultDatabaseErrorHandler.java
index 7fa2b40..cf019e1 100755
--- a/core/java/android/database/DefaultDatabaseErrorHandler.java
+++ b/core/java/android/database/DefaultDatabaseErrorHandler.java
@@ -15,14 +15,14 @@
  */
 package android.database;
 
-import java.io.File;
-import java.util.List;
-
 import android.database.sqlite.SQLiteDatabase;
 import android.database.sqlite.SQLiteException;
 import android.util.Log;
 import android.util.Pair;
 
+import java.io.File;
+import java.util.List;
+
 /**
  * Default class used to define the action to take when database corruption is reported
  * by sqlite.
@@ -52,6 +52,7 @@
      */
     public void onCorruption(SQLiteDatabase dbObj) {
         Log.e(TAG, "Corruption reported by sqlite on database: " + dbObj.getPath());
+        SQLiteDatabase.wipeDetected(dbObj.getPath(), "corruption");
 
         // is the corruption detected even before database could be 'opened'?
         if (!dbObj.isOpen()) {
@@ -99,7 +100,7 @@
         }
         Log.e(TAG, "deleting the database file: " + fileName);
         try {
-            SQLiteDatabase.deleteDatabase(new File(fileName));
+            SQLiteDatabase.deleteDatabase(new File(fileName), /*removeCheckFile=*/ false);
         } catch (Exception e) {
             /* print warning and ignore exception */
             Log.w(TAG, "delete failed: " + e.getMessage());
diff --git a/core/java/android/database/sqlite/SQLiteConnection.java b/core/java/android/database/sqlite/SQLiteConnection.java
index 5c4f16a..20505ca 100644
--- a/core/java/android/database/sqlite/SQLiteConnection.java
+++ b/core/java/android/database/sqlite/SQLiteConnection.java
@@ -34,6 +34,7 @@
 import dalvik.system.CloseGuard;
 
 import java.io.File;
+import java.io.IOException;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Date;
@@ -414,6 +415,10 @@
         final String newLocale = mConfiguration.locale.toString();
         nativeRegisterLocalizedCollators(mConnectionPtr, newLocale);
 
+        if (!mConfiguration.isInMemoryDb()) {
+            checkDatabaseWiped();
+        }
+
         // If the database is read-only, we cannot modify the android metadata table
         // or existing indexes.
         if (mIsReadOnlyConnection) {
@@ -449,6 +454,36 @@
         }
     }
 
+    private void checkDatabaseWiped() {
+        if (!SQLiteGlobal.checkDbWipe()) {
+            return;
+        }
+        try {
+            final File checkFile = new File(mConfiguration.path
+                    + SQLiteGlobal.WIPE_CHECK_FILE_SUFFIX);
+
+            final boolean hasMetadataTable = executeForLong(
+                    "SELECT count(*) FROM sqlite_master"
+                            + " WHERE type='table' AND name='android_metadata'", null, null) > 0;
+            final boolean hasCheckFile = checkFile.exists();
+
+            if (!mIsReadOnlyConnection && !hasCheckFile) {
+                // Create the check file, unless it's a readonly connection,
+                // in which case we can't create the metadata table anyway.
+                checkFile.createNewFile();
+            }
+
+            if (!hasMetadataTable && hasCheckFile) {
+                // Bad. The DB is gone unexpectedly.
+                SQLiteDatabase.wipeDetected(mConfiguration.path, "unknown");
+            }
+
+        } catch (RuntimeException | IOException ex) {
+            SQLiteDatabase.wtfAsSystemServer(TAG,
+                    "Unexpected exception while checking for wipe", ex);
+        }
+    }
+
     // Called by SQLiteConnectionPool only.
     void reconfigure(SQLiteDatabaseConfiguration configuration) {
         mOnlyAllowReadOnlyOperations = false;
diff --git a/core/java/android/database/sqlite/SQLiteConnectionPool.java b/core/java/android/database/sqlite/SQLiteConnectionPool.java
index 3ee348b..dbc1766 100644
--- a/core/java/android/database/sqlite/SQLiteConnectionPool.java
+++ b/core/java/android/database/sqlite/SQLiteConnectionPool.java
@@ -24,6 +24,7 @@
 import android.os.OperationCanceledException;
 import android.os.SystemClock;
 import android.text.TextUtils;
+import android.util.ArraySet;
 import android.util.Log;
 import android.util.PrefixPrinter;
 import android.util.Printer;
@@ -34,6 +35,7 @@
 import dalvik.system.CloseGuard;
 
 import java.io.Closeable;
+import java.io.File;
 import java.util.ArrayList;
 import java.util.Map;
 import java.util.WeakHashMap;
@@ -1105,9 +1107,12 @@
      * @param printer The printer to receive the dump, not null.
      * @param verbose True to dump more verbose information.
      */
-    public void dump(Printer printer, boolean verbose) {
+    public void dump(Printer printer, boolean verbose, ArraySet<String> directories) {
         Printer indentedPrinter = PrefixPrinter.create(printer, "    ");
         synchronized (mLock) {
+            if (directories != null) {
+                directories.add(new File(mConfiguration.path).getParent());
+            }
             printer.println("Connection pool for " + mConfiguration.path + ":");
             printer.println("  Open: " + mIsOpen);
             printer.println("  Max connections: " + mMaxConnectionPoolSize);
diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java
index eb5c720..f9c2c3e 100644
--- a/core/java/android/database/sqlite/SQLiteDatabase.java
+++ b/core/java/android/database/sqlite/SQLiteDatabase.java
@@ -22,6 +22,8 @@
 import android.annotation.Nullable;
 import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityManager;
+import android.app.ActivityThread;
+import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.database.Cursor;
 import android.database.DatabaseErrorHandler;
@@ -34,6 +36,7 @@
 import android.os.OperationCanceledException;
 import android.os.SystemProperties;
 import android.text.TextUtils;
+import android.util.ArraySet;
 import android.util.EventLog;
 import android.util.Log;
 import android.util.Pair;
@@ -45,9 +48,14 @@
 
 import java.io.File;
 import java.io.FileFilter;
+import java.io.IOException;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.attribute.BasicFileAttributes;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
@@ -808,6 +816,12 @@
      * @return True if the database was successfully deleted.
      */
     public static boolean deleteDatabase(@NonNull File file) {
+        return deleteDatabase(file, /*removeCheckFile=*/ true);
+    }
+
+
+    /** @hide */
+    public static boolean deleteDatabase(@NonNull File file, boolean removeCheckFile) {
         if (file == null) {
             throw new IllegalArgumentException("file must not be null");
         }
@@ -818,6 +832,9 @@
         deleted |= new File(file.getPath() + "-shm").delete();
         deleted |= new File(file.getPath() + "-wal").delete();
 
+        // This file is not a standard SQLite file, so don't update the deleted flag.
+        new File(file.getPath() + SQLiteGlobal.WIPE_CHECK_FILE_SUFFIX).delete();
+
         File dir = file.getParentFile();
         if (dir != null) {
             final String prefix = file.getName() + "-mj";
@@ -2170,21 +2187,61 @@
      * Dump detailed information about all open databases in the current process.
      * Used by bug report.
      */
-    static void dumpAll(Printer printer, boolean verbose) {
+    static void dumpAll(Printer printer, boolean verbose, boolean isSystem) {
+        // Use this ArraySet to collect file paths.
+        final ArraySet<String> directories = new ArraySet<>();
+
         for (SQLiteDatabase db : getActiveDatabases()) {
-            db.dump(printer, verbose);
+            db.dump(printer, verbose, isSystem, directories);
+        }
+
+        // Dump DB files in the directories.
+        if (directories.size() > 0) {
+            final String[] dirs = directories.toArray(new String[directories.size()]);
+            Arrays.sort(dirs);
+            for (String dir : dirs) {
+                dumpDatabaseDirectory(printer, new File(dir), isSystem);
+            }
         }
     }
 
-    private void dump(Printer printer, boolean verbose) {
+    private void dump(Printer printer, boolean verbose, boolean isSystem, ArraySet directories) {
         synchronized (mLock) {
             if (mConnectionPoolLocked != null) {
                 printer.println("");
-                mConnectionPoolLocked.dump(printer, verbose);
+                mConnectionPoolLocked.dump(printer, verbose, directories);
             }
         }
     }
 
+    private static void dumpDatabaseDirectory(Printer pw, File dir, boolean isSystem) {
+        pw.println("");
+        pw.println("Database files in " + dir.getAbsolutePath() + ":");
+        final File[] files = dir.listFiles();
+        if (files == null || files.length == 0) {
+            pw.println("  [none]");
+            return;
+        }
+        Arrays.sort(files, (a, b) -> a.getName().compareTo(b.getName()));
+
+        for (File f : files) {
+            if (isSystem) {
+                // If called within the system server, the directory contains other files too, so
+                // filter by file extensions.
+                // (If it's an app, just print all files because they may not use *.db
+                // extension.)
+                final String name = f.getName();
+                if (!(name.endsWith(".db") || name.endsWith(".db-wal")
+                        || name.endsWith(".db-journal")
+                        || name.endsWith(SQLiteGlobal.WIPE_CHECK_FILE_SUFFIX))) {
+                    continue;
+                }
+            }
+            pw.println(String.format("  %-40s %7db %s", f.getName(), f.length(),
+                    SQLiteDatabase.getFileTimestamps(f.getAbsolutePath())));
+        }
+    }
+
     /**
      * Returns list of full pathnames of all attached databases including the main database
      * by executing 'pragma database_list' on the database.
@@ -2611,7 +2668,7 @@
                 return this;
             }
 
-            /**
+            /**w
              * Sets <a href="https://sqlite.org/pragma.html#pragma_synchronous">synchronous mode</a>
              * .
              * @return
@@ -2646,5 +2703,34 @@
     @Retention(RetentionPolicy.SOURCE)
     public @interface DatabaseOpenFlags {}
 
+    /** @hide */
+    public static void wipeDetected(String filename, String reason) {
+        wtfAsSystemServer(TAG, "DB wipe detected:"
+                + " package=" + ActivityThread.currentPackageName()
+                + " reason=" + reason
+                + " file=" + filename
+                + " " + getFileTimestamps(filename)
+                + " checkfile " + getFileTimestamps(filename + SQLiteGlobal.WIPE_CHECK_FILE_SUFFIX),
+                new Throwable("STACKTRACE"));
+    }
+
+    /** @hide */
+    public static String getFileTimestamps(String path) {
+        try {
+            BasicFileAttributes attr = Files.readAttributes(
+                    FileSystems.getDefault().getPath(path), BasicFileAttributes.class);
+            return "ctime=" + attr.creationTime()
+                    + " mtime=" + attr.lastModifiedTime()
+                    + " atime=" + attr.lastAccessTime();
+        } catch (IOException e) {
+            return "[unable to obtain timestamp]";
+        }
+    }
+
+    /** @hide */
+    static void wtfAsSystemServer(String tag, String message, Throwable stacktrace) {
+        Log.e(tag, message, stacktrace);
+        ContentResolver.onDbCorruption(tag, message, stacktrace);
+    }
 }
 
diff --git a/core/java/android/database/sqlite/SQLiteDebug.java b/core/java/android/database/sqlite/SQLiteDebug.java
index 1c66204..f220205 100644
--- a/core/java/android/database/sqlite/SQLiteDebug.java
+++ b/core/java/android/database/sqlite/SQLiteDebug.java
@@ -189,6 +189,11 @@
      * @param args Command-line arguments supplied to dumpsys dbinfo
      */
     public static void dump(Printer printer, String[] args) {
+        dump(printer, args, false);
+    }
+
+    /** @hide */
+    public static void dump(Printer printer, String[] args, boolean isSystem) {
         boolean verbose = false;
         for (String arg : args) {
             if (arg.equals("-v")) {
@@ -196,6 +201,6 @@
             }
         }
 
-        SQLiteDatabase.dumpAll(printer, verbose);
+        SQLiteDatabase.dumpAll(printer, verbose, isSystem);
     }
 }
diff --git a/core/java/android/database/sqlite/SQLiteGlobal.java b/core/java/android/database/sqlite/SQLiteGlobal.java
index 67e5f65..ff286fd 100644
--- a/core/java/android/database/sqlite/SQLiteGlobal.java
+++ b/core/java/android/database/sqlite/SQLiteGlobal.java
@@ -42,6 +42,9 @@
     /** @hide */
     public static final String SYNC_MODE_FULL = "FULL";
 
+    /** @hide */
+    static final String WIPE_CHECK_FILE_SUFFIX = "-wipecheck";
+
     private static final Object sLock = new Object();
 
     private static int sDefaultPageSize;
@@ -181,4 +184,8 @@
                         com.android.internal.R.integer.db_wal_truncate_size));
     }
 
+    /** @hide */
+    public static boolean checkDbWipe() {
+        return true;
+    }
 }
diff --git a/core/java/android/hardware/biometrics/BiometricConstants.java b/core/java/android/hardware/biometrics/BiometricConstants.java
index 2a64c2e..c814b7c 100644
--- a/core/java/android/hardware/biometrics/BiometricConstants.java
+++ b/core/java/android/hardware/biometrics/BiometricConstants.java
@@ -38,7 +38,7 @@
      * BiometricManager.
      * @hide
      */
-    int BIOMETRIC_ERROR_NONE = 0;
+    int BIOMETRIC_SUCCESS = 0;
 
     /**
      * The hardware is unavailable. Try again later.
diff --git a/core/java/android/hardware/biometrics/BiometricFaceConstants.java b/core/java/android/hardware/biometrics/BiometricFaceConstants.java
index c788bc5..1d9330d 100644
--- a/core/java/android/hardware/biometrics/BiometricFaceConstants.java
+++ b/core/java/android/hardware/biometrics/BiometricFaceConstants.java
@@ -224,12 +224,25 @@
     public static final int FACE_ACQUIRED_RECALIBRATE = 13;
 
     /**
+     * The face is too different from a previous acquisition. This condition
+     * only applies to enrollment. This can happen if the user passes the
+     * device to someone else in the middle of enrollment.
+     */
+    public static final int FACE_ACQUIRED_TOO_DIFFERENT = 14;
+
+    /**
+     * The face is too similar to a previous acquisition. This condition only
+     * applies to enrollment. The user should change their pose.
+     */
+    public static final int FACE_ACQUIRED_TOO_SIMILAR = 15;
+
+    /**
      * Hardware vendors may extend this list if there are conditions that do not fall under one of
      * the above categories. Vendors are responsible for providing error strings for these errors.
      *
      * @hide
      */
-    public static final int FACE_ACQUIRED_VENDOR = 14;
+    public static final int FACE_ACQUIRED_VENDOR = 16;
 
     /**
      * @hide
diff --git a/core/java/android/hardware/biometrics/BiometricManager.java b/core/java/android/hardware/biometrics/BiometricManager.java
index 1d40001..fe00604 100644
--- a/core/java/android/hardware/biometrics/BiometricManager.java
+++ b/core/java/android/hardware/biometrics/BiometricManager.java
@@ -35,24 +35,31 @@
     /**
      * No error detected.
      */
-    public static final int ERROR_NONE = BiometricConstants.BIOMETRIC_ERROR_NONE;
+    public static final int BIOMETRIC_SUCCESS =
+            BiometricConstants.BIOMETRIC_SUCCESS;
 
     /**
      * The hardware is unavailable. Try again later.
      */
-    public static final int ERROR_UNAVAILABLE = BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE;
+    public static final int BIOMETRIC_ERROR_UNAVAILABLE =
+            BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE;
 
     /**
      * The user does not have any biometrics enrolled.
      */
-    public static final int ERROR_NO_BIOMETRICS = BiometricConstants.BIOMETRIC_ERROR_NO_BIOMETRICS;
+    public static final int BIOMETRIC_ERROR_NO_BIOMETRICS =
+            BiometricConstants.BIOMETRIC_ERROR_NO_BIOMETRICS;
 
     /**
      * There is no biometric hardware.
      */
-    public static final int ERROR_NO_HARDWARE = BiometricConstants.BIOMETRIC_ERROR_HW_NOT_PRESENT;
+    public static final int BIOMETRIC_ERROR_NO_HARDWARE =
+            BiometricConstants.BIOMETRIC_ERROR_HW_NOT_PRESENT;
 
-    @IntDef({ERROR_NONE, ERROR_UNAVAILABLE, ERROR_NO_BIOMETRICS, ERROR_NO_HARDWARE})
+    @IntDef({BIOMETRIC_SUCCESS,
+            BIOMETRIC_ERROR_UNAVAILABLE,
+            BIOMETRIC_ERROR_NO_BIOMETRICS,
+            BIOMETRIC_ERROR_NO_HARDWARE})
     @interface BiometricError {}
 
     private final Context mContext;
@@ -72,9 +79,10 @@
      * Determine if biometrics can be used. In other words, determine if {@link BiometricPrompt}
      * can be expected to be shown (hardware available, templates enrolled, user-enabled).
      *
-     * @return Returns {@link #ERROR_NO_BIOMETRICS} if the user does not have any enrolled, or
-     *     {@link #ERROR_UNAVAILABLE} if none are currently supported/enabled. Returns
-     *     {@link #ERROR_NONE} if a biometric can currently be used (enrolled and available).
+     * @return Returns {@link #BIOMETRIC_ERROR_NO_BIOMETRICS} if the user does not have any
+     *     enrolled, or {@link #BIOMETRIC_ERROR_UNAVAILABLE} if none are currently
+     *     supported/enabled. Returns {@link #BIOMETRIC_SUCCESS} if a biometric can currently be
+     *     used (enrolled and available).
      */
     @RequiresPermission(USE_BIOMETRIC)
     public @BiometricError int canAuthenticate() {
@@ -86,7 +94,7 @@
             }
         } else {
             Slog.w(TAG, "hasEnrolledBiometrics(): Service not connected");
-            return ERROR_UNAVAILABLE;
+            return BIOMETRIC_ERROR_UNAVAILABLE;
         }
     }
 
diff --git a/core/java/android/hardware/face/FaceManager.java b/core/java/android/hardware/face/FaceManager.java
index 536c4a5..322863a 100644
--- a/core/java/android/hardware/face/FaceManager.java
+++ b/core/java/android/hardware/face/FaceManager.java
@@ -311,6 +311,21 @@
     }
 
     /**
+     * Pokes the the driver to have it start looking for faces again.
+     * @hide
+     */
+    @RequiresPermission(MANAGE_BIOMETRIC)
+    public void userActivity() {
+        if (mService != null) {
+            try {
+                mService.userActivity();
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+    }
+
+    /**
      * Sets the active user. This is meant to be used to select the current profile for enrollment
      * to allow separate enrolled faces for a work profile
      *
diff --git a/core/java/android/hardware/face/IFaceService.aidl b/core/java/android/hardware/face/IFaceService.aidl
index 6681bd7..47df8e8 100644
--- a/core/java/android/hardware/face/IFaceService.aidl
+++ b/core/java/android/hardware/face/IFaceService.aidl
@@ -98,4 +98,6 @@
     int setRequireAttention(boolean requireAttention, in byte [] token);
 
     boolean getRequireAttention(in byte [] token);
+
+    void userActivity();
 }
diff --git a/core/java/android/hardware/location/ContextHubClient.java b/core/java/android/hardware/location/ContextHubClient.java
index 5de89e3..56da719 100644
--- a/core/java/android/hardware/location/ContextHubClient.java
+++ b/core/java/android/hardware/location/ContextHubClient.java
@@ -130,30 +130,42 @@
      * {@link PendingIntent} through a {@link BroadcastReceiver}, and maps an {@link Intent} to a
      * {@link ContextHubClientCallback}.
      *
-     * @param intent    The PendingIntent to register for this client
-     * @param nanoAppId the unique ID of the nanoapp to receive events for
+     * @param pendingIntent the PendingIntent to register for this client
+     * @param nanoAppId     the unique ID of the nanoapp to receive events for
      * @return true on success, false otherwise
      *
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
-    public boolean registerIntent(@NonNull PendingIntent intent, long nanoAppId) {
-        // TODO: Implement this
-        return false;
+    public boolean registerIntent(@NonNull PendingIntent pendingIntent, long nanoAppId) {
+        Preconditions.checkNotNull(pendingIntent, "PendingIntent cannot be null");
+
+        try {
+            return mClientProxy.registerIntent(pendingIntent, nanoAppId);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
     }
 
     /**
      * Unregisters an intent previously registered via {@link #registerIntent(PendingIntent, long)}.
      * If this intent has not been registered for this client, this method returns false.
      *
+     * @param pendingIntent the PendingIntent to unregister
+     *
      * @return true on success, false otherwise
      *
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
-    public boolean unregisterIntent(@NonNull PendingIntent intent) {
-        // TODO: Implement this
-        return false;
+    public boolean unregisterIntent(@NonNull PendingIntent pendingIntent) {
+        Preconditions.checkNotNull(pendingIntent, "PendingIntent cannot be null");
+
+        try {
+            return mClientProxy.unregisterIntent(pendingIntent);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
     }
 
     /**
diff --git a/core/java/android/hardware/location/ContextHubManager.java b/core/java/android/hardware/location/ContextHubManager.java
index 6541ecd..b0b77f3 100644
--- a/core/java/android/hardware/location/ContextHubManager.java
+++ b/core/java/android/hardware/location/ContextHubManager.java
@@ -800,22 +800,22 @@
      * through {@link #createClient(ContextHubInfo, ContextHubClientCallback, Executor)} or
      * equivalent at an earlier time.
      *
-     * @param intent   the intent that is associated with a client
-     * @param hubInfo  the hub to attach this client to
-     * @param callback the notification callback to register
-     * @param executor the executor to invoke the callback
+     * @param pendingIntent the PendingIntent that has been registered with a client
+     * @param hubInfo       the hub to attach this client to
+     * @param callback      the notification callback to register
+     * @param executor      the executor to invoke the callback
      * @return the registered client object
      *
-     * @throws IllegalArgumentException if hubInfo does not represent a valid hub, or the intent
+     * @throws IllegalArgumentException if hubInfo does not represent a valid hub, or pendingIntent
      *                                  was not associated with a client
      * @throws IllegalStateException    if there were too many registered clients at the service
-     * @throws NullPointerException     if intent, hubInfo, callback, or executor is null
+     * @throws NullPointerException     if pendingIntent, hubInfo, callback, or executor is null
      *
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
     @NonNull public ContextHubClient createClient(
-            @NonNull PendingIntent intent, @NonNull ContextHubInfo hubInfo,
+            @NonNull PendingIntent pendingIntent, @NonNull ContextHubInfo hubInfo,
             @NonNull ContextHubClientCallback callback,
             @NonNull @CallbackExecutor Executor executor) {
         // TODO: Implement this
@@ -823,26 +823,27 @@
     }
 
     /**
-     * Equivalent to {@link #createClient(Intent, ContextHubInfo, ContextHubClientCallback,
+     * Equivalent to {@link #createClient(PendingIntent, ContextHubInfo, ContextHubClientCallback,
      * Executor)} with the executor using the main thread's Looper.
      *
-     * @param intent   the intent that is associated with a client
-     * @param hubInfo  the hub to attach this client to
-     * @param callback the notification callback to register
+     * @param pendingIntent the PendingIntent that has been registered with a client
+     * @param hubInfo       the hub to attach this client to
+     * @param callback      the notification callback to register
      * @return the registered client object
      *
-     * @throws IllegalArgumentException if hubInfo does not represent a valid hub, or the intent
+     * @throws IllegalArgumentException if hubInfo does not represent a valid hub, or pendingIntent
      *                                  was not associated with a client
      * @throws IllegalStateException    if there were too many registered clients at the service
-     * @throws NullPointerException     if intent, hubInfo, or callback is null
+     * @throws NullPointerException     if pendingIntent, hubInfo, or callback is null
      *
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
     @NonNull public ContextHubClient createClient(
-            @NonNull PendingIntent intent, @NonNull ContextHubInfo hubInfo,
+            @NonNull PendingIntent pendingIntent, @NonNull ContextHubInfo hubInfo,
             @NonNull ContextHubClientCallback callback) {
-        return createClient(intent, hubInfo, callback, new HandlerExecutor(Handler.getMain()));
+        return createClient(
+                pendingIntent, hubInfo, callback, new HandlerExecutor(Handler.getMain()));
     }
 
     /**
diff --git a/core/java/android/hardware/location/IContextHubClient.aidl b/core/java/android/hardware/location/IContextHubClient.aidl
index d81126a..7559cd5 100644
--- a/core/java/android/hardware/location/IContextHubClient.aidl
+++ b/core/java/android/hardware/location/IContextHubClient.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.location;
 
+import android.app.PendingIntent;
 import android.hardware.location.NanoAppMessage;
 
 /**
@@ -28,4 +29,10 @@
 
     // Closes the connection with the Context Hub
     void close();
+
+    // Registers a PendingIntent with the client
+    boolean registerIntent(in PendingIntent intent, long nanoAppId);
+
+    // Unregisters a PendingIntent from the client
+    boolean unregisterIntent(in PendingIntent intent);
 }
diff --git a/core/java/android/hardware/radio/Utils.java b/core/java/android/hardware/radio/Utils.java
index 9887f78..dd7f5b2 100644
--- a/core/java/android/hardware/radio/Utils.java
+++ b/core/java/android/hardware/radio/Utils.java
@@ -47,7 +47,7 @@
 
     static @NonNull Map<String, String> readStringMap(@NonNull Parcel in) {
         int size = in.readInt();
-        Map<String, String> map = new HashMap<>();
+        Map<String, String> map = new HashMap<>(size);
         while (size-- > 0) {
             String key = in.readString();
             String value = in.readString();
@@ -70,7 +70,7 @@
 
     static @NonNull Map<String, Integer> readStringIntMap(@NonNull Parcel in) {
         int size = in.readInt();
-        Map<String, Integer> map = new HashMap<>();
+        Map<String, Integer> map = new HashMap<>(size);
         while (size-- > 0) {
             String key = in.readString();
             int value = in.readInt();
@@ -90,7 +90,7 @@
 
     static <T> Set<T> createSet(@NonNull Parcel in, Parcelable.Creator<T> c) {
         int size = in.readInt();
-        Set<T> set = new HashSet<>();
+        Set<T> set = new HashSet<>(size);
         while (size-- > 0) {
             set.add(in.readTypedObject(c));
         }
@@ -107,15 +107,12 @@
     }
 
     static Set<Integer> createIntSet(@NonNull Parcel in) {
-        return createSet(in, new Parcelable.Creator<Integer>() {
-            public Integer createFromParcel(Parcel in) {
-                return in.readInt();
-            }
-
-            public Integer[] newArray(int size) {
-                return new Integer[size];
-            }
-        });
+        int size = in.readInt();
+        Set<Integer> set = new HashSet<>(size);
+        while (size-- > 0) {
+            set.add(in.readInt());
+        }
+        return set;
     }
 
     static <T extends Parcelable> void writeTypedCollection(@NonNull Parcel dest,
diff --git a/core/java/android/net/NetworkMisc.java b/core/java/android/net/NetworkMisc.java
index a2da6ea..c0487b5 100644
--- a/core/java/android/net/NetworkMisc.java
+++ b/core/java/android/net/NetworkMisc.java
@@ -65,6 +65,12 @@
      */
     public String subscriberId;
 
+    /**
+     * Set to skip 464xlat. This means the device will treat the network as IPv6-only and
+     * will not attempt to detect a NAT64 via RFC 7050 DNS lookups.
+     */
+    public boolean skip464xlat;
+
     public NetworkMisc() {
     }
 
@@ -75,6 +81,7 @@
             acceptUnvalidated = nm.acceptUnvalidated;
             subscriberId = nm.subscriberId;
             provisioningNotificationDisabled = nm.provisioningNotificationDisabled;
+            skip464xlat = nm.skip464xlat;
         }
     }
 
@@ -90,6 +97,7 @@
         out.writeInt(acceptUnvalidated ? 1 : 0);
         out.writeString(subscriberId);
         out.writeInt(provisioningNotificationDisabled ? 1 : 0);
+        out.writeInt(skip464xlat ? 1 : 0);
     }
 
     public static final Creator<NetworkMisc> CREATOR = new Creator<NetworkMisc>() {
@@ -101,6 +109,7 @@
             networkMisc.acceptUnvalidated = in.readInt() != 0;
             networkMisc.subscriberId = in.readString();
             networkMisc.provisioningNotificationDisabled = in.readInt() != 0;
+            networkMisc.skip464xlat = in.readInt() != 0;
             return networkMisc;
         }
 
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index d5fb2e7..299b232 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -91,16 +91,16 @@
     public static final int MASK_ALL_NETWORKS     = 0b11110000;
 
     public static final int FIREWALL_RULE_DEFAULT = 0;
-    public static final int FIREWALL_RULE_ALLOW = 1;
-    public static final int FIREWALL_RULE_DENY = 2;
+    public static final int FIREWALL_RULE_ALLOW = INetd.FIREWALL_RULE_ALLOW;
+    public static final int FIREWALL_RULE_DENY = INetd.FIREWALL_RULE_DENY;
 
-    public static final int FIREWALL_TYPE_WHITELIST = 0;
-    public static final int FIREWALL_TYPE_BLACKLIST = 1;
+    public static final int FIREWALL_TYPE_WHITELIST = INetd.FIREWALL_WHITELIST;
+    public static final int FIREWALL_TYPE_BLACKLIST = INetd.FIREWALL_BLACKLIST;
 
-    public static final int FIREWALL_CHAIN_NONE = 0;
-    public static final int FIREWALL_CHAIN_DOZABLE = 1;
-    public static final int FIREWALL_CHAIN_STANDBY = 2;
-    public static final int FIREWALL_CHAIN_POWERSAVE = 3;
+    public static final int FIREWALL_CHAIN_NONE = INetd.FIREWALL_CHAIN_NONE;
+    public static final int FIREWALL_CHAIN_DOZABLE = INetd.FIREWALL_CHAIN_DOZABLE;
+    public static final int FIREWALL_CHAIN_STANDBY = INetd.FIREWALL_CHAIN_STANDBY;
+    public static final int FIREWALL_CHAIN_POWERSAVE = INetd.FIREWALL_CHAIN_POWERSAVE;
 
     public static final String FIREWALL_CHAIN_NAME_NONE = "none";
     public static final String FIREWALL_CHAIN_NAME_DOZABLE = "dozable";
diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java
index e270fc2..5447f59 100644
--- a/core/java/android/net/NetworkStats.java
+++ b/core/java/android/net/NetworkStats.java
@@ -811,14 +811,19 @@
      * packet needs to be subtracted from the root UID on the base interface both for tx
      * and rx traffic (http://b/12249687, http:/b/33681750).
      *
+     * As for eBPF, the per uid stats is collected by different hook, the rx packets on base
+     * interface will not be counted. Thus, the adjustment on root uid is only needed in tx
+     * direction.
+     *
      * <p>This method will behave fine if {@code stackedIfaces} is an non-synchronized but add-only
      * {@code ConcurrentHashMap}
      * @param baseTraffic Traffic on the base interfaces. Will be mutated.
      * @param stackedTraffic Stats with traffic stacked on top of our ifaces. Will also be mutated.
      * @param stackedIfaces Mapping ipv6if -> ipv4if interface where traffic is counted on both.
+     * @param useBpfStats True if eBPF is in use.
      */
     public static void apply464xlatAdjustments(NetworkStats baseTraffic,
-            NetworkStats stackedTraffic, Map<String, String> stackedIfaces) {
+            NetworkStats stackedTraffic, Map<String, String> stackedIfaces, boolean useBpfStats) {
         // Total 464xlat traffic to subtract from uid 0 on all base interfaces.
         // stackedIfaces may grow afterwards, but NetworkStats will just be resized automatically.
         final NetworkStats adjustments = new NetworkStats(0, stackedIfaces.size());
@@ -837,15 +842,20 @@
                 continue;
             }
             // Subtract any 464lat traffic seen for the root UID on the current base interface.
+            // However, for eBPF, the per uid stats is collected by different hook, the rx packets
+            // on base interface will not be counted. Thus, the adjustment on root uid is only
+            // needed in tx direction.
             adjust.iface = baseIface;
-            adjust.rxBytes = -(entry.rxBytes + entry.rxPackets * IPV4V6_HEADER_DELTA);
+            if (!useBpfStats) {
+                adjust.rxBytes = -(entry.rxBytes + entry.rxPackets * IPV4V6_HEADER_DELTA);
+                adjust.rxPackets = -entry.rxPackets;
+            }
             adjust.txBytes = -(entry.txBytes + entry.txPackets * IPV4V6_HEADER_DELTA);
-            adjust.rxPackets = -entry.rxPackets;
             adjust.txPackets = -entry.txPackets;
             adjustments.combineValues(adjust);
 
-            // For 464xlat traffic, xt_qtaguid only counts the bytes of the native IPv4 packet sent
-            // on the stacked interface with prefix "v4-" and drops the IPv6 header size after
+            // For 464xlat traffic, per uid stats only counts the bytes of the native IPv4 packet
+            // sent on the stacked interface with prefix "v4-" and drops the IPv6 header size after
             // unwrapping. To account correctly for on-the-wire traffic, add the 20 additional bytes
             // difference for all packets (http://b/12249687, http:/b/33681750).
             entry.rxBytes += entry.rxPackets * IPV4V6_HEADER_DELTA;
@@ -864,8 +874,8 @@
      * base and stacked traffic.
      * @param stackedIfaces Mapping ipv6if -> ipv4if interface where traffic is counted on both.
      */
-    public void apply464xlatAdjustments(Map<String, String> stackedIfaces) {
-        apply464xlatAdjustments(this, this, stackedIfaces);
+    public void apply464xlatAdjustments(Map<String, String> stackedIfaces, boolean useBpfStats) {
+        apply464xlatAdjustments(this, this, stackedIfaces, useBpfStats);
     }
 
     /**
diff --git a/core/java/android/net/UidRange.aidl b/core/java/android/net/UidRange.aidl
new file mode 100644
index 0000000..f70fc8e
--- /dev/null
+++ b/core/java/android/net/UidRange.aidl
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+/**
+ * An inclusive range of UIDs.
+ *
+ * {@hide}
+ */
+parcelable UidRange;
\ No newline at end of file
diff --git a/core/java/android/net/UidRange.java b/core/java/android/net/UidRange.java
index 3164929..793c82d 100644
--- a/core/java/android/net/UidRange.java
+++ b/core/java/android/net/UidRange.java
@@ -19,17 +19,14 @@
 import static android.os.UserHandle.PER_USER_RANGE;
 
 import android.os.Parcel;
-import android.os.Parcelable;
 
 /**
  * An inclusive range of UIDs.
  *
  * @hide
  */
-public final class UidRange implements Parcelable {
-    public final int start;
-    public final int stop;
-
+public final class UidRange extends UidRangeParcel {
+    private UidRange() {}
     public UidRange(int startUid, int stopUid) {
         if (startUid < 0) throw new IllegalArgumentException("Invalid start UID.");
         if (stopUid < 0) throw new IllegalArgumentException("Invalid stop UID.");
@@ -89,26 +86,18 @@
         return start + "-" + stop;
     }
 
-    // implement the Parcelable interface
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeInt(start);
-        dest.writeInt(stop);
-    }
+    /**
+     * DO NOT override "writeToParcel" and "readFromParcel" in this class.
+     * The parceling code is autogenerated by the superclass.
+     */
 
     public static final Creator<UidRange> CREATOR =
         new Creator<UidRange>() {
             @Override
             public UidRange createFromParcel(Parcel in) {
-                int start = in.readInt();
-                int stop = in.readInt();
-
-                return new UidRange(start, stop);
+                UidRange obj = new UidRange();
+                obj.readFromParcel(in);
+                return obj;
             }
             @Override
             public UidRange[] newArray(int size) {
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index 8b6194c..e4f0358 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -555,6 +555,79 @@
     }
 
     /**
+     * Listener to be notified about each proxy-side binder call.
+     *
+     * See {@link setProxyTransactListener}.
+     * @hide
+     */
+    public interface ProxyTransactListener {
+        /**
+         * Called before onTransact.
+         *
+         * @return an object that will be passed back to #onTransactEnded (or null).
+         */
+        Object onTransactStarted(IBinder binder, int transactionCode);
+
+        /**
+         * Called after onTranact (even when an exception is thrown).
+         *
+         * @param session The object return by #onTransactStarted.
+         */
+        void onTransactEnded(@Nullable Object session);
+    }
+
+    /**
+     * Propagates the work source to binder calls executed by the system server.
+     *
+     * <li>By default, this listener will propagate the worksource if the outgoing call happens on
+     * the same thread as the incoming binder call.
+     * <li>Custom attribution can be done by calling {@link ThreadLocalWorkSourceUid#set(int)}.
+     * @hide
+     */
+    public static class PropagateWorkSourceTransactListener implements ProxyTransactListener {
+        @Override
+        public Object onTransactStarted(IBinder binder, int transactionCode) {
+           // Note that {@link Binder#getCallingUid()} is already set to the UID of the current
+           // process when this method is called.
+           //
+           // We use ThreadLocalWorkSourceUid instead. It also allows feature owners to set
+           // {@link ThreadLocalWorkSourceUid#set(int) manually to attribute resources to a UID.
+            int uid = ThreadLocalWorkSourceUid.get();
+            if (uid >= 0) {
+                int originalUid = Binder.setThreadWorkSource(uid);
+                return Integer.valueOf(originalUid);
+            }
+            return null;
+        }
+
+        @Override
+        public void onTransactEnded(Object session) {
+            if (session != null) {
+                int uid = (int) session;
+                Binder.setThreadWorkSource(uid);
+            }
+        }
+    }
+
+    /**
+     * Sets a listener for the transact method on the proxy-side.
+     *
+     * <li>The listener is global. Only fast operations should be done to avoid thread
+     * contentions.
+     * <li>The listener implementation needs to handle synchronization if needed. The methods on the
+     * listener can be called concurrently.
+     * <li>Listener set will be used for new transactions. On-going transaction will still use the
+     * previous listener (if already set).
+     * <li>The listener is called on the critical path of the binder transaction so be careful about
+     * performance.
+     * <li>Never execute another binder transaction inside the listener.
+     * @hide
+     */
+    public static void setProxyTransactListener(@Nullable ProxyTransactListener listener) {
+        BinderProxy.setTransactListener(listener);
+    }
+
+    /**
      * Default implementation is a stub that returns false.  You will want
      * to override this to do the appropriate unmarshalling of transactions.
      *
diff --git a/core/java/android/os/BinderProxy.java b/core/java/android/os/BinderProxy.java
index 591370f..720c167 100644
--- a/core/java/android/os/BinderProxy.java
+++ b/core/java/android/os/BinderProxy.java
@@ -17,6 +17,7 @@
 package android.os;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.util.Log;
 import android.util.SparseIntArray;
 
@@ -45,6 +46,15 @@
     // Assume the process-wide default value when created
     volatile boolean mWarnOnBlocking = Binder.sWarnOnBlocking;
 
+    private static volatile Binder.ProxyTransactListener sTransactListener = null;
+
+    /**
+     * @see {@link Binder#setProxyTransactListener(listener)}.
+     */
+    public static void setTransactListener(@Nullable Binder.ProxyTransactListener listener) {
+        sTransactListener = listener;
+    }
+
     /*
      * Map from longs to BinderProxy, retaining only a WeakReference to the BinderProxies.
      * We roll our own only because we need to lazily remove WeakReferences during accesses
@@ -469,9 +479,21 @@
             Trace.traceBegin(Trace.TRACE_TAG_ALWAYS,
                     stackTraceElement.getClassName() + "." + stackTraceElement.getMethodName());
         }
+
+        // Make sure the listener won't change while processing a transaction.
+        final Binder.ProxyTransactListener transactListener = sTransactListener;
+        Object session = null;
+        if (transactListener != null) {
+            session = transactListener.onTransactStarted(this, code);
+        }
+
         try {
             return transactNative(code, data, reply, flags);
         } finally {
+            if (transactListener != null) {
+                transactListener.onTransactEnded(session);
+            }
+
             if (tracingEnabled) {
                 Trace.traceEnd(Trace.TRACE_TAG_ALWAYS);
             }
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index f71fdd7..0b90f54 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -22,16 +22,19 @@
 import static android.os.ParcelFileDescriptor.MODE_READ_WRITE;
 import static android.os.ParcelFileDescriptor.MODE_TRUNCATE;
 import static android.os.ParcelFileDescriptor.MODE_WRITE_ONLY;
+import static android.system.OsConstants.F_OK;
 import static android.system.OsConstants.O_APPEND;
 import static android.system.OsConstants.O_CREAT;
 import static android.system.OsConstants.O_RDONLY;
 import static android.system.OsConstants.O_RDWR;
 import static android.system.OsConstants.O_TRUNC;
 import static android.system.OsConstants.O_WRONLY;
+import static android.system.OsConstants.R_OK;
 import static android.system.OsConstants.SPLICE_F_MORE;
 import static android.system.OsConstants.SPLICE_F_MOVE;
 import static android.system.OsConstants.S_ISFIFO;
 import static android.system.OsConstants.S_ISREG;
+import static android.system.OsConstants.W_OK;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -1300,6 +1303,23 @@
     }
 
     /** {@hide} */
+    public static int translateModeAccessToPosix(int mode) {
+        if (mode == F_OK) {
+            // There's not an exact mapping, so we attempt a read-only open to
+            // determine if a file exists
+            return O_RDONLY;
+        } else if ((mode & (R_OK | W_OK)) == (R_OK | W_OK)) {
+            return O_RDWR;
+        } else if ((mode & R_OK) == R_OK) {
+            return O_RDONLY;
+        } else if ((mode & W_OK) == W_OK) {
+            return O_WRONLY;
+        } else {
+            throw new IllegalArgumentException("Bad mode: " + mode);
+        }
+    }
+
+    /** {@hide} */
     @VisibleForTesting
     public static class MemoryPipe extends Thread implements AutoCloseable {
         private final FileDescriptor[] pipe;
diff --git a/core/java/android/os/ParcelFileDescriptor.java b/core/java/android/os/ParcelFileDescriptor.java
index a54c589..70688fd 100644
--- a/core/java/android/os/ParcelFileDescriptor.java
+++ b/core/java/android/os/ParcelFileDescriptor.java
@@ -291,22 +291,7 @@
     }
 
     private static FileDescriptor openInternal(File file, int mode) throws FileNotFoundException {
-        if ((mode & MODE_READ_WRITE) == 0) {
-            throw new IllegalArgumentException(
-                    "Must specify MODE_READ_ONLY, MODE_WRITE_ONLY, or MODE_READ_WRITE");
-        }
-
-        int flags = 0;
-        switch (mode & MODE_READ_WRITE) {
-            case 0:
-            case MODE_READ_ONLY: flags = O_RDONLY; break;
-            case MODE_WRITE_ONLY: flags = O_WRONLY; break;
-            case MODE_READ_WRITE: flags = O_RDWR; break;
-        }
-
-        if ((mode & MODE_CREATE) != 0) flags |= O_CREAT;
-        if ((mode & MODE_TRUNCATE) != 0) flags |= O_TRUNC;
-        if ((mode & MODE_APPEND) != 0) flags |= O_APPEND;
+        final int flags = FileUtils.translateModePfdToPosix(mode);
 
         int realMode = S_IRWXU | S_IRWXG;
         if ((mode & MODE_WORLD_READABLE) != 0) realMode |= S_IROTH;
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 379d28c..651caec 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -990,6 +990,8 @@
     /** @hide */
     public static final int PROC_TAB_TERM = (int)'\t';
     /** @hide */
+    public static final int PROC_NEWLINE_TERM = (int) '\n';
+    /** @hide */
     public static final int PROC_COMBINE = 0x100;
     /** @hide */
     public static final int PROC_PARENS = 0x200;
@@ -1009,7 +1011,8 @@
      *
      * <p>The format is a list of integers, where every integer describes a variable in the file. It
      * specifies how the variable is syntactically terminated (e.g. {@link Process#PROC_SPACE_TERM},
-     * {@link Process#PROC_TAB_TERM}, {@link Process#PROC_ZERO_TERM}).
+     * {@link Process#PROC_TAB_TERM}, {@link Process#PROC_ZERO_TERM}, {@link
+     * Process#PROC_NEWLINE_TERM}).
      *
      * <p>If the variable should be parsed and returned to the caller, the termination type should
      * be binary OR'd with the type of output (e.g. {@link Process#PROC_OUT_STRING}, {@link
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 00b989e..1a84197 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -1278,6 +1278,8 @@
      * @return whether this process is running under the primary user.
      * @hide
      */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
     public boolean isPrimaryUser() {
         UserInfo user = getUserInfo(UserHandle.myUserId());
         return user != null && user.isPrimary();
@@ -1295,10 +1297,15 @@
     }
 
     /**
+     * Used to check if this process is running as an admin user. An admin user is allowed to
+     * modify or configure certain settings that aren't available to non-admin users,
+     * create and delete additional users, etc. There can be more than one admin users.
+     *
+     * @return whether this process is running under an admin user.
      * @hide
-     * Returns whether the caller is running as an admin user. There can be more than one admin
-     * user.
      */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
     public boolean isAdminUser() {
         return isUserAdmin(UserHandle.myUserId());
     }
@@ -1323,12 +1330,14 @@
     }
 
     /**
-     * Returns whether the caller is running as restricted profile. Restricted profile may have
-     * a reduced number of available apps, app restrictions and account restrictions.
-     * @return whether the user making this call is a linked user
+     * Used to check if this process is running under a restricted profile. Restricted profiles
+     * may have a reduced number of available apps, app restrictions, and account restrictions.
+     *
+     * @return whether this process is running under a restricted profile.
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
     public boolean isRestrictedProfile() {
         try {
             return mService.isRestricted();
@@ -1374,10 +1383,13 @@
     }
 
     /**
-     * Checks if the calling app is running as a guest user.
-     * @return whether the caller is a guest user.
+     * Used to check if this process is running under a guest user. A guest user may be transient.
+     *
+     * @return whether this process is running under a guest user.
      * @hide
      */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
     public boolean isGuestUser() {
         UserInfo user = getUserInfo(UserHandle.myUserId());
         return user != null && user.isGuest();
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index df771df..c91cda6 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -132,6 +132,15 @@
     public static final String PROP_ISOLATED_STORAGE = "persist.sys.isolated_storage";
 
     /** {@hide} */
+    public static final String PROP_FORCE_AUDIO = "persist.fw.force_audio";
+    /** {@hide} */
+    public static final String PROP_FORCE_VIDEO = "persist.fw.force_video";
+    /** {@hide} */
+    public static final String PROP_FORCE_IMAGES = "persist.fw.force_images";
+    /** {@hide} */
+    public static final String PROP_FORCE_LEGACY = "persist.fw.force_legacy";
+
+    /** {@hide} */
     public static final String UUID_PRIVATE_INTERNAL = null;
     /** {@hide} */
     public static final String UUID_PRIMARY_PHYSICAL = "primary_physical";
diff --git a/core/java/android/os/storage/StorageManagerInternal.java b/core/java/android/os/storage/StorageManagerInternal.java
index 63ff7b2..816a730 100644
--- a/core/java/android/os/storage/StorageManagerInternal.java
+++ b/core/java/android/os/storage/StorageManagerInternal.java
@@ -101,9 +101,11 @@
      * Delete storage sandbox for the given package.
      *
      * @param packageName The package for which the sandbox needs to be destroyed.
+     * @param sharedUserId The sharedUserId if specified by the package.
      * @param userId The userId in which the sandbox needs to be destroyed.
      */
-    public abstract void destroySandboxForApp(@NonNull String packageName, int userId);
+    public abstract void destroySandboxForApp(@NonNull String packageName,
+            @Nullable String sharedUserId, int userId);
 
     /**
      * @return Labels of storage volumes that are visible to the given userId.
diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java
index bc72c4e..c0fa1de 100644
--- a/core/java/android/provider/CallLog.java
+++ b/core/java/android/provider/CallLog.java
@@ -684,6 +684,9 @@
             values.put(PHONE_ACCOUNT_ID, accountId);
             values.put(PHONE_ACCOUNT_ADDRESS, accountAddress);
             values.put(NEW, Integer.valueOf(1));
+            if ((ci != null) && (ci.name != null)) {
+                values.put(CACHED_NAME, ci.name);
+            }
             values.put(ADD_FOR_ALL_USERS, addForAllUsers ? 1 : 0);
 
             if (callType == MISSED_TYPE) {
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index 954d18a..67e52aa 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -731,6 +731,8 @@
     public static final String EXTRA_PARENT_URI = "parentUri";
     /** {@hide} */
     public static final String EXTRA_URI = "uri";
+    /** {@hide} */
+    public static final String EXTRA_URI_PERMISSIONS = "uriPermissions";
 
     /**
      * @see #createWebLinkIntent(ContentResolver, Uri, Bundle)
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index f5660b9..1fce8e6 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -46,9 +46,6 @@
 
 import com.android.internal.annotations.GuardedBy;
 
-import libcore.io.IoUtils;
-
-import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
@@ -63,7 +60,10 @@
 public final class MediaStore {
     private final static String TAG = "MediaStore";
 
+    /** The authority for the media provider */
     public static final String AUTHORITY = "media";
+    /** A content:// style uri to the authority for the media provider */
+    public static final Uri AUTHORITY_URI = Uri.parse("content://" + AUTHORITY);
 
     private static final String CONTENT_AUTHORITY_SLASH = "content://" + AUTHORITY + "/";
 
@@ -82,6 +82,11 @@
      */
     public static final String RETRANSLATE_CALL = "update_titles";
 
+    /** {@hide} */
+    public static final String GET_DOCUMENT_URI_CALL = "get_document_uri";
+    /** {@hide} */
+    public static final String GET_MEDIA_URI_CALL = "get_media_uri";
+
     /**
      * This is for internal use by the media scanner only.
      * Name of the (optional) Uri parameter that determines whether to skip deleting
@@ -2027,6 +2032,27 @@
              * <P>Type: INTEGER</P>
              */
             public static final String BOOKMARK = "bookmark";
+
+            /**
+             * The standard of color aspects
+             * <P>Type: INTEGER</P>
+             * @hide
+             */
+            public static final String COLOR_STANDARD = "color_standard";
+
+            /**
+             * The transfer of color aspects
+             * <P>Type: INTEGER</P>
+             * @hide
+             */
+            public static final String COLOR_TRANSFER = "color_transfer";
+
+            /**
+             * The range of color aspects
+             * <P>Type: INTEGER</P>
+             * @hide
+             */
+            public static final String COLOR_RANGE = "color_range";
         }
 
         public static final class Media implements VideoColumns {
@@ -2231,6 +2257,18 @@
     }
 
     /**
+     * Return the volume name that the given {@link Uri} references.
+     */
+    public static @NonNull String getVolumeName(@NonNull Uri uri) {
+        final List<String> segments = uri.getPathSegments();
+        if (uri.getAuthority().equals(AUTHORITY) && segments != null && segments.size() > 0) {
+            return segments.get(0);
+        } else {
+            throw new IllegalArgumentException("Not a media Uri: " + uri);
+        }
+    }
+
+    /**
      * Uri for querying the state of the media scanner.
      */
     public static Uri getMediaScannerUri() {
@@ -2275,84 +2313,62 @@
     }
 
     /**
-     * Gets a URI backed by a {@link DocumentsProvider} that points to the same media
-     * file as the specified mediaUri. This allows apps who have permissions to access
-     * media files in Storage Access Framework to perform file operations through that
-     * on media files.
+     * Return a {@link DocumentsProvider} Uri that is an equivalent to the given
+     * {@link MediaStore} Uri.
      * <p>
-     * Note: this method doesn't grant any URI permission. Callers need to obtain
-     * permission before calling this method. One way to obtain permission is through
-     * a 3-step process:
-     * <ol>
-     *     <li>Call {@link android.os.storage.StorageManager#getStorageVolume(File)} to
-     *     obtain the {@link android.os.storage.StorageVolume} of a media file;</li>
+     * This allows apps with Storage Access Framework permissions to convert
+     * between {@link MediaStore} and {@link DocumentsProvider} Uris that refer
+     * to the same underlying item. Note that this method doesn't grant any new
+     * permissions; callers must already hold permissions obtained with
+     * {@link Intent#ACTION_OPEN_DOCUMENT} or related APIs.
      *
-     *     <li>Invoke the intent returned by
-     *     {@link android.os.storage.StorageVolume#createAccessIntent(String)} to
-     *     obtain the access of the volume or one of its specific subdirectories;</li>
-     *
-     *     <li>Check whether permission is granted and take persistent permission.</li>
-     * </ol>
-     * @param mediaUri the media URI which document URI is requested
-     * @return the document URI
+     * @param mediaUri The {@link MediaStore} Uri to convert.
+     * @return An equivalent {@link DocumentsProvider} Uri. Returns {@code null}
+     *         if no equivalent was found.
+     * @see #getMediaUri(Context, Uri)
      */
     public static Uri getDocumentUri(Context context, Uri mediaUri) {
+        final ContentResolver resolver = context.getContentResolver();
+        final List<UriPermission> uriPermissions = resolver.getPersistedUriPermissions();
 
-        try {
-            final ContentResolver resolver = context.getContentResolver();
-
-            final String path = getFilePath(resolver, mediaUri);
-            final List<UriPermission> uriPermissions = resolver.getPersistedUriPermissions();
-
-            return getDocumentUri(resolver, path, uriPermissions);
+        try (ContentProviderClient client = resolver.acquireContentProviderClient(AUTHORITY)) {
+            final Bundle in = new Bundle();
+            in.putParcelable(DocumentsContract.EXTRA_URI, mediaUri);
+            in.putParcelableList(DocumentsContract.EXTRA_URI_PERMISSIONS, uriPermissions);
+            final Bundle out = client.call(GET_DOCUMENT_URI_CALL, null, in);
+            return out.getParcelable(DocumentsContract.EXTRA_URI);
         } catch (RemoteException e) {
             throw e.rethrowAsRuntimeException();
         }
     }
 
-    private static String getFilePath(ContentResolver resolver, Uri mediaUri)
-            throws RemoteException {
+    /**
+     * Return a {@link MediaStore} Uri that is an equivalent to the given
+     * {@link DocumentsProvider} Uri.
+     * <p>
+     * This allows apps with Storage Access Framework permissions to convert
+     * between {@link MediaStore} and {@link DocumentsProvider} Uris that refer
+     * to the same underlying item. Note that this method doesn't grant any new
+     * permissions; callers must already hold permissions obtained with
+     * {@link Intent#ACTION_OPEN_DOCUMENT} or related APIs.
+     *
+     * @param documentUri The {@link DocumentsProvider} Uri to convert.
+     * @return An equivalent {@link MediaStore} Uri. Returns {@code null} if no
+     *         equivalent was found.
+     * @see #getDocumentUri(Context, Uri)
+     */
+    public static Uri getMediaUri(Context context, Uri documentUri) {
+        final ContentResolver resolver = context.getContentResolver();
+        final List<UriPermission> uriPermissions = resolver.getPersistedUriPermissions();
 
-        try (ContentProviderClient client =
-                     resolver.acquireUnstableContentProviderClient(AUTHORITY)) {
-            final Cursor c = client.query(
-                    mediaUri,
-                    new String[]{ MediaColumns.DATA },
-                    null, /* selection */
-                    null, /* selectionArg */
-                    null /* sortOrder */);
-
-            final String path;
-            try {
-                if (c.getCount() == 0) {
-                    throw new IllegalStateException("Not found media file under URI: " + mediaUri);
-                }
-
-                if (!c.moveToFirst()) {
-                    throw new IllegalStateException("Failed to move cursor to the first item.");
-                }
-
-                path = c.getString(0);
-            } finally {
-                IoUtils.closeQuietly(c);
-            }
-
-            return path;
-        }
-    }
-
-    private static Uri getDocumentUri(
-            ContentResolver resolver, String path, List<UriPermission> uriPermissions)
-            throws RemoteException {
-
-        try (ContentProviderClient client = resolver.acquireUnstableContentProviderClient(
-                DocumentsContract.EXTERNAL_STORAGE_PROVIDER_AUTHORITY)) {
+        try (ContentProviderClient client = resolver.acquireContentProviderClient(AUTHORITY)) {
             final Bundle in = new Bundle();
-            in.putParcelableList(
-                    DocumentsContract.EXTERNAL_STORAGE_PROVIDER_AUTHORITY + ".extra.uriPermissions",
-                    uriPermissions);
-            final Bundle out = client.call("getDocumentId", path, in);
+            in.putParcelable(DocumentsContract.EXTRA_URI, documentUri);
+            in.putParcelableList(DocumentsContract.EXTRA_URI_PERMISSIONS, uriPermissions);
+            final Bundle out = client.call(GET_MEDIA_URI_CALL, null, in);
             return out.getParcelable(DocumentsContract.EXTRA_URI);
+        } catch (RemoteException e) {
+            throw e.rethrowAsRuntimeException();
         }
     }
 }
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 80e8f78..f58624f 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -6038,6 +6038,7 @@
          * shortcut. Must be its flattened {@link ComponentName}.
          * @hide
          */
+        @TestApi
         public static final String ACCESSIBILITY_SHORTCUT_TARGET_SERVICE =
                 "accessibility_shortcut_target_service";
 
@@ -6947,6 +6948,7 @@
          * each release when there is new setup information to show.
          * @hide
          */
+        @SystemApi
         public static final String LAST_SETUP_SHOWN = "last_setup_shown";
 
         /**
@@ -7387,8 +7389,16 @@
         public static final String DIALER_DEFAULT_APPLICATION = "dialer_default_application";
 
         /**
-         * Specifies the package name currently configured to be the default application to perform
-         * the user-defined call redirection service with Telecom.
+         * Specifies the component name currently configured to be the default call screening
+         * application
+         * @hide
+         */
+        public static final String CALL_SCREENING_DEFAULT_COMPONENT =
+                "call_screening_default_component";
+
+        /**
+         * Specifies the component name currently configured to be the default application to
+         * perform the user-defined call redirection service with Telecom.
          * @hide
          */
         @UnsupportedAppUsage
diff --git a/core/java/android/rolecontrollerservice/IRoleControllerService.aidl b/core/java/android/rolecontrollerservice/IRoleControllerService.aidl
new file mode 100644
index 0000000..0000b9f
--- /dev/null
+++ b/core/java/android/rolecontrollerservice/IRoleControllerService.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.rolecontrollerservice;
+
+import android.app.role.IRoleManagerCallback;
+
+/**
+ * @hide
+ */
+oneway interface IRoleControllerService {
+
+    void onAddRoleHolder(in String roleName, in String packageName,
+                         in IRoleManagerCallback callback);
+
+    void onRemoveRoleHolder(in String roleName, in String packageName,
+                           in IRoleManagerCallback callback);
+
+    void onClearRoleHolders(in String roleName, in IRoleManagerCallback callback);
+}
diff --git a/core/java/android/rolecontrollerservice/RoleControllerService.java b/core/java/android/rolecontrollerservice/RoleControllerService.java
new file mode 100644
index 0000000..da11bca
--- /dev/null
+++ b/core/java/android/rolecontrollerservice/RoleControllerService.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.rolecontrollerservice;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.app.Service;
+import android.app.role.IRoleManagerCallback;
+import android.app.role.RoleManager;
+import android.app.role.RoleManagerCallback;
+import android.content.Intent;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.util.Log;
+
+import com.android.internal.util.Preconditions;
+
+import java.util.concurrent.Executor;
+
+/**
+ * Abstract base class for the role controller service.
+ * <p>
+ * Subclass should implement the business logic for role management, including enforcing role
+ * requirements and granting or revoking relevant privileges of roles. This class can only be
+ * implemented by the permission controller app which is registered in {@code PackageManager}.
+ *
+ * @hide
+ */
+@SystemApi
+public abstract class RoleControllerService extends Service {
+
+    private static final String LOG_TAG = RoleControllerService.class.getSimpleName();
+
+    /**
+     * The {@link Intent} that must be declared as handled by the service. The service should also
+     * require the {@link android.Manifest.permission#BIND_ROLE_CONTROLLER_SERVICE} permission so
+     * that other applications can not abuse it.
+     */
+    public static final String SERVICE_INTERFACE =
+            "android.rolecontrollerservice.RoleControllerService";
+
+    @Nullable
+    @Override
+    public final IBinder onBind(@Nullable Intent intent) {
+        return new IRoleControllerService.Stub() {
+
+            @Override
+            public void onAddRoleHolder(String roleName, String packageName,
+                    IRoleManagerCallback callback) {
+                Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
+                Preconditions.checkStringNotEmpty(packageName,
+                        "packageName cannot be null or empty");
+                Preconditions.checkNotNull(callback, "callback cannot be null");
+                RoleControllerService.this.onAddRoleHolder(roleName, packageName,
+                        new RoleManagerCallbackDelegate(callback));
+            }
+
+            @Override
+            public void onRemoveRoleHolder(String roleName, String packageName,
+                    IRoleManagerCallback callback) {
+                Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
+                Preconditions.checkStringNotEmpty(packageName,
+                        "packageName cannot be null or empty");
+                Preconditions.checkNotNull(callback, "callback cannot be null");
+                RoleControllerService.this.onRemoveRoleHolder(roleName, packageName,
+                        new RoleManagerCallbackDelegate(callback));
+            }
+
+            @Override
+            public void onClearRoleHolders(String roleName, IRoleManagerCallback callback) {
+                Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
+                Preconditions.checkNotNull(callback, "callback cannot be null");
+                RoleControllerService.this.onClearRoleHolders(roleName,
+                        new RoleManagerCallbackDelegate(callback));
+            }
+        };
+    }
+
+    /**
+     * Add a specific application to the holders of a role. If the role is exclusive, the previous
+     * holder will be replaced.
+     * <p>
+     * Implementation should enforce the role requirements and grant or revoke the relevant
+     * privileges of roles.
+     *
+     * @param roleName the name of the role to add the role holder for
+     * @param packageName the package name of the application to add to the role holders
+     * @param callback the callback for whether this call is successful
+     *
+     * @see RoleManager#addRoleHolderAsUser(String, String, UserHandle, Executor,
+     *      RoleManagerCallback)
+     */
+    public abstract void onAddRoleHolder(@NonNull String roleName, @NonNull String packageName,
+            @NonNull RoleManagerCallback callback);
+
+    /**
+     * Remove a specific application from the holders of a role.
+     *
+     * @param roleName the name of the role to remove the role holder for
+     * @param packageName the package name of the application to remove from the role holders
+     * @param callback the callback for whether this call is successful
+     *
+     * @see RoleManager#removeRoleHolderAsUser(String, String, UserHandle, Executor,
+     *      RoleManagerCallback)
+     */
+    public abstract void onRemoveRoleHolder(@NonNull String roleName, @NonNull String packageName,
+            @NonNull RoleManagerCallback callback);
+
+    /**
+     * Remove all holders of a role.
+     *
+     * @param roleName the name of the role to remove role holders for
+     * @param callback the callback for whether this call is successful
+     *
+     * @see RoleManager#clearRoleHoldersAsUser(String, UserHandle, Executor, RoleManagerCallback)
+     */
+    public abstract void onClearRoleHolders(@NonNull String roleName,
+            @NonNull RoleManagerCallback callback);
+
+    private static class RoleManagerCallbackDelegate implements RoleManagerCallback {
+
+        private IRoleManagerCallback mCallback;
+
+        RoleManagerCallbackDelegate(IRoleManagerCallback callback) {
+            mCallback = callback;
+        }
+
+        @Override
+        public void onSuccess() {
+            try {
+                mCallback.onSuccess();
+            } catch (RemoteException e) {
+                Log.e(LOG_TAG, "Error calling onSuccess() callback");
+            }
+        }
+
+        @Override
+        public void onFailure() {
+            try {
+                mCallback.onFailure();
+            } catch (RemoteException e) {
+                Log.e(LOG_TAG, "Error calling onFailure() callback");
+            }
+        }
+    }
+}
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index 3ab8a0a..e5fd292 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -1269,29 +1269,47 @@
      * scrolling on the specified line.
      */
     public float getLineLeft(int line) {
-        int dir = getParagraphDirection(line);
-        Alignment align = getParagraphAlignment(line);
+        final int dir = getParagraphDirection(line);
+        final Alignment align = getParagraphAlignment(line);
 
-        if (align == Alignment.ALIGN_LEFT) {
-            return 0;
-        } else if (align == Alignment.ALIGN_NORMAL) {
-            if (dir == DIR_RIGHT_TO_LEFT)
-                return getParagraphRight(line) - getLineMax(line);
-            else
-                return 0;
-        } else if (align == Alignment.ALIGN_RIGHT) {
-            return mWidth - getLineMax(line);
-        } else if (align == Alignment.ALIGN_OPPOSITE) {
-            if (dir == DIR_RIGHT_TO_LEFT)
-                return 0;
-            else
+        // First convert combinations of alignment and direction settings to
+        // three basic cases: ALIGN_LEFT, ALIGN_RIGHT and ALIGN_CENTER.
+        // For unexpected cases, it will fallback to ALIGN_LEFT.
+        final Alignment resultAlign;
+        switch(align) {
+            case ALIGN_NORMAL:
+                resultAlign =
+                        dir == DIR_RIGHT_TO_LEFT ? Alignment.ALIGN_RIGHT : Alignment.ALIGN_LEFT;
+                break;
+            case ALIGN_OPPOSITE:
+                resultAlign =
+                        dir == DIR_RIGHT_TO_LEFT ? Alignment.ALIGN_LEFT : Alignment.ALIGN_RIGHT;
+                break;
+            case ALIGN_CENTER:
+                resultAlign = Alignment.ALIGN_CENTER;
+                break;
+            case ALIGN_RIGHT:
+                resultAlign = Alignment.ALIGN_RIGHT;
+                break;
+            default: /* align == Alignment.ALIGN_LEFT */
+                resultAlign = Alignment.ALIGN_LEFT;
+        }
+
+        // Here we must use getLineMax() to do the computation, because it maybe overridden by
+        // derived class. And also note that line max equals the width of the text in that line
+        // plus the leading margin.
+        switch (resultAlign) {
+            case ALIGN_CENTER:
+                final int left = getParagraphLeft(line);
+                final float max = getLineMax(line);
+                // This computation only works when mWidth equals leadingMargin plus
+                // the width of text in this line. If this condition doesn't meet anymore,
+                // please change here too.
+                return (float) Math.floor(left + (mWidth - max) / 2);
+            case ALIGN_RIGHT:
                 return mWidth - getLineMax(line);
-        } else { /* align == Alignment.ALIGN_CENTER */
-            int left = getParagraphLeft(line);
-            int right = getParagraphRight(line);
-            int max = ((int) getLineMax(line)) & ~1;
-
-            return left + ((right - left) - max) / 2;
+            default: /* resultAlign == Alignment.ALIGN_LEFT */
+                return 0;
         }
     }
 
@@ -1300,29 +1318,40 @@
      * scrolling on the specified line.
      */
     public float getLineRight(int line) {
-        int dir = getParagraphDirection(line);
-        Alignment align = getParagraphAlignment(line);
+        final int dir = getParagraphDirection(line);
+        final Alignment align = getParagraphAlignment(line);
 
-        if (align == Alignment.ALIGN_LEFT) {
-            return getParagraphLeft(line) + getLineMax(line);
-        } else if (align == Alignment.ALIGN_NORMAL) {
-            if (dir == DIR_RIGHT_TO_LEFT)
+        final Alignment resultAlign;
+        switch(align) {
+            case ALIGN_NORMAL:
+                resultAlign =
+                        dir == DIR_RIGHT_TO_LEFT ? Alignment.ALIGN_RIGHT : Alignment.ALIGN_LEFT;
+                break;
+            case ALIGN_OPPOSITE:
+                resultAlign =
+                        dir == DIR_RIGHT_TO_LEFT ? Alignment.ALIGN_LEFT : Alignment.ALIGN_RIGHT;
+                break;
+            case ALIGN_CENTER:
+                resultAlign = Alignment.ALIGN_CENTER;
+                break;
+            case ALIGN_RIGHT:
+                resultAlign = Alignment.ALIGN_RIGHT;
+                break;
+            default: /* align == Alignment.ALIGN_LEFT */
+                resultAlign = Alignment.ALIGN_LEFT;
+        }
+
+        switch (resultAlign) {
+            case ALIGN_CENTER:
+                final int right = getParagraphRight(line);
+                final float max = getLineMax(line);
+                // This computation only works when mWidth equals leadingMargin plus width of the
+                // text in this line. If this condition doesn't meet anymore, please change here.
+                return (float) Math.ceil(right - (mWidth - max) / 2);
+            case ALIGN_RIGHT:
                 return mWidth;
-            else
-                return getParagraphLeft(line) + getLineMax(line);
-        } else if (align == Alignment.ALIGN_RIGHT) {
-            return mWidth;
-        } else if (align == Alignment.ALIGN_OPPOSITE) {
-            if (dir == DIR_RIGHT_TO_LEFT)
+            default: /* resultAlign == Alignment.ALIGN_LEFT */
                 return getLineMax(line);
-            else
-                return mWidth;
-        } else { /* align == Alignment.ALIGN_CENTER */
-            int left = getParagraphLeft(line);
-            int right = getParagraphRight(line);
-            int max = ((int) getLineMax(line)) & ~1;
-
-            return right - ((right - left) - max) / 2;
         }
     }
 
@@ -1671,7 +1700,7 @@
      * Return the vertical position of the baseline of the specified line.
      */
     public final int getLineBaseline(int line) {
-        // getLineTop(line+1) == getLineTop(line)
+        // getLineTop(line+1) == getLineBottom(line)
         return getLineTop(line+1) - getLineDescent(line);
     }
 
diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java
index 195de07..b970c25 100644
--- a/core/java/android/text/TextUtils.java
+++ b/core/java/android/text/TextUtils.java
@@ -84,7 +84,7 @@
 public class TextUtils {
     private static final String TAG = "TextUtils";
 
-    // Zero-width character used to fill ellipsized strings when codepoint lenght must be preserved.
+    // Zero-width character used to fill ellipsized strings when codepoint length must be preserved.
     /* package */ static final char ELLIPSIS_FILLER = '\uFEFF'; // ZERO WIDTH NO-BREAK SPACE
 
     // TODO: Based on CLDR data, these need to be localized for Dzongkha (dz) and perhaps
diff --git a/core/java/android/transition/Transition.java b/core/java/android/transition/Transition.java
index b79228d..8819d22 100644
--- a/core/java/android/transition/Transition.java
+++ b/core/java/android/transition/Transition.java
@@ -531,7 +531,7 @@
             View view = unmatchedStart.keyAt(i);
             if (view != null && isValidTarget(view)) {
                 TransitionValues end = unmatchedEnd.remove(view);
-                if (end != null && end.view != null && isValidTarget(end.view)) {
+                if (end != null && isValidTarget(end.view)) {
                     TransitionValues start = unmatchedStart.removeAt(i);
                     mStartValuesList.add(start);
                     mEndValuesList.add(end);
@@ -738,9 +738,8 @@
                     if (end != null) {
                         view = end.view;
                         String[] properties = getTransitionProperties();
-                        if (view != null && properties != null && properties.length > 0) {
-                            infoValues = new TransitionValues();
-                            infoValues.view = view;
+                        if (properties != null && properties.length > 0) {
+                            infoValues = new TransitionValues(view);
                             TransitionValues newValues = endValues.viewValues.get(view);
                             if (newValues != null) {
                                 for (int j = 0; j < properties.length; ++j) {
@@ -1431,8 +1430,7 @@
                 int id = mTargetIds.get(i);
                 View view = sceneRoot.findViewById(id);
                 if (view != null) {
-                    TransitionValues values = new TransitionValues();
-                    values.view = view;
+                    TransitionValues values = new TransitionValues(view);
                     if (start) {
                         captureStartValues(values);
                     } else {
@@ -1449,8 +1447,7 @@
             }
             for (int i = 0; i < mTargets.size(); ++i) {
                 View view = mTargets.get(i);
-                TransitionValues values = new TransitionValues();
-                values.view = view;
+                TransitionValues values = new TransitionValues(view);
                 if (start) {
                     captureStartValues(values);
                 } else {
@@ -1576,8 +1573,7 @@
             }
         }
         if (view.getParent() instanceof ViewGroup) {
-            TransitionValues values = new TransitionValues();
-            values.view = view;
+            TransitionValues values = new TransitionValues(view);
             if (start) {
                 captureStartValues(values);
             } else {
diff --git a/core/java/android/transition/TransitionValues.java b/core/java/android/transition/TransitionValues.java
index 11f2962..85fa67d 100644
--- a/core/java/android/transition/TransitionValues.java
+++ b/core/java/android/transition/TransitionValues.java
@@ -16,6 +16,7 @@
 
 package android.transition;
 
+import android.annotation.NonNull;
 import android.util.ArrayMap;
 import android.view.View;
 import android.view.ViewGroup;
@@ -43,19 +44,32 @@
  */
 public class TransitionValues {
 
+    /** @deprecated Use {@link #TransitionValues(View)} instead */
+    @Deprecated
+    public TransitionValues() {
+    }
+
+    public TransitionValues(@NonNull View view) {
+        this.view = view;
+    }
+
     /**
      * The View with these values
      */
+    @SuppressWarnings("NullableProblems") // Can't make it final because of deprecated constructor.
+    @NonNull
     public View view;
 
     /**
      * The set of values tracked by transitions for this scene
      */
+    @NonNull
     public final Map<String, Object> values = new ArrayMap<String, Object>();
 
     /**
      * The Transitions that targeted this view.
      */
+    @NonNull
     final ArrayList<Transition> targetedTransitions = new ArrayList<Transition>();
 
     @Override
diff --git a/core/java/android/transition/Visibility.java b/core/java/android/transition/Visibility.java
index bd2bef4..3c4b8c3 100644
--- a/core/java/android/transition/Visibility.java
+++ b/core/java/android/transition/Visibility.java
@@ -360,15 +360,49 @@
             return null;
         }
 
-        View startView = (startValues != null) ? startValues.view : null;
-        View endView = (endValues != null) ? endValues.view : null;
+        if (startValues == null) {
+            // startValues(and startView) will never be null for disappear transition.
+            return null;
+        }
+
+        final View startView = startValues.view;
+        final View endView = (endValues != null) ? endValues.view : null;
         View overlayView = null;
         View viewToKeep = null;
-        if (endView == null || endView.getParent() == null) {
-            if (endView != null) {
-                // endView was removed from its parent - add it to the overlay
-                overlayView = endView;
-            } else if (startView != null) {
+        boolean reusingOverlayView = false;
+
+        View savedOverlayView = (View) startView.getTag(R.id.transition_overlay_view_tag);
+        if (savedOverlayView != null) {
+            // we've already created overlay for the start view.
+            // it means that we are applying two visibility
+            // transitions for the same view
+            overlayView = savedOverlayView;
+            reusingOverlayView = true;
+        } else {
+            boolean needOverlayForStartView = false;
+
+            if (endView == null || endView.getParent() == null) {
+                if (endView != null) {
+                    // endView was removed from its parent - add it to the overlay
+                    overlayView = endView;
+                } else {
+                    needOverlayForStartView = true;
+                }
+            } else {
+                // visibility change
+                if (endVisibility == View.INVISIBLE) {
+                    viewToKeep = endView;
+                } else {
+                    // Becoming GONE
+                    if (startView == endView) {
+                        viewToKeep = endView;
+                    } else {
+                        needOverlayForStartView = true;
+                    }
+                }
+            }
+
+            if (needOverlayForStartView) {
                 // endView does not exist. Use startView only under certain
                 // conditions, because placing a view in an overlay necessitates
                 // it being removed from its current parent
@@ -385,74 +419,69 @@
                     if (!parentVisibilityInfo.visibilityChange) {
                         overlayView = TransitionUtils.copyViewImage(sceneRoot, startView,
                                 startParent);
-                    } else if (startParent.getParent() == null) {
+                    } else {
                         int id = startParent.getId();
-                        if (id != View.NO_ID && sceneRoot.findViewById(id) != null
-                                && mCanRemoveViews) {
+                        if (startParent.getParent() == null && id != View.NO_ID
+                                && sceneRoot.findViewById(id) != null && mCanRemoveViews) {
                             // no parent, but its parent is unparented  but the parent
                             // hierarchy has been replaced by a new hierarchy with the same id
                             // and it is safe to un-parent startView
                             overlayView = startView;
+                        } else {
+                            // TODO: Handle this case as well
                         }
                     }
                 }
             }
-        } else {
-            // visibility change
-            if (endVisibility == View.INVISIBLE) {
-                viewToKeep = endView;
-            } else {
-                // Becoming GONE
-                if (startView == endView) {
-                    viewToKeep = endView;
-                } else if (mCanRemoveViews) {
-                    overlayView = startView;
-                } else {
-                    overlayView = TransitionUtils.copyViewImage(sceneRoot, startView,
-                            (View) startView.getParent());
-                }
-            }
         }
-        final int finalVisibility = endVisibility;
 
         if (overlayView != null) {
             // TODO: Need to do this for general case of adding to overlay
-            int[] screenLoc = (int[]) startValues.values.get(PROPNAME_SCREEN_LOCATION);
-            int screenX = screenLoc[0];
-            int screenY = screenLoc[1];
-            int[] loc = new int[2];
-            sceneRoot.getLocationOnScreen(loc);
-            overlayView.offsetLeftAndRight((screenX - loc[0]) - overlayView.getLeft());
-            overlayView.offsetTopAndBottom((screenY - loc[1]) - overlayView.getTop());
-            final ViewGroupOverlay overlay = sceneRoot.getOverlay();
-            overlay.add(overlayView);
-            Animator animator = onDisappear(sceneRoot, overlayView, startValues, endValues);
-            if (animator == null) {
-                overlay.remove(overlayView);
+            final ViewGroupOverlay overlay;
+            if (!reusingOverlayView) {
+                overlay = sceneRoot.getOverlay();
+                int[] screenLoc = (int[]) startValues.values.get(PROPNAME_SCREEN_LOCATION);
+                int screenX = screenLoc[0];
+                int screenY = screenLoc[1];
+                int[] loc = new int[2];
+                sceneRoot.getLocationOnScreen(loc);
+                overlayView.offsetLeftAndRight((screenX - loc[0]) - overlayView.getLeft());
+                overlayView.offsetTopAndBottom((screenY - loc[1]) - overlayView.getTop());
+                overlay.add(overlayView);
             } else {
-                final View finalOverlayView = overlayView;
-                addListener(new TransitionListenerAdapter() {
+                overlay = null;
+            }
+            Animator animator = onDisappear(sceneRoot, overlayView, startValues, endValues);
+            if (!reusingOverlayView) {
+                if (animator == null) {
+                    overlay.remove(overlayView);
+                } else {
+                    startView.setTagInternal(R.id.transition_overlay_view_tag, overlayView);
+                    final View finalOverlayView = overlayView;
+                    addListener(new TransitionListenerAdapter() {
 
-                    @Override
-                    public void onTransitionPause(Transition transition) {
-                        overlay.remove(finalOverlayView);
-                    }
-
-                    @Override
-                    public void onTransitionResume(Transition transition) {
-                        if (finalOverlayView.getParent() == null) {
-                            overlay.add(finalOverlayView);
-                        } else {
-                            cancel();
+                        @Override
+                        public void onTransitionPause(Transition transition) {
+                            overlay.remove(finalOverlayView);
                         }
-                    }
 
-                    @Override
-                    public void onTransitionEnd(Transition transition) {
-                        overlay.remove(finalOverlayView);
-                        transition.removeListener(this);
-                    }
-                });
+                        @Override
+                        public void onTransitionResume(Transition transition) {
+                            if (finalOverlayView.getParent() == null) {
+                                overlay.add(finalOverlayView);
+                            } else {
+                                cancel();
+                            }
+                        }
+
+                        @Override
+                        public void onTransitionEnd(Transition transition) {
+                            startView.setTagInternal(R.id.transition_overlay_view_tag, null);
+                            overlay.remove(finalOverlayView);
+                            transition.removeListener(this);
+                        }
+                    });
+                }
             }
             return animator;
         }
@@ -463,7 +492,7 @@
             Animator animator = onDisappear(sceneRoot, viewToKeep, startValues, endValues);
             if (animator != null) {
                 DisappearListener disappearListener = new DisappearListener(viewToKeep,
-                        finalVisibility, mSuppressLayout);
+                        endVisibility, mSuppressLayout);
                 animator.addListener(disappearListener);
                 animator.addPauseListener(disappearListener);
                 addListener(disappearListener);
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index db2c190..fb44eda 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -48,7 +48,8 @@
         DEFAULT_FLAGS.put("settings_data_usage_v2", "false");
         DEFAULT_FLAGS.put("settings_seamless_transfer", "false");
         DEFAULT_FLAGS.put(HEARING_AID_SETTINGS, "false");
-        DEFAULT_FLAGS.put(EMERGENCY_DIAL_SHORTCUTS, "false");
+        DEFAULT_FLAGS.put(EMERGENCY_DIAL_SHORTCUTS, "true");
+        DEFAULT_FLAGS.put("settings_network_and_internet_v2", "false");
     }
 
     /**
diff --git a/core/java/android/util/MathUtils.java b/core/java/android/util/MathUtils.java
index 37bb597..56558d0 100644
--- a/core/java/android/util/MathUtils.java
+++ b/core/java/android/util/MathUtils.java
@@ -17,6 +17,7 @@
 package android.util;
 
 import android.annotation.UnsupportedAppUsage;
+import android.graphics.Rect;
 
 /**
  * A class that contains utility methods related to numbers.
@@ -227,4 +228,18 @@
         }
         throw new IllegalArgumentException("Addition overflow: " + a + " + " + b);
     }
+
+    /**
+     * Resize a {@link Rect} so one size would be {@param largestSide}.
+     *
+     * @param outToResize Rectangle that will be resized.
+     * @param largestSide Size of the largest side.
+     */
+    public static void fitRect(Rect outToResize, int largestSide) {
+        if (outToResize.isEmpty()) {
+            return;
+        }
+        float maxSize = Math.max(outToResize.width(), outToResize.height());
+        outToResize.scale(largestSide / maxSize);
+    }
 }
diff --git a/core/java/android/view/GhostView.java b/core/java/android/view/GhostView.java
index 98ed217..74c801b 100644
--- a/core/java/android/view/GhostView.java
+++ b/core/java/android/view/GhostView.java
@@ -52,7 +52,7 @@
             RecordingCanvas dlCanvas = (RecordingCanvas) canvas;
             mView.mRecreateDisplayList = true;
             RenderNode renderNode = mView.updateDisplayListIfDirty();
-            if (renderNode.isValid()) {
+            if (renderNode.hasDisplayList()) {
                 dlCanvas.insertReorderBarrier(); // enable shadow for this rendernode
                 dlCanvas.drawRenderNode(renderNode);
                 dlCanvas.insertInorderBarrier(); // re-disable reordering/shadows
diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java
index 9aab419..a4d3ce7 100644
--- a/core/java/android/view/LayoutInflater.java
+++ b/core/java/android/view/LayoutInflater.java
@@ -26,6 +26,7 @@
 import android.content.res.TypedArray;
 import android.content.res.XmlResourceParser;
 import android.graphics.Canvas;
+import android.os.Build;
 import android.os.Handler;
 import android.os.Message;
 import android.os.Trace;
@@ -78,7 +79,7 @@
      * This field should be made private, so it is hidden from the SDK.
      * {@hide}
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     protected final Context mContext;
 
     // these are optional, set by the caller
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index f17a458..f3cb376 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -897,7 +897,7 @@
         HwuiContext(boolean isWideColorGamut) {
             mRenderNode = RenderNode.create("HwuiCanvas", null);
             mRenderNode.setClipToBounds(false);
-            mRenderNode.setAllowForceDark(false);
+            mRenderNode.setForceDarkAllowed(false);
             mIsWideColorGamut = isWideColorGamut;
             mHwuiRenderer = nHwuiCreate(mRenderNode.mNativeRenderNode, mNativeObject,
                     isWideColorGamut);
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index c1ab4d4..f0f4c1c 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -694,7 +694,7 @@
         Trace.traceBegin(Trace.TRACE_TAG_VIEW, "Record View#draw()");
         updateViewTreeDisplayList(view);
 
-        if (mRootNodeNeedsUpdate || !mRootNode.isValid()) {
+        if (mRootNodeNeedsUpdate || !mRootNode.hasDisplayList()) {
             RecordingCanvas canvas = mRootNode.start(mSurfaceWidth, mSurfaceHeight);
             try {
                 final int saveCount = canvas.save();
@@ -857,7 +857,7 @@
 
 
     void buildLayer(RenderNode node) {
-        if (node.isValid()) {
+        if (node.hasDisplayList()) {
             nBuildLayer(mNativeProxy, node.mNativeRenderNode);
         }
     }
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index c829182..1493cd7 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -5542,6 +5542,10 @@
                     break;
                 case com.android.internal.R.styleable.View_accessibilityHeading:
                     setAccessibilityHeading(a.getBoolean(attr, false));
+                    break;
+                case R.styleable.View_forceDarkAllowed:
+                    mRenderNode.setForceDarkAllowed(a.getBoolean(attr, true));
+                    break;
             }
         }
 
@@ -15286,11 +15290,9 @@
      * If a theme is isLightTheme="false", then force dark is globally disabled for that theme.
      *
      * @param allow Whether or not to allow force dark.
-     *
-     * @hide
      */
-    public void setAllowForceDark(boolean allow) {
-        if (mRenderNode.setAllowForceDark(allow)) {
+    public void setForceDarkAllowed(boolean allow) {
+        if (mRenderNode.setForceDarkAllowed(allow)) {
             // Currently toggling force-dark requires a new display list push to apply
             // TODO: Make it not clobber the display list so this is just a damageSelf() instead
             invalidate();
@@ -15298,15 +15300,13 @@
     }
 
     /**
-     * See {@link #setAllowForceDark(boolean)}
+     * See {@link #setForceDarkAllowed(boolean)}
      *
      * @return true if force dark is allowed (default), false if it is disabled
-     *
-     * @hide
      */
     @ViewDebug.ExportedProperty(category = "drawing")
-    public boolean getAllowForceDark() {
-        return mRenderNode.getAllowForceDark();
+    public boolean isForceDarkAllowed() {
+        return mRenderNode.isForceDarkAllowed();
     }
 
     /**
@@ -16658,7 +16658,7 @@
     @UnsupportedAppUsage
     void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
         if (!isHardwareAccelerated()
-                || !mRenderNode.isValid()
+                || !mRenderNode.hasDisplayList()
                 || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
             if (invalidateParent) {
                 invalidateParentCaches();
@@ -19047,7 +19047,7 @@
         switch (mLayerType) {
             case LAYER_TYPE_HARDWARE:
                 updateDisplayListIfDirty();
-                if (attachInfo.mThreadedRenderer != null && mRenderNode.isValid()) {
+                if (attachInfo.mThreadedRenderer != null && mRenderNode.hasDisplayList()) {
                     attachInfo.mThreadedRenderer.buildLayer(mRenderNode);
                 }
                 break;
@@ -19214,11 +19214,11 @@
         }
 
         if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
-                || !renderNode.isValid()
+                || !renderNode.hasDisplayList()
                 || (mRecreateDisplayList)) {
             // Don't need to recreate the display list, just need to tell our
             // children to restore/recreate theirs
-            if (renderNode.isValid()
+            if (renderNode.hasDisplayList()
                     && !mRecreateDisplayList) {
                 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
                 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
@@ -19235,7 +19235,7 @@
             int height = mBottom - mTop;
             int layerType = getLayerType();
 
-            final RecordingCanvas canvas = renderNode.start(width, height);
+            final RecordingCanvas canvas = renderNode.startRecording(width, height);
 
             try {
                 if (layerType == LAYER_TYPE_SOFTWARE) {
@@ -19266,7 +19266,7 @@
                     }
                 }
             } finally {
-                renderNode.end(canvas);
+                renderNode.endRecording();
                 setDisplayListProperties(renderNode);
             }
         } else {
@@ -20118,7 +20118,7 @@
             // Delay getting the display list until animation-driven alpha values are
             // set up and possibly passed on to the view
             renderNode = updateDisplayListIfDirty();
-            if (!renderNode.isValid()) {
+            if (!renderNode.hasDisplayList()) {
                 // Uncommon, but possible. If a view is removed from the hierarchy during the call
                 // to getDisplayList(), the display list will be marked invalid and we should not
                 // try to use it again.
@@ -20581,7 +20581,7 @@
             mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
 
             final RenderNode renderNode = mBackgroundRenderNode;
-            if (renderNode != null && renderNode.isValid()) {
+            if (renderNode != null && renderNode.hasDisplayList()) {
                 setBackgroundRenderNodeProperties(renderNode);
                 ((RecordingCanvas) canvas).drawRenderNode(renderNode);
                 return;
@@ -20635,7 +20635,7 @@
         final Rect bounds = drawable.getBounds();
         final int width = bounds.width();
         final int height = bounds.height();
-        final RecordingCanvas canvas = renderNode.start(width, height);
+        final RecordingCanvas canvas = renderNode.startRecording(width, height);
 
         // Reverse left/top translation done by drawable canvas, which will
         // instead be applied by rendernode's LTRB bounds below. This way, the
@@ -20646,7 +20646,7 @@
         try {
             drawable.draw(canvas);
         } finally {
-            renderNode.end(canvas);
+            renderNode.endRecording();
         }
 
         // Set up drawable properties that are view-independent.
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 7da31eb..4876148 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -243,9 +243,10 @@
     final Context mContext;
     /**
      * TODO(b/116349163): Check if we can merge this into {@link #mContext}.
+     * @hide
      */
     @NonNull
-    private Context mDisplayContext;
+    public Context mDisplayContext;
 
     @UnsupportedAppUsage
     final IWindowSession mWindowSession;
@@ -1096,15 +1097,21 @@
     private void updateForceDarkMode() {
         if (mAttachInfo.mThreadedRenderer == null) return;
 
-        boolean nightMode = getNightMode() == Configuration.UI_MODE_NIGHT_YES;
-        TypedArray a = mContext.obtainStyledAttributes(R.styleable.Theme);
-        boolean isLightTheme = a.getBoolean(R.styleable.Theme_isLightTheme, false);
-        a.recycle();
+        boolean useAutoDark = getNightMode() == Configuration.UI_MODE_NIGHT_YES;
 
-        boolean changed = mAttachInfo.mThreadedRenderer.setForceDark(nightMode);
-        changed |= mAttachInfo.mThreadedRenderer.getRootNode().setAllowForceDark(isLightTheme);
+        // Allow debug.hwui.force_dark to override the target SDK check
+        if (useAutoDark && !SystemProperties.getBoolean("debug.hwui.force_dark", false)) {
+            useAutoDark = mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.Q;
+        }
 
-        if (changed) {
+        if (useAutoDark) {
+            TypedArray a = mContext.obtainStyledAttributes(R.styleable.Theme);
+            useAutoDark = a.getBoolean(R.styleable.Theme_isLightTheme, true)
+                    && a.getBoolean(R.styleable.Theme_forceDarkAllowed, true);
+            a.recycle();
+        }
+
+        if (mAttachInfo.mThreadedRenderer.setForceDark(useAutoDark)) {
             // TODO: Don't require regenerating all display lists to apply this setting
             invalidateWorld(mView);
         }
@@ -2316,10 +2323,12 @@
                         mResizeMode = freeformResizing
                                 ? RESIZE_MODE_FREEFORM
                                 : RESIZE_MODE_DOCKED_DIVIDER;
+                        final boolean backdropSizeMatchesFrame =
+                                mWinFrame.width() == mPendingBackDropFrame.width()
+                                        && mWinFrame.height() == mPendingBackDropFrame.height();
                         // TODO: Need cutout?
-                        startDragResizing(mPendingBackDropFrame,
-                                mWinFrame.equals(mPendingBackDropFrame), mPendingVisibleInsets,
-                                mPendingStableInsets, mResizeMode);
+                        startDragResizing(mPendingBackDropFrame, !backdropSizeMatchesFrame,
+                                mPendingVisibleInsets, mPendingStableInsets, mResizeMode);
                     } else {
                         // We shouldn't come here, but if we come we should end the resize.
                         endDragResizing();
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index e88682e..a7d0cfb 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -23,8 +23,11 @@
 import android.accessibilityservice.AccessibilityServiceInfo.FeedbackType;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
+import android.annotation.SystemApi;
 import android.annotation.SystemService;
+import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Context;
@@ -204,6 +207,7 @@
      *
      * @hide
      */
+    @TestApi
     public interface AccessibilityServicesStateChangeListener {
 
         /**
@@ -778,6 +782,7 @@
      *                for a callback on the process's main handler.
      * @hide
      */
+    @TestApi
     public void addAccessibilityServicesStateChangeListener(
             @NonNull AccessibilityServicesStateChangeListener listener, @Nullable Handler handler) {
         synchronized (mLock) {
@@ -793,6 +798,7 @@
      *
      * @hide
      */
+    @TestApi
     public void removeAccessibilityServicesStateChangeListener(
             @NonNull AccessibilityServicesStateChangeListener listener) {
         synchronized (mLock) {
@@ -1056,6 +1062,9 @@
      *
      * @hide
      */
+    @SystemApi
+    @TestApi
+    @RequiresPermission(Manifest.permission.MANAGE_ACCESSIBILITY)
     public void performAccessibilityShortcut() {
         final IAccessibilityManager service;
         synchronized (mLock) {
@@ -1139,6 +1148,30 @@
         }
     }
 
+    /**
+     * Get the component name of the service currently assigned to the accessibility shortcut.
+     *
+     * @return The flattened component name
+     * @hide
+     */
+    @TestApi
+    @RequiresPermission(Manifest.permission.MANAGE_ACCESSIBILITY)
+    @Nullable
+    public String getAccessibilityShortcutService() {
+        final IAccessibilityManager service;
+        synchronized (mLock) {
+            service = getServiceLocked();
+        }
+        if (service != null) {
+            try {
+                return service.getAccessibilityShortcutService();
+            } catch (RemoteException re) {
+                re.rethrowFromSystemServer();
+            }
+        }
+        return null;
+    }
+
     private IAccessibilityManager getServiceLocked() {
         if (mService == null) {
             tryConnectToServiceLocked(null);
diff --git a/core/java/android/view/accessibility/IAccessibilityManager.aidl b/core/java/android/view/accessibility/IAccessibilityManager.aidl
index 3e2ef18..61a8a1da 100644
--- a/core/java/android/view/accessibility/IAccessibilityManager.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityManager.aidl
@@ -67,9 +67,12 @@
 
     void notifyAccessibilityButtonVisibilityChanged(boolean available);
 
-    // Requires WRITE_SECURE_SETTINGS
+    // Requires Manifest.permission.MANAGE_ACCESSIBILITY
     void performAccessibilityShortcut();
 
+    // Requires Manifest.permission.MANAGE_ACCESSIBILITY
+    String getAccessibilityShortcutService();
+
     // System process only
     boolean sendFingerprintGesture(int gestureKeyCode);
 
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index e370e11..4cbb097 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -30,6 +30,7 @@
 import android.content.pm.PackageManager;
 import android.graphics.Rect;
 import android.inputmethodservice.InputMethodService;
+import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
@@ -469,26 +470,53 @@
     }
 
     /**
-     * Checks the consistency between {@link InputMethodManager} state and {@link View} state.
+     * Returns fallback {@link InputMethodManager} if the called one is not likely to be compatible
+     * with the given {@code view}.
      *
-     * @param view {@link View} to be checked
-     * @return {@code true} if {@code view} is not {@code null} and there is a {@link Context}
-     *         mismatch between {@link InputMethodManager} and {@code view}
+     * @param view {@link View} to be checked.
+     * @return {@code null} when it is unnecessary (or impossible) to use fallback
+     *         {@link InputMethodManager} to which IME API calls need to be re-dispatched.
+     *          Non-{@code null} {@link InputMethodManager} if this method believes it'd be safer to
+     *          re-dispatch IME APIs calls on it.
      */
-    private boolean shouldDispatchToViewContext(@Nullable View view) {
+    @Nullable
+    private InputMethodManager getFallbackInputMethodManagerIfNecessary(@Nullable View view) {
         if (view == null) {
-            return false;
+            return null;
         }
-        final int viewDisplayId = view.getContext().getDisplayId();
-        if (viewDisplayId != mDisplayId) {
-            Log.w(TAG, "b/117267690: Context mismatch found. view=" + view + " belongs to"
-                    + " displayId=" + viewDisplayId
-                    + " but InputMethodManager belongs to displayId=" + mDisplayId
-                    + ". Use the right InputMethodManager instance to avoid performance overhead.",
-                    new Throwable());
-            return true;
+        // As evidenced in Bug 118341760, view.getViewRootImpl().getDisplayId() is supposed to be
+        // more reliable to determine with which display the given view is interacting than
+        // view.getContext().getDisplayId() / view.getContext().getSystemService(), which can be
+        // easily messed up by app developers (or library authors) by creating inconsistent
+        // ContextWrapper objects that re-dispatch those methods to other Context such as
+        // ApplicationContext.
+        final ViewRootImpl viewRootImpl = view.getViewRootImpl();
+        if (viewRootImpl == null) {
+            return null;
         }
-        return false;
+        final int viewRootDisplayId = viewRootImpl.getDisplayId();
+        if (viewRootDisplayId == mDisplayId) {
+            // Expected case.  Good to go.
+            return null;
+        }
+        final InputMethodManager fallbackImm =
+                viewRootImpl.mDisplayContext.getSystemService(InputMethodManager.class);
+        if (fallbackImm == null) {
+            Log.e(TAG, "b/117267690: Failed to get non-null fallback IMM. view=" + view);
+            return null;
+        }
+        if (fallbackImm.mDisplayId != viewRootDisplayId) {
+            Log.e(TAG, "b/117267690: Failed to get fallback IMM with expected displayId="
+                    + viewRootDisplayId + " actual IMM#displayId=" + fallbackImm.mDisplayId
+                    + " view=" + view);
+            return null;
+        }
+        Log.w(TAG, "b/117267690: Display ID mismatch found."
+                + " ViewRootImpl displayId=" + viewRootDisplayId
+                + " InputMethodManager displayId=" + mDisplayId
+                + ". Use the right InputMethodManager instance to avoid performance overhead.",
+                new Throwable());
+        return fallbackImm;
     }
 
     private static boolean canStartInput(View servedView) {
@@ -737,45 +765,77 @@
         return false;
     }
 
-    private static IInputMethodManager getIInputMethodManager() throws ServiceNotFoundException {
-        if (!isInEditMode()) {
-            return IInputMethodManager.Stub.asInterface(
-                    ServiceManager.getServiceOrThrow(Context.INPUT_METHOD_SERVICE));
-        }
-        // If InputMethodManager is running for layoutlib, stub out IPCs into IMMS.
-        final Class<IInputMethodManager> c = IInputMethodManager.class;
-        return (IInputMethodManager) Proxy.newProxyInstance(c.getClassLoader(),
-                new Class[]{c}, (proxy, method, args) -> {
-                    final Class<?> returnType = method.getReturnType();
-                    if (returnType == boolean.class) {
-                        return false;
-                    } else if (returnType == int.class) {
-                        return 0;
-                    } else if (returnType == long.class) {
-                        return 0L;
-                    } else if (returnType == short.class) {
-                        return 0;
-                    } else if (returnType == char.class) {
-                        return 0;
-                    } else if (returnType == byte.class) {
-                        return 0;
-                    } else if (returnType == float.class) {
-                        return 0f;
-                    } else if (returnType == double.class) {
-                        return 0.0;
-                    } else {
-                        return null;
-                    }
-                });
+    @NonNull
+    private static InputMethodManager createInstance(int displayId, Looper looper) {
+        return isInEditMode() ? createStubInstance(displayId, looper)
+                : createRealInstance(displayId, looper);
     }
 
-    InputMethodManager(int displayId, Looper looper) throws ServiceNotFoundException {
-        mService = getIInputMethodManager();
+    @NonNull
+    private static InputMethodManager createRealInstance(int displayId, Looper looper) {
+        final IInputMethodManager service;
+        try {
+            service = IInputMethodManager.Stub.asInterface(
+                    ServiceManager.getServiceOrThrow(Context.INPUT_METHOD_SERVICE));
+        } catch (ServiceNotFoundException e) {
+            throw new IllegalStateException(e);
+        }
+        final InputMethodManager imm = new InputMethodManager(service, displayId, looper);
+        // InputMethodManagerService#addClient() relies on Binder.getCalling{Pid, Uid}() to
+        // associate PID/UID with each IME client. This means:
+        //  A. if this method call will be handled as an IPC, there is no problem.
+        //  B. if this method call will be handled as an in-proc method call, we need to
+        //     ensure that Binder.getCalling{Pid, Uid}() return Process.my{Pid, Uid}()
+        // Either ways we can always call Binder.{clear, restore}CallingIdentity() because
+        // 1) doing so has no effect for A and 2) doing so is sufficient for B.
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            service.addClient(imm.mClient, imm.mIInputContext, displayId);
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+        return imm;
+    }
+
+    @NonNull
+    private static InputMethodManager createStubInstance(int displayId, Looper looper) {
+        // If InputMethodManager is running for layoutlib, stub out IPCs into IMMS.
+        final Class<IInputMethodManager> c = IInputMethodManager.class;
+        final IInputMethodManager stubInterface =
+                (IInputMethodManager) Proxy.newProxyInstance(c.getClassLoader(),
+                        new Class[]{c}, (proxy, method, args) -> {
+                            final Class<?> returnType = method.getReturnType();
+                            if (returnType == boolean.class) {
+                                return false;
+                            } else if (returnType == int.class) {
+                                return 0;
+                            } else if (returnType == long.class) {
+                                return 0L;
+                            } else if (returnType == short.class) {
+                                return 0;
+                            } else if (returnType == char.class) {
+                                return 0;
+                            } else if (returnType == byte.class) {
+                                return 0;
+                            } else if (returnType == float.class) {
+                                return 0f;
+                            } else if (returnType == double.class) {
+                                return 0.0;
+                            } else {
+                                return null;
+                            }
+                        });
+        return new InputMethodManager(stubInterface, displayId, looper);
+    }
+
+    private InputMethodManager(IInputMethodManager service, int displayId, Looper looper) {
+        mService = service;
         mMainLooper = looper;
         mH = new H(looper);
         mDisplayId = displayId;
-        mIInputContext = new ControlledInputConnectionWrapper(looper,
-                mDummyInputConnection, this);
+        mIInputContext = new ControlledInputConnectionWrapper(looper, mDummyInputConnection, this);
     }
 
     /**
@@ -785,7 +845,7 @@
      * @return {@link InputMethodManager} instance
      * @hide
      */
-    @Nullable
+    @NonNull
     public static InputMethodManager forContext(Context context) {
         final int displayId = context.getDisplayId();
         // For better backward compatibility, we always use Looper.getMainLooper() for the default
@@ -795,7 +855,7 @@
         return forContextInternal(displayId, looper);
     }
 
-    @Nullable
+    @NonNull
     private static InputMethodManager forContextInternal(int displayId, Looper looper) {
         final boolean isDefaultDisplay = displayId == Display.DEFAULT_DISPLAY;
         synchronized (sLock) {
@@ -803,12 +863,7 @@
             if (instance != null) {
                 return instance;
             }
-            try {
-                instance = new InputMethodManager(displayId, looper);
-                instance.mService.addClient(instance.mClient, instance.mIInputContext, displayId);
-            } catch (ServiceNotFoundException | RemoteException e) {
-                throw new IllegalStateException(e);
-            }
+            instance = createInstance(displayId, looper);
             // For backward compatibility, store the instance also to sInstance for default display.
             if (sInstance == null && isDefaultDisplay) {
                 sInstance = instance;
@@ -972,8 +1027,9 @@
      */
     public boolean isActive(View view) {
         // Re-dispatch if there is a context mismatch.
-        if (shouldDispatchToViewContext(view)) {
-            return view.getContext().getSystemService(InputMethodManager.class).isActive(view);
+        final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
+        if (fallbackImm != null) {
+            return fallbackImm.isActive(view);
         }
 
         checkFocus();
@@ -1060,9 +1116,9 @@
 
     public void displayCompletions(View view, CompletionInfo[] completions) {
         // Re-dispatch if there is a context mismatch.
-        if (shouldDispatchToViewContext(view)) {
-            view.getContext().getSystemService(InputMethodManager.class)
-                    .displayCompletions(view, completions);
+        final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
+        if (fallbackImm != null) {
+            fallbackImm.displayCompletions(view, completions);
             return;
         }
 
@@ -1085,9 +1141,9 @@
 
     public void updateExtractedText(View view, int token, ExtractedText text) {
         // Re-dispatch if there is a context mismatch.
-        if (shouldDispatchToViewContext(view)) {
-            view.getContext().getSystemService(InputMethodManager.class)
-                    .updateExtractedText(view, token, text);
+        final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
+        if (fallbackImm != null) {
+            fallbackImm.updateExtractedText(view, token, text);
             return;
         }
 
@@ -1133,9 +1189,9 @@
      */
     public boolean showSoftInput(View view, int flags) {
         // Re-dispatch if there is a context mismatch.
-        if (shouldDispatchToViewContext(view)) {
-            return view.getContext().getSystemService(InputMethodManager.class)
-                    .showSoftInput(view, flags);
+        final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
+        if (fallbackImm != null) {
+            return fallbackImm.showSoftInput(view, flags);
         }
 
         return showSoftInput(view, flags, null);
@@ -1201,9 +1257,9 @@
      */
     public boolean showSoftInput(View view, int flags, ResultReceiver resultReceiver) {
         // Re-dispatch if there is a context mismatch.
-        if (shouldDispatchToViewContext(view)) {
-            return view.getContext().getSystemService(InputMethodManager.class)
-                    .showSoftInput(view, flags, resultReceiver);
+        final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
+        if (fallbackImm != null) {
+            return fallbackImm.showSoftInput(view, flags, resultReceiver);
         }
 
         checkFocus();
@@ -1370,8 +1426,9 @@
      */
     public void restartInput(View view) {
         // Re-dispatch if there is a context mismatch.
-        if (shouldDispatchToViewContext(view)) {
-            view.getContext().getSystemService(InputMethodManager.class).restartInput(view);
+        final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
+        if (fallbackImm != null) {
+            fallbackImm.restartInput(view);
             return;
         }
 
@@ -1799,9 +1856,9 @@
     public void updateSelection(View view, int selStart, int selEnd,
             int candidatesStart, int candidatesEnd) {
         // Re-dispatch if there is a context mismatch.
-        if (shouldDispatchToViewContext(view)) {
-            view.getContext().getSystemService(InputMethodManager.class)
-                    .updateSelection(view, selStart, selEnd, candidatesStart, candidatesEnd);
+        final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
+        if (fallbackImm != null) {
+            fallbackImm.updateSelection(view, selStart, selEnd, candidatesStart, candidatesEnd);
             return;
         }
 
@@ -1843,8 +1900,9 @@
      */
     public void viewClicked(View view) {
         // Re-dispatch if there is a context mismatch.
-        if (shouldDispatchToViewContext(view)) {
-            view.getContext().getSystemService(InputMethodManager.class).viewClicked(view);
+        final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
+        if (fallbackImm != null) {
+            fallbackImm.viewClicked(view);
             return;
         }
 
@@ -1913,9 +1971,9 @@
     @Deprecated
     public void updateCursor(View view, int left, int top, int right, int bottom) {
         // Re-dispatch if there is a context mismatch.
-        if (shouldDispatchToViewContext(view)) {
-            view.getContext().getSystemService(InputMethodManager.class)
-                    .updateCursor(view, left, top, right, bottom);
+        final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
+        if (fallbackImm != null) {
+            fallbackImm.updateCursor(view, left, top, right, bottom);
             return;
         }
 
@@ -1951,9 +2009,9 @@
             return;
         }
         // Re-dispatch if there is a context mismatch.
-        if (shouldDispatchToViewContext(view)) {
-            view.getContext().getSystemService(InputMethodManager.class)
-                    .updateCursorAnchorInfo(view, cursorAnchorInfo);
+        final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
+        if (fallbackImm != null) {
+            fallbackImm.updateCursorAnchorInfo(view, cursorAnchorInfo);
             return;
         }
 
@@ -2003,9 +2061,9 @@
      */
     public void sendAppPrivateCommand(View view, String action, Bundle data) {
         // Re-dispatch if there is a context mismatch.
-        if (shouldDispatchToViewContext(view)) {
-            view.getContext().getSystemService(InputMethodManager.class)
-                    .sendAppPrivateCommand(view, action, data);
+        final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
+        if (fallbackImm != null) {
+            fallbackImm.sendAppPrivateCommand(view, action, data);
             return;
         }
 
@@ -2181,9 +2239,9 @@
     public void dispatchKeyEventFromInputMethod(@Nullable View targetView,
             @NonNull KeyEvent event) {
         // Re-dispatch if there is a context mismatch.
-        if (shouldDispatchToViewContext(targetView)) {
-            targetView.getContext().getSystemService(InputMethodManager.class)
-                    .dispatchKeyEventFromInputMethod(targetView, event);
+        final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(targetView);
+        if (fallbackImm != null) {
+            fallbackImm.dispatchKeyEventFromInputMethod(targetView, event);
             return;
         }
 
diff --git a/core/java/android/view/textclassifier/ConversationActions.java b/core/java/android/view/textclassifier/ConversationActions.java
new file mode 100644
index 0000000..5fcf227
--- /dev/null
+++ b/core/java/android/view/textclassifier/ConversationActions.java
@@ -0,0 +1,779 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.view.textclassifier;
+
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import android.annotation.FloatRange;
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.StringDef;
+import android.app.Person;
+import android.app.RemoteAction;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.SpannedString;
+import android.util.ArraySet;
+
+import com.android.internal.util.Preconditions;
+
+import java.lang.annotation.Retention;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Represents a list of actions suggested by a {@link TextClassifier} on a given conversation.
+ *
+ * @see TextClassifier#suggestConversationActions(Request)
+ */
+public final class ConversationActions implements Parcelable {
+
+    public static final Creator<ConversationActions> CREATOR =
+            new Creator<ConversationActions>() {
+                @Override
+                public ConversationActions createFromParcel(Parcel in) {
+                    return new ConversationActions(in);
+                }
+
+                @Override
+                public ConversationActions[] newArray(int size) {
+                    return new ConversationActions[size];
+                }
+            };
+
+    /** @hide */
+    @Retention(SOURCE)
+    @StringDef(
+            value = {
+                    TYPE_VIEW_CALENDAR,
+                    TYPE_VIEW_MAP,
+                    TYPE_TRACK_FLIGHT,
+                    TYPE_OPEN_URL,
+                    TYPE_SEND_SMS,
+                    TYPE_CALL_PHONE,
+                    TYPE_SEND_EMAIL,
+                    TYPE_TEXT_REPLY,
+                    TYPE_CREATE_REMINDER,
+                    TYPE_SHARE_LOCATION
+            },
+            prefix = "TYPE_")
+    public @interface ActionType {}
+
+    /**
+     * Indicates an action to view a calendar at a specified time.
+     */
+    public static final String TYPE_VIEW_CALENDAR = "view_calendar";
+    /**
+     * Indicates an action to view the map at a specified location.
+     */
+    public static final String TYPE_VIEW_MAP = "view_map";
+    /**
+     * Indicates an action to track a flight.
+     */
+    public static final String TYPE_TRACK_FLIGHT = "track_flight";
+    /**
+     * Indicates an action to open an URL.
+     */
+    public static final String TYPE_OPEN_URL = "open_url";
+    /**
+     * Indicates an action to send a SMS.
+     */
+    public static final String TYPE_SEND_SMS = "send_sms";
+    /**
+     * Indicates an action to call a phone number.
+     */
+    public static final String TYPE_CALL_PHONE = "call_phone";
+    /**
+     * Indicates an action to send an email.
+     */
+    public static final String TYPE_SEND_EMAIL = "send_email";
+    /**
+     * Indicates an action to reply with a text message.
+     */
+    public static final String TYPE_TEXT_REPLY = "text_reply";
+    /**
+     * Indicates an action to create a reminder.
+     */
+    public static final String TYPE_CREATE_REMINDER = "create_reminder";
+    /**
+     * Indicates an action to reply with a location.
+     */
+    public static final String TYPE_SHARE_LOCATION = "share_location";
+
+    /** @hide */
+    @Retention(SOURCE)
+    @StringDef(
+            value = {
+                    HINT_FOR_NOTIFICATION,
+                    HINT_FOR_IN_APP,
+            },
+            prefix = "HINT_")
+    public @interface Hint {}
+    /**
+     * To indicate the generated actions will be used within the app.
+     */
+    public static final String HINT_FOR_IN_APP = "in_app";
+    /**
+     * To indicate the generated actions will be used for notification.
+     */
+    public static final String HINT_FOR_NOTIFICATION = "notification";
+
+    private List<ConversationAction> mConversationActions;
+
+    /** Constructs a {@link ConversationActions} object. */
+    public ConversationActions(@NonNull List<ConversationAction> conversationActions) {
+        mConversationActions =
+                Collections.unmodifiableList(Preconditions.checkNotNull(conversationActions));
+    }
+
+    private ConversationActions(Parcel in) {
+        mConversationActions =
+                Collections.unmodifiableList(in.createTypedArrayList(ConversationAction.CREATOR));
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel parcel, int flags) {
+        parcel.writeTypedList(mConversationActions);
+    }
+
+    /** Returns an immutable list of {@link ConversationAction} objects. */
+    @NonNull
+    public List<ConversationAction> getConversationActions() {
+        return mConversationActions;
+    }
+
+    /** Represents the action suggested by a {@link TextClassifier} on a given conversation. */
+    public static final class ConversationAction implements Parcelable {
+
+        public static final Creator<ConversationAction> CREATOR =
+                new Creator<ConversationAction>() {
+                    @Override
+                    public ConversationAction createFromParcel(Parcel in) {
+                        return new ConversationAction(in);
+                    }
+
+                    @Override
+                    public ConversationAction[] newArray(int size) {
+                        return new ConversationAction[size];
+                    }
+                };
+
+        @NonNull
+        @ActionType
+        private final String mType;
+        @NonNull
+        private final CharSequence mTextReply;
+        @Nullable
+        private final RemoteAction mAction;
+
+        @FloatRange(from = 0, to = 1)
+        private final float mScore;
+
+        @NonNull
+        private final Bundle mExtras;
+
+        private ConversationAction(
+                @NonNull String type,
+                @Nullable RemoteAction action,
+                @Nullable CharSequence textReply,
+                float score,
+                @NonNull Bundle extras) {
+            mType = Preconditions.checkNotNull(type);
+            mAction = action;
+            mTextReply = textReply;
+            mScore = score;
+            mExtras = Preconditions.checkNotNull(extras);
+        }
+
+        private ConversationAction(Parcel in) {
+            mType = in.readString();
+            mAction = in.readParcelable(null);
+            mTextReply = in.readCharSequence();
+            mScore = in.readFloat();
+            mExtras = in.readBundle();
+        }
+
+        @Override
+        public void writeToParcel(Parcel parcel, int flags) {
+            parcel.writeString(mType);
+            parcel.writeParcelable(mAction, flags);
+            parcel.writeCharSequence(mTextReply);
+            parcel.writeFloat(mScore);
+            parcel.writeBundle(mExtras);
+        }
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        @NonNull
+        @ActionType
+        /** Returns the type of this action, for example, {@link #TYPE_VIEW_CALENDAR}. */
+        public String getType() {
+            return mType;
+        }
+
+        @Nullable
+        /**
+         * Returns a RemoteAction object, which contains the icon, label and a PendingIntent, for
+         * the specified action type.
+         */
+        public RemoteAction getAction() {
+            return mAction;
+        }
+
+        /**
+         * Returns the confidence score for the specified action. The value ranges from 0 (low
+         * confidence) to 1 (high confidence).
+         */
+        @FloatRange(from = 0, to = 1)
+        public float getConfidenceScore() {
+            return mScore;
+        }
+
+        /**
+         * Returns the text reply that could be sent as a reply to the given conversation.
+         * <p>
+         * This is only available when the type of the action is {@link #TYPE_TEXT_REPLY}.
+         */
+        @Nullable
+        public CharSequence getTextReply() {
+            return mTextReply;
+        }
+
+        /**
+         * Returns the extended data related to this conversation action.
+         *
+         * <p><b>NOTE: </b>Each call to this method returns a new bundle copy so clients should
+         * prefer to hold a reference to the returned bundle rather than frequently calling this
+         * method.
+         */
+        @NonNull
+        public Bundle getExtras() {
+            return mExtras.deepCopy();
+        }
+
+        /** Builder class to construct {@link ConversationAction}. */
+        public static final class Builder {
+            @Nullable
+            @ActionType
+            private String mType;
+            @Nullable
+            private RemoteAction mAction;
+            @Nullable
+            private CharSequence mTextReply;
+            private float mScore;
+            @Nullable
+            private Bundle mExtras;
+
+            public Builder(@NonNull @ActionType String actionType) {
+                mType = Preconditions.checkNotNull(actionType);
+            }
+
+            /**
+             * Sets an action that may be performed on the given conversation.
+             */
+            @NonNull
+            public Builder setAction(@Nullable RemoteAction action) {
+                mAction = action;
+                return this;
+            }
+
+            /**
+             * Sets a text reply that may be performed on the given conversation.
+             */
+            @NonNull
+            public Builder setTextReply(@Nullable CharSequence textReply) {
+                mTextReply = textReply;
+                return this;
+            }
+
+            /** Sets the confident score. */
+            @NonNull
+            public Builder setConfidenceScore(@FloatRange(from = 0, to = 1) float score) {
+                mScore = score;
+                return this;
+            }
+
+            /**
+             * Sets the extended data for the conversation action object.
+             */
+            @NonNull
+            public Builder setExtras(@Nullable Bundle extras) {
+                mExtras = extras;
+                return this;
+            }
+
+            /** Builds the {@link ConversationAction} object. */
+            @NonNull
+            public ConversationAction build() {
+                return new ConversationAction(
+                        mType,
+                        mAction,
+                        mTextReply,
+                        mScore,
+                        mExtras == null ? Bundle.EMPTY : mExtras.deepCopy());
+            }
+        }
+    }
+
+    /** Represents a message in the conversation. */
+    public static final class Message implements Parcelable {
+        @Nullable
+        private final Person mAuthor;
+        @Nullable
+        private final ZonedDateTime mComposeTime;
+        @Nullable
+        private final CharSequence mText;
+        @NonNull
+        private final Bundle mExtras;
+
+        private Message(
+                @Nullable Person author,
+                @Nullable ZonedDateTime composeTime,
+                @Nullable CharSequence text,
+                @NonNull Bundle bundle) {
+            mAuthor = author;
+            mComposeTime = composeTime;
+            mText = text;
+            mExtras = Preconditions.checkNotNull(bundle);
+        }
+
+        private Message(Parcel in) {
+            mAuthor = in.readParcelable(null);
+            mComposeTime =
+                    in.readInt() == 0
+                            ? null
+                            : ZonedDateTime.parse(
+                                    in.readString(), DateTimeFormatter.ISO_ZONED_DATE_TIME);
+            mText = in.readCharSequence();
+            mExtras = in.readBundle();
+        }
+
+        @Override
+        public void writeToParcel(Parcel parcel, int flags) {
+            parcel.writeParcelable(mAuthor, flags);
+            parcel.writeInt(mComposeTime != null ? 1 : 0);
+            if (mComposeTime != null) {
+                parcel.writeString(mComposeTime.format(DateTimeFormatter.ISO_ZONED_DATE_TIME));
+            }
+            parcel.writeCharSequence(mText);
+            parcel.writeBundle(mExtras);
+        }
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        public static final Creator<Message> CREATOR =
+                new Creator<Message>() {
+                    @Override
+                    public Message createFromParcel(Parcel in) {
+                        return new Message(in);
+                    }
+
+                    @Override
+                    public Message[] newArray(int size) {
+                        return new Message[size];
+                    }
+                };
+
+        /** Returns the person that composed the message. */
+        @Nullable
+        public Person getAuthor() {
+            return mAuthor;
+        }
+
+        /** Returns the compose time of the message. */
+        @Nullable
+        public ZonedDateTime getTime() {
+            return mComposeTime;
+        }
+
+        /** Returns the text of the message. */
+        @Nullable
+        public CharSequence getText() {
+            return mText;
+        }
+
+        /**
+         * Returns the extended data related to this conversation action.
+         *
+         * <p><b>NOTE: </b>Each call to this method returns a new bundle copy so clients should
+         * prefer to hold a reference to the returned bundle rather than frequently calling this
+         * method.
+         */
+        @NonNull
+        public Bundle getExtras() {
+            return mExtras.deepCopy();
+        }
+
+        /** Builder class to construct a {@link Message} */
+        public static final class Builder {
+            @Nullable
+            private Person mAuthor;
+            @Nullable
+            private ZonedDateTime mComposeTime;
+            @Nullable
+            private CharSequence mText;
+            @Nullable
+            private Bundle mExtras;
+
+            /** Sets the person who composed this message. */
+            @NonNull
+            public Builder setAuthor(@Nullable Person author) {
+                mAuthor = author;
+                return this;
+            }
+
+            /** Sets the text of this message */
+            @NonNull
+            public Builder setText(@Nullable CharSequence text) {
+                mText = text;
+                return this;
+            }
+
+            /** Sets the compose time of this message */
+            @NonNull
+            public Builder setComposeTime(@Nullable ZonedDateTime composeTime) {
+                mComposeTime = composeTime;
+                return this;
+            }
+
+            /** Sets a set of extended data to the message. */
+            @NonNull
+            public Builder setExtras(@Nullable Bundle bundle) {
+                this.mExtras = bundle;
+                return this;
+            }
+
+            /** Builds the {@link Message} object. */
+            @NonNull
+            public Message build() {
+                return new Message(
+                        mAuthor,
+                        mComposeTime,
+                        mText == null ? null : new SpannedString(mText),
+                        mExtras == null ? new Bundle() : mExtras.deepCopy());
+            }
+        }
+    }
+
+    /** Configuration object for specifying what action types to identify. */
+    public static final class TypeConfig implements Parcelable {
+        @NonNull
+        @ActionType
+        private final Set<String> mExcludedTypes;
+        @NonNull
+        @ActionType
+        private final Set<String> mIncludedTypes;
+        private final boolean mIncludeTypesFromTextClassifier;
+
+        private TypeConfig(
+                @NonNull Set<String> includedTypes,
+                @NonNull Set<String> excludedTypes,
+                boolean includeTypesFromTextClassifier) {
+            mIncludedTypes = Preconditions.checkNotNull(includedTypes);
+            mExcludedTypes = Preconditions.checkNotNull(excludedTypes);
+            mIncludeTypesFromTextClassifier = includeTypesFromTextClassifier;
+        }
+
+        private TypeConfig(Parcel in) {
+            mIncludedTypes = new ArraySet<>(in.createStringArrayList());
+            mExcludedTypes = new ArraySet<>(in.createStringArrayList());
+            mIncludeTypesFromTextClassifier = in.readByte() != 0;
+        }
+
+        @Override
+        public void writeToParcel(Parcel parcel, int flags) {
+            parcel.writeStringList(new ArrayList<>(mIncludedTypes));
+            parcel.writeStringList(new ArrayList<>(mExcludedTypes));
+            parcel.writeByte((byte) (mIncludeTypesFromTextClassifier ? 1 : 0));
+        }
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        public static final Creator<TypeConfig> CREATOR =
+                new Creator<TypeConfig>() {
+                    @Override
+                    public TypeConfig createFromParcel(Parcel in) {
+                        return new TypeConfig(in);
+                    }
+
+                    @Override
+                    public TypeConfig[] newArray(int size) {
+                        return new TypeConfig[size];
+                    }
+                };
+
+        /**
+         * Returns a final list of types that the text classifier should look for.
+         *
+         * <p>NOTE: This method is intended for use by a text classifier.
+         *
+         * @param defaultTypes types the text classifier thinks should be included before factoring
+         *    in the included/excluded types given by the client.
+         */
+        @NonNull
+        public Collection<String> resolveTypes(@Nullable Collection<String> defaultTypes) {
+            Set<String> types = new ArraySet<>();
+            if (mIncludeTypesFromTextClassifier && defaultTypes != null) {
+                types.addAll(defaultTypes);
+            }
+            types.addAll(mIncludedTypes);
+            types.removeAll(mExcludedTypes);
+            return Collections.unmodifiableCollection(types);
+        }
+
+        /**
+         * Return whether the client allows the text classifier to include its own list of default
+         * types. If this function returns {@code true}, the text classifier can consider specifying
+         * a default list of entity types in {@link #resolveTypes(Collection)}.
+         *
+         * <p>NOTE: This method is intended for use by a text classifier.
+         *
+         * @see #resolveTypes(Collection)
+         */
+        public boolean shouldIncludeTypesFromTextClassifier() {
+            return mIncludeTypesFromTextClassifier;
+        }
+
+        /** Builder class to construct the {@link TypeConfig} object. */
+        public static final class Builder {
+            @Nullable
+            private Collection<String> mExcludedTypes;
+            @Nullable
+            private Collection<String> mIncludedTypes;
+            private boolean mIncludeTypesFromTextClassifier = true;
+
+            /**
+             * Sets a collection of types that are explicitly included, for example, {@link
+             * #TYPE_VIEW_CALENDAR}.
+             */
+            @NonNull
+            public Builder setIncludedTypes(
+                    @Nullable @ActionType Collection<String> includedTypes) {
+                mIncludedTypes = includedTypes;
+                return this;
+            }
+
+            /**
+             * Sets a collection of types that are explicitly excluded, for example, {@link
+             * #TYPE_VIEW_CALENDAR}.
+             */
+            @NonNull
+            public Builder setExcludedTypes(
+                    @Nullable @ActionType Collection<String> excludedTypes) {
+                mExcludedTypes = excludedTypes;
+                return this;
+            }
+
+            /**
+             * Specifies whether or not to include the types suggested by the text classifier. By
+             * default, it is included.
+             */
+            @NonNull
+            public Builder includeTypesFromTextClassifier(boolean includeTypesFromTextClassifier) {
+                mIncludeTypesFromTextClassifier = includeTypesFromTextClassifier;
+                return this;
+            }
+
+            /**
+             * Combines all of the options that have been set and returns a new {@link TypeConfig}
+             * object.
+             */
+            @NonNull
+            public TypeConfig build() {
+                return new TypeConfig(
+                        mIncludedTypes == null
+                                ? Collections.emptySet()
+                                : new ArraySet<>(mIncludedTypes),
+                        mExcludedTypes == null
+                                ? Collections.emptySet()
+                                : new ArraySet<>(mExcludedTypes),
+                        mIncludeTypesFromTextClassifier);
+            }
+        }
+    }
+
+    /**
+     * A request object for generating conversation action suggestions.
+     *
+     * @see TextClassifier#suggestConversationActions(Request)
+     */
+    public static final class Request implements Parcelable {
+        @NonNull
+        private final List<Message> mConversation;
+        @NonNull
+        private final TypeConfig mTypeConfig;
+        private final int mMaxSuggestions;
+        @NonNull
+        @Hint
+        private final List<String> mHints;
+
+        private Request(
+                @NonNull List<Message> conversation,
+                @NonNull TypeConfig typeConfig,
+                int maxSuggestions,
+                @Nullable @Hint List<String> hints) {
+            mConversation = Preconditions.checkNotNull(conversation);
+            mTypeConfig = Preconditions.checkNotNull(typeConfig);
+            mMaxSuggestions = maxSuggestions;
+            mHints = hints;
+        }
+
+        private Request(Parcel in) {
+            List<Message> conversation = new ArrayList<>();
+            in.readParcelableList(conversation, null);
+            mConversation = Collections.unmodifiableList(conversation);
+            mTypeConfig = in.readParcelable(null);
+            mMaxSuggestions = in.readInt();
+            List<String> hints = new ArrayList<>();
+            in.readStringList(hints);
+            mHints = Collections.unmodifiableList(hints);
+        }
+
+        @Override
+        public void writeToParcel(Parcel parcel, int flags) {
+            parcel.writeParcelableList(mConversation, flags);
+            parcel.writeParcelable(mTypeConfig, flags);
+            parcel.writeInt(mMaxSuggestions);
+            parcel.writeStringList(mHints);
+        }
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        public static final Creator<Request> CREATOR =
+                new Creator<Request>() {
+                    @Override
+                    public Request createFromParcel(Parcel in) {
+                        return new Request(in);
+                    }
+
+                    @Override
+                    public Request[] newArray(int size) {
+                        return new Request[size];
+                    }
+                };
+
+        /** Returns the type config. */
+        @NonNull
+        public TypeConfig getTypeConfig() {
+            return mTypeConfig;
+        }
+
+        /** Returns an immutable list of messages that make up the conversation. */
+        @NonNull
+        public List<Message> getConversation() {
+            return mConversation;
+        }
+
+        /**
+         * Return the maximal number of suggestions the caller wants, value 0 means no restriction.
+         */
+        @IntRange(from = 0)
+        public int getMaxSuggestions() {
+            return mMaxSuggestions;
+        }
+
+        /** Returns an immutable list of hints */
+        @Nullable
+        @Hint
+        public List<String> getHints() {
+            return mHints;
+        }
+
+        /** Builder object to construct the {@link Request} object. */
+        public static final class Builder {
+            @NonNull
+            private List<Message> mConversation;
+            @Nullable
+            private TypeConfig mTypeConfig;
+            private int mMaxSuggestions;
+            @Nullable
+            @Hint
+            private List<String> mHints;
+
+            /**
+             * Constructs a builder.
+             *
+             * @param conversation the conversation that the text classifier is going to generate
+             *     actions for.
+             */
+            public Builder(@NonNull List<Message> conversation) {
+                mConversation = Preconditions.checkNotNull(conversation);
+            }
+
+            /**
+             * Sets the hints to help text classifier to generate actions. It could be used to help
+             * text classifier to infer what types of actions the caller may be interested in.
+             */
+            public Builder setHints(@Nullable @Hint List<String> hints) {
+                mHints = hints;
+                return this;
+            }
+
+            /** Sets the type config. */
+            @NonNull
+            public Builder setTypeConfig(@Nullable TypeConfig typeConfig) {
+                mTypeConfig = typeConfig;
+                return this;
+            }
+
+            /** Sets the maximum number of suggestions you want.
+             * <p>
+             * Value 0 means no restriction.
+             */
+            @NonNull
+            public Builder setMaxSuggestions(@IntRange(from = 0) int maxSuggestions) {
+                mMaxSuggestions = Preconditions.checkArgumentNonnegative(maxSuggestions);
+                return this;
+            }
+
+            /** Builds the {@link Request} object. */
+            @NonNull
+            public Request build() {
+                return new Request(
+                        Collections.unmodifiableList(mConversation),
+                        mTypeConfig == null ? new TypeConfig.Builder().build() : mTypeConfig,
+                        mMaxSuggestions,
+                        mHints == null
+                                ? Collections.emptyList()
+                                : Collections.unmodifiableList(mHints));
+            }
+        }
+    }
+}
diff --git a/core/java/android/view/textclassifier/TextClassification.java b/core/java/android/view/textclassifier/TextClassification.java
index 9511a9e..d972bb8 100644
--- a/core/java/android/view/textclassifier/TextClassification.java
+++ b/core/java/android/view/textclassifier/TextClassification.java
@@ -33,6 +33,7 @@
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.Icon;
+import android.os.Bundle;
 import android.os.LocaleList;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -126,6 +127,7 @@
     @NonNull private final List<RemoteAction> mActions;
     @NonNull private final EntityConfidence mEntityConfidence;
     @Nullable private final String mId;
+    @NonNull private final Bundle mExtras;
 
     private TextClassification(
             @Nullable String text,
@@ -135,7 +137,8 @@
             @Nullable OnClickListener legacyOnClickListener,
             @NonNull List<RemoteAction> actions,
             @NonNull Map<String, Float> entityConfidence,
-            @Nullable String id) {
+            @Nullable String id,
+            @NonNull Bundle extras) {
         mText = text;
         mLegacyIcon = legacyIcon;
         mLegacyLabel = legacyLabel;
@@ -144,6 +147,7 @@
         mActions = Collections.unmodifiableList(actions);
         mEntityConfidence = new EntityConfidence(entityConfidence);
         mId = id;
+        mExtras = extras;
     }
 
     /**
@@ -255,6 +259,18 @@
         return mId;
     }
 
+    /**
+     * Returns the extended data.
+     *
+     * <p><b>NOTE: </b>Each call to this method returns a new bundle copy so clients should
+     * prefer to hold a reference to the returned bundle rather than frequently calling this
+     * method.
+     */
+    @NonNull
+    public Bundle getExtras() {
+        return mExtras.deepCopy();
+    }
+
     @Override
     public String toString() {
         return String.format(Locale.US,
@@ -359,6 +375,7 @@
         @Nullable private Intent mLegacyIntent;
         @Nullable private OnClickListener mLegacyOnClickListener;
         @Nullable private String mId;
+        @Nullable private Bundle mExtras;
 
         /**
          * Sets the classified text.
@@ -471,12 +488,22 @@
         }
 
         /**
+         * Sets the extended data.
+         */
+        @NonNull
+        public Builder setExtras(@Nullable Bundle extras) {
+            mExtras = extras;
+            return this;
+        }
+
+        /**
          * Builds and returns a {@link TextClassification} object.
          */
         @NonNull
         public TextClassification build() {
             return new TextClassification(mText, mLegacyIcon, mLegacyLabel, mLegacyIntent,
-                    mLegacyOnClickListener, mActions, mEntityConfidence, mId);
+                    mLegacyOnClickListener, mActions, mEntityConfidence, mId,
+                    mExtras == null ? Bundle.EMPTY : mExtras.deepCopy());
         }
     }
 
@@ -490,18 +517,21 @@
         private final int mEndIndex;
         @Nullable private final LocaleList mDefaultLocales;
         @Nullable private final ZonedDateTime mReferenceTime;
+        @NonNull private final Bundle mExtras;
 
         private Request(
                 CharSequence text,
                 int startIndex,
                 int endIndex,
                 LocaleList defaultLocales,
-                ZonedDateTime referenceTime) {
+                ZonedDateTime referenceTime,
+                Bundle extras) {
             mText = text;
             mStartIndex = startIndex;
             mEndIndex = endIndex;
             mDefaultLocales = defaultLocales;
             mReferenceTime = referenceTime;
+            mExtras = extras;
         }
 
         /**
@@ -548,6 +578,18 @@
         }
 
         /**
+         * Returns the extended data.
+         *
+         * <p><b>NOTE: </b>Each call to this method returns a new bundle copy so clients should
+         * prefer to hold a reference to the returned bundle rather than frequently calling this
+         * method.
+         */
+        @NonNull
+        public Bundle getExtras() {
+            return mExtras.deepCopy();
+        }
+
+        /**
          * A builder for building TextClassification requests.
          */
         public static final class Builder {
@@ -555,6 +597,7 @@
             private final CharSequence mText;
             private final int mStartIndex;
             private final int mEndIndex;
+            private Bundle mExtras;
 
             @Nullable private LocaleList mDefaultLocales;
             @Nullable private ZonedDateTime mReferenceTime;
@@ -602,11 +645,23 @@
             }
 
             /**
+             * Sets the extended data.
+             *
+             * @return this builder
+             */
+            @NonNull
+            public Builder setExtras(@Nullable Bundle extras) {
+                mExtras = extras;
+                return this;
+            }
+
+            /**
              * Builds and returns the request object.
              */
             @NonNull
             public Request build() {
-                return new Request(mText, mStartIndex, mEndIndex, mDefaultLocales, mReferenceTime);
+                return new Request(mText, mStartIndex, mEndIndex, mDefaultLocales, mReferenceTime,
+                        mExtras == null ? Bundle.EMPTY : mExtras.deepCopy());
             }
         }
 
@@ -628,6 +683,7 @@
             if (mReferenceTime != null) {
                 dest.writeString(mReferenceTime.toString());
             }
+            dest.writeBundle(mExtras);
         }
 
         public static final Parcelable.Creator<Request> CREATOR =
@@ -649,6 +705,7 @@
             mEndIndex = in.readInt();
             mDefaultLocales = in.readInt() == 0 ? null : LocaleList.CREATOR.createFromParcel(in);
             mReferenceTime = in.readInt() == 0 ? null : ZonedDateTime.parse(in.readString());
+            mExtras = in.readBundle();
         }
     }
 
@@ -664,6 +721,7 @@
         dest.writeTypedList(mActions);
         mEntityConfidence.writeToParcel(dest, flags);
         dest.writeString(mId);
+        dest.writeBundle(mExtras);
     }
 
     public static final Parcelable.Creator<TextClassification> CREATOR =
@@ -695,6 +753,7 @@
         mLegacyIntent = null; // mLegacyIntent is not parcelled.
         mEntityConfidence = EntityConfidence.CREATOR.createFromParcel(in);
         mId = in.readString();
+        mExtras = in.readBundle();
     }
 
     // Best effort attempt to try to load a drawable from the provided icon.
diff --git a/core/java/android/view/textclassifier/TextClassifier.java b/core/java/android/view/textclassifier/TextClassifier.java
index 2e92f14..e675744 100644
--- a/core/java/android/view/textclassifier/TextClassifier.java
+++ b/core/java/android/view/textclassifier/TextClassifier.java
@@ -325,6 +325,17 @@
     }
 
     /**
+     * Suggests and returns a list of actions according to the given conversation.
+     */
+    @WorkerThread
+    default ConversationActions suggestConversationActions(
+            @NonNull ConversationActions.Request request) {
+        Preconditions.checkNotNull(request);
+        Utils.checkMainThread();
+        return new ConversationActions(Collections.emptyList());
+    }
+
+    /**
      * Reports a selection event.
      *
      * <p><strong>NOTE: </strong>If a TextClassifier has been destroyed, calls to this method should
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 48c164f..feef853 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -257,7 +257,7 @@
             needsToBeShifted = true;
         }
         boolean needsRecord() {
-            return isDirty || !renderNode.isValid();
+            return isDirty || !renderNode.hasDisplayList();
         }
     }
     private TextRenderNode[] mTextRenderNodes;
@@ -542,7 +542,7 @@
             for (int i = 0; i < mTextRenderNodes.length; i++) {
                 RenderNode displayList = mTextRenderNodes[i] != null
                         ? mTextRenderNodes[i].renderNode : null;
-                if (displayList != null && displayList.isValid()) {
+                if (displayList != null && displayList.hasDisplayList()) {
                     displayList.discardDisplayList();
                 }
             }
diff --git a/core/java/com/android/internal/net/NetworkStatsFactory.java b/core/java/com/android/internal/net/NetworkStatsFactory.java
index d1c2799..0a7cff6 100644
--- a/core/java/com/android/internal/net/NetworkStatsFactory.java
+++ b/core/java/com/android/internal/net/NetworkStatsFactory.java
@@ -113,11 +113,12 @@
 
     /**
      * Applies 464xlat adjustments with ifaces noted with {@link #noteStackedIface(String, String)}.
-     * @see NetworkStats#apply464xlatAdjustments(NetworkStats, NetworkStats, Map)
+     * @see NetworkStats#apply464xlatAdjustments(NetworkStats, NetworkStats, Map, boolean)
      */
     public static void apply464xlatAdjustments(NetworkStats baseTraffic,
-            NetworkStats stackedTraffic) {
-        NetworkStats.apply464xlatAdjustments(baseTraffic, stackedTraffic, sStackedIfaces);
+            NetworkStats stackedTraffic, boolean useBpfStats) {
+        NetworkStats.apply464xlatAdjustments(baseTraffic, stackedTraffic, sStackedIfaces,
+                useBpfStats);
     }
 
     @VisibleForTesting
@@ -263,7 +264,7 @@
 
         // No locking here: apply464xlatAdjustments behaves fine with an add-only ConcurrentHashMap.
         // TODO: remove this and only apply adjustments in NetworkStatsService.
-        stats.apply464xlatAdjustments(sStackedIfaces);
+        stats.apply464xlatAdjustments(sStackedIfaces, mUseBpfStats);
 
         return stats;
     }
diff --git a/core/java/com/android/internal/os/BinderCallsStats.java b/core/java/com/android/internal/os/BinderCallsStats.java
index 856712f..70fc72f 100644
--- a/core/java/com/android/internal/os/BinderCallsStats.java
+++ b/core/java/com/android/internal/os/BinderCallsStats.java
@@ -140,6 +140,7 @@
             latencyDuration = 0;
         }
         final int callingUid = getCallingUid();
+        final int workSourceUid = getWorkSourceUid();
 
         synchronized (mLock) {
             // This was already checked in #callStart but check again while synchronized.
@@ -147,7 +148,8 @@
                 return;
             }
 
-            final UidEntry uidEntry = getUidEntry(callingUid);
+            final boolean isWorkSourceSet = workSourceUid >= 0;
+            final UidEntry uidEntry = getUidEntry(isWorkSourceSet ? workSourceUid : callingUid);
             uidEntry.callCount++;
 
             if (recordCall) {
@@ -155,7 +157,8 @@
                 uidEntry.recordedCallCount++;
 
                 final CallStat callStat = uidEntry.getOrCreate(
-                        s.binderClass, s.transactionCode, mDeviceState.isScreenInteractive());
+                        callingUid, s.binderClass, s.transactionCode,
+                        mDeviceState.isScreenInteractive());
                 callStat.callCount++;
                 callStat.recordedCallCount++;
                 callStat.cpuTimeMicros += duration;
@@ -174,7 +177,8 @@
                 // Only record the total call count if we already track data for this key.
                 // It helps to keep the memory usage down when sampling is enabled.
                 final CallStat callStat = uidEntry.get(
-                        s.binderClass, s.transactionCode, mDeviceState.isScreenInteractive());
+                        callingUid, s.binderClass, s.transactionCode,
+                        mDeviceState.isScreenInteractive());
                 if (callStat != null) {
                     callStat.callCount++;
                 }
@@ -251,7 +255,8 @@
                 final UidEntry entry = mUidEntries.valueAt(entryIdx);
                 for (CallStat stat : entry.getCallStatsList()) {
                     ExportedCallStat exported = new ExportedCallStat();
-                    exported.uid = entry.uid;
+                    exported.workSourceUid = entry.workSourceUid;
+                    exported.callingUid = stat.callingUid;
                     exported.className = stat.binderClass.getName();
                     exported.binderClass = stat.binderClass;
                     exported.transactionCode = stat.transactionCode;
@@ -338,10 +343,8 @@
         entries.sort(Comparator.<UidEntry>comparingDouble(value -> value.cpuTimeMicros).reversed());
         final String datasetSizeDesc = verbose ? "" : "(top 90% by cpu time) ";
         final StringBuilder sb = new StringBuilder();
-        final List<UidEntry> topEntries = verbose ? entries
-                : getHighestValues(entries, value -> value.cpuTimeMicros, 0.9);
         pw.println("Per-UID raw data " + datasetSizeDesc
-                + "(package/uid, call_desc, screen_interactive, "
+                + "(package/uid, worksource, call_desc, screen_interactive, "
                 + "cpu_time_micros, max_cpu_time_micros, "
                 + "latency_time_micros, max_latency_time_micros, exception_count, "
                 + "max_request_size_bytes, max_reply_size_bytes, recorded_call_count, "
@@ -351,7 +354,9 @@
         for (ExportedCallStat e : exportedCallStats) {
             sb.setLength(0);
             sb.append("    ")
-                    .append(uidToString(e.uid, appIdToPkgNameMap))
+                    .append(uidToString(e.callingUid, appIdToPkgNameMap))
+                    .append(',')
+                    .append(uidToString(e.workSourceUid, appIdToPkgNameMap))
                     .append(',').append(e.className)
                     .append('#').append(e.methodName)
                     .append(',').append(e.screenInteractive)
@@ -372,7 +377,7 @@
         final List<UidEntry> summaryEntries = verbose ? entries
                 : getHighestValues(entries, value -> value.cpuTimeMicros, 0.9);
         for (UidEntry entry : summaryEntries) {
-            String uidStr = uidToString(entry.uid, appIdToPkgNameMap);
+            String uidStr = uidToString(entry.workSourceUid, appIdToPkgNameMap);
             pw.println(String.format("  %10d %3.0f%% %8d %8d %s",
                     entry.cpuTimeMicros, 100d * entry.cpuTimeMicros / totalCpuTime,
                     entry.recordedCallCount, entry.callCount, uidStr));
@@ -415,11 +420,15 @@
         return Binder.getCallingUid();
     }
 
+    protected int getWorkSourceUid() {
+        return Binder.getThreadWorkSource();
+    }
+
     protected long getElapsedRealtimeMicro() {
         return SystemClock.elapsedRealtimeNanos() / 1000;
     }
 
-    private boolean shouldRecordDetailedData() {
+    protected boolean shouldRecordDetailedData() {
         return mRandom.nextInt() % mPeriodicSamplingInterval == 0;
     }
 
@@ -462,7 +471,8 @@
      * Aggregated data by uid/class/method to be sent through WestWorld.
      */
     public static class ExportedCallStat {
-        public int uid;
+        public int callingUid;
+        public int workSourceUid;
         public String className;
         public String methodName;
         public boolean screenInteractive;
@@ -483,10 +493,12 @@
 
     @VisibleForTesting
     public static class CallStat {
-        public Class<? extends Binder> binderClass;
-        public int transactionCode;
+        // The UID who executed the transaction (i.e. Binder#getCallingUid).
+        public final int callingUid;
+        public final Class<? extends Binder> binderClass;
+        public final int transactionCode;
         // True if the screen was interactive when the call ended.
-        public boolean screenInteractive;
+        public final boolean screenInteractive;
         // Number of calls for which we collected data for. We do not record data for all the calls
         // when sampling is on.
         public long recordedCallCount;
@@ -508,8 +520,9 @@
         public long maxReplySizeBytes;
         public long exceptionCount;
 
-        CallStat(Class<? extends Binder> binderClass, int transactionCode,
+        CallStat(int callingUid, Class<? extends Binder> binderClass, int transactionCode,
                 boolean screenInteractive) {
+            this.callingUid = callingUid;
             this.binderClass = binderClass;
             this.transactionCode = transactionCode;
             this.screenInteractive = screenInteractive;
@@ -518,6 +531,7 @@
 
     /** Key used to store CallStat object in a Map. */
     public static class CallStatKey {
+        public int callingUid;
         public Class<? extends Binder> binderClass;
         public int transactionCode;
         private boolean screenInteractive;
@@ -529,7 +543,8 @@
             }
 
             final CallStatKey key = (CallStatKey) o;
-            return transactionCode == key.transactionCode
+            return callingUid == key.callingUid
+                    && transactionCode == key.transactionCode
                     && screenInteractive == key.screenInteractive
                     && (binderClass.equals(key.binderClass));
         }
@@ -538,6 +553,7 @@
         public int hashCode() {
             int result = binderClass.hashCode();
             result = 31 * result + transactionCode;
+            result = 31 * result + callingUid;
             result = 31 * result + (screenInteractive ? 1231 : 1237);
             return result;
         }
@@ -546,7 +562,9 @@
 
     @VisibleForTesting
     public static class UidEntry {
-        int uid;
+        // The UID who is responsible for the binder transaction. If the bluetooth process execute a
+        // transaction on behalf of app foo, the workSourceUid will be the uid of app foo.
+        public int workSourceUid;
         // Number of calls for which we collected data for. We do not record data for all the calls
         // when sampling is on.
         public long recordedCallCount;
@@ -558,7 +576,7 @@
         public long cpuTimeMicros;
 
         UidEntry(int uid) {
-            this.uid = uid;
+            this.workSourceUid = uid;
         }
 
         // Aggregate time spent per each call name: call_desc -> cpu_time_micros
@@ -566,22 +584,25 @@
         private CallStatKey mTempKey = new CallStatKey();
 
         @Nullable
-        CallStat get(Class<? extends Binder> binderClass, int transactionCode,
+        CallStat get(int callingUid, Class<? extends Binder> binderClass, int transactionCode,
                 boolean screenInteractive) {
             // Use a global temporary key to avoid creating new objects for every lookup.
+            mTempKey.callingUid = callingUid;
             mTempKey.binderClass = binderClass;
             mTempKey.transactionCode = transactionCode;
             mTempKey.screenInteractive = screenInteractive;
             return mCallStats.get(mTempKey);
         }
 
-        CallStat getOrCreate(Class<? extends Binder> binderClass, int transactionCode,
-                boolean screenInteractive) {
-            CallStat mapCallStat = get(binderClass, transactionCode, screenInteractive);
+        CallStat getOrCreate(int callingUid, Class<? extends Binder> binderClass,
+                int transactionCode, boolean screenInteractive) {
+            CallStat mapCallStat = get(callingUid, binderClass, transactionCode, screenInteractive);
             // Only create CallStat if it's a new entry, otherwise update existing instance
             if (mapCallStat == null) {
-                mapCallStat = new CallStat(binderClass, transactionCode, screenInteractive);
+                mapCallStat = new CallStat(callingUid, binderClass, transactionCode,
+                        screenInteractive);
                 CallStatKey key = new CallStatKey();
+                key.callingUid = callingUid;
                 key.binderClass = binderClass;
                 key.transactionCode = transactionCode;
                 key.screenInteractive = screenInteractive;
@@ -613,12 +634,12 @@
             }
 
             UidEntry uidEntry = (UidEntry) o;
-            return uid == uidEntry.uid;
+            return workSourceUid == uidEntry.workSourceUid;
         }
 
         @Override
         public int hashCode() {
-            return uid;
+            return workSourceUid;
         }
     }
 
diff --git a/core/java/com/android/internal/os/KernelCpuThreadReader.java b/core/java/com/android/internal/os/KernelCpuThreadReader.java
new file mode 100644
index 0000000..6b277a0
--- /dev/null
+++ b/core/java/com/android/internal/os/KernelCpuThreadReader.java
@@ -0,0 +1,306 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.os;
+
+import android.annotation.Nullable;
+import android.os.Process;
+import android.util.Slog;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.io.IOException;
+import java.nio.file.DirectoryStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+
+/**
+ * Given a process, will iterate over the child threads of the process, and return the CPU usage
+ * statistics for each child thread. The CPU usage statistics contain the amount of time spent in a
+ * frequency band.
+ */
+public class KernelCpuThreadReader {
+
+    private static final String TAG = "KernelCpuThreadReader";
+
+    private static final boolean DEBUG = false;
+
+    /**
+     * The name of the file to read CPU statistics from, must be found in {@code
+     * /proc/$PID/task/$TID}
+     */
+    private static final String CPU_STATISTICS_FILENAME = "time_in_state";
+
+    /**
+     * The name of the file to read process command line invocation from, must be found in
+     * {@code /proc/$PID/}
+     */
+    private static final String PROCESS_NAME_FILENAME = "cmdline";
+
+    /**
+     * The name of the file to read thread name from, must be found in
+     * {@code /proc/$PID/task/$TID}
+     */
+    private static final String THREAD_NAME_FILENAME = "comm";
+
+    /**
+     * Default process name when the name can't be read
+     */
+    private static final String DEFAULT_PROCESS_NAME = "unknown_process";
+
+    /**
+     * Default thread name when the name can't be read
+     */
+    private static final String DEFAULT_THREAD_NAME = "unknown_thread";
+
+    /**
+     * Default mount location of the {@code proc} filesystem
+     */
+    private static final Path DEFAULT_PROC_PATH = Paths.get("/proc");
+
+    /**
+     * The initial {@code time_in_state} file for {@link ProcTimeInStateReader}
+     */
+    private static final Path DEFAULT_INITIAL_TIME_IN_STATE_PATH =
+            DEFAULT_PROC_PATH.resolve("self/time_in_state");
+
+    /**
+     * Where the proc filesystem is mounted
+     */
+    private final Path mProcPath;
+
+    /**
+     * Frequencies read from the {@code time_in_state} file. Read from {@link
+     * #mProcTimeInStateReader#getCpuFrequenciesKhz()} and cast to {@code int[]}
+     */
+    private final int[] mFrequenciesKhz;
+
+    /**
+     * Used to read and parse {@code time_in_state} files
+     */
+    private final ProcTimeInStateReader mProcTimeInStateReader;
+
+    private KernelCpuThreadReader() throws IOException {
+        this(DEFAULT_PROC_PATH, DEFAULT_INITIAL_TIME_IN_STATE_PATH);
+    }
+
+    /**
+     * Create with a path where `proc` is mounted. Used primarily for testing
+     *
+     * @param procPath where `proc` is mounted (to find, see {@code mount | grep ^proc})
+     * @param initialTimeInStatePath where the initial {@code time_in_state} file exists to define
+     * format
+     */
+    @VisibleForTesting
+    public KernelCpuThreadReader(Path procPath, Path initialTimeInStatePath) throws IOException {
+        mProcPath = procPath;
+        mProcTimeInStateReader = new ProcTimeInStateReader(initialTimeInStatePath);
+
+        // Copy mProcTimeInState's frequencies, casting the longs to ints
+        long[] frequenciesKhz = mProcTimeInStateReader.getFrequenciesKhz();
+        mFrequenciesKhz = new int[frequenciesKhz.length];
+        for (int i = 0; i < frequenciesKhz.length; i++) {
+            mFrequenciesKhz[i] = (int) frequenciesKhz[i];
+        }
+    }
+
+    /**
+     * Create the reader and handle exceptions during creation
+     *
+     * @return the reader, null if an exception was thrown during creation
+     */
+    @Nullable
+    public static KernelCpuThreadReader create() {
+        try {
+            return new KernelCpuThreadReader();
+        } catch (IOException e) {
+            Slog.e(TAG, "Failed to initialize KernelCpuThreadReader", e);
+            return null;
+        }
+    }
+
+    /**
+     * Read all of the CPU usage statistics for each child thread of the current process
+     *
+     * @return process CPU usage containing usage of all child threads
+     */
+    @Nullable
+    public ProcessCpuUsage getCurrentProcessCpuUsage() {
+        return getProcessCpuUsage(
+                mProcPath.resolve("self"),
+                Process.myPid(),
+                Process.myUid());
+    }
+
+    /**
+     * Read all of the CPU usage statistics for each child thread of a process
+     *
+     * @param processPath the {@code /proc} path of the thread
+     * @param processId the ID of the process
+     * @param uid the ID of the user who owns the process
+     * @return process CPU usage containing usage of all child threads
+     */
+    @Nullable
+    private ProcessCpuUsage getProcessCpuUsage(Path processPath, int processId, int uid) {
+        if (DEBUG) {
+            Slog.d(TAG, "Reading CPU thread usages with directory " + processPath
+                    + " process ID " + processId
+                    + " and user ID " + uid);
+        }
+
+        final Path allThreadsPath = processPath.resolve("task");
+        final ArrayList<ThreadCpuUsage> threadCpuUsages = new ArrayList<>();
+        try (DirectoryStream<Path> threadPaths = Files.newDirectoryStream(allThreadsPath)) {
+            for (Path threadDirectory : threadPaths) {
+                ThreadCpuUsage threadCpuUsage = getThreadCpuUsage(threadDirectory);
+                if (threadCpuUsage != null) {
+                    threadCpuUsages.add(threadCpuUsage);
+                }
+            }
+        } catch (IOException e) {
+            Slog.w(TAG, "Failed to iterate over thread paths", e);
+            return null;
+        }
+
+        // If we found no threads, then the process has exited while we were reading from it
+        if (threadCpuUsages.isEmpty()) {
+            return null;
+        }
+
+        if (DEBUG) {
+            Slog.d(TAG, "Read CPU usage of " + threadCpuUsages.size() + " threads");
+        }
+        return new ProcessCpuUsage(
+                processId,
+                getProcessName(processPath),
+                uid,
+                threadCpuUsages);
+    }
+
+    /**
+     * Get the CPU frequencies that correspond to the times reported in
+     * {@link ThreadCpuUsage#usageTimesMillis}
+     */
+    @Nullable
+    public int[] getCpuFrequenciesKhz() {
+        return mFrequenciesKhz;
+    }
+
+    /**
+     * Get a thread's CPU usage
+     *
+     * @param threadDirectory the {@code /proc} directory of the thread
+     * @return null in the case that the directory read failed
+     */
+    @Nullable
+    private ThreadCpuUsage getThreadCpuUsage(Path threadDirectory) {
+        // Get the thread ID from the directory name
+        final int threadId;
+        try {
+            final String directoryName = threadDirectory.getFileName().toString();
+            threadId = Integer.parseInt(directoryName);
+        } catch (NumberFormatException e) {
+            Slog.w(TAG, "Failed to parse thread ID when iterating over /proc/*/task", e);
+            return null;
+        }
+
+        // Get the thread name from the thread directory
+        final String threadName = getThreadName(threadDirectory);
+
+        // Get the CPU statistics from the directory
+        final Path threadCpuStatPath = threadDirectory.resolve(CPU_STATISTICS_FILENAME);
+        final long[] cpuUsagesLong = mProcTimeInStateReader.getUsageTimesMillis(threadCpuStatPath);
+        if (cpuUsagesLong == null) {
+            return null;
+        }
+
+        // Convert long[] to int[]
+        final int[] cpuUsages = new int[cpuUsagesLong.length];
+        for (int i = 0; i < cpuUsagesLong.length; i++) {
+            cpuUsages[i] = (int) cpuUsagesLong[i];
+        }
+
+        return new ThreadCpuUsage(threadId, threadName, cpuUsages);
+    }
+
+    /**
+     * Get the command used to start a process
+     */
+    private String getProcessName(Path processPath) {
+        final Path processNamePath = processPath.resolve(PROCESS_NAME_FILENAME);
+
+        final String processName =
+                ProcStatsUtil.readSingleLineProcFile(processNamePath.toString());
+        if (processName != null) {
+            return processName;
+        }
+        return DEFAULT_PROCESS_NAME;
+    }
+
+    /**
+     * Get the name of a thread, given the {@code /proc} path of the thread
+     */
+    private String getThreadName(Path threadPath) {
+        final Path threadNamePath = threadPath.resolve(THREAD_NAME_FILENAME);
+        final String threadName =
+                ProcStatsUtil.readNullSeparatedFile(threadNamePath.toString());
+        if (threadName == null) {
+            return DEFAULT_THREAD_NAME;
+        }
+        return threadName;
+    }
+
+    /**
+     * CPU usage of a process
+     */
+    public static class ProcessCpuUsage {
+        public final int processId;
+        public final String processName;
+        public final int uid;
+        public final ArrayList<ThreadCpuUsage> threadCpuUsages;
+
+        ProcessCpuUsage(
+                int processId,
+                String processName,
+                int uid,
+                ArrayList<ThreadCpuUsage> threadCpuUsages) {
+            this.processId = processId;
+            this.processName = processName;
+            this.uid = uid;
+            this.threadCpuUsages = threadCpuUsages;
+        }
+    }
+
+    /**
+     * CPU usage of a thread
+     */
+    public static class ThreadCpuUsage {
+        public final int threadId;
+        public final String threadName;
+        public final int[] usageTimesMillis;
+
+        ThreadCpuUsage(
+                int threadId,
+                String threadName,
+                int[] usageTimesMillis) {
+            this.threadId = threadId;
+            this.threadName = threadName;
+            this.usageTimesMillis = usageTimesMillis;
+        }
+    }
+}
diff --git a/core/java/com/android/internal/os/ProcStatsUtil.java b/core/java/com/android/internal/os/ProcStatsUtil.java
new file mode 100644
index 0000000..0651975
--- /dev/null
+++ b/core/java/com/android/internal/os/ProcStatsUtil.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.os;
+
+import android.annotation.Nullable;
+import android.os.StrictMode;
+import android.util.Slog;
+
+import java.io.ByteArrayOutputStream;
+import java.io.FileInputStream;
+import java.io.IOException;
+
+/**
+ * Utility functions for reading {@code proc} files
+ */
+final class ProcStatsUtil {
+
+    private static final String TAG = "ProcStatsUtil";
+
+    /**
+     * How much to read into a buffer when reading a proc file
+     */
+    private static final int READ_SIZE = 1024;
+
+    /**
+     * Class only contains static utility functions, and should not be instantiated
+     */
+    private ProcStatsUtil() {
+    }
+
+    /**
+     * Read a {@code proc} file where the contents are separated by null bytes. Replaces the null
+     * bytes with spaces, and removes any trailing null bytes
+     *
+     * @param path path of the file to read
+     */
+    @Nullable
+    static String readNullSeparatedFile(String path) {
+        String contents = readSingleLineProcFile(path);
+        if (contents == null) {
+            return null;
+        }
+
+        // Content is either double-null terminated, or terminates at end of line. Remove anything
+        // after the double-null
+        final int endIndex = contents.indexOf("\0\0");
+        if (endIndex != -1) {
+            contents = contents.substring(0, endIndex);
+        }
+
+        // Change the null-separated contents into space-seperated
+        return contents.replace("\0", " ");
+    }
+
+    /**
+     * Read a {@code proc} file that contains a single line (e.g. {@code /proc/$PID/cmdline}, {@code
+     * /proc/$PID/comm})
+     *
+     * @param path path of the file to read
+     */
+    @Nullable
+    static String readSingleLineProcFile(String path) {
+        return readTerminatedProcFile(path, (byte) '\n');
+    }
+
+    /**
+     * Read a {@code proc} file that terminates with a specific byte
+     *
+     * @param path path of the file to read
+     * @param terminator byte that terminates the file. We stop reading once this character is
+     * seen, or at the end of the file
+     */
+    @Nullable
+    public static String readTerminatedProcFile(String path, byte terminator) {
+        // Permit disk reads here, as /proc isn't really "on disk" and should be fast.
+        // TODO: make BlockGuard ignore /proc/ and /sys/ files perhaps?
+        final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads();
+        try (FileInputStream is = new FileInputStream(path)) {
+            ByteArrayOutputStream byteStream = null;
+            final byte[] buffer = new byte[READ_SIZE];
+            while (true) {
+                // Read file into buffer
+                final int len = is.read(buffer);
+                if (len <= 0) {
+                    // If we've read nothing, we're done
+                    break;
+                }
+
+                // Find the terminating character
+                int terminatingIndex = -1;
+                for (int i = 0; i < len; i++) {
+                    if (buffer[i] == terminator) {
+                        terminatingIndex = i;
+                        break;
+                    }
+                }
+                final boolean foundTerminator = terminatingIndex != -1;
+
+                // If we have found it and the byte stream isn't initialized, we don't need to
+                // initialize it and can return the string here
+                if (foundTerminator && byteStream == null) {
+                    return new String(buffer, 0, terminatingIndex);
+                }
+
+                // Initialize the byte stream
+                if (byteStream == null) {
+                    byteStream = new ByteArrayOutputStream(READ_SIZE);
+                }
+
+                // Write the whole buffer if terminator not found, or up to the terminator if found
+                byteStream.write(buffer, 0, foundTerminator ? terminatingIndex : len);
+
+                // If we've found the terminator, we can finish
+                if (foundTerminator) {
+                    break;
+                }
+            }
+
+            // If the byte stream is null at the end, this means that we have read an empty file
+            if (byteStream == null) {
+                return "";
+            }
+            return byteStream.toString();
+        } catch (IOException e) {
+            Slog.w(TAG, "Failed to open proc file", e);
+            return null;
+        } finally {
+            StrictMode.setThreadPolicy(savedPolicy);
+        }
+    }
+}
diff --git a/core/java/com/android/internal/os/ProcTimeInStateReader.java b/core/java/com/android/internal/os/ProcTimeInStateReader.java
new file mode 100644
index 0000000..3a63498
--- /dev/null
+++ b/core/java/com/android/internal/os/ProcTimeInStateReader.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.os;
+
+import android.annotation.Nullable;
+import android.os.Process;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+/**
+ * Reads and parses {@code time_in_state} files in the {@code proc} filesystem.
+ *
+ * Every line in a {@code time_in_state} file contains two numbers, separated by a single space
+ * character. The first number is the frequency of the CPU used in kilohertz. The second number is
+ * the time spent in this frequency. In the {@code time_in_state} file, this is given in 10s of
+ * milliseconds, but this class returns in milliseconds. This can be per user, process, or thread
+ * depending on which {@code time_in_state} file is used.
+ *
+ * For example, a {@code time_in_state} file would look like this:
+ * <pre>
+ *   300000 3
+ *   364800 0
+ *   ...
+ *   1824000 0
+ *   1900800 1
+ * </pre>
+ *
+ * This file would indicate that the CPU has spent 30 milliseconds at frequency 300,000KHz (300Mhz)
+ * and 10 milliseconds at frequency 1,900,800KHz (1.9GHz).
+ */
+public class ProcTimeInStateReader {
+    private static final String TAG = "ProcTimeInStateReader";
+
+    /**
+     * The format of a single line of the {@code time_in_state} file that exports the frequency
+     * values
+     */
+    private static final int[] TIME_IN_STATE_LINE_FREQUENCY_FORMAT = {
+            Process.PROC_OUT_LONG | Process.PROC_SPACE_TERM,
+            Process.PROC_NEWLINE_TERM,
+    };
+
+    /**
+     * The format of a single line of the {@code time_in_state} file that exports the time values
+     */
+    private static final int[] TIME_IN_STATE_LINE_TIME_FORMAT = {
+            Process.PROC_SPACE_TERM,
+            Process.PROC_OUT_LONG | Process.PROC_NEWLINE_TERM,
+    };
+
+    /**
+     * The format of the {@code time_in_state} file, defined using {@link Process}'s {@code
+     * PROC_OUT_LONG} and related variables
+     *
+     * Defined on first successful read of {@code time_in_state} file.
+     */
+    private int[] mTimeInStateTimeFormat;
+
+    /**
+     * The frequencies reported in each {@code time_in_state} file
+     *
+     * Defined on first successful read of {@code time_in_state} file.
+     */
+    private long[] mFrequenciesKhz;
+
+    /**
+     * @param initialTimeInStateFile the file to base the format of the frequency files on, and to
+     * read frequencies from. Expected to be in the same format as all other {@code time_in_state}
+     * files, and contain the same frequencies.
+     * @throws IOException if reading the initial {@code time_in_state} file failed
+     */
+    public ProcTimeInStateReader(Path initialTimeInStateFile) throws IOException {
+        initializeTimeInStateFormat(initialTimeInStateFile);
+    }
+
+    /**
+     * Read the CPU usages from a file
+     *
+     * @param timeInStatePath path where the CPU usages are read from
+     * @return list of CPU usage times from the file. These correspond to the CPU frequencies given
+     * by {@link ProcTimeInStateReader#getFrequenciesKhz}
+     */
+    @Nullable
+    public long[] getUsageTimesMillis(final Path timeInStatePath) {
+        // Read in the time_in_state file
+        final long[] readLongs = new long[mFrequenciesKhz.length];
+        final boolean readSuccess = Process.readProcFile(
+                timeInStatePath.toString(),
+                mTimeInStateTimeFormat,
+                null, readLongs, null);
+        if (!readSuccess) {
+            return null;
+        }
+        // Usage time is given in 10ms, so convert to ms
+        for (int i = 0; i < readLongs.length; i++) {
+            readLongs[i] *= 10;
+        }
+        return readLongs;
+    }
+
+    /**
+     * Get the frequencies found in each {@code time_in_state} file
+     *
+     * @return list of CPU frequencies. These correspond to the CPU times given by {@link
+     * ProcTimeInStateReader#getUsageTimesMillis(Path)}()}.
+     */
+    @Nullable
+    public long[] getFrequenciesKhz() {
+        return mFrequenciesKhz;
+    }
+
+    /**
+     * Set the {@link #mTimeInStateTimeFormat} and {@link #mFrequenciesKhz} variables based on the
+     * an input file. If the file is empty, these variables aren't set
+     *
+     * This needs to be run once on the first invocation of {@link #getUsageTimesMillis(Path)}. This
+     * is because we need to know how many frequencies are available in order to parse time
+     * {@code time_in_state} file using {@link Process#readProcFile}, which only accepts
+     * fixed-length formats. Also, as the frequencies do not change between {@code time_in_state}
+     * files, we read and store them here.
+     *
+     * @param timeInStatePath the input file to base the format off of
+     */
+    private void initializeTimeInStateFormat(final Path timeInStatePath) throws IOException {
+        // Read the bytes of the `time_in_state` file
+        byte[] timeInStateBytes = Files.readAllBytes(timeInStatePath);
+
+        // The number of lines in the `time_in_state` file is the number of frequencies available
+        int numFrequencies = 0;
+        for (int i = 0; i < timeInStateBytes.length; i++) {
+            if (timeInStateBytes[i] == '\n') {
+                numFrequencies++;
+            }
+        }
+        if (numFrequencies == 0) {
+            throw new IOException("Empty time_in_state file");
+        }
+
+        // Set `mTimeInStateTimeFormat` and `timeInStateFrequencyFormat` to the correct length, and
+        // then copy in the `TIME_IN_STATE_{FREQUENCY,TIME}_LINE_FORMAT` until it's full. As we only
+        // use the frequency format in this method, it is not an member variable.
+        final int[] timeInStateTimeFormat =
+                new int[numFrequencies * TIME_IN_STATE_LINE_TIME_FORMAT.length];
+        final int[] timeInStateFrequencyFormat =
+                new int[numFrequencies * TIME_IN_STATE_LINE_FREQUENCY_FORMAT.length];
+        for (int i = 0; i < numFrequencies; i++) {
+            System.arraycopy(
+                    TIME_IN_STATE_LINE_FREQUENCY_FORMAT, 0, timeInStateFrequencyFormat,
+                    i * TIME_IN_STATE_LINE_FREQUENCY_FORMAT.length,
+                    TIME_IN_STATE_LINE_FREQUENCY_FORMAT.length);
+            System.arraycopy(
+                    TIME_IN_STATE_LINE_TIME_FORMAT, 0, timeInStateTimeFormat,
+                    i * TIME_IN_STATE_LINE_TIME_FORMAT.length,
+                    TIME_IN_STATE_LINE_TIME_FORMAT.length);
+        }
+
+        // Read the frequencies from the `time_in_state` file and store them, as they will be the
+        // same for every `time_in_state` file
+        final long[] readLongs = new long[numFrequencies];
+        final boolean readSuccess = Process.parseProcLine(
+                timeInStateBytes, 0, timeInStateBytes.length, timeInStateFrequencyFormat,
+                null, readLongs, null);
+        if (!readSuccess) {
+            throw new IOException("Failed to parse time_in_state file");
+        }
+
+        mTimeInStateTimeFormat = timeInStateTimeFormat;
+        mFrequenciesKhz = readLongs;
+    }
+}
diff --git a/core/java/com/android/internal/os/ProcessCpuTracker.java b/core/java/com/android/internal/os/ProcessCpuTracker.java
index 1ee4269..4b878c7 100644
--- a/core/java/com/android/internal/os/ProcessCpuTracker.java
+++ b/core/java/com/android/internal/os/ProcessCpuTracker.java
@@ -28,10 +28,7 @@
 
 import com.android.internal.util.FastPrintWriter;
 
-import libcore.io.IoUtils;
-
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.text.SimpleDateFormat;
@@ -40,7 +37,6 @@
 import java.util.Comparator;
 import java.util.Date;
 import java.util.List;
-import java.util.StringTokenizer;
 
 public class ProcessCpuTracker {
     private static final String TAG = "ProcessCpuTracker";
@@ -176,8 +172,6 @@
 
     private boolean mFirst = true;
 
-    private byte[] mBuffer = new byte[4096];
-
     public interface FilterStats {
         /** Which stats to pick when filtering */
         boolean needed(Stats stats);
@@ -863,40 +857,11 @@
         pw.println();
     }
 
-    private String readFile(String file, char endChar) {
-        // Permit disk reads here, as /proc/meminfo isn't really "on
-        // disk" and should be fast.  TODO: make BlockGuard ignore
-        // /proc/ and /sys/ files perhaps?
-        StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads();
-        FileInputStream is = null;
-        try {
-            is = new FileInputStream(file);
-            int len = is.read(mBuffer);
-            is.close();
-
-            if (len > 0) {
-                int i;
-                for (i=0; i<len; i++) {
-                    if (mBuffer[i] == endChar) {
-                        break;
-                    }
-                }
-                return new String(mBuffer, 0, i);
-            }
-        } catch (java.io.FileNotFoundException e) {
-        } catch (java.io.IOException e) {
-        } finally {
-            IoUtils.closeQuietly(is);
-            StrictMode.setThreadPolicy(savedPolicy);
-        }
-        return null;
-    }
-
     private void getName(Stats st, String cmdlineFile) {
         String newName = st.name;
         if (st.name == null || st.name.equals("app_process")
                 || st.name.equals("<pre-initialized>")) {
-            String cmdName = readFile(cmdlineFile, '\0');
+            String cmdName = ProcStatsUtil.readTerminatedProcFile(cmdlineFile, (byte) '\0');
             if (cmdName != null && cmdName.length() > 1) {
                 newName = cmdName;
                 int i = newName.lastIndexOf("/");
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index 98b7b5d..65213c0 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -216,6 +216,11 @@
      */
     native protected static void nativeUnmountStorageOnInit();
 
+    private static void callPostForkSystemServerHooks() {
+        // SystemServer specific post fork hooks run before child post fork hooks.
+        VM_HOOKS.postForkSystemServer();
+    }
+
     private static void callPostForkChildHooks(int runtimeFlags, boolean isSystemServer,
             boolean isZygote, String instructionSet) {
         VM_HOOKS.postForkChild(runtimeFlags, isSystemServer, isZygote, instructionSet);
diff --git a/core/java/com/android/internal/policy/BackdropFrameRenderer.java b/core/java/com/android/internal/policy/BackdropFrameRenderer.java
index f14007b..cc958f4 100644
--- a/core/java/com/android/internal/policy/BackdropFrameRenderer.java
+++ b/core/java/com/android/internal/policy/BackdropFrameRenderer.java
@@ -69,7 +69,6 @@
     private ColorDrawable mNavigationBarColor;
     private boolean mOldFullscreen;
     private boolean mFullscreen;
-    private final int mResizeMode;
     private final Rect mOldSystemInsets = new Rect();
     private final Rect mOldStableInsets = new Rect();
     private final Rect mSystemInsets = new Rect();
@@ -79,7 +78,7 @@
     public BackdropFrameRenderer(DecorView decorView, ThreadedRenderer renderer, Rect initialBounds,
             Drawable resizingBackgroundDrawable, Drawable captionBackgroundDrawable,
             Drawable userCaptionBackgroundDrawable, int statusBarColor, int navigationBarColor,
-            boolean fullscreen, Rect systemInsets, Rect stableInsets, int resizeMode) {
+            boolean fullscreen, Rect systemInsets, Rect stableInsets) {
         setName("ResizeFrame");
 
         mRenderer = renderer;
@@ -100,7 +99,6 @@
         mStableInsets.set(stableInsets);
         mOldSystemInsets.set(systemInsets);
         mOldStableInsets.set(stableInsets);
-        mResizeMode = resizeMode;
 
         // Kick off our draw thread.
         start();
@@ -109,33 +107,35 @@
     void onResourcesLoaded(DecorView decorView, Drawable resizingBackgroundDrawable,
             Drawable captionBackgroundDrawableDrawable, Drawable userCaptionBackgroundDrawable,
             int statusBarColor, int navigationBarColor) {
-        mDecorView = decorView;
-        mResizingBackgroundDrawable = resizingBackgroundDrawable != null
-                        && resizingBackgroundDrawable.getConstantState() != null
-                ? resizingBackgroundDrawable.getConstantState().newDrawable()
-                : null;
-        mCaptionBackgroundDrawable = captionBackgroundDrawableDrawable != null
-                        && captionBackgroundDrawableDrawable.getConstantState() != null
-                ? captionBackgroundDrawableDrawable.getConstantState().newDrawable()
-                : null;
-        mUserCaptionBackgroundDrawable = userCaptionBackgroundDrawable != null
-                        && userCaptionBackgroundDrawable.getConstantState() != null
-                ? userCaptionBackgroundDrawable.getConstantState().newDrawable()
-                : null;
-        if (mCaptionBackgroundDrawable == null) {
-            mCaptionBackgroundDrawable = mResizingBackgroundDrawable;
-        }
-        if (statusBarColor != 0) {
-            mStatusBarColor = new ColorDrawable(statusBarColor);
-            addSystemBarNodeIfNeeded();
-        } else {
-            mStatusBarColor = null;
-        }
-        if (navigationBarColor != 0) {
-            mNavigationBarColor = new ColorDrawable(navigationBarColor);
-            addSystemBarNodeIfNeeded();
-        } else {
-            mNavigationBarColor = null;
+        synchronized (this) {
+            mDecorView = decorView;
+            mResizingBackgroundDrawable = resizingBackgroundDrawable != null
+                    && resizingBackgroundDrawable.getConstantState() != null
+                    ? resizingBackgroundDrawable.getConstantState().newDrawable()
+                    : null;
+            mCaptionBackgroundDrawable = captionBackgroundDrawableDrawable != null
+                    && captionBackgroundDrawableDrawable.getConstantState() != null
+                    ? captionBackgroundDrawableDrawable.getConstantState().newDrawable()
+                    : null;
+            mUserCaptionBackgroundDrawable = userCaptionBackgroundDrawable != null
+                    && userCaptionBackgroundDrawable.getConstantState() != null
+                    ? userCaptionBackgroundDrawable.getConstantState().newDrawable()
+                    : null;
+            if (mCaptionBackgroundDrawable == null) {
+                mCaptionBackgroundDrawable = mResizingBackgroundDrawable;
+            }
+            if (statusBarColor != 0) {
+                mStatusBarColor = new ColorDrawable(statusBarColor);
+                addSystemBarNodeIfNeeded();
+            } else {
+                mStatusBarColor = null;
+            }
+            if (navigationBarColor != 0) {
+                mNavigationBarColor = new ColorDrawable(navigationBarColor);
+                addSystemBarNodeIfNeeded();
+            } else {
+                mNavigationBarColor = null;
+            }
         }
     }
 
@@ -186,7 +186,7 @@
      * All resources of the renderer will be released. This function can be called from the
      * the UI thread as well as the renderer thread.
      */
-    public void releaseRenderer() {
+    void releaseRenderer() {
         synchronized (this) {
             if (mRenderer != null) {
                 // Invalidate the current content bounds.
@@ -268,7 +268,7 @@
      * @param ySize The height of the content.
      * @return true if a frame should be requested after the content is drawn; false otherwise.
      */
-    public boolean onContentDrawn(int xOffset, int yOffset, int xSize, int ySize) {
+    boolean onContentDrawn(int xOffset, int yOffset, int xSize, int ySize) {
         synchronized (this) {
             final boolean firstCall = mLastContentWidth == 0;
             // The current content buffer is drawn here.
@@ -291,7 +291,7 @@
         }
     }
 
-    public void onRequestDraw(boolean reportNextDraw) {
+    void onRequestDraw(boolean reportNextDraw) {
         synchronized (this) {
             mReportNextDraw = reportNextDraw;
             mOldTargetRect.set(0, 0, 0, 0);
@@ -329,8 +329,8 @@
             return;
         }
 
-        // Since the surface is spanning the entire screen, we have to add the start offset of
-        // the bounds to get to the surface location.
+        // Content may not be drawn at the surface origin, so we want to keep the offset when we're
+        // resizing it.
         final int left = mLastXOffset + newBounds.left;
         final int top = mLastYOffset + newBounds.top;
         final int width = newBounds.width();
@@ -414,6 +414,8 @@
     }
 
     void setUserCaptionBackgroundDrawable(Drawable userCaptionBackgroundDrawable) {
-        mUserCaptionBackgroundDrawable = userCaptionBackgroundDrawable;
+        synchronized (this) {
+            mUserCaptionBackgroundDrawable = userCaptionBackgroundDrawable;
+        }
     }
 }
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index 94140ab..aa7bdb6 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -2093,7 +2093,7 @@
                     initialBounds, mResizingBackgroundDrawable, mCaptionBackgroundDrawable,
                     mUserCaptionBackgroundDrawable, getCurrentColor(mStatusColorViewState),
                     getCurrentColor(mNavigationColorViewState), fullscreen, systemInsets,
-                    stableInsets, resizeMode);
+                    stableInsets);
 
             // Get rid of the shadow while we are resizing. Shadow drawing takes considerable time.
             // If we want to get the shadow shown while resizing, we would need to elevate a new
@@ -2229,7 +2229,14 @@
         // or it didn't change.
         if ((wasAdjustedForStack || mElevationAdjustedForStack)
                 && getElevation() != elevation) {
-            mWindow.setElevation(elevation);
+            if (!isResizing()) {
+                mWindow.setElevation(elevation);
+            } else {
+                // Just suppress the shadow when resizing, don't adjust surface insets because it'll
+                // cause a flicker when drag resize for freeform window starts. #onContentDrawn()
+                // will compensate the offset when passing to BackdropFrameRenderer.
+                setElevation(elevation);
+            }
         }
     }
 
diff --git a/core/java/com/android/internal/statusbar/NotificationVisibility.java b/core/java/com/android/internal/statusbar/NotificationVisibility.java
index ea0344d..a7203e7 100644
--- a/core/java/com/android/internal/statusbar/NotificationVisibility.java
+++ b/core/java/com/android/internal/statusbar/NotificationVisibility.java
@@ -27,7 +27,6 @@
 public class NotificationVisibility implements Parcelable {
     private static final String TAG = "NoViz";
     private static final int MAX_POOL_SIZE = 25;
-    private static ArrayDeque<NotificationVisibility> sPool = new ArrayDeque<>(MAX_POOL_SIZE);
     private static int sNexrId = 0;
 
     public String key;
@@ -119,11 +118,6 @@
     }
 
     private static NotificationVisibility obtain() {
-        synchronized (sPool) {
-            if (!sPool.isEmpty()) {
-                return sPool.poll();
-            }
-        }
         return new NotificationVisibility();
     }
 
@@ -135,16 +129,7 @@
      * </p>
      */
     public void recycle() {
-        if (key == null) {
-            // do nothing on multiple recycles
-            return;
-        }
-        key = null;
-        if (sPool.size() < MAX_POOL_SIZE) {
-            synchronized (sPool) {
-                sPool.offer(this);
-            }
-        }
+        // With a modern GC, this is no longer useful for objects this small.
     }
 
     /**
diff --git a/core/java/com/android/internal/widget/LockPatternView.java b/core/java/com/android/internal/widget/LockPatternView.java
index 97896f0..b799728 100644
--- a/core/java/com/android/internal/widget/LockPatternView.java
+++ b/core/java/com/android/internal/widget/LockPatternView.java
@@ -69,6 +69,7 @@
     private static final int ASPECT_LOCK_HEIGHT = 2; // Fixed height; width will be minimum of (w,h)
 
     private static final boolean PROFILE_DRAWING = false;
+    private static final float LINE_FADE_ALPHA_MULTIPLIER = 3.5f;
     private final CellState[][] mCellStates;
 
     private final int mDotSize;
@@ -1170,9 +1171,9 @@
                 float centerX = getCenterXForColumn(cell.column);
                 float centerY = getCenterYForRow(cell.row);
                 if (i != 0) {
-                   // Set this line segment to slowly fade over the next second.
+                   // Set this line segment to fade away animated.
                    int lineFadeVal = (int) Math.min((elapsedRealtime -
-                           mLineFadeStart[i])/2f, 255f);
+                           mLineFadeStart[i]) * LINE_FADE_ALPHA_MULTIPLIER, 255f);
 
                     CellState state = mCellStates[cell.row][cell.column];
                     currentPath.rewind();
diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java
index d68e8f8..ae0f8b9 100644
--- a/core/java/com/android/server/SystemConfig.java
+++ b/core/java/com/android/server/SystemConfig.java
@@ -337,16 +337,11 @@
         readPermissions(Environment.buildPath(
                 Environment.getProductDirectory(), "etc", "permissions"), ALLOW_ALL);
 
-        // Allow /product_services to customize system configs around libs, features, permissions
-        // and apps.
-        int productServicesPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PERMISSIONS |
-                ALLOW_APP_CONFIGS | ALLOW_PRIVAPP_PERMISSIONS;
+        // Allow /product_services to customize all system configs
         readPermissions(Environment.buildPath(
-                Environment.getProductServicesDirectory(), "etc", "sysconfig"),
-                productServicesPermissionFlag);
+                Environment.getProductServicesDirectory(), "etc", "sysconfig"), ALLOW_ALL);
         readPermissions(Environment.buildPath(
-                Environment.getProductServicesDirectory(), "etc", "permissions"),
-                productServicesPermissionFlag);
+                Environment.getProductServicesDirectory(), "etc", "permissions"), ALLOW_ALL);
     }
 
     void readPermissions(File libraryDir, int permissionFlag) {
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 59c29e2..c96aaba 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -42,6 +42,7 @@
         "com_google_android_gles_jni_EGLImpl.cpp",
         "com_google_android_gles_jni_GLImpl.cpp", // TODO: .arm
         "android_app_Activity.cpp",
+	"android_app_ActivityThread.cpp",
         "android_app_NativeActivity.cpp",
         "android_app_admin_SecurityLog.cpp",
         "android_opengl_EGL14.cpp",
diff --git a/core/jni/android/graphics/FontFamily.cpp b/core/jni/android/graphics/FontFamily.cpp
index fb571df..e07a208 100644
--- a/core/jni/android/graphics/FontFamily.cpp
+++ b/core/jni/android/graphics/FontFamily.cpp
@@ -129,7 +129,7 @@
         return false;
     }
     std::shared_ptr<minikin::MinikinFont> minikinFont =
-            std::make_shared<MinikinFontSkia>(std::move(face), fontPtr, fontSize, ttcIndex,
+            std::make_shared<MinikinFontSkia>(std::move(face), fontPtr, fontSize, "", ttcIndex,
                     builder->axes);
     minikin::Font::Builder fontBuilder(minikinFont);
 
diff --git a/core/jni/android/graphics/Typeface.cpp b/core/jni/android/graphics/Typeface.cpp
index 34ec365..30d6ff4 100644
--- a/core/jni/android/graphics/Typeface.cpp
+++ b/core/jni/android/graphics/Typeface.cpp
@@ -20,11 +20,13 @@
 #include "FontUtils.h"
 #include "GraphicsJNI.h"
 #include <nativehelper/ScopedPrimitiveArray.h>
+#include <nativehelper/ScopedUtfChars.h>
 #include "SkTypeface.h"
 #include <android_runtime/android_util_AssetManager.h>
 #include <androidfw/AssetManager.h>
 #include <hwui/Typeface.h>
 #include <minikin/FontFamily.h>
+#include <minikin/SystemFonts.h>
 
 using namespace android;
 
@@ -108,6 +110,7 @@
 // CriticalNative
 static void Typeface_setDefault(jlong faceHandle) {
     Typeface::setDefault(toTypeface(faceHandle));
+    minikin::SystemFonts::registerDefault(toTypeface(faceHandle)->fFontCollection);
 }
 
 static jobject Typeface_getSupportedAxes(JNIEnv *env, jobject, jlong faceHandle) {
@@ -128,6 +131,12 @@
     return result;
 }
 
+static void Typeface_registerGenericFamily(JNIEnv *env, jobject, jstring familyName, jlong ptr) {
+    ScopedUtfChars familyNameChars(env, familyName);
+    minikin::SystemFonts::registerFallback(familyNameChars.c_str(),
+                                           toTypeface(ptr)->fFontCollection);
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 
 static const JNINativeMethod gTypefaceMethods[] = {
@@ -144,6 +153,8 @@
                                            (void*)Typeface_createFromArray },
     { "nativeSetDefault",         "(J)V",   (void*)Typeface_setDefault },
     { "nativeGetSupportedAxes",   "(J)[I",  (void*)Typeface_getSupportedAxes },
+    { "nativeRegisterGenericFamily", "(Ljava/lang/String;J)V",
+          (void*)Typeface_registerGenericFamily },
 };
 
 int register_android_graphics_Typeface(JNIEnv* env)
diff --git a/core/jni/android/graphics/fonts/Font.cpp b/core/jni/android/graphics/fonts/Font.cpp
index 2d1d7a0..8178318 100644
--- a/core/jni/android/graphics/fonts/Font.cpp
+++ b/core/jni/android/graphics/fonts/Font.cpp
@@ -134,7 +134,7 @@
 
 // Regular JNI
 static jlong Font_Builder_build(JNIEnv* env, jobject clazz, jlong builderPtr, jobject buffer,
-        jint weight, jboolean italic, jint ttcIndex) {
+        jstring filePath, jint weight, jboolean italic, jint ttcIndex) {
     NPE_CHECK_RETURN_ZERO(env, buffer);
     std::unique_ptr<NativeFontBuilder> builder(toBuilder(builderPtr));
     const void* fontPtr = env->GetDirectBufferAddress(buffer);
@@ -148,6 +148,7 @@
                           "buffer size must not be zero or negative");
         return 0;
     }
+    ScopedUtfChars fontPath(env, filePath);
     jobject fontRef = MakeGlobalRefOrDie(env, buffer);
     sk_sp<SkData> data(SkData::MakeWithProc(fontPtr, fontSize,
             release_global_ref, reinterpret_cast<void*>(fontRef)));
@@ -171,8 +172,9 @@
         return 0;
     }
     std::shared_ptr<minikin::MinikinFont> minikinFont =
-            std::make_shared<MinikinFontSkia>(std::move(face), fontPtr, fontSize, ttcIndex,
-                    builder->axes);
+            std::make_shared<MinikinFontSkia>(std::move(face), fontPtr, fontSize,
+                                              std::string_view(fontPath.c_str(), fontPath.size()),
+                                              ttcIndex, builder->axes);
     minikin::Font font = minikin::Font::Builder(minikinFont).setWeight(weight)
                     .setSlant(static_cast<minikin::FontStyle::Slant>(italic)).build();
     return reinterpret_cast<jlong>(new FontWrapper(std::move(font)));
@@ -188,7 +190,7 @@
 static const JNINativeMethod gFontBuilderMethods[] = {
     { "nInitBuilder", "()J", (void*) Font_Builder_initBuilder },
     { "nAddAxis", "(JIF)V", (void*) Font_Builder_addAxis },
-    { "nBuild", "(JLjava/nio/ByteBuffer;IZI)J", (void*) Font_Builder_build },
+    { "nBuild", "(JLjava/nio/ByteBuffer;Ljava/lang/String;IZI)J", (void*) Font_Builder_build },
     { "nGetReleaseNativeFont", "()J", (void*) Font_Builder_getReleaseNativeFont },
 
     { "nGetNativeAsset", "(Landroid/content/res/AssetManager;Ljava/lang/String;ZI)J",
diff --git a/core/jni/android_app_ActivityThread.cpp b/core/jni/android_app_ActivityThread.cpp
new file mode 100644
index 0000000..d56e4c5
--- /dev/null
+++ b/core/jni/android_app_ActivityThread.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "jni.h"
+#include "GraphicsJNI.h"
+#include <nativehelper/JNIHelp.h>
+
+#include <minikin/Layout.h>
+#include <renderthread/RenderProxy.h>
+
+#include "core_jni_helpers.h"
+#include <unistd.h>
+
+namespace android {
+
+static void android_app_ActivityThread_purgePendingResources(JNIEnv* env, jobject clazz) {
+    // Don't care about return values.
+    mallopt(M_PURGE, 0);
+}
+
+static void
+android_app_ActivityThread_dumpGraphics(JNIEnv* env, jobject clazz, jobject javaFileDescriptor) {
+    int fd = jniGetFDFromFileDescriptor(env, javaFileDescriptor);
+    android::uirenderer::renderthread::RenderProxy::dumpGraphicsMemory(fd);
+    minikin::Layout::dumpMinikinStats(fd);
+}
+
+
+static JNINativeMethod gActivityThreadMethods[] = {
+    // ------------ Regular JNI ------------------
+    { "nPurgePendingResources",        "()V",
+      (void*) android_app_ActivityThread_purgePendingResources },
+    { "nDumpGraphicsInfo",        "(Ljava/io/FileDescriptor;)V",
+      (void*) android_app_ActivityThread_dumpGraphics }
+};
+
+int register_android_app_ActivityThread(JNIEnv* env) {
+    return RegisterMethodsOrDie(env, "android/app/ActivityThread",
+            gActivityThreadMethods, NELEM(gActivityThreadMethods));
+}
+
+};
diff --git a/core/jni/android_graphics_Canvas.cpp b/core/jni/android_graphics_Canvas.cpp
index dca2da3..84f53468 100644
--- a/core/jni/android_graphics_Canvas.cpp
+++ b/core/jni/android_graphics_Canvas.cpp
@@ -523,10 +523,11 @@
     Paint* paint = reinterpret_cast<Paint*>(paintHandle);
     const Typeface* typeface = paint->getAndroidTypeface();
     ScopedCharArrayRO text(env, charArray);
+    // drawTextString and drawTextChars doesn't use context info
     get_canvas(canvasHandle)->drawText(
-            text.get(), text.size(),  // text buffer
-            index, count,  // draw range
-            0, text.size(),  // context range
+            text.get() + index, count,  // text buffer
+            0, count,  // draw range
+            0, count,  // context range
             x, y,  // draw position
             static_cast<minikin::Bidi>(bidiFlags), *paint, typeface, nullptr /* measured text */);
 }
@@ -537,10 +538,12 @@
     ScopedStringChars text(env, strObj);
     Paint* paint = reinterpret_cast<Paint*>(paintHandle);
     const Typeface* typeface = paint->getAndroidTypeface();
+    const int count = end - start;
+    // drawTextString and drawTextChars doesn't use context info
     get_canvas(canvasHandle)->drawText(
-            text.get(), text.size(),  // text buffer
-            start, end - start,  // draw range
-            0, text.size(),  // context range
+            text.get() + start, count,  // text buffer
+            0, count,  // draw range
+            0, count,  // context range
             x, y,  // draw position
             static_cast<minikin::Bidi>(bidiFlags), *paint, typeface, nullptr /* measured text */);
 }
diff --git a/core/jni/android_media_AudioFormat.h b/core/jni/android_media_AudioFormat.h
index da4cdb6..83a8c2e 100644
--- a/core/jni/android_media_AudioFormat.h
+++ b/core/jni/android_media_AudioFormat.h
@@ -127,10 +127,9 @@
     case AUDIO_FORMAT_DOLBY_TRUEHD:
         return ENCODING_DOLBY_TRUEHD;
     case AUDIO_FORMAT_AAC_ELD:
-            return ENCODING_AAC_ELD;
-    // FIXME needs addition of AUDIO_FORMAT_AAC_XHE
-    //case AUDIO_FORMAT_AAC_XHE:
-    //    return ENCODING_AAC_XHE;
+        return ENCODING_AAC_ELD;
+    case AUDIO_FORMAT_AAC_XHE:
+        return ENCODING_AAC_XHE;
     case AUDIO_FORMAT_AC4:
         return ENCODING_AC4;
     case AUDIO_FORMAT_E_AC3_JOC:
diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp
index 6456fe6..bf22dd2 100644
--- a/core/jni/android_media_AudioTrack.cpp
+++ b/core/jni/android_media_AudioTrack.cpp
@@ -29,6 +29,7 @@
 #include <media/AudioSystem.h>
 #include <media/AudioTrack.h>
 
+#include <android-base/macros.h>
 #include <binder/MemoryHeapBase.h>
 #include <binder/MemoryBase.h>
 
@@ -134,41 +135,53 @@
         callbackInfo->busy = true;
     }
 
+    // used as default argument when event callback doesn't have any, or number of
+    // frames for EVENT_CAN_WRITE_MORE_DATA
+    int arg = 0;
+    bool postEvent = false;
     switch (event) {
     // Offload only events
-    case AudioTrack::EVENT_STREAM_END:
-    case AudioTrack::EVENT_MORE_DATA:
-    // a.k.a. tear down
-    case AudioTrack::EVENT_NEW_IAUDIOTRACK:
+    case AudioTrack::EVENT_CAN_WRITE_MORE_DATA:
+        // this event will read the info return parameter of the callback:
+        // for JNI offload, use the returned size to indicate:
+        // 1/ no data is returned through callback, as it's all done through write()
+        // 2/ do not wait as AudioTrack does when it receives 0 bytes
         if (callbackInfo->isOffload) {
-            JNIEnv *env = AndroidRuntime::getJNIEnv();
-            if (user != NULL && env != NULL) {
-                env->CallStaticVoidMethod(
-                        callbackInfo->audioTrack_class,
-                        javaAudioTrackFields.postNativeEventInJava,
-                        callbackInfo->audioTrack_ref, event, 0,0, NULL);
-                if (env->ExceptionCheck()) {
-                    env->ExceptionDescribe();
-                    env->ExceptionClear();
-                }
-            }
-        } break;
+            AudioTrack::Buffer* pBuffer = (AudioTrack::Buffer*) info;
+            const size_t availableForWrite = pBuffer->size;
+            arg = availableForWrite > INT32_MAX ? INT32_MAX : (int) availableForWrite;
+            pBuffer->size = 0;
+        }
+        FALLTHROUGH_INTENDED;
+    case AudioTrack::EVENT_STREAM_END:
+    case AudioTrack::EVENT_NEW_IAUDIOTRACK: // a.k.a. tear down
+        if (callbackInfo->isOffload) {
+            postEvent = true;
+        }
+        break;
 
     // PCM and offload events
     case AudioTrack::EVENT_MARKER:
-    case AudioTrack::EVENT_NEW_POS: {
+    case AudioTrack::EVENT_NEW_POS:
+        postEvent = true;
+        break;
+    default:
+        // event will not be posted
+        break;
+    }
+
+    if (postEvent) {
         JNIEnv *env = AndroidRuntime::getJNIEnv();
-        if (user != NULL && env != NULL) {
+        if (env != NULL) {
             env->CallStaticVoidMethod(
                     callbackInfo->audioTrack_class,
                     javaAudioTrackFields.postNativeEventInJava,
-                    callbackInfo->audioTrack_ref, event, 0,0, NULL);
+                    callbackInfo->audioTrack_ref, event, arg, 0, NULL);
             if (env->ExceptionCheck()) {
                 env->ExceptionDescribe();
                 env->ExceptionClear();
             }
         }
-        } break;
     }
 
     {
@@ -215,10 +228,10 @@
         jint audioFormat, jint buffSizeInBytes, jint memoryMode, jintArray jSession,
         jlong nativeAudioTrack, jboolean offload) {
 
-    ALOGV("sampleRates=%p, channel mask=%x, index mask=%x, audioFormat(Java)=%d, buffSize=%d"
-        "nativeAudioTrack=0x%" PRIX64,
+    ALOGV("sampleRates=%p, channel mask=%x, index mask=%x, audioFormat(Java)=%d, buffSize=%d,"
+        " nativeAudioTrack=0x%" PRIX64 ", offload=%d",
         jSampleRate, channelPositionMask, channelIndexMask, audioFormat, buffSizeInBytes,
-        nativeAudioTrack);
+        nativeAudioTrack, offload);
 
     sp<AudioTrack> lpTrack = 0;
 
@@ -318,7 +331,7 @@
         lpJniStorage->mCallbackData.busy = false;
 
         audio_offload_info_t offloadInfo;
-        if (offload) {
+        if (offload == JNI_TRUE) {
             offloadInfo = AUDIO_INFO_INITIALIZER;
             offloadInfo.format = format;
             offloadInfo.sample_rate = sampleRateInHertz;
@@ -331,23 +344,23 @@
         status_t status = NO_ERROR;
         switch (memoryMode) {
         case MODE_STREAM:
-
             status = lpTrack->set(
                     AUDIO_STREAM_DEFAULT,// stream type, but more info conveyed in paa (last argument)
                     sampleRateInHertz,
                     format,// word length, PCM
                     nativeChannelMask,
-                    frameCount,
-                    AUDIO_OUTPUT_FLAG_NONE,
+                    offload ? 0 : frameCount,
+                    offload ? AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD : AUDIO_OUTPUT_FLAG_NONE,
                     audioCallback, &(lpJniStorage->mCallbackData),//callback, callback data (user)
                     0,// notificationFrames == 0 since not using EVENT_MORE_DATA to feed the AudioTrack
                     0,// shared mem
                     true,// thread can call Java
                     sessionId,// audio session ID
-                    AudioTrack::TRANSFER_SYNC,
+                    offload ? AudioTrack::TRANSFER_SYNC_NOTIF_CALLBACK : AudioTrack::TRANSFER_SYNC,
                     offload ? &offloadInfo : NULL,
                     -1, -1,                       // default uid, pid values
                     paa);
+
             break;
 
         case MODE_STATIC:
diff --git a/core/jni/android_view_DisplayListCanvas.cpp b/core/jni/android_view_DisplayListCanvas.cpp
index 8998cd7..e0fd1a6 100644
--- a/core/jni/android_view_DisplayListCanvas.cpp
+++ b/core/jni/android_view_DisplayListCanvas.cpp
@@ -88,17 +88,6 @@
     sp<InvokeRunnableMessage> mMessage;
 };
 
-
-// ---------------- Regular JNI -----------------------------
-
-static void
-android_app_ActivityThread_dumpGraphics(JNIEnv* env, jobject clazz, jobject javaFileDescriptor) {
-    int fd = jniGetFDFromFileDescriptor(env, javaFileDescriptor);
-    android::uirenderer::renderthread::RenderProxy::dumpGraphicsMemory(fd);
-    minikin::Layout::dumpMinikinStats(fd);
-}
-
-
 // ---------------- @FastNative -----------------------------
 
 static void android_view_DisplayListCanvas_callDrawGLFunction(JNIEnv* env, jobject clazz,
@@ -205,12 +194,6 @@
     { "nDrawRoundRect",           "(JJJJJJJJ)V",(void*) android_view_DisplayListCanvas_drawRoundRectProps },
 };
 
-static JNINativeMethod gActivityThreadMethods[] = {
-        // ------------ Regular JNI ------------------
-    { "nDumpGraphicsInfo",        "(Ljava/io/FileDescriptor;)V",
-                                               (void*) android_app_ActivityThread_dumpGraphics }
-};
-
 int register_android_view_DisplayListCanvas(JNIEnv* env) {
     jclass runnableClass = FindClassOrDie(env, "java/lang/Runnable");
     gRunnableMethodId = GetMethodIDOrDie(env, runnableClass, "run", "()V");
@@ -218,9 +201,4 @@
     return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
 }
 
-int register_android_app_ActivityThread(JNIEnv* env) {
-    return RegisterMethodsOrDie(env, "android/app/ActivityThread",
-            gActivityThreadMethods, NELEM(gActivityThreadMethods));
-}
-
 };
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 3e04bb3..4e20e29 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -84,6 +84,7 @@
 static const char kIsolatedStorage[] = "persist.sys.isolated_storage";
 static const char kZygoteClassName[] = "com/android/internal/os/Zygote";
 static jclass gZygoteClass;
+static jmethodID gCallPostForkSystemServerHooks;
 static jmethodID gCallPostForkChildHooks;
 
 static bool g_is_security_enforced = true;
@@ -886,6 +887,18 @@
   // Unset the SIGCHLD handler, but keep ignoring SIGHUP (rationale in SetSignalHandlers).
   UnsetChldSignalHandler();
 
+  if (is_system_server) {
+    env->CallStaticVoidMethod(gZygoteClass, gCallPostForkSystemServerHooks);
+    if (env->ExceptionCheck()) {
+      fail_fn("Error calling post fork system server hooks.");
+    }
+    // TODO(oth): Remove hardcoded label here (b/117874058).
+    static const char* kSystemServerLabel = "u:r:system_server:s0";
+    if (selinux_android_setcon(kSystemServerLabel) != 0) {
+      fail_fn(CREATE_ERROR("selinux_android_setcon(%s)", kSystemServerLabel));
+    }
+  }
+
   env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, runtime_flags,
                             is_system_server, is_child_zygote, instructionSet);
   if (env->ExceptionCheck()) {
@@ -1181,6 +1194,9 @@
 
 int register_com_android_internal_os_Zygote(JNIEnv* env) {
   gZygoteClass = MakeGlobalRefOrDie(env, FindClassOrDie(env, kZygoteClassName));
+  gCallPostForkSystemServerHooks = GetStaticMethodIDOrDie(env, gZygoteClass,
+                                                          "callPostForkSystemServerHooks",
+                                                          "()V");
   gCallPostForkChildHooks = GetStaticMethodIDOrDie(env, gZygoteClass, "callPostForkChildHooks",
                                                    "(IZZLjava/lang/String;)V");
 
diff --git a/core/proto/android/app/notification_channel.proto b/core/proto/android/app/notification_channel.proto
index 75cc18b..435d32f 100644
--- a/core/proto/android/app/notification_channel.proto
+++ b/core/proto/android/app/notification_channel.proto
@@ -57,4 +57,7 @@
     // If this is a blockable system notification channel.
     optional bool is_blockable_system = 17;
     optional bool fg_service_shown = 18;
+    // Default is true.
+    // Allows the notifications to appear outside of the shade in floating windows
+    optional bool allow_app_overlay = 19;
 }
diff --git a/core/proto/android/app/notification_channel_group.proto b/core/proto/android/app/notification_channel_group.proto
index 4fb27b0..6d6ceb2 100644
--- a/core/proto/android/app/notification_channel_group.proto
+++ b/core/proto/android/app/notification_channel_group.proto
@@ -36,4 +36,7 @@
     optional string description = 3;
     optional bool is_blocked = 4;
     repeated NotificationChannelProto channels = 5;
+    // Default is true.
+    // Allows the notifications to appear outside of the shade in floating windows
+    optional bool allow_app_overlay = 6;
 }
diff --git a/core/proto/android/app/settings_enums.proto b/core/proto/android/app/settings_enums.proto
index 2797550..1dc435c0 100644
--- a/core/proto/android/app/settings_enums.proto
+++ b/core/proto/android/app/settings_enums.proto
@@ -56,5 +56,8 @@
 
   // Settings > Display > Lock screen display > On lock screen
   LOCK_SCREEN_NOTIFICATION_CONTENT = 1584;
+
+  // ConfirmDeviceCredentials > BiometricPrompt
+  BIOMETRIC_FRAGMENT = 1585;
 }
 
diff --git a/core/proto/android/stats/launcher/launcher.proto b/core/proto/android/stats/launcher/launcher.proto
new file mode 100644
index 0000000..dbd0e03
--- /dev/null
+++ b/core/proto/android/stats/launcher/launcher.proto
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+package android.stats.launcher;
+option java_multiple_files = true;
+
+enum LauncherAction {
+    DEFAULT_ACTION = 0;
+    LAUNCH_APP = 1;
+    LAUNCH_TASK = 2;
+    DISMISS_TASK = 3;
+    LONGPRESS = 4;
+    DRAGDROP = 5;
+    SWIPE_UP = 6;
+    SWIPE_DOWN = 7;
+    SWIPE_LEFT = 8;
+    SWIPE_RIGHT = 9;
+}
+
+enum LauncherState {
+    BACKGROUND = 0;
+    HOME = 1;
+    OVERVIEW = 2;
+    ALLAPPS = 3;
+}
+
+message LauncherTarget {
+    enum Type {
+        NONE = 0;
+        ITEM_TYPE = 1;
+        CONTROL_TYPE = 2;
+        CONTAINER_TYPE = 3;
+    }
+    enum Item {
+        DEFAULT_ITEM = 0;
+        APP_ICON = 1;
+        SHORTCUT = 2;
+        WIDGET = 3;
+        FOLDER_ICON = 4;
+        DEEPSHORTCUT = 5;
+        SEARCHBOX = 6;
+        EDITTEXT = 7;
+        NOTIFICATION = 8;
+        TASK = 9;
+    }
+    enum Container {
+        DEFAULT_CONTAINER = 0;
+        HOTSEAT = 1;
+        FOLDER = 2;
+        PREDICTION = 3;
+        SEARCHRESULT = 4;
+    }
+    enum Control {
+        DEFAULT_CONTROL = 0;
+        MENU = 1;
+        UNINSTALL = 2;
+        REMOVE = 3;
+    }
+    optional Type type = 1;
+    optional Item item = 2;
+    optional Container container = 3;
+    optional Control control = 4;
+    optional string launch_component = 5;
+    optional int32 page_id = 6;
+    optional int32 grid_x = 7;
+    optional int32 grid_y = 8;
+}
+
+message LauncherExtension {
+    repeated LauncherTarget src_target = 1;
+    repeated LauncherTarget dst_target = 2;
+}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 374c7ea..e728ead 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -400,6 +400,7 @@
 
     <protected-broadcast android:name="android.telecom.action.DEFAULT_DIALER_CHANGED" />
     <protected-broadcast android:name="android.provider.action.DEFAULT_SMS_PACKAGE_CHANGED" />
+    <protected-broadcast android:name="android.provider.action.SMS_MMS_DB_CREATED" />
     <protected-broadcast android:name="android.intent.action.CONTENT_CHANGED" />
     <protected-broadcast android:name="android.provider.Telephony.MMS_DOWNLOADED" />
 
@@ -2939,6 +2940,12 @@
     <permission android:name="android.permission.BIND_COMPANION_DEVICE_MANAGER_SERVICE"
         android:protectionLevel="signature" />
 
+    <!-- Must be required by the RoleControllerService to ensure that only the system can bind to
+         it.
+         @hide -->
+    <permission android:name="android.permission.BIND_ROLE_CONTROLLER_SERVICE"
+        android:protectionLevel="signature" />
+
     <!-- @SystemApi Must be required by the RuntimePermissionPresenterService to ensure
          that only the system can bind to it.
          @hide -->
@@ -3273,6 +3280,11 @@
     <permission android:name="android.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS"
         android:protectionLevel="signature|privileged" />
 
+    <!-- @SystemApi Allows an application to manage the holders of a role.
+         @hide -->
+    <permission android:name="android.permission.MANAGE_ROLE_HOLDERS"
+                android:protectionLevel="signature|installer" />
+
     <!-- @SystemApi Allows an application to use SurfaceFlinger's low level features.
          <p>Not for use by third-party applications.
          @hide
@@ -4187,6 +4199,11 @@
     <permission android:name="android.permission.READ_CLIPBOARD_IN_BACKGROUND"
         android:protectionLevel="signature" />
 
+    <!-- @SystemApi Allows modifying accessibility state.
+         @hide -->
+    <permission android:name="android.permission.MANAGE_ACCESSIBILITY"
+                android:protectionLevel="signature|setup" />
+
     <application android:process="system"
                  android:persistent="true"
                  android:hasCode="false"
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 5028150..9ba991b 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Mikrofoon"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"oudio op te neem"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"Laat &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toe om oudio op te neem?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"Aktiwiteitherkenning"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"herken aktiwiteit"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"Laat &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toe om jou fisieke aktiwiteit te herken?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Kamera"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"foto\'s en video te neem"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"Laat &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toe om foto\'s te neem en video\'s op te neem?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Hierdie program kan jou ligging kry op grond van jou netwerkhulpbronne soos selfoontorings en Wi-Fi-netwerke. Hierdie liggingdienste moet aangeskakel en op jou tablet beskikbaar wees sodat die program hulle kan gebruik."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Hierdie program kan jou ligging kry op grond van jou netwerkhulpbronne soos selfoontorings en Wi-Fi-netwerke. Hierdie liggingdienste moet aangeskakel en op jou TV beskikbaar wees sodat die program hulle kan gebruik."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Hierdie program kan jou ligging kry op grond van jou netwerkhulpbronne soos selfoontorings en Wi-Fi-netwerke. Hierdie liggingdienste moet aangeskakel en op jou foon beskikbaar wees sodat die program hulle kan gebruik."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"kry presiese ligging op die agtergrond"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"Hierdie program kan enige tyd terwyl dit op die agtergrond is jou presiese ligging kry. Hierdie liggingdienste moet aangeskakel wees en op jou foon beskikbaar wees sodat die program hulle kan gebruik. Dit kan veroorsaak dat meer batterykrag gebruik word."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"kry ligging op die agtergrond"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"As dit bo en behalwe toegang tot die benaderde of presiese ligging verleen word, kan die program die ligging kry terwyl dit op die agtergrond werk."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"verander jou klankinstellings"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Laat die program toe om globale klankinstellings soos volume en watter luidspreker vir uitvoer gebruik word, te verander."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"neem klank op"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"Hierdie program kan enige tyd oudio met die mikrofoon opneem."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"stuur bevele na die SIM"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Laat die program toe om bevele na die SIM te stuur. Dit is baie gevaarlik."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"herken fisieke aktiwiteit"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"Hierdie program kan jou fisieke aktiwiteit herken."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"neem foto\'s en video\'s"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"Hierdie program kan enige tyd met die kamera foto\'s neem en video\'s opneem."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"beheer vibrasie"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Laat die program toe om jou fotoversameling te wysig."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"lees liggings in jou mediaversameling"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Laat die program toe om liggings in jou mediaversameling te lees."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"Die program <xliff:g id="APP">%s</xliff:g> wil staaf."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Biometriese hardeware is nie beskikbaar nie"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Gedeeltelike vingerafdruk is bespeur. Probeer asseblief weer."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Kon nie vingerafdruk verwerk nie. Probeer asseblief weer."</string>
@@ -1897,14 +1903,14 @@
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> outovul-voorstelle</item>
       <item quantity="one">Een outovul-voorstel</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"Stoor in &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Stoor <xliff:g id="TYPE">%1$s</xliff:g> in &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Stoor <xliff:g id="TYPE_0">%1$s</xliff:g> en <xliff:g id="TYPE_1">%2$s</xliff:g> in &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Stoor <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> en <xliff:g id="TYPE_2">%3$s</xliff:g> in &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"Dateer op na &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Dateer <xliff:g id="TYPE">%1$s</xliff:g> op na &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Dateer <xliff:g id="TYPE_0">%1$s</xliff:g> en <xliff:g id="TYPE_1">%2$s</xliff:g> op na &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Dateer <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> en <xliff:g id="TYPE_2">%3$s</xliff:g> op na &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"Stoor in "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"Stoor <xliff:g id="TYPE">%1$s</xliff:g> in "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"Stoor <xliff:g id="TYPE_0">%1$s</xliff:g> en <xliff:g id="TYPE_1">%2$s</xliff:g> in "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"Stoor <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> en <xliff:g id="TYPE_2">%3$s</xliff:g> in "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"Dateer op in "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"Dateer <xliff:g id="TYPE">%1$s</xliff:g> op in "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"Dateer <xliff:g id="TYPE_0">%1$s</xliff:g> en <xliff:g id="TYPE_1">%2$s</xliff:g> op in "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"Dateer hierdie items op in "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> en <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Stoor"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Nee, dankie"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"Dateer op"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 217d631..5b2286b 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"ማይክሮፎን"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"ኦዲዮ ይቅዱ"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ኦዲዮን እንዲቀዳ ይፈቀድለት?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"የእንቅስቃሴ ለይቶ ማወቅ"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"እንቅስቃሴን ለይቶ ማወቅ"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; አካላዊ እንቅስቃሴዎን ለይቶ እንዲያውቅ ይፈቀድለት?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"ካሜራ"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"ስዕሎች ያንሱ እና ቪዲዮ ይቅረጹ"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ስዕሎችን እንዲያነሳ እና ቪዲዮን እንዲቀርጽ ይፈቀድለት?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"ይህ መተግበሪያ እንደ የሕዋስ ማማዎች እና የWi-Fi አውታረ መረቦች ከመሳሰሉ የአውታረ መረብ ምንጮች ላይ በመመርኮዝ የእርስዎን መገኛ አካባቢ ማግኘት ይችላል። እነዚህ የመገኛ አካባቢ አገልግሎቶች መተግበሪያው መጠቀም እንዲችል ሊበሩ እና በእርስዎ ጡባዊ ላይ ሊገኙ የሚችሉ መሆን አለባቸው።"</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"ይህ መተግበሪያ እንደ የሕዋስ ማማዎች እና የWi-Fi አውታረ መረቦች ከመሳሰሉ የአውታረ መረብ ምንጮች ላይ በመመርኮዝ የእርስዎን መገኛ አካባቢ ማግኘት ይችላል። እነዚህ የመገኛ አካባቢ አገልግሎቶች እርስዎ መጠቀም እንዲችሉ ሊበሩ እና በእርስዎ ቴሌቪዥን ላይ ሊገኙ የሚችሉ መሆን አለባቸው።"</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"ይህ መተግበሪያ እንደ የሕዋስ ማማዎች እና የWi-Fi አውታረ መረቦች ከመሳሰሉ የአውታረ መረብ ምንጮች ላይ በመመርኮዝ የእርስዎን መገኛ አካባቢ ማግኘት ይችላል። እነዚህ የመገኛ አካባቢ አገልግሎቶች መተግበሪያው መጠቀም እንዲችል ሊበሩ እና በእርስዎ ስልክ ላይ ሊገኙ የሚችሉ መሆን አለባቸው።"</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"በበስተጀርባ ትክክለኛ መገኛ አካባቢ ላይ ድረስ"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"ይህ መተግበሪያ በማናቸውም ጊዜ በበስተጀርባ ሲሆን ብቻ ትክክለኛውን መገኛ አካባቢ ማግኘት ይችላል። እነዚህ የመገኛ አካባቢ አገልግሎቶች መተግበሪያው መጠቀም እንዲችል ሊበሩ እና በእርስዎ ስልክ ላይ ሊገኙ የሚችሉ መሆን አለባቸው።"</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"አካባቢን በበስተጀርባ ድረስ"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"ይህ ከግምታዊ ወይም ትክክለኛ አካባቢ በተጨማሪ ከተሰጠ መተግበሪያው በበስተጀርባ እያሄደ ሳለ አካባቢውን መድረስ ይችላል።"</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"የድምፅ ቅንብሮችን ለውጥ"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"መተግበሪያው አንደ የድምጽ መጠን እና ለውጽአት የትኛውን የድምጽ ማጉያ ጥቅም ላይ እንደዋለ የመሳሰሉ ሁለንተናዊ የድምጽ ቅንብሮችን እንዲያስተካክል ይፈቅድለታል።"</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"ኦዲዮ ይቅዱ"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"ይህ መተግበሪያ በማናቸውም ጊዜ ማይክራፎኑን በመጠቀም ኦዲዮን መቅዳት ይችላል።"</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"ወደ ሲሙ ትዕዛዞችን መላክ"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"መተግበሪያው ትዕዛዞችን ወደ ሲሙ እንዲልክ ያስችለዋል። ይሄ በጣማ አደገኛ ነው።"</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"አካላዊ እንቅስቃሴን ለይቶ ማወቅ"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"ይህ መተግበሪያ አካላዊ እንቅስቃሴዎን ለይቶ ሊያውቅ ይችላል።"</string>
     <string name="permlab_camera" msgid="3616391919559751192">"ፎቶዎች እና ቪዲዮዎች ያንሱ"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"ይህ መተግበሪያ በማናቸውም ጊዜ ካሜራውን በመጠቀም ፎቶ ሊያነሳ እና ቪዲዮዎችን ሊቀርጽ ይችላል።"</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"ነዛሪ ተቆጣጠር"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"መተግበሪያው የፎቶ ስብስብዎን እንዲቀይረው ያስችለዋል።"</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"አካባቢዎችን ከሚዲያ ስብስብዎ ማንበብ"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"መተግበሪያው አካባቢዎችን ከሚዲያ ስብስብዎ እንዲያነብብ ያስችለዋል።"</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"መተግበሪያ <xliff:g id="APP">%s</xliff:g> ማረጋገጥ ይፈልጋል"</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"ባዮሜትራዊ ሃርድዌር አይገኝም"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"ከፊል የጣት አሻራ ተገኝቷል። እባክዎ እንደገና ይሞክሩ።"</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"ጣት አሻራን መስራት አልተቻለም። እባክዎ እንደገና ይሞክሩ።"</string>
@@ -1897,14 +1903,14 @@
       <item quantity="one"><xliff:g id="COUNT">%1$s</xliff:g> ራስ-ሙላ ጥቆማዎች</item>
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> ራስ-ሙላ ጥቆማዎች</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"ወደ &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; ይቀመጥ?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"<xliff:g id="TYPE">%1$s</xliff:g> ወደ &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; ይቀመጥ?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"<xliff:g id="TYPE_0">%1$s</xliff:g> እና <xliff:g id="TYPE_1">%2$s</xliff:g> ወደ &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; ይቀመጡ?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"<xliff:g id="TYPE_0">%1$s</xliff:g>፣ <xliff:g id="TYPE_1">%2$s</xliff:g> እና <xliff:g id="TYPE_2">%3$s</xliff:g> ወደ &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; ይቀመጡ?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"ወደ &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; ይዘመን?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"<xliff:g id="TYPE">%1$s</xliff:g> ወደ &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; ይዘመን?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"<xliff:g id="TYPE_0">%1$s</xliff:g> እና <xliff:g id="TYPE_1">%2$s</xliff:g> ወደ &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; ይዘመኑ?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"<xliff:g id="TYPE_0">%1$s</xliff:g>፣ <xliff:g id="TYPE_1">%2$s</xliff:g> እና <xliff:g id="TYPE_2">%3$s</xliff:g> ወደ &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; ይዘመኑ?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"ወደ "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" ይቀመጥ?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"<xliff:g id="TYPE">%1$s</xliff:g> ወደ "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" ይቀመጡ?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"<xliff:g id="TYPE_0">%1$s</xliff:g> እና <xliff:g id="TYPE_1">%2$s</xliff:g> ወደ "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" ይቀመጡ?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"<xliff:g id="TYPE_0">%1$s</xliff:g>፣ <xliff:g id="TYPE_1">%2$s</xliff:g> እና <xliff:g id="TYPE_2">%3$s</xliff:g> ወደ "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" ይቀመጡ?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"በ"<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" ውስጥ ይዘመን?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"<xliff:g id="TYPE">%1$s</xliff:g> በ"<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" ውስጥ ይዘመን?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"<xliff:g id="TYPE_0">%1$s</xliff:g> እና <xliff:g id="TYPE_1">%2$s</xliff:g> በ"<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" ውስጥ ይዘመኑ?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"እነዚህ ንጥሎች በ"<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" ውስጥ ይዘመኑ፦ <xliff:g id="TYPE_0">%1$s</xliff:g>፣ <xliff:g id="TYPE_1">%2$s</xliff:g> እና <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"አስቀምጥ"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"አይ፣ አመሰግናለሁ"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"አዘምን"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index c11279a..9a48e14 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -171,10 +171,10 @@
     <string name="contentServiceSync" msgid="8353523060269335667">"مزامنة"</string>
     <string name="contentServiceSyncNotificationTitle" msgid="7036196943673524858">"تتعذّر المزامنة."</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="4884451152168188763">"تمت محاولة حذف مقدار كبير من محتوى <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
-    <string name="low_memory" product="tablet" msgid="6494019234102154896">"سعة تخزين الجهاز اللوحي ممتلئة! احذف بعض الملفات لإخلاء مساحة."</string>
-    <string name="low_memory" product="watch" msgid="4415914910770005166">"سعة تخزين المشاهدة ممتلئة! احذف بعض الملفات لتحرير مساحة."</string>
-    <string name="low_memory" product="tv" msgid="516619861191025923">"سعة تخزين التلفزيون ممتلئة. يمكنك حذف بعض الملفات لتوفير مساحة فارغة."</string>
-    <string name="low_memory" product="default" msgid="3475999286680000541">"سعة تخزين الهاتف ممتلئة. احذف بعض الملفات لإخلاء مساحة."</string>
+    <string name="low_memory" product="tablet" msgid="6494019234102154896">"مساحة تخزين الجهاز اللوحي ممتلئة! احذف بعض الملفات لإخلاء مساحة."</string>
+    <string name="low_memory" product="watch" msgid="4415914910770005166">"مساحة تخزين المشاهدة ممتلئة! احذف بعض الملفات لتحرير مساحة."</string>
+    <string name="low_memory" product="tv" msgid="516619861191025923">"مساحة تخزين التلفزيون ممتلئة. يمكنك حذف بعض الملفات لتوفير مساحة فارغة."</string>
+    <string name="low_memory" product="default" msgid="3475999286680000541">"مساحة تخزين الهاتف ممتلئة. احذف بعض الملفات لإخلاء مساحة."</string>
     <plurals name="ssl_ca_cert_warning" formatted="false" msgid="5106721205300213569">
       <item quantity="zero">تم تثبيت شهادة المرجع المصدق</item>
       <item quantity="two">تم تثبيت شهادتي المرجع المصدق</item>
@@ -304,6 +304,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"الميكروفون"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"تسجيل الصوت"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"‏هل تريد السماح لتطبيق &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; بتسجيل الصوت؟"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"التعرّف على النشاط"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"التعرّف على النشاط"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"‏هل تريد السماح للتطبيق &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; بالتعرّف على نشاطك البدني؟"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"الكاميرا"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"التقاط صور وتسجيل فيديو"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"‏هل تريد السماح لتطبيق &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; بالتقاط الصور وتسجيل الفيديو؟"</string>
@@ -430,14 +433,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"‏يمكن لهذا التطبيق معرفة موقعك من خلال مصادر الشبكات مثل أبراج الجوّال وشبكات Wi-Fi. ويجب تشغيل خدمات المواقع هذه وأن تكون متاحة على الجهاز اللوحي حتى يتمكن التطبيق من استخدامها."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"‏يمكن لهذا التطبيق معرفة موقعك من خلال مصادر الشبكات مثل أبراج الجوّال وشبكات Wi-Fi. ويجب تشغيل خدمات المواقع هذه وأن تكون متاحة على جهاز التلفزيون حتى يتمكن التطبيق من استخدامها."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"‏يمكن لهذا التطبيق معرفة موقعك من خلال مصادر الشبكات مثل أبراج الجوّال وشبكات Wi-Fi. ويجب تشغيل خدمات المواقع هذه وأن تكون متاحة على الهاتف حتى يتمكن التطبيق من استخدامها."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"الوصول إلى الموقع الجغرافي الدقيق في الخلفية"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"يمكن لهذا التطبيق معرفة موقعك الجغرافي بالضبط في أي وقت يعمل به في الخلفية. ويجب تفعيل خدمات الموقع الجغرافي هذه وأن تكون متاحة على الهاتف حتى يتمكن التطبيق من استخدامها. وقد يؤدي هذا إلى زيادة استهلاك طاقة البطارية."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"الوصول إلى الموقع الجغرافي في الخلفية"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"إذا تمّ منح إذن التطبيق هذا بالإضافة إلى الموقع الجغرافي التقريبي أو الدقيق، يمكن للتطبيق الوصول إلى الموقع الجغرافي أثناء تشغيله في الخلفية."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"تغيير إعداداتك الصوتية"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"للسماح للتطبيق بتعديل إعدادات الصوت العامة مثل مستوى الصوت وأي السماعات يتم استخدامها للاستماع."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"تسجيل الصوت"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"يمكن لهذا التطبيق تسجيل الصوت باستخدام الميكروفون في أي وقت."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"‏إرسال أوامر إلى شريحة SIM"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"‏السماح للتطبيق بإرسال أوامر إلى شريحة SIM. وهذا أمر بالغ الخطورة."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"التعرّف على النشاط البدني"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"يمكن لهذا التطبيق التعرّف على نشاطك البدني."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"التقاط صور وفيديوهات"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"يمكن لهذا التطبيق التقاط صور وتسجيل فيديوهات باستخدام الكاميرا في أي وقت."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"التحكم في الاهتزاز"</string>
@@ -530,6 +535,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"للسماح للتطبيق بتعديل مجموعة صورك."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"قراءة المواقع من مجموعة الوسائط التابعة لك"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"للسماح للتطبيق بقراءة المواقع من مجموعة الوسائط التابعة لك."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"يتطلَّب التطبيق <xliff:g id="APP">%s</xliff:g> المصادقة."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"معدّات المقاييس الحيوية غير متاحة."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"تم اكتشاف بصمة الإصبع بشكل جزئي؛ يرجى إعادة المحاولة."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"تعذرت معالجة بصمة الإصبع. يُرجى إعادة المحاولة."</string>
@@ -676,7 +682,7 @@
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"تعيين تشفير التخزين"</string>
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"يمكنك طلب تشفير بيانات التطبيق المخزنة."</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"إيقاف الكاميرات"</string>
-    <string name="policydesc_disableCamera" msgid="2306349042834754597">"يمكنك منح استخدام جميع كاميرات الجهاز."</string>
+    <string name="policydesc_disableCamera" msgid="2306349042834754597">"يمكنك منع استخدام جميع كاميرات الجهاز."</string>
     <string name="policylab_disableKeyguardFeatures" msgid="8552277871075367771">"إيقاف بعض ميزات قفل الشاشة"</string>
     <string name="policydesc_disableKeyguardFeatures" msgid="2044755691354158439">"منع استخدام بعض ميزات قفل الشاشة."</string>
   <string-array name="phoneTypes">
@@ -1173,7 +1179,7 @@
     <string name="view_flight_desc" msgid="3876322502674253506">"تتبُّع الرحلة الجوية المختارة"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"مساحة التخزين منخفضة"</string>
     <string name="low_internal_storage_view_text" msgid="6640505817617414371">"قد لا تعمل بعض وظائف النظام"</string>
-    <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"ليست هناك سعة تخزينية كافية للنظام. تأكد من أنه لديك مساحة خالية تبلغ ٢٥٠ ميغابايت وأعد التشغيل."</string>
+    <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"ليست هناك مساحة تخزين كافية للنظام. تأكد من أنه لديك مساحة خالية تبلغ ٢٥٠ ميغابايت وأعد التشغيل."</string>
     <string name="app_running_notification_title" msgid="8718335121060787914">"<xliff:g id="APP_NAME">%1$s</xliff:g> قيد التشغيل"</string>
     <string name="app_running_notification_text" msgid="1197581823314971177">"انقر للحصول على مزيد من المعلومات أو لإيقاف التطبيق."</string>
     <string name="ok" msgid="5970060430562524910">"حسنًا"</string>
@@ -1249,7 +1255,7 @@
     <string name="android_start_title" product="default" msgid="4536778526365907780">"جارٍ بدء تشغيل الهاتف…"</string>
     <string name="android_start_title" product="tablet" msgid="4929837533850340472">"جارٍ بدء تشغيل الجهاز اللوحي…"</string>
     <string name="android_start_title" product="device" msgid="7467484093260449437">"جارٍ بدء تشغيل الجهاز…"</string>
-    <string name="android_upgrading_fstrim" msgid="8036718871534640010">"جارٍ تحسين سعة التخزين."</string>
+    <string name="android_upgrading_fstrim" msgid="8036718871534640010">"جارٍ تحسين مساحة التخزين."</string>
     <string name="android_upgrading_notification_title" product="default" msgid="1511552415039349062">"جارٍ إنهاء تحديث النظام…"</string>
     <string name="app_upgrading_toast" msgid="3008139776215597053">"جارٍ ترقية <xliff:g id="APPLICATION">%1$s</xliff:g>…"</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"جارٍ تحسين التطبيق <xliff:g id="NUMBER_0">%1$d</xliff:g> من <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
@@ -1594,7 +1600,7 @@
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"المزيد من الخيارات"</string>
     <string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s، %2$s"</string>
     <string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s، %2$s، %3$s"</string>
-    <string name="storage_internal" msgid="3570990907910199483">"سعة التخزين المشتركة الداخلية"</string>
+    <string name="storage_internal" msgid="3570990907910199483">"مساحة التخزين المشتركة الداخلية"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"‏بطاقة SD"</string>
     <string name="storage_sd_card_label" msgid="6347111320774379257">"‏بطاقة SD من <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
     <string name="storage_usb_drive" msgid="6261899683292244209">"‏محرك أقراص USB"</string>
@@ -2016,7 +2022,7 @@
     <string name="app_category_news" msgid="7496506240743986873">"الأخبار والمجلات"</string>
     <string name="app_category_maps" msgid="5878491404538024367">"الخرائط والتنقل"</string>
     <string name="app_category_productivity" msgid="3742083261781538852">"الإنتاجية"</string>
-    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"سعة التخزين للجهاز"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="3295871267414816228">"مساحة التخزين للجهاز"</string>
     <string name="adb_debugging_notification_channel_tv" msgid="5537766997350092316">"‏تصحيح أخطاء USB"</string>
     <string name="time_picker_hour_label" msgid="2979075098868106450">"ساعة"</string>
     <string name="time_picker_minute_label" msgid="5168864173796598399">"دقيقة"</string>
@@ -2037,14 +2043,14 @@
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> اقتراح للملء التلقائي</item>
       <item quantity="one">اقتراح واحد للملء التلقائي</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"‏هل تريد الحفظ في &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;؟"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"‏هل تريد حفظ <xliff:g id="TYPE">%1$s</xliff:g> في &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;؟"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"‏هل تريد حفظ <xliff:g id="TYPE_0">%1$s</xliff:g> و<xliff:g id="TYPE_1">%2$s</xliff:g> في &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;؟"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"‏هل تريد حفظ <xliff:g id="TYPE_0">%1$s</xliff:g> و<xliff:g id="TYPE_1">%2$s</xliff:g> و<xliff:g id="TYPE_2">%3$s</xliff:g> في &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;؟"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"‏هل تريد التعديل إلى &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;؟"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"‏هل تريد تعديل <xliff:g id="TYPE">%1$s</xliff:g> إلى &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;؟"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"‏هل تريد تعديل <xliff:g id="TYPE_0">%1$s</xliff:g> و<xliff:g id="TYPE_1">%2$s</xliff:g> إلى &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;؟"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"‏هل تريد تعديل <xliff:g id="TYPE_0">%1$s</xliff:g> و<xliff:g id="TYPE_1">%2$s</xliff:g> و<xliff:g id="TYPE_2">%3$s</xliff:g> إلى &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;؟"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"هل تريد الحفظ في "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"؟"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"هل تريد حفظ <xliff:g id="TYPE">%1$s</xliff:g> في "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"؟"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"هل تريد حفظ <xliff:g id="TYPE_0">%1$s</xliff:g> و<xliff:g id="TYPE_1">%2$s</xliff:g> في "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"؟"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"هل تريد حفظ <xliff:g id="TYPE_0">%1$s</xliff:g> و<xliff:g id="TYPE_1">%2$s</xliff:g> و<xliff:g id="TYPE_2">%3$s</xliff:g> في "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"؟"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"هل تريد التحديث في "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"؟"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"هل تريد تحديث <xliff:g id="TYPE">%1$s</xliff:g> في "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"؟"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"هل تريد تحديث <xliff:g id="TYPE_0">%1$s</xliff:g> و<xliff:g id="TYPE_1">%2$s</xliff:g> في "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"؟"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"هل تريد تحديث هذه العناصر في "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g> و<xliff:g id="TYPE_1">%2$s</xliff:g> و<xliff:g id="TYPE_2">%3$s</xliff:g>؟"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"حفظ"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"لا، شكرًا"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"تعديل"</string>
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index 5a0a7ec..4df7643 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"মাইক্ৰ\'ফ\'ন"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"অডিঅ\' ৰেকর্ড কৰিব পাৰে"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক অডিঅ\' ৰেকৰ্ড কৰিবলৈ অনুমতি দিবনে?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"কার্যকলাপ চিনাক্তকৰণ"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"কাৰ্যকলাপ চিনাক্ত কৰক"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক নিজৰ শাৰীৰিক কাৰ্যকলাপ চিনাক্ত কৰাৰ অনুমতি দিবনে?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"কেমেৰা"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"ফট\' তুলিব আৰু ভিডিঅ\' ৰেকৰ্ড কৰিব পাৰে"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ক ছবি তুলিবলৈ আৰু ভিডিঅ\' ৰেকৰ্ড কৰিবলৈ অনুমতি দিবনে?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"চেল টাৱাৰ আৰু ৱাই-ফাই নেটৱর্কৰ দৰে নেটৱর্কৰ উৎসসমূহক ভিত্তি কৰি এই এপটোৱে আপোনাৰ অৱস্থান নিৰ্ণয় কৰিব পাৰে। এই অৱস্থানৰ সেৱাসমূহ অন হৈ থাকিলে আৰু আপোনাৰ টেবলেটটোত উপলব্ধ হ\'লেহে এপটোৱে সেইবোৰ ব্যৱহাৰ কৰিবলৈ সক্ষম হ\'ব।"</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"চেল টাৱাৰ আৰু ৱাই-ফাই নেটৱর্কৰ দৰে নেটৱর্কৰ উৎসসমূহক ভিত্তি কৰি এই এপটোৱে আপোনাৰ অৱস্থান নিৰ্ণয় কৰিব পাৰে। এই অৱস্থানৰ সেৱাসমূহ অন হৈ থাকিলে আৰু আপোনাৰ টিভিত উপলব্ধ হ\'লেহে এপটোৱে সেইবোৰ ব্যৱহাৰ কৰিবলৈ সক্ষম হ\'ব।"</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"এই এপটোৱে ম\'বাইলৰ টাৱাৰ আৰু ৱাই-ফাইৰ নেটৱৰ্ক আদিৰ দৰে নেটৱৰ্কৰ উৎসসমূহক ভিত্তি কৰি আপোনাৰ অৱস্থান চিনাক্ত কৰিব পাৰে। সেই অৱস্থান সেৱাসমূহ আপোনাৰ ফ\'নত সক্ষম অৱস্থাত থাকিলেহে এপটোৱে সেইবোৰ ব্যৱহাৰ কৰিব পাৰিব।"</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"নেপথ্যত সঠিক অৱস্থান পাব পাৰে"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"এই এপটোৱে যেতিয়া ই নেপথ্যত চলি থাকে তেতিয়া আপোনাৰ সঠিক অৱস্থান নিৰ্ণয় কৰিব পাৰে। এপটোৱে ব্যৱহাৰ কৰিব পৰাকৈ এই অৱস্থান সেৱাসমূহ অন হৈ থাকিবই লাগিব আৰু আপোনাৰ ফ\'নত উপলব্ধ হ\'ব লাগিব। ইয়াৰ ফলত বেটাৰিৰ খৰচ বাঢ়িব পাৰে।"</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"নেপথ্যত চলি থকা সময়ত অৱস্থানৰ এক্সেছ"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"ইয়াৰ উপৰিও যদি ইয়াক আনুমানিক বা সঠিক অৱস্থানৰ এক্সেছ দিয়া হয়, তেন্তে উক্ত এপে নেপথ্যত চলি থকাৰ সময়ত অৱস্থানৰ এক্সেছ লাভ কৰিব পাৰে।"</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"আপোনাৰ অডিঅ\' ছেটিংসমূহ সলনি কৰক"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"এপটোক ভলিউমৰ দৰে গ্ল\'বেল অডিঅ\' ছেটিংসমূহ যাৰ স্পীকাৰক আউটপুটৰ বাবে ব্যৱহাৰ হয় তাক সলনি কৰিবলৈ অনুমতি দিয়ে৷"</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"অডিঅ\' ৰেকর্ড কৰক"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"এই এপটোৱে যিকোনো সময়তে মাইক্ৰ\'ফ\'ন ব্যৱহাৰ কৰি অডিঅ\' ৰেকৰ্ড কৰিব পাৰে।"</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"ছিমলৈ নিৰ্দেশ পঠিয়াব পাৰে"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"ছিমলৈ নিৰ্দেশসমূহ প্ৰেৰণ কৰিবলৈ এপক অনুমতি দিয়ে। ই অতি ক্ষতিকাৰক।"</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"শাৰীৰিক কাৰ্যকলাপ চিনাক্ত কৰক"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"এই এপটোৱে আপোনাৰ শাৰীৰিক কাৰ্যকলাপ চিনাক্ত কৰিব পাৰে।"</string>
     <string name="permlab_camera" msgid="3616391919559751192">"ফট\' তোলা আৰু ভিডিঅ\' ৰেকৰ্ড কৰা"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"এই এপে যিকোনো সময়তে কেমেৰা ব্যৱহাৰ কৰি ফট\' তুলিব আৰু ভিডিঅ\' ৰেকর্ড কৰিব পাৰে।"</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"কম্পন নিয়ন্ত্ৰণ কৰক"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"এপক আপোনাৰ ফট’ সংগ্ৰহ সালসলনি কৰিবলৈ দিয়ে।"</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"আপোনাৰ মিডিয়া সংগ্ৰহৰ অৱস্থান পঢ়িবলৈ"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"এপক আপোনাৰ মিডিয়া সংগ্ৰহৰ অৱস্থান পঢ়িবলৈ দিয়ে।"</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"<xliff:g id="APP">%s</xliff:g> এপে বিশ্বাসযোগ্যতাৰ প্ৰমাণ কৰিব বিচাৰে।"</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"বায়োমেট্ৰিক হাৰ্ডৱেৰ উপলব্ধ নহয়"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"ফিংগাৰপ্ৰিণ্ট আংশিকভাৱে চিনাক্ত কৰা হৈছে। অনুগ্ৰহ কৰি আকৌ চেষ্টা কৰক৷"</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"ফিগাৰপ্ৰিণ্টৰ প্ৰক্ৰিয়া সম্পাদন কৰিবপৰা নগ\'ল। অনুগ্ৰহ কৰি আকৌ চেষ্টা কৰক৷"</string>
@@ -1898,14 +1904,14 @@
       <item quantity="one"><xliff:g id="COUNT">%1$s</xliff:g>টা স্বয়ংপূৰ্তি পৰামৰ্শ</item>
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g>টা স্বয়ংপূৰ্তি পৰামৰ্শ</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;ত ছেভ কৰিবনে?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"<xliff:g id="TYPE">%1$s</xliff:g>ক &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;ত ছেভ কৰিবনে?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"<xliff:g id="TYPE_0">%1$s</xliff:g> আৰু <xliff:g id="TYPE_1">%2$s</xliff:g>ক &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;ত ছেভ কৰিবনে?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, আৰু <xliff:g id="TYPE_2">%3$s</xliff:g>ক &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;ত ছেভ কৰিবনে?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"আপডে’ট কৰি &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; বনাবনে?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"<xliff:g id="TYPE">%1$s</xliff:g>ক আপডে’ট কৰি &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; বনাবনে?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"<xliff:g id="TYPE_0">%1$s</xliff:g> আৰু <xliff:g id="TYPE_1">%2$s</xliff:g>ক আপডে’ট কৰি &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; বনাবনে?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> আৰু <xliff:g id="TYPE_2">%3$s</xliff:g>ক আপডে’ট কৰি to &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; বনাবনে?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"ত ছেভ কৰিবনে?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594"><b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"ত <xliff:g id="TYPE">%1$s</xliff:g>ক ছেভ কৰিবনে?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432"><b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"ত <xliff:g id="TYPE_0">%1$s</xliff:g> আৰু <xliff:g id="TYPE_1">%2$s</xliff:g>ক ছেভ কৰিবনে?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555"><b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"ত <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> আৰু <xliff:g id="TYPE_2">%3$s</xliff:g>ক ছেভ কৰিবনে?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"ত আপডে\'ট কৰিবনে?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233"><b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"ত <xliff:g id="TYPE">%1$s</xliff:g> আপডে\'ট কৰিবনে?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484"><b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"ত <xliff:g id="TYPE_0">%1$s</xliff:g> আৰু <xliff:g id="TYPE_1">%2$s</xliff:g> আপডে\'ট কৰিবনে?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"এই তথ্যবোৰ "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> আৰু <xliff:g id="TYPE_2">%3$s</xliff:g>ত আপডে\'ট কৰিবনে ?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"ছেভ কৰক"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"নালাগে, ধন্যবাদ"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"আপডে’ট কৰক"</string>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index af65bbb..4bb6c1f 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Mikrofon"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"səsi qeydə alın"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tətbiqinə səs yazmaq icazəsi verilsin?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"Fəaliyyətin tanınması"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"fəaliyyəti tanıyın"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tətbiqinin fiziki fəaliyyətinizi tanımasına icazə verilsin?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Kamera"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"şəkil çəkin və video yazın"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tətbiqinə şəkil və video çəkmək icazəsi verilsin?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Bu tətbiq mobil qüllələr və Wi-Fi şəbəkələri kimi şəbəkə mənbələrinin əassında əkanınızı əldə edə bilər. Bu məkan xidmətləri aktiv edilməlidir və planşetdə tətbiq tərəfindən istifadə üçün əlçatan olmalıdır."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Bu tətbiq mobil qüllələr və Wi-Fi şəbəkələri kimi şəbəkə mənbələrinin əassında əkanınızı əldə edə bilər. Bu məkan xidmətləri aktiv edilməlidir və TV\'də tətbiq tərəfindən istifadə üçün əlçatan olmalıdır."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Bu tətbiq mobil qüllələr və Wi-Fi şəbəkələri kimi şəbəkə mənbələrinin əassında əkanınızı əldə edə bilər. Bu məkan xidmətləri aktiv edilməlidir və telefonda tətbiq tərəfindən istifadə üçün əlçatan olmalıdır."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"arxa fonda dəqiq məkana daxil olun"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"Bu tətbiq istənilən zaman arxa fonda olduqda dəqiq məkanınızı əldə edə bilər. Tətbiqin bunlardan istifadə etməsi üçün bu məkan xidmətləri aktiv edilməlidir və telefonda əlçatan olmalıdır. Bu, batareya sərfiyyatını artıra bilər."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"arxa fonda məkan girişi"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Bu, təqribi və ya dəqiq məkan girişinə əlavə olaraq verilərsə, tətbiq arxa fonda işləyərkən məkana daxil ola bilər."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"audio ayarlarınızı dəyişir"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Tətbiqə səs və hansı spikerin çıxış üçün istifadə olunduğu kimi qlobal səs ayarlarını dəyişdirməyə imkan verir."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"səs yaz"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"Bu tətbiq istədiyiniz zaman mikrofonu istifadə edərək audio qeyd edə bilər."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"əmrləri SIM\'ə göndərin"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Tətbiqə SIM-ə əmrlər göndərməyə imkan verir. Bu, çox təhlükəlidir."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"fiziki fəaliyyəti tanıyın"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"Bu tətbiq fiziki fəaliyyətinizi tanıya bilər."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"şəkil və video çəkmək"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"Bu tətbiq istədiyiniz zaman kameranı istifadə edərək şəkil çəkə və video qeydə ala bilər."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"vibrasiyaya nəzarət edir"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Tətbiqin foto kolleksiyanıza düzəliş etməsinə icazə verir."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"media kolleksiyanızdan məkanları oxuyun"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Tətbiqin media kolleksiyanızdan məkanları oxumasına icazə verin."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"<xliff:g id="APP">%s</xliff:g> doğrulamaq istəyir."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Biometrik proqram əlçatan deyil"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Barmaq qismən müəyyən olundu. Lütfən, yenidən cəhd edin."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Barmaq izi tanınmadı. Lütfən, yenidən cəhd edin."</string>
@@ -1897,14 +1903,14 @@
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> avtomatik doldurma təklifi</item>
       <item quantity="one">Bir avtomatik doldurma təklifi</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; etiketində yadda saxlansın?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"<xliff:g id="TYPE">%1$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;b&gt; etiketində yadda saxlansın?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"<xliff:g id="TYPE_0">%1$s</xliff:g> və <xliff:g id="TYPE_1">%2$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; etiketində yadda saxlansın?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> və <xliff:g id="TYPE_2">%3$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; etiketində yadda saxlansın?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; etiketində yenilənsin?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"<xliff:g id="TYPE">%1$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;b&gt; etiketində yenilənsin?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"<xliff:g id="TYPE_0">%1$s</xliff:g> və <xliff:g id="TYPE_1">%2$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; etiketində yenilənsin?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> və <xliff:g id="TYPE_2">%3$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; etiketində yenilənsin?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" ünvanında yadda saxlansın?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"<xliff:g id="TYPE">%1$s</xliff:g> "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" ünvanında yadda saxlansın?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"<xliff:g id="TYPE_0">%1$s</xliff:g> və <xliff:g id="TYPE_1">%2$s</xliff:g> "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" ünvanında yadda saxlansın?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> və <xliff:g id="TYPE_2">%3$s</xliff:g> "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" ünvanında yadda saxlansın?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" ünvanında yenilənsin?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"<xliff:g id="TYPE">%1$s</xliff:g> "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" ünvanında yenilənsin?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"<xliff:g id="TYPE_0">%1$s</xliff:g> və <xliff:g id="TYPE_1">%2$s</xliff:g> "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" ünvanında yenilənsin?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"Bu elementlər "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" ünvanında yenilənsin: <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> və <xliff:g id="TYPE_2">%3$s</xliff:g> ?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Yadda saxlayın"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Xeyr, çox sağ olun"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"Yeniləyin"</string>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 805082a..e650f2d 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -295,6 +295,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Mikrofon"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"snima zvuk"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"Želite li da omogućite da &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; snima zvuk?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"Prepoznavanje aktivnosti"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"prepoznavanje aktivnosti"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"Želite li da omogućite da &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; prepoznaje fizičke aktivnosti?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Kamera"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"snima slike i video"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"Želite li da omogućite da &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; snima slike i video snimke?"</string>
@@ -421,14 +424,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Ova aplikacija može da pristupi vašoj lokaciji pomoću izvora mreže, kao što su mobilni predajnici i Wi-Fi mreže. Ove usluge lokacije moraju da budu uključene i dostupne na tabletu da bi aplikacija mogla da ih koristi."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Ova aplikacija može da pristupi vašoj lokaciji pomoću izvora mreže, kao što su mobilni predajnici i Wi-Fi mreže. Ove usluge lokacije moraju da budu uključene i dostupne na TV-u da bi aplikacija mogla da ih koristi."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Ova aplikacija može da pristupi vašoj lokaciji pomoću izvora mreže, kao što su mobilni predajnici i Wi-Fi mreže. Ove usluge lokacije moraju da budu uključene i dostupne na telefonu da bi aplikacija mogla da ih koristi."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"pristup preciznoj lokaciji u pozadini"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"Ova aplikacija može da odredi vašu tačnu lokaciju svaki put kada radi u pozadini. Ove usluge lokacije moraju da budu uključene i dostupne na telefonu da bi aplikacija mogla da ih koristi. To može da poveća potrošnju baterije."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"pristup lokaciji u pozadini"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Ako se pored približnog ili preciznog pristupa lokacija odobri i ovaj, aplikacija može da pristupa lokaciji dok je pokrenuta u pozadini."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"promena audio podešavanja"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Dozvoljava aplikaciji da menja globalna audio podešavanja kao što su jačina zvuka i izbor zvučnika koji se koristi kao izlaz."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"snimanje audio zapisa"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"Ova aplikacija može da snima zvuk pomoću mikrofona u bilo kom trenutku."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"slanje komandi na SIM"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Omogućava aplikaciji da šalje komande SIM kartici. To je veoma opasno."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"prepoznavanje fizičkih aktivnosti"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"Ova aplikacija može da prepozna fizičke aktivnosti."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"snimanje fotografija i video snimaka"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"Ova aplikacija može da snima fotografije i video snimke pomoću kamere u bilo kom trenutku."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"kontrola vibracije"</string>
@@ -521,6 +526,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Dozvoljava aplikaciji da menja kolekciju slika."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"čitanje lokacija iz medijske kolekcije"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Dozvoljava aplikaciji da čita lokacije iz medijske kolekcije."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"Aplikacija <xliff:g id="APP">%s</xliff:g> želi da potvrdi vaš identitet."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Biometrijski hardver nije dostupan"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Otkriven je delimični otisak prsta. Probajte ponovo."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Nije uspela obrada otiska prsta. Probajte ponovo."</string>
@@ -1932,14 +1938,14 @@
       <item quantity="few"><xliff:g id="COUNT">%1$s</xliff:g> automatski popunjena predloga</item>
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> automatski popunjenih predloga</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"Želite li da sačuvate u: &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Želite li da sačuvate stavku <xliff:g id="TYPE">%1$s</xliff:g> u: &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Želite li da sačuvate stavke <xliff:g id="TYPE_0">%1$s</xliff:g> i <xliff:g id="TYPE_1">%2$s</xliff:g> u: &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Želite li da sačuvate stavke <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> i <xliff:g id="TYPE_2">%3$s</xliff:g> u: &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"Želite li da ažurirate na &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Želite li da ažurirate stavku <xliff:g id="TYPE">%1$s</xliff:g> na &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Želite li da ažurirate stavke <xliff:g id="TYPE_0">%1$s</xliff:g> i <xliff:g id="TYPE_1">%2$s</xliff:g> na &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Želite li da ažurirate stavke <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> i <xliff:g id="TYPE_2">%3$s</xliff:g> na &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"Želite li da sačuvate u usluzi "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"Želite li da sačuvate stavku <xliff:g id="TYPE">%1$s</xliff:g> u usluzi "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"Želite li da sačuvate stavke <xliff:g id="TYPE_0">%1$s</xliff:g> i <xliff:g id="TYPE_1">%2$s</xliff:g> u usluzi "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"Želite li da sačuvate stavke <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> i <xliff:g id="TYPE_2">%3$s</xliff:g> u usluzi "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"Želite li da ažurirate u usluzi "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"Želite li da ažurirate stavku <xliff:g id="TYPE">%1$s</xliff:g> u usluzi "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"Želite li da ažurirate stavke <xliff:g id="TYPE_0">%1$s</xliff:g> i <xliff:g id="TYPE_1">%2$s</xliff:g> u usluzi "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"Želite li da ažurirate ove stavke u usluzi "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> i <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Sačuvaj"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Ne, hvala"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"Ažuriraj"</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 7692220..db75d1d 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -298,6 +298,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Мікрафон"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"запісваць аўдыя"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"Дазволіць праграме &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; запісваць аўдыя?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"Распазнаванне актыўнасці"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"распазнаваць актыўнасць"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"Дазволіць праграме &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; распазнаваць фізічную актыўнасць?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Камера"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"рабіць фатаздымкі і запісваць відэа"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"Дазволіць праграме &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; рабіць фота і запісваць відэа?"</string>
@@ -424,14 +427,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Гэта праграма можа атрымліваць звесткі пра ваша месцазнаходжанне на падставе даных сеткавых крыніц, такіх як вышкі сотавай сувязі і сеткі Wi-Fi. Гэтыя сэрвісы вызначэння месцазнаходжання павінны быць уключаны i даступныя на вашым планшэце, каб праграма магла іх выкарыстоўваць."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Гэта праграма можа атрымліваць звесткі пра ваша месцазнаходжанне на падставе даных сеткавых крыніц, такіх як вышкі сотавай сувязі і сеткі Wi-Fi. Гэтыя сэрвісы вызначэння месцазнаходжання павінны быць уключаны i даступныя на вашым тэлевізары, каб праграма магла іх выкарыстоўваць."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Гэта праграма можа атрымліваць звесткі пра ваша месцазнаходжанне на падставе даных сеткавых крыніц, такіх як вышкі сотавай сувязі і сеткі Wi-Fi. Гэтыя сэрвісы вызначэння месцазнаходжання павінны быць уключаны i даступныя на вашым тэлефоне, каб праграма магла іх выкарыстоўваць."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"доступ да дакладнага месцазнаходжання ў фонавым рэжыме"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"Гэта праграма можа атрымліваць звесткі пра ваша дакладнае месцазнаходжанне ў любы час, калі яна працуе ў фонавым рэжыме. Службы геалакацыі павінны быць уключаны і даступныя на вашым тэлефоне, каб праграма магла імі карыстацца. Гэта можа павялічыць спажыванне зараду акумулятара."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"доступ да вызначэння месцазнаходжання ў фонавым рэжыме"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Акрамя доступу да прыкладнага ці дакладнага месцазнаходжання праграма можа мець доступ да вызначэння геалакацыі ў фонавым рэжыме працы. На гэта патрабуецца дазвол."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"змяняць налады аудыё"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Дазваляе прыкладанням змяняць глабальныя налады гуку, такія як моц і тое, што дынамік выкарыстоўваецца для выхаду."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"запісваць аўдыё"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"Гэта праграма можа у любы час запісваць аўдыя, выкарыстоўваючы мікрафон."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"адпраўляць каманды на SIM-карту"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Дазваляе праграме адпраўляць каманды SIM-карце. Гэта вельмі небяспечна."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"распазнаваць фізічную актыўнасць"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"Гэта праграма можа распазнаваць фізічную актыўнасць."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"рабіць фатаграфіі і відэа"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"Гэта праграма можа рабіць фота і запісваць відэа з дапамогай камеры ў любы час."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"кіраванне вібрацыяй"</string>
@@ -524,6 +529,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Праграма зможа змяняць фотакалекцыю."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"паказваць месцазнаходжанне ў калекцыі мультымедыя"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Праграма зможа паказваць месцазнаходжанне ў калекцыі мультымедыя."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"Праграма \"<xliff:g id="APP">%s</xliff:g>\" патрабуе аўтэнтыфікацыі."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Біяметрычнае абсталяванне недаступнае"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Выяўлена частка адбіткаў пальцаў. Паспрабуйце яшчэ раз."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Не атрымалася апрацаваць адбітак пальца. Паспрабуйце яшчэ раз."</string>
@@ -1967,14 +1973,14 @@
       <item quantity="many"><xliff:g id="COUNT">%1$s</xliff:g> прапаноў аўтазапаўнення</item>
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> прапановы аўтазапаўнення</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"Захаваць у &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Захаваць <xliff:g id="TYPE">%1$s</xliff:g> у &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Захаваць <xliff:g id="TYPE_0">%1$s</xliff:g> і <xliff:g id="TYPE_1">%2$s</xliff:g> у &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Захаваць <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> і <xliff:g id="TYPE_2">%3$s</xliff:g> у &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"Абнавіць у &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Абнавіць <xliff:g id="TYPE">%1$s</xliff:g> у &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Абнавіць <xliff:g id="TYPE_0">%1$s</xliff:g> і <xliff:g id="TYPE_1">%2$s</xliff:g> у &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Абнавіць <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> і <xliff:g id="TYPE_2">%3$s</xliff:g> у &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"Захаваць у сэрвісе "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"Захаваць даныя \"<xliff:g id="TYPE">%1$s</xliff:g>\" у сэрвісе "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"Захаваць даныя \"<xliff:g id="TYPE_0">%1$s</xliff:g>\" і \"<xliff:g id="TYPE_1">%2$s</xliff:g>\" у сэрвісе "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"Захаваць даныя \"<xliff:g id="TYPE_0">%1$s</xliff:g>\", \"<xliff:g id="TYPE_1">%2$s</xliff:g>\" і \"<xliff:g id="TYPE_2">%3$s</xliff:g>\" у сэрвісе "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"Абнавіць у сэрвісе "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"Абнавіць даныя \"<xliff:g id="TYPE">%1$s</xliff:g>\" у сэрвісе "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"Абнавіць даныя \"<xliff:g id="TYPE_0">%1$s</xliff:g>\" і \"<xliff:g id="TYPE_1">%2$s</xliff:g>\" у сэрвісе "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"Абнавіць наступныя элементы ў сэрвісе "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> і <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Захаваць"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Не, дзякуй"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"Абнавіць"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 33c4898..e2e5bd4 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Микрофон"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"записва звук"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"Да се разреши ли на &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да записва аудио?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"Разпознаване на активността"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"разпознаване на активността"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"Да се разреши ли на &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да разпознава физическата ви активност?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Камера"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"да прави снимки и записва видеоклипове"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"Да се разреши ли на &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да прави снимки и да записва видеоклипове?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Приложението може да получава данни за местоположението ви въз основа на мрежови източници, като клетъчни кули и Wi-Fi. Тези услуги за местоположение трябва да са включени и налице на таблета ви, за да могат да се използват от приложението."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Приложението може да получава данни за местоположението ви въз основа на мрежови източници, като клетъчни кули и Wi-Fi. Тези услуги за местоположение трябва да са включени и налице на телевизора ви, за да могат да се използват от приложението."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Приложението може да получава данни за местоположението ви въз основа на мрежови източници, като клетъчни кули и Wi-Fi. Тези услуги за местоположение трябва да са включени и налице на телефона ви, за да могат да се използват от приложението."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"достъп до точното местоположение на заден план"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"Приложението може да получава данни за точното ви местоположение по всяко време, когато работи на заден план. Тези услуги за местоположение трябва да са включени и налице на телефона ви, за да могат да се използват от приложението. Това може да увеличи потреблението на батерията."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"достъп до местоположението на заден план"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Ако разрешението бъде предоставено в допълнение към достъпа до приблизителното или точното местоположение, приложението може да осъществява достъп до местоположението, докато се изпълнява на заден план."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"промяна на настройките ви за звука"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Разрешава на приложението да променя глобалните настройки за звука, като например силата и това, кой високоговорител се използва за изход."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"записва звук"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"Това приложение може по всяко време да записва звук посредством микрофона."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"изпращане на команди до SIM картата"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Разрешава на приложението да изпраща команди до SIM картата. Това е много опасно."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"разпознаване на физическата активност"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"Това приложение може да разпознава физическата ви активност."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"правене на снимки и видеоклипове"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"Това приложение може по всяко време да прави снимки и да записва видеоклипове посредством камерата."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"контролиране на вибрирането"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Разрешава на приложението да променя колекцията ви от снимки."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"да чете местоположенията от мултимедийната ви колекция"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Разрешава на приложението да чете местоположенията от мултимедийната ви колекция."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"Приложението <xliff:g id="APP">%s</xliff:g> изисква удостоверяване."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Биометричният хардуер не е налице"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Открит е частичен отпечатък. Моля, опитайте отново."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Отпечатъкът не можа да се обработи. Моля, опитайте отново."</string>
@@ -1897,14 +1903,14 @@
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> предложения за автоматично попълване</item>
       <item quantity="one">1 предложение за автоматично попълване</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"Да се запази ли в/ъв &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"<xliff:g id="TYPE">%1$s</xliff:g> да се запази ли в/ъв &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"<xliff:g id="TYPE_0">%1$s</xliff:g> и <xliff:g id="TYPE_1">%2$s</xliff:g> да се запазят ли в/ъв &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> и <xliff:g id="TYPE_2">%3$s</xliff:g> да се запазят ли в/ъв &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"Да се актуализира ли в(ъв) &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"<xliff:g id="TYPE">%1$s</xliff:g> да се актуализира ли в(ъв) &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"<xliff:g id="TYPE_0">%1$s</xliff:g> и <xliff:g id="TYPE_1">%2$s</xliff:g> да се актуализират ли в(ъв) &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> и <xliff:g id="TYPE_2">%3$s</xliff:g> да се актуализират ли в(ъв) &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"Искате ли да запазите в(ъв) "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"Искате ли да запазите <xliff:g id="TYPE">%1$s</xliff:g> в(ъв) "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"Искате ли да запазите <xliff:g id="TYPE_0">%1$s</xliff:g> и <xliff:g id="TYPE_1">%2$s</xliff:g> в(ъв) "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"Искате ли да запазите <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> и <xliff:g id="TYPE_2">%3$s</xliff:g> в(ъв) "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"Искате ли да актуализирате в(ъв) "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"Искате ли да актуализирате <xliff:g id="TYPE">%1$s</xliff:g> в(ъв) "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"Искате ли да актуализирате <xliff:g id="TYPE_0">%1$s</xliff:g> и <xliff:g id="TYPE_1">%2$s</xliff:g> в(ъв) "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"Искате ли да актуализирате тези елементи в(ъв) "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> и <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Запазване"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Не, благодаря"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"Актуализиране"</string>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index f0787b4..0122c6c 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"মাইক্রোফোন"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"অডিও রেকর্ড"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-কে অডিও রেকর্ড করতে দেবেন?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"অ্যাক্টিভিটি শনাক্তকরণ"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"অ্যাক্টিভিটি শনাক্ত করুন"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; কে আপনার শারীরিক অ্যাক্টিভিটি শনাক্ত করার অনুমতি দেবেন?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"ক্যামেরা"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"ছবি তোলা এবং ভিডিও রেকর্ড"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-কে ফটো তুলতে এবং ভিডিও রেকর্ড করতে দেবেন?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"মোবাইল টাওয়ার এবং ওয়াই-ফাই নেটওয়ার্কগুলির মত নেটওয়ার্ক উৎসগুলির উপর ভিত্তি করে এই অ্যাপটি আপনার লোকেশন শনাক্ত করতে পারে৷ এই লোকেশন পরিষেবাগুলি অবশ্যই চালু রাখতে হবে এবং অ্যাপটি যাতে সেগুলি ব্যবহার করতে পারে সেইজন্য সেগুলিকে আপনার ট্যাবলেটে উপলব্ধ করে রাখতে হবে৷"</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"মোবাইল টাওয়ার এবং ওয়াই-ফাই নেটওয়ার্কগুলির মত নেটওয়ার্কের উৎসগুলির উপর ভিত্তি করে এই অ্যাপটি আপনার লোকেশন শনাক্ত করতে পারে৷ এই লোকেশন পরিষেবাগুলি অবশ্যই চালু রাখতে হবে এবং অ্যাপটি যাতে সেগুলি ব্যবহার করতে পারে সেজন্য সেগুলিকে আপনার টিভিতে উপলব্ধ করে রাখতে হবে৷"</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"মোবাইল টাওয়ার এবং ওয়াই-ফাই নেটওয়ার্কগুলির মত নেটওয়ার্ক উৎসগুলির উপর ভিত্তি করে এই অ্যাপটি আপনার লোকেশন শনাক্ত করতে পারে৷ এই লোকেশন পরিষেবাগুলি অবশ্যই চালু রাখতে হবে এবং অ্যাপটি যাতে সেগুলি ব্যবহার করতে পারে সেজন্য সেগুলিকে আপনার ফোনে উপলব্ধ করে রাখতে হবে৷"</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"ব্যাকগ্রাউন্ডে চলতে থাকলে আপনার যথাযথ লোকেশন অ্যাক্সেস করা"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"এই অ্যাপটি ব্যাকগ্রাউন্ডে চলতে থাকলে যেকোনও সময়ে আপনার যথাযথ লোকেশন জানতে পারবে। এই লোকেশন পরিষেবাগুলি অবশ্যই চালু রাখতে হবে এবং আপনার ফোনে সেগুলি উপলভ্য থাকতে হবে যাতে অ্যাপটি সেগুলি ব্যবহার করতে পারে। এর জন্য অতিরিক্ত ব্যাটারি খরচ হতে পারে।"</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"ব্যাকগ্রাউন্ডে লোকেশন অ্যাক্সেস করা"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"আনুমানিক বা একদম যথাযথ লোকেশন অ্যাক্সেস করার অনুমতি দেওয়া হলে এই অ্যাপটি ব্যাকগ্রাউন্ডে চালু থাকাকালীন আপনার লোকেশন অ্যাক্সেস করতে পারবে।"</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"আপনার অডিও সেটিংস পরিবর্তন করে"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"ভলিউম এবং যেখানে স্পিকার আউটপুট হিসাবে ব্যবহৃত হয় সেই সব ক্ষেত্রে গ্লোবাল অডিও সেটিংসের সংশোধন করতে অ্যাপ্লিকেশনটিকে মঞ্জুর করে৷"</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"অডিও রেকর্ড"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"এই অ্যাপটি মাইক্রোফোন ব্যবহার করে যে কোনো সময় অডিও রেকর্ড করতে পারে৷"</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"সিম এ আদেশগুলি পাঠান"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"অ্যাপ্লিকেশানটিকে সিম কার্ডে কমান্ডগুলি পাঠানোর অনুমতি দেয়৷ এটি খুবই বিপজ্জনক৷"</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"শারীরিক অ্যাক্টিভিটি শনাক্ত করুন"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"এই অ্যাপ আপনার শারীরিক অ্যাক্টিভিটি শনাক্ত করতে পারবে।"</string>
     <string name="permlab_camera" msgid="3616391919559751192">"ছবি এবং ভিডিও তোলে"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"এই অ্যাপটি যে কোনো সময় ক্যামেরা ব্যবহার করে ছবি তুলতে বা ভিডিও রেকর্ড করতে পারে৷"</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"ভাইব্রেশন নিয়ন্ত্রণ করুন"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"অ্যাপকে আপনার ফটো সংগ্রহ পরিবর্তন করার অনুমতি দিন।"</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"ডিয়া সংগ্রহ থেকে লোকেশন দেখতে দিন"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"আপনার মিডিয়া সংগ্রহ থেকে লোকেশন দেখতে অ্যাপকে অনুমতি দিন।"</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"<xliff:g id="APP">%s</xliff:g> অ্যাপ্লিকেশন যাচাই করতে চাইছে।"</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"বায়োমেট্রিক হার্ডওয়্যার পাওয়া যাবে না"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"আঙ্গুলের ছাপ আংশিক শনাক্ত করা হয়েছে৷ অনুগ্রহ করে আবার চেষ্টা করুন৷"</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"আঙ্গুলের ছাপ প্রক্রিয়া করা যায়নি৷ অনুগ্রহ করে আবার চেষ্টা করুন৷"</string>
@@ -648,7 +654,7 @@
     <string name="policylab_resetPassword" msgid="4934707632423915395">"স্ক্রিন লক পরিবর্তন করুন"</string>
     <string name="policydesc_resetPassword" msgid="1278323891710619128">"স্ক্রিন লক পরিবর্তন করুন৷"</string>
     <string name="policylab_forceLock" msgid="2274085384704248431">"স্ক্রিনটি লক করে"</string>
-    <string name="policydesc_forceLock" msgid="1141797588403827138">"স্ক্রিন কখন কিভাবে লক হবে তা নিয়ন্ত্রণ করে৷"</string>
+    <string name="policydesc_forceLock" msgid="1141797588403827138">"স্ক্রিন কখন কীভাবে লক হবে তা নিয়ন্ত্রণ করে৷"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"সমস্ত ডেটা মুছে দেয়"</string>
     <string name="policydesc_wipeData" product="tablet" msgid="4306184096067756876">"ফ্যাক্টরি ডেটা আবার সেট কার্য সম্পাদনার দ্বারা কোনো রকম সতর্কতা ছাড়াই ট্যাবলেটের ডেটা মোছে৷"</string>
     <string name="policydesc_wipeData" product="tv" msgid="5816221315214527028">"সতর্কীকরণ ছাড়াই একটি ফ্যাক্টরি ডেটা আবার সেট করার দ্বারা টিভির ডেটা মুছে ফেলে৷"</string>
@@ -1873,7 +1879,7 @@
     <string name="suspended_widget_accessibility" msgid="6712143096475264190">"অক্ষম করা <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="conference_call" msgid="3751093130790472426">"কনফারেন্স কল"</string>
     <string name="tooltip_popup_title" msgid="5253721848739260181">"টুলটিপ"</string>
-    <string name="app_category_game" msgid="5431836943981492993">"গেম্স"</string>
+    <string name="app_category_game" msgid="5431836943981492993">"গেম"</string>
     <string name="app_category_audio" msgid="1659853108734301647">"মিউজিক ও অডিও"</string>
     <string name="app_category_video" msgid="2728726078629384196">"চলচ্চিত্র ও ভিডিওগুলি"</string>
     <string name="app_category_image" msgid="4867854544519846048">"ফটো ও ছবিগুলি"</string>
@@ -1898,14 +1904,14 @@
       <item quantity="one">স্বতঃপূর্ণ করার <xliff:g id="COUNT">%1$s</xliff:g>টি প্রস্তাবনা</item>
       <item quantity="other">স্বতঃপূর্ণ করার <xliff:g id="COUNT">%1$s</xliff:g>টি প্রস্তাবনা</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; এ সংরক্ষণ করবেন?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"<xliff:g id="TYPE">%1$s</xliff:g> কে &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;এ সংরক্ষণ করবেন?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"<xliff:g id="TYPE_0">%1$s</xliff:g> এবং <xliff:g id="TYPE_1">%2$s</xliff:g> কে &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; এ সংরক্ষণ করবেন?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, এবং <xliff:g id="TYPE_2">%3$s</xliff:g> কে &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; এ সংরক্ষণ করবেন?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;-তে আপডেট করতে চান?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"<xliff:g id="TYPE">%1$s</xliff:g> থেকে &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;-এ আপডেট করতে চান?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"<xliff:g id="TYPE_0">%1$s</xliff:g> এবং <xliff:g id="TYPE_1">%2$s</xliff:g>o &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;-এ আপডেট করতে চান?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>,এবং <xliff:g id="TYPE_2">%3$s</xliff:g> to &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; আপডেট করতে চান?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"-এ সেভ করতে চান?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594"><b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"-এ <xliff:g id="TYPE">%1$s</xliff:g> সেভ করতে চান?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432"><b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"-এ <xliff:g id="TYPE_0">%1$s</xliff:g> এবং <xliff:g id="TYPE_1">%2$s</xliff:g> সেভ করতে চান?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555"><b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"-এ <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> এবং <xliff:g id="TYPE_2">%3$s</xliff:g> সেভ করতে চান?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"-এ আপডেট করতে চান?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233"><b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"-এ <xliff:g id="TYPE">%1$s</xliff:g> আপডেট করতে চান?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484"><b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"-এ <xliff:g id="TYPE_0">%1$s</xliff:g> এবং <xliff:g id="TYPE_1">%2$s</xliff:g> আপডেট করতে চান?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922"><b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"-এ এই আইটেমগুলি আপডেট করতে চান: <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> এবং <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"সেভ করুন"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"না থাক"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"আপডেট করুন"</string>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index e895ce0..425dfe5 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -295,6 +295,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Mikrofon"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"snima zvuk"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"Dozvoliti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; snimanje zvuka?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"Prepoznavanje aktivnosti"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"prepoznavanje aktivnosti"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"Dozvoliti aplikaciji<xliff:g id="APP_NAME">%1$s</xliff:g> prepoznavanje vaše fizičke aktivnosti?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Kamera"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"slika i snima videozapise"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"Dozvoliti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; snimanje slika i videozapisa?"</string>
@@ -421,14 +424,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Ova aplikacija može odrediti vašu lokaciju na osnovu izvora mreže kao što su predajnici za mobilnu mrežu i WiFi mreže. Ove usluge za određivanje lokacije moraju biti uključene i omogućene na vašem tabletu kako bi ih aplikacija mogla koristiti."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Ova aplikacija može odrediti vašu lokaciju na osnovu izvora mreže kao što su predajnici za mobilnu mrežu i WiFi mreže. Ove usluge za određivanje lokacije moraju biti uključene i omogućene na vašem TV-u kako bi ih aplikacija mogla koristiti."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Ova aplikacija može odrediti vašu lokaciju na osnovu izvora mreže kao što su predajnici za mobilnu mrežu i WiFi mreže. Ove usluge za određivanje lokacije moraju biti uključene i omogućene na vašem telefonu kako bi ih aplikacija mogla koristiti."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"pristupi tačnoj lokaciji u pozadini"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"Ova aplikacija može odrediti vašu tačnu lokaciju u svakom trenutku kada je u pozadini. Ove usluge za određivanje lokacije moraju biti uključene i dostupne na vašem telefonu da ih aplikacija može koristiti. To može izazvati povećanje potrošnje baterije."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"pristup lokaciji u pozadini"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Ako je ovo odobreno, pored pristupa približnoj ili tačnoj lokaciji, aplikacija može pristupiti lokaciji dok radi u pozadini."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"izmjene postavki zvuka"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Omogućava aplikaciji izmjenu općih postavki zvuka, kao što su jačina zvuka i izbor izlaznog zvučnika."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"snimanje audiozapisa"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"Ova aplikacija može u svakom trenutku snimati zvuk koristeći mikrofon."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"slanje komandi SIM kartici"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Omogućava aplikaciji slanje naredbi na SIM. Ovo je vrlo opasno."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"prepoznavanje fizičke aktivnosti"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"Ova aplikacija može prepoznati vašu fizičku aktivnost."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"snimanje slika i videozapisa"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"Ova aplikacija može slikati fotografije i snimati videozapise koristeći kameru bilo kada."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"kontrola vibracije"</string>
@@ -521,6 +526,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Omogućava aplikaciji da mijenja vašu kolekciju fotografija."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"čitanje lokacija iz kolekcije medija"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Omogućava aplikaciji da čita lokacije iz vaše kolekcije medija."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"Aplikacija <xliff:g id="APP">%s</xliff:g> traži autentifikaciju."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Biometrijski hardver nije dostupan"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Otkriven je djelomičan otisak prsta. Pokušajte ponovo."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Nije uspjela obrada otiska prsta. Pokušajte ponovo."</string>
@@ -831,7 +837,7 @@
     <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="2725973286239344555">"Pogrešno ste unijeli svoju lozinku <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. \n\nBroj sekundi do sljedećeg pokušaja: <xliff:g id="NUMBER_1">%2$d</xliff:g>"</string>
     <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6216672706545696955">"Pogrešno ste unijeli svoj PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. \n\nBroj sekundi do sljedećeg pokušaja: <xliff:g id="NUMBER_1">%2$d</xliff:g>"</string>
     <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="9191611984625460820">"Pogrešno ste unijeli uzorak za otključavanje <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Možete pokušati još <xliff:g id="NUMBER_1">%2$d</xliff:g> puta. Nakon toga ćete morati otključati tablet prijavom na svoj Google račun.\n\n Broj sekundi do sljedećeg pokušaja: <xliff:g id="NUMBER_2">%3$d</xliff:g>"</string>
-    <string name="lockscreen_failed_attempts_almost_glogin" product="tv" msgid="5316664559603394684">"Uzorak za otključavanje ste neispravno nacrtali <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. U slučaju još <xliff:g id="NUMBER_1">%2$d</xliff:g> pokušaja bez uspjeha, bit će zatraženo da TV otključate pomoću Google prijave.\n\n Pokušajte opet za <xliff:g id="NUMBER_2">%3$d</xliff:g> sek."</string>
+    <string name="lockscreen_failed_attempts_almost_glogin" product="tv" msgid="5316664559603394684">"Uzorak za otključavanje ste neispravno nacrtali <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. U slučaju još <xliff:g id="NUMBER_1">%2$d</xliff:g> pokušaja bez uspjeha, bit će zatraženo da TV otključate pomoću Google prijave.\n\n Pokušajte opet za <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
     <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="2590227559763762751">"Pogrešno ste unijeli uzorak za otključavanje <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Možete pokušati još <xliff:g id="NUMBER_1">%2$d</xliff:g> puta. Nakon toga ćete morati otključati telefon prijavom na svoj Google račun.\n\n Broj sekundi do sljedećeg pokušaja: <xliff:g id="NUMBER_2">%3$d</xliff:g>"</string>
     <string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet" msgid="6128106399745755604">"Pogrešno ste pokušali otključati tablet <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. Možete pokušati još <xliff:g id="NUMBER_1">%2$d</xliff:g> puta. Ukoliko ni tada ne uspijete otključati tablet, tablet će se vratiti na fabričke postavke i svi korisnički podaci bit će izgubljeni."</string>
     <string name="lockscreen_failed_attempts_almost_at_wipe" product="tv" msgid="950408382418270260">"Pokušali ste <xliff:g id="NUMBER_0">%1$d</xliff:g> puta neispravno otključati TV. U slučaju još <xliff:g id="NUMBER_1">%2$d</xliff:g> pokušaja bez uspjeha, TV će biti vraćen na fabričke postavke i svi podaci korisnika bit će izgubljeni."</string>
@@ -1635,9 +1641,9 @@
     <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"Pokušali ste otključati tablet na pogrešan način <xliff:g id="NUMBER">%d</xliff:g> puta. Tablet će sada biti vraćen na fabričke postavke."</string>
     <string name="kg_failed_attempts_now_wiping" product="tv" msgid="4987878286750741463">"Pokušali ste <xliff:g id="NUMBER">%d</xliff:g> puta neispravno otključati TV. TV će sada biti vraćen na fabričke postavke."</string>
     <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"Pokušali ste otključati telefon na pogrešan način <xliff:g id="NUMBER">%d</xliff:g> puta. Telefon će sada biti vraćen na fabričke postavke."</string>
-    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"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 tablet pomoću e-pošte. \n\n Pokušajte ponovo za <xliff:g id="NUMBER_2">%3$d</xliff:g> sek."</string>
-    <string name="kg_failed_attempts_almost_at_login" product="tv" msgid="4224651132862313471">"Uzorak za otključavanje ste pogrešno nacrtali <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. U slučaju još <xliff:g id="NUMBER_1">%2$d</xliff:g> pokušaja bez uspjeha, bit će zatraženo da TV otključate pomoću računa e-pošte.\n\n Pokušajte opet za <xliff:g id="NUMBER_2">%3$d</xliff:g> sek."</string>
-    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"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> sek."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"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 tablet 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_failed_attempts_almost_at_login" product="tv" msgid="4224651132862313471">"Uzorak za otključavanje ste pogrešno nacrtali <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. U slučaju još <xliff:g id="NUMBER_1">%2$d</xliff:g> pokušaja bez uspjeha, bit će zatraženo da TV otključate pomoću računa e-pošte.\n\n Pokušajte opet za <xliff:g id="NUMBER_2">%3$d</xliff:g> s."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"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="4160700433287233771">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"Ukloni"</string>
     <string name="safe_media_volume_warning" product="default" msgid="2276318909314492312">"Želite li pojačati zvuk iznad preporučenog nivoa?\n\nDužim slušanjem glasnog zvuka možete oštetiti sluh."</string>
@@ -1934,14 +1940,14 @@
       <item quantity="few"><xliff:g id="COUNT">%1$s</xliff:g> prijedloga za automatsko popunjavanje</item>
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> prijedloga za automatsko popunjavanje</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"Želite li sačuvati u &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Želite li da se <xliff:g id="TYPE">%1$s</xliff:g> sačuva u &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Želite li da se <xliff:g id="TYPE_0">%1$s</xliff:g> i <xliff:g id="TYPE_1">%2$s</xliff:g> sačuvaju u &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Želite li da se <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, i <xliff:g id="TYPE_2">%3$s</xliff:g> sačuvaju &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"Želite li ažurirati na &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Želite li da se <xliff:g id="TYPE">%1$s</xliff:g> ažurira na &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Želite li da se <xliff:g id="TYPE_0">%1$s</xliff:g> i <xliff:g id="TYPE_1">%2$s</xliff:g> ažuriraju na &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Želite li da se <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, i <xliff:g id="TYPE_2">%3$s</xliff:g> ažuriraju na &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"Sačuvati u "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"Sačuvati <xliff:g id="TYPE">%1$s</xliff:g> u "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"Sačuvati <xliff:g id="TYPE_0">%1$s</xliff:g> i <xliff:g id="TYPE_1">%2$s</xliff:g> u "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"Sačuvati <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> i <xliff:g id="TYPE_2">%3$s</xliff:g> u "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"Ažurirati u "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"Ažurirati <xliff:g id="TYPE">%1$s</xliff:g> u "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"Ažurirati <xliff:g id="TYPE_0">%1$s</xliff:g> i <xliff:g id="TYPE_1">%2$s</xliff:g> u "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"Ažurirati ove stavke u "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> i <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Sačuvaj"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Ne, hvala"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"Ažuriraj"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index b1d4994..a212014 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Micròfon"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"gravar àudio"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"Vols permetre que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; gravi àudio?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"Reconeixement de l\'activitat"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"reconèixer l\'activitat"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"Vols permetre que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; reconegui la teva activitat física?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Càmera"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"fer fotos i vídeos"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"Vols permetre que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; faci fotos i vídeos?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Aquesta aplicació pot obtenir la teva ubicació a partir de fonts de xarxa, com ara torres de telefonia mòbil i xarxes Wi-Fi. Aquests serveis d\'ubicació han d\'estar activats i disponibles a la tauleta perquè l\'aplicació els pugui utilitzar."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Aquesta aplicació pot obtenir la teva ubicació a partir de fonts de xarxa, com ara torres de telefonia mòbil i xarxes Wi-Fi. Aquests serveis d\'ubicació han d\'estar activats i disponibles al televisor perquè l\'aplicació els pugui utilitzar."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Aquesta aplicació pot obtenir la teva ubicació a partir de fonts de xarxa, com ara torres de telefonia mòbil i xarxes Wi-Fi. Aquests serveis d\'ubicació han d\'estar activats i disponibles al telèfon perquè l\'aplicació els pugui utilitzar."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"accedeix a la ubicació exacta en segon pla"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"Aquesta aplicació pot obtenir la teva ubicació exacta sempre que estigui en segon pla. Aquests serveis d\'ubicació han d\'estar activats i disponibles al telèfon perquè l\'aplicació els pugui utilitzar, i això pot fer que el consum de bateria augmenti."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"accedir a la ubicació en segon pla"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Si es concedeix aquest permís, a més de l\'accés a la ubicació aproximada o exacta, l\'aplicació pot accedir a la ubicació mentre s\'executa en segon pla."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"canviar la configuració d\'àudio"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Permet que l\'aplicació modifiqui la configuració d\'àudio general, com ara el volum i l\'altaveu de sortida que es fa servir."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"gravar àudio"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"Aquesta aplicació pot gravar àudio amb el micròfon en qualsevol moment."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"enviar ordres a la SIM"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Permet que l\'aplicació enviï ordres a la SIM. Això és molt perillós."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"reconèixer l\'activitat física"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"Aquesta aplicació pot reconèixer la teva activitat física."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"fer fotos i vídeos"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"Aquesta aplicació pot fer fotos i gravar vídeos amb la càmera en qualsevol moment."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"controlar la vibració"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Permet que l\'aplicació modifiqui la teva col·lecció de fotos."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"llegir les ubicacions de les teves col·leccions multimèdia"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Permet que l\'aplicació llegeixi les ubicacions de les teves col·leccions multimèdia."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"L\'aplicació <xliff:g id="APP">%s</xliff:g> vol que t\'autentiquis."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Maquinari biomètric no disponible"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"S\'ha detectat una empremta digital parcial. Torna-ho a provar."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"No s\'ha pogut processar l\'empremta digital. Torna-ho a provar."</string>
@@ -1897,14 +1903,14 @@
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> suggeriments d\'emplenament automàtic</item>
       <item quantity="one">Un suggeriment d\'emplenament automàtic</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"Vols desar-ho a <xliff:g id="LABEL">%1$s</xliff:g>?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Vols desar <xliff:g id="TYPE">%1$s</xliff:g> a <xliff:g id="LABEL">%2$s</xliff:g>?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Vols desar <xliff:g id="TYPE_0">%1$s</xliff:g> i <xliff:g id="TYPE_1">%2$s</xliff:g> a <xliff:g id="LABEL">%3$s</xliff:g>?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Vols desar <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> i <xliff:g id="TYPE_2">%3$s</xliff:g> a <xliff:g id="LABEL">%4$s</xliff:g>?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"Vols actualitzar les dades a &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Vols actualitzar <xliff:g id="TYPE">%1$s</xliff:g> a &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Vols actualitzar <xliff:g id="TYPE_0">%1$s</xliff:g> i <xliff:g id="TYPE_1">%2$s</xliff:g> a &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Vols actualitzar <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> i <xliff:g id="TYPE_2">%3$s</xliff:g> a &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"Vols desar-ho a "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"Vols desar <xliff:g id="TYPE">%1$s</xliff:g> a "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"Vols desar <xliff:g id="TYPE_0">%1$s</xliff:g> i <xliff:g id="TYPE_1">%2$s</xliff:g> a "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"Vols desar <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> i <xliff:g id="TYPE_2">%3$s</xliff:g> a "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"Vols actualitzar-ho a "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"Vols actualitzar <xliff:g id="TYPE">%1$s</xliff:g> a "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"Vols actualitzar <xliff:g id="TYPE_0">%1$s</xliff:g> i <xliff:g id="TYPE_1">%2$s</xliff:g> a "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"Vols actualitzar <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> i <xliff:g id="TYPE_2">%3$s</xliff:g> a "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Desa"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"No, gràcies"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"Actualitza"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index a537d6d..d71f72c 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -298,6 +298,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Mikrofon"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"nahrávání zvuku"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"Povolit aplikaci &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; nahrávat zvuk?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"Rozpoznávání aktivity"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"rozpoznávání aktivity"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"Povolit aplikaci &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; rozpoznávat vaši fyzickou aktivitu?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Fotoaparát"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"pořizování fotografií a nahrávání videa"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"Povolit aplikaci &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; fotit a nahrávat video?"</string>
@@ -424,14 +427,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Tato aplikace může zjistit vaši polohu podle zdrojů sítě, jako jsou vysílací věže nebo sítě Wi-Fi. Aby tyto služby určování polohy mohla aplikace používat, musí být v tabletu dostupné a musí být zapnuté."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Tato aplikace může zjistit vaši polohu podle zdrojů sítě, jako jsou vysílací věže nebo sítě Wi-Fi. Aby tyto služby určování polohy mohla aplikace používat, musí být v televizi dostupné a musí být zapnuté."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Tato aplikace může zjistit vaši polohu podle zdrojů sítě, jako jsou vysílací věže nebo sítě Wi-Fi. Aby tyto služby určování polohy mohla aplikace používat, musí být v telefonu dostupné a musí být zapnuté."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"přístup k přesné poloze na pozadí"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"Tato aplikace může zjistit vaši přesnou polohu vždy, když běží na pozadí. Aby tyto služby určování polohy mohla aplikace používat, musí být v telefonu dostupné a musí být zapnuté. Tyto služby mohou způsobit rychlejší vybíjení baterie."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"přístup k poloze na pozadí"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Bude-li oprávnění uděleno dodatečně k přístupu k přibližné nebo přesné poloze, aplikace bude moci používat polohu při spuštění na pozadí."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"změna nastavení zvuku"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Umožňuje aplikaci změnit globální nastavení zvuku, například hlasitost či reproduktor pro výstup zvuku."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"nahrávání zvuku"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"Tato aplikace může pomocí mikrofonu kdykoli zaznamenat zvuk."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"odesílání příkazů do SIM karty"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Umožňuje aplikaci odesílat příkazy na kartu SIM. Toto oprávnění je velmi nebezpečné."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"rozpoznávání fyzické aktivity"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"Tyto aplikace dokážou rozpoznat vaši fyzickou aktivitu."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"pořizování fotografií a videí"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"Tato aplikace může pomocí fotoaparátu kdykoli pořídit snímek nebo nahrát video."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"ovládání vibrací"</string>
@@ -524,6 +529,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Umožňuje aplikaci upravit vaši sbírku fotek."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"čtení míst ze sbírky médií"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Umožňuje aplikaci číst místa z vaší sbírky médií."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"Aplikace <xliff:g id="APP">%s</xliff:g> potřebuje provést ověření."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Biometrický hardware není k dispozici"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Byla zjištěna jen část otisku prstu. Zkuste to znovu."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Zpracování otisku prstu se nezdařilo. Zkuste to znovu."</string>
@@ -1967,14 +1973,14 @@
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> návrhů automatického vyplňování</item>
       <item quantity="one">1 návrh automatického vyplňování</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"Uložit do služby &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Uložit položku <xliff:g id="TYPE">%1$s</xliff:g> do služby &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Uložit položky <xliff:g id="TYPE_0">%1$s</xliff:g> a <xliff:g id="TYPE_1">%2$s</xliff:g> do služby &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Uložit položky <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> a <xliff:g id="TYPE_2">%3$s</xliff:g> do služby &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"Aktualizovat službu &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Aktualizovat položku <xliff:g id="TYPE">%1$s</xliff:g> ve službě &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Aktualizovat položky <xliff:g id="TYPE_0">%1$s</xliff:g> a <xliff:g id="TYPE_1">%2$s</xliff:g> ve službě &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Aktualizovat položky <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> a <xliff:g id="TYPE_2">%3$s</xliff:g> ve službě &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"Uložit do služby "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"Uložit údaj <xliff:g id="TYPE">%1$s</xliff:g> do služby "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"Uložit údaje <xliff:g id="TYPE_0">%1$s</xliff:g> a <xliff:g id="TYPE_1">%2$s</xliff:g> do služby "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"Uložit údaje <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> a <xliff:g id="TYPE_2">%3$s</xliff:g> do služby "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"Aktualizovat ve službě "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"Aktualizovat údaj <xliff:g id="TYPE">%1$s</xliff:g> ve službě "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"Aktualizovat údaje <xliff:g id="TYPE_0">%1$s</xliff:g> a <xliff:g id="TYPE_1">%2$s</xliff:g> ve službě "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"Aktualizovat tyto položky ve službě "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> a <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Uložit"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Ne, děkuji"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"Aktualizovat"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 28c08b1..6e9ae6b 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Mikrofon"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"optage lyd"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"Vil du give &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tilladelse til at optage lyd?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"Aktivitetsgenkendelse"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"genkend aktivitet"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"Vil du tillade, at &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; genkender din fysiske aktivitet?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Kamera"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"tage billeder og optage video"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"Vil du give &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tilladelse til at tage billeder og optage video?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Denne app kan bestemme din placering ved hjælp af netværkskilder, som f.eks. mobilmaster og Wi-Fi-netværk. Disse placeringstjenester skal være aktiverede og tilgængelige på din tablet, før appen kan bruge dem."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Denne app kan bestemme din placering ved hjælp af netværkskilder, som f.eks. mobilmaster og Wi-Fi-netværk. Disse placeringstjenester skal være aktiverede og tilgængelige på dit fjernsyn, før appen kan bruge dem."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Denne app kan bestemme din placering ved hjælp af netværkskilder, som f.eks. mobilmaster og Wi-Fi-netværk. Disse placeringstjenester skal være aktiverede og tilgængelige på din telefon, før appen kan bruge dem."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"få adgang til nøjagtig placering i baggrunden"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"Denne app kan få din nøjagtige placering, når den er i baggrunden. Disse placeringstjenester skal være aktiverede og tilgængelige på din telefon, før appen kan bruge dem. Dette kan øge batteriforbruget."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"adgang til placering i baggrunden"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Hvis appen godkendes, og der gives adgang til den omtrentlige eller nøjagtige placering, kan appen registrere placeringen, mens den kører i baggrunden."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"skifte dine lydindstillinger"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Tillader, at appen kan ændre globale lydindstillinger, som f.eks. lydstyrke og hvilken højttaler der bruges til output."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"optage lyd"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"Denne app kan til enhver tid optage lyd via mikrofonen."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"send kommandoer til SIM"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Tillader, at appen sender kommandoer til SIM-kortet. Dette er meget farligt."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"genkend fysisk aktivitet"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"Denne app kan genkende din fysiske aktivitet."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"tage billeder og optage video"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"Med denne app kan du tage billeder og optage video med kameraet når som helst."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"administrere vibration"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Tillader, at appen kan ændre din billedsamling."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"læse placeringer fra din mediesamling"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Tillader, at appen kan læse placeringer fra din mediesamling."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"<xliff:g id="APP">%s</xliff:g>-appen kræver din godkendelse."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Biometrisk hardware er ikke tilgængelig"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Der blev registreret et delvist fingeraftryk. Prøv igen."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Fingeraftrykket kunne ikke behandles. Prøv igen."</string>
@@ -944,7 +950,7 @@
     <string name="menu_sym_shortcut_label" msgid="4019695553731017933">"Sym+"</string>
     <string name="menu_function_shortcut_label" msgid="1984053777418162618">"Fn+"</string>
     <string name="menu_space_shortcut_label" msgid="2410328639272162537">"plads"</string>
-    <string name="menu_enter_shortcut_label" msgid="2743362785111309668">"indtast"</string>
+    <string name="menu_enter_shortcut_label" msgid="2743362785111309668">"angiv"</string>
     <string name="menu_delete_shortcut_label" msgid="3658178007202748164">"slet"</string>
     <string name="search_go" msgid="8298016669822141719">"Søg"</string>
     <string name="search_hint" msgid="1733947260773056054">"Søg…"</string>
@@ -1897,14 +1903,14 @@
       <item quantity="one"><xliff:g id="COUNT">%1$s</xliff:g> forslag fra autofyld</item>
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> forslag fra autofyld</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"Vil du gemme i &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Vil du gemme <xliff:g id="TYPE">%1$s</xliff:g> i &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Vil du gemme <xliff:g id="TYPE_0">%1$s</xliff:g> og <xliff:g id="TYPE_1">%2$s</xliff:g> i &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Vil du gemme <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> og <xliff:g id="TYPE_2">%3$s</xliff:g> i &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"Vil du opdatere til &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Vil du opdatere <xliff:g id="TYPE">%1$s</xliff:g> til &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Vil du opdatere <xliff:g id="TYPE_0">%1$s</xliff:g> og <xliff:g id="TYPE_1">%2$s</xliff:g> til &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Vil du opdatere <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> og <xliff:g id="TYPE_2">%3$s</xliff:g> til &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"Vil du gemme i "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"Vil du gemme <xliff:g id="TYPE">%1$s</xliff:g> i "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"Vil du gemme <xliff:g id="TYPE_0">%1$s</xliff:g> og <xliff:g id="TYPE_1">%2$s</xliff:g> i "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"Vil du gemme <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> og <xliff:g id="TYPE_2">%3$s</xliff:g> i "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"Vil du opdatere i "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"Vil du opdatere <xliff:g id="TYPE">%1$s</xliff:g> i "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"Vil du opdatere <xliff:g id="TYPE_0">%1$s</xliff:g> og <xliff:g id="TYPE_1">%2$s</xliff:g> i "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"Vil du opdatere disse elementer i "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> og <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Gem"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Nej tak"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"Opdater"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 4a2efbd..e0f8201 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Mikrofon"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"Audio aufnehmen"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; erlauben, Audioaufnahmen zu machen?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"Aktivitätserkennung"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"Aktivitäten erkennen"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; erlauben, deine körperlichen Aktivitäten zu erkennen?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Kamera"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"Bilder und Videos aufnehmen"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; erlauben, Bilder und Videos aufzunehmen?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Diese App kann deinen Standort mithilfe von Netzwerkquellen wie Mobilfunkmasten und WLAN ermitteln. Die App kann diese Standortdienste nur verwenden, wenn sie auf deinem Tablet aktiviert und verfügbar sind."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Diese App kann deinen Standort mithilfe von Netzwerkquellen wie Mobilfunkmasten und WLAN ermitteln. Die App kann diese Standortdienste nur verwenden, wenn sie auf deinem Fernseher aktiviert und verfügbar sind."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Diese App kann deinen Standort mithilfe von Netzwerkquellen wie Mobilfunkmasten und WLAN ermitteln. Die App kann diese Standortdienste nur verwenden, wenn sie auf deinem Smartphone aktiviert und verfügbar sind."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"im Hintergrund auf den genauen Standort zugreifen"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"Diese App kann deinen genauen Standort jederzeit im Hintergrund ermitteln. Die App kann diese Standortdienste nur verwenden, wenn sie auf deinem Smartphone aktiviert und verfügbar sind. Hierdurch kann sich der Akkuverbrauch erhöhen."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"Im Hintergrund auf den Standort zugreifen"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Wenn zusätzlich zum Zugriff auf den ungefähren oder genauen Standort diese Erlaubnis erteilt wird, kann die App bei Ausführung im Hintergrund auf den Standort zugreifen."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"Audio-Einstellungen ändern"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Ermöglicht der App, globale Audio-Einstellungen zu ändern, etwa die Lautstärke und den Lautsprecher für die Ausgabe."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"Audio aufnehmen"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"Diese App kann jederzeit Audio über das Mikrofon aufnehmen."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"Befehle an die SIM senden"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Ermöglicht der App das Senden von Befehlen an die SIM-Karte. Dies ist äußerst risikoreich."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"körperlichen Aktivitäten erkennen"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"Diese App kann deine körperlichen Aktivitäten erkennen."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"Bilder und Videos aufnehmen"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"Diese App kann mit der Kamera jederzeit Bilder und Videos aufnehmen."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"Vibrationsalarm steuern"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Ermöglicht der App, deine Fotosammlung zu ändern."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"Standorte aus meiner Mediensammlung abrufen"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Ermöglicht der App, Standorte aus deiner Mediensammlung abzurufen."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"<xliff:g id="APP">%s</xliff:g> möchte, dass du dich authentifizierst."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Biometrische Hardware nicht verfügbar"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Fingerabdruck teilweise erkannt. Bitte versuche es noch einmal."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Fingerabdruck konnte nicht verarbeitet werden. Bitte versuche es noch einmal."</string>
@@ -545,7 +551,7 @@
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"Fingerabdruck-Symbol"</string>
     <string name="permlab_manageFace" msgid="2137540986007309781">"Gesichtserkennungshardware verwalten"</string>
-    <string name="permdesc_manageFace" msgid="8919637120670185330">"Ermöglicht der App, Methoden zum Hinzufügen oder Entfernen von Gesichtsvorlagen anzuwenden."</string>
+    <string name="permdesc_manageFace" msgid="8919637120670185330">"Ermöglicht der App,  Gesichtsvorlagen hinzuzufügen oder zu entfernen."</string>
     <string name="permlab_useFaceAuthentication" msgid="8996134460546804535">"Gesichtserkennungshardware verwenden"</string>
     <string name="permdesc_useFaceAuthentication" msgid="5011118722951833089">"Ermöglicht der App, für die Authentifizierung Gesichtserkennungshardware zu verwenden"</string>
     <string name="face_acquired_insufficient" msgid="5901287247766106330">"Kann Gesicht nicht verarbeiten. Versuch es erneut."</string>
@@ -1897,14 +1903,14 @@
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> AutoFill-Vorschläge</item>
       <item quantity="one">1 AutoFill-Vorschlag</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"In &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; speichern?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"<xliff:g id="TYPE">%1$s</xliff:g> in &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; speichern?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"<xliff:g id="TYPE_0">%1$s</xliff:g> und <xliff:g id="TYPE_1">%2$s</xliff:g> in &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; speichern?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> und <xliff:g id="TYPE_2">%3$s</xliff:g> in &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; speichern?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"Über &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; aktualisieren?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"<xliff:g id="TYPE">%1$s</xliff:g> über &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; aktualisieren?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"<xliff:g id="TYPE_0">%1$s</xliff:g> und <xliff:g id="TYPE_1">%2$s</xliff:g> über &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; aktualisieren?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> und <xliff:g id="TYPE_2">%3$s</xliff:g> über &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; aktualisieren?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"In "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" speichern?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"<xliff:g id="TYPE">%1$s</xliff:g> in "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" speichern?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"<xliff:g id="TYPE_0">%1$s</xliff:g> und <xliff:g id="TYPE_1">%2$s</xliff:g> in "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" speichern?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> und <xliff:g id="TYPE_2">%3$s</xliff:g> in "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" speichern?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"In "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" aktualisieren?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"<xliff:g id="TYPE">%1$s</xliff:g> in "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" aktualisieren?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"<xliff:g id="TYPE_0">%1$s</xliff:g> und <xliff:g id="TYPE_1">%2$s</xliff:g> in "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" aktualisieren?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> und <xliff:g id="TYPE_2">%3$s</xliff:g> in "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" aktualisieren?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Speichern"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Nein danke"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"Aktualisieren"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 04b9749..6090465 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Μικρόφωνο"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"ηχογραφεί"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"Να επιτρέπεται στην εφαρμογή &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; η εγγραφή ήχου;"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"Αναγνώριση δραστηριότητας"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"αναγνώριση δραστηριότητας"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"Να επιτρέπεται στην εφαρμογή &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; να αναγνωρίζει τη σωματική σας δραστηριότητα;"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Κάμερα"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"γίνεται λήψη φωτογραφιών και εγγραφή βίντεο"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"Να επιτρέπεται στην εφαρμογή &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; η λήψη φωτογραφιών και η εγγραφή βίντεο;"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Αυτή η εφαρμογή μπορεί να ανιχνεύσει την τοποθεσία σας βάσει πηγών δικτύου, όπως κεραίες κινητής τηλεφωνίας και δίκτυα Wi-Fi. Αυτές οι υπηρεσίες τοποθεσίας θα πρέπει να είναι ενεργοποιημένες και διαθέσιμες στο tablet που χρησιμοποιείτε, προκειμένου να μπορεί να τις χρησιμοποιήσει η εφαρμογή."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Αυτή η εφαρμογή μπορεί να ανιχνεύσει την τοποθεσία σας βάσει πηγών δικτύου, όπως κεραίες κινητής τηλεφωνίας και δίκτυα Wi-Fi. Αυτές οι υπηρεσίες τοποθεσίας θα πρέπει να είναι ενεργοποιημένες και διαθέσιμες στην τηλεόρασή σας, προκειμένου να μπορεί να τις χρησιμοποιήσει η εφαρμογή."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Αυτή η εφαρμογή μπορεί να ανιχνεύσει την τοποθεσία σας βάσει πηγών δικτύου, όπως κεραίες κινητής τηλεφωνίας και δίκτυα Wi-Fi. Αυτές οι υπηρεσίες τοποθεσίας θα πρέπει να είναι ενεργοποιημένες και διαθέσιμες στο τηλέφωνό σας, προκειμένου να μπορεί να τις χρησιμοποιήσει η εφαρμογή."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"πρόσβαση στην ακριβή τοποθεσία στο παρασκήνιο"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"Αυτή η εφαρμογή μπορεί να ανιχνεύσει την ακριβή τοποθεσία σας οποτεδήποτε βρίσκεται στο παρασκήνιο. Αυτές οι υπηρεσίες τοποθεσίας θα πρέπει να είναι ενεργοποιημένες και διαθέσιμες στο τηλέφωνό σας, προκειμένου να μπορεί να τις χρησιμοποιήσει η εφαρμογή. Με την ενεργοποίηση αυτής της ρύθμισης, μπορεί να αυξηθεί η κατανάλωση μπαταρίας."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"πρόσβαση στην τοποθεσία στο παρασκήνιο"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Εάν εκχωρηθεί επιπρόσθετα σε μια καταπροσέγγιση ή ακριβή πρόσβαση τοποθεσίας, η εφαρμογή μπορεί να έχει πρόσβαση στην τοποθεσία κατά την εκτέλεση στο παρασκήνιο."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"αλλάζει τις ρυθμίσεις ήχου"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Επιτρέπει στην εφαρμογή την τροποποίηση καθολικών ρυθμίσεων ήχου, όπως η ένταση και ποιο ηχείο χρησιμοποιείται για έξοδο."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"εγγράφει ήχο"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"Αυτή η εφαρμογή μπορεί να κάνει εγγραφή ήχου χρησιμοποιώντας το μικρόφωνο, ανά πάσα στιγμή."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"στέλνει εντολές στην κάρτα SIM"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Επιτρέπει στην εφαρμογή την αποστολή εντολών στην κάρτα SIM. Αυτό είναι εξαιρετικά επικίνδυνο."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"αναγνώριση σωματικής δραστηριότητας"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"Αυτή η εφαρμογή μπορεί να αναγνωρίσει τη σωματική σας δραστηριότητα."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"κάνει λήψη φωτογραφιών και βίντεο"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"Αυτή η εφαρμογή μπορεί να τραβήξει φωτογραφίες και βίντεο χρησιμοποιώντας την κάμερα, ανά πάσα στιγμή."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"ελέγχει τη δόνηση"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Επιτρέπει στην εφαρμογή να τροποποιήσει τη συλλογή φωτογραφιών σας."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"ανάγνωση τοποθεσιών από τη συλλογή πολυμέσων σας"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Επιτρέπει στην εφαρμογή να διαβάσει τοποθεσίες από τη συλλογή πολυμέσων σας."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"Η εφαρμογή <xliff:g id="APP">%s</xliff:g> επιθυμεί έλεγχο ταυτότητας."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Δεν υπάρχει διαθέσιμος βιομετρικός εξοπλισμός"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Εντοπίστηκε μερικό μοναδικό χαρακτηριστικό. Δοκιμάστε ξανά."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Δεν ήταν δυνατή η επεξεργασία του μοναδικού χαρακτηριστικού. Δοκιμάστε ξανά."</string>
@@ -1897,14 +1903,14 @@
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> προτάσεις αυτόματης συμπλήρωσης</item>
       <item quantity="one">Μία πρόταση αυτόματης συμπλήρωσης</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"Αποθήκευση σε &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;;"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Αποθήκευση <xliff:g id="TYPE">%1$s</xliff:g> σε &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;;"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Αποθήκευση <xliff:g id="TYPE_0">%1$s</xliff:g> και <xliff:g id="TYPE_1">%2$s</xliff:g> σε &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;;"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Αποθήκευση <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> και <xliff:g id="TYPE_2">%3$s</xliff:g> σε &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;;"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"Να γίνει ενημέρωση στο &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;;"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Να γίνει ενημέρωση των δεδομένων <xliff:g id="TYPE">%1$s</xliff:g> στην υπηρεσία &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;;"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Να γίνει ενημέρωση των δεδομένων <xliff:g id="TYPE_0">%1$s</xliff:g> και <xliff:g id="TYPE_1">%2$s</xliff:g> στην υπηρεσία &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;;"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Να γίνει ενημέρωση των δεδομένων <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> και <xliff:g id="TYPE_2">%3$s</xliff:g> στην υπηρεσία &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;;"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"Αποθήκευση σε "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>";"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"Αποθήκευση <xliff:g id="TYPE">%1$s</xliff:g> σε "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>";"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"Αποθήκευση <xliff:g id="TYPE_0">%1$s</xliff:g> και <xliff:g id="TYPE_1">%2$s</xliff:g> σε "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>";"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"Αποθήκευση <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> και <xliff:g id="TYPE_2">%3$s</xliff:g> σε "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>";"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"Ενημέρωση σε "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>";"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"Ενημέρωση <xliff:g id="TYPE">%1$s</xliff:g> σε "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>";"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"Ενημέρωση <xliff:g id="TYPE_0">%1$s</xliff:g> και <xliff:g id="TYPE_1">%2$s</xliff:g> σε "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>";"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"Ενημέρωση αυτών των στοιχείων "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> και <xliff:g id="TYPE_2">%3$s</xliff:g>;"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Αποθήκευση"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Όχι, ευχαριστώ"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"Ενημέρωση"</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 8592355..e102e5b 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Microphone"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"record audio"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to record audio?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"Activity recognition"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"recognise activity"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to recognise your physical activity?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Camera"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"take pictures and record video"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to take pictures and record video?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"This app can pick up your location based on network sources such as phone masts and Wi-Fi networks. These location services must be turned on and available on your tablet for the app to be able to use them."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"This app can pick up your location based on network sources such as mobile towers and Wi-Fi networks. These location services must be turned on and available on your TV for the app to be able to use them."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"This app can get your location based on network sources such as phone masts and Wi-Fi networks. These location services must be turned on and available on your phone for the app to be able to use them."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"access precise location in the background"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"This app can get your exact location any time it is in the background. These location services must be turned on and available on your phone for the app to be able to use them. This may increase battery consumption."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"access location in the background"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"If this is granted additionally to the approximate or precise location access, the app can access the location while running in the background."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"change your audio settings"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Allows the app to modify global audio settings such as volume and which speaker is used for output."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"record audio"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"This app can record audio using the microphone at any time."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"send commands to the SIM"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Allows the app to send commands to the SIM. This is very dangerous."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"recognise physical activity"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"This app can recognise your physical activity."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"take pictures and videos"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"This app can take pictures and record videos using the camera at any time."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"control vibration"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Allows the app to modify your photo collection."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"read locations from your media collection"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Allows the app to read locations from your media collection."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"Application <xliff:g id="APP">%s</xliff:g> wants to authenticate."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Biometric hardware unavailable"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Partial fingerprint detected. Please try again."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Couldn\'t process fingerprint. Please try again."</string>
@@ -1897,14 +1903,14 @@
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> auto-fill suggestions</item>
       <item quantity="one">One auto-fill suggestion</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"Save to &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Save <xliff:g id="TYPE">%1$s</xliff:g> to &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Save <xliff:g id="TYPE_0">%1$s</xliff:g> and <xliff:g id="TYPE_1">%2$s</xliff:g> to &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Save <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, and <xliff:g id="TYPE_2">%3$s</xliff:g> to &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"Update to &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Update <xliff:g id="TYPE">%1$s</xliff:g> to &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Update <xliff:g id="TYPE_0">%1$s</xliff:g> and <xliff:g id="TYPE_1">%2$s</xliff:g> to &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Update <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> and <xliff:g id="TYPE_2">%3$s</xliff:g> to &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"Save to "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"Save <xliff:g id="TYPE">%1$s</xliff:g> to "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"Save <xliff:g id="TYPE_0">%1$s</xliff:g> and <xliff:g id="TYPE_1">%2$s</xliff:g> to "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"Save <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> and <xliff:g id="TYPE_2">%3$s</xliff:g> to "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"Update in "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"Update <xliff:g id="TYPE">%1$s</xliff:g> in "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"Update <xliff:g id="TYPE_0">%1$s</xliff:g> and <xliff:g id="TYPE_1">%2$s</xliff:g> in "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"Update these items in "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> and <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Save"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"No, thanks"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"Update"</string>
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index 1e075f8..518efc9 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Microphone"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"record audio"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to record audio?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"Activity recognition"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"recognise activity"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to recognise your physical activity?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Camera"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"take pictures and record video"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to take pictures and record video?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"This app can pick up your location based on network sources such as phone masts and Wi-Fi networks. These location services must be turned on and available on your tablet for the app to be able to use them."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"This app can pick up your location based on network sources such as mobile towers and Wi-Fi networks. These location services must be turned on and available on your TV for the app to be able to use them."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"This app can get your location based on network sources such as phone masts and Wi-Fi networks. These location services must be turned on and available on your phone for the app to be able to use them."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"access precise location in the background"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"This app can get your exact location any time it is in the background. These location services must be turned on and available on your phone for the app to be able to use them. This may increase battery consumption."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"access location in the background"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"If this is granted additionally to the approximate or precise location access, the app can access the location while running in the background."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"change your audio settings"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Allows the app to modify global audio settings such as volume and which speaker is used for output."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"record audio"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"This app can record audio using the microphone at any time."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"send commands to the SIM"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Allows the app to send commands to the SIM. This is very dangerous."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"recognise physical activity"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"This app can recognise your physical activity."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"take pictures and videos"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"This app can take pictures and record videos using the camera at any time."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"control vibration"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Allows the app to modify your photo collection."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"read locations from your media collection"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Allows the app to read locations from your media collection."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"Application <xliff:g id="APP">%s</xliff:g> wants to authenticate."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Biometric hardware unavailable"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Partial fingerprint detected. Please try again."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Couldn\'t process fingerprint. Please try again."</string>
@@ -1897,14 +1903,14 @@
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> auto-fill suggestions</item>
       <item quantity="one">One auto-fill suggestion</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"Save to &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Save <xliff:g id="TYPE">%1$s</xliff:g> to &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Save <xliff:g id="TYPE_0">%1$s</xliff:g> and <xliff:g id="TYPE_1">%2$s</xliff:g> to &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Save <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, and <xliff:g id="TYPE_2">%3$s</xliff:g> to &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"Update to &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Update <xliff:g id="TYPE">%1$s</xliff:g> to &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Update <xliff:g id="TYPE_0">%1$s</xliff:g> and <xliff:g id="TYPE_1">%2$s</xliff:g> to &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Update <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> and <xliff:g id="TYPE_2">%3$s</xliff:g> to &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"Save to "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"Save <xliff:g id="TYPE">%1$s</xliff:g> to "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"Save <xliff:g id="TYPE_0">%1$s</xliff:g> and <xliff:g id="TYPE_1">%2$s</xliff:g> to "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"Save <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> and <xliff:g id="TYPE_2">%3$s</xliff:g> to "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"Update in "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"Update <xliff:g id="TYPE">%1$s</xliff:g> in "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"Update <xliff:g id="TYPE_0">%1$s</xliff:g> and <xliff:g id="TYPE_1">%2$s</xliff:g> in "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"Update these items in "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> and <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Save"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"No, thanks"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"Update"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 8592355..e102e5b 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Microphone"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"record audio"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to record audio?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"Activity recognition"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"recognise activity"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to recognise your physical activity?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Camera"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"take pictures and record video"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to take pictures and record video?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"This app can pick up your location based on network sources such as phone masts and Wi-Fi networks. These location services must be turned on and available on your tablet for the app to be able to use them."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"This app can pick up your location based on network sources such as mobile towers and Wi-Fi networks. These location services must be turned on and available on your TV for the app to be able to use them."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"This app can get your location based on network sources such as phone masts and Wi-Fi networks. These location services must be turned on and available on your phone for the app to be able to use them."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"access precise location in the background"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"This app can get your exact location any time it is in the background. These location services must be turned on and available on your phone for the app to be able to use them. This may increase battery consumption."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"access location in the background"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"If this is granted additionally to the approximate or precise location access, the app can access the location while running in the background."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"change your audio settings"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Allows the app to modify global audio settings such as volume and which speaker is used for output."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"record audio"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"This app can record audio using the microphone at any time."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"send commands to the SIM"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Allows the app to send commands to the SIM. This is very dangerous."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"recognise physical activity"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"This app can recognise your physical activity."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"take pictures and videos"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"This app can take pictures and record videos using the camera at any time."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"control vibration"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Allows the app to modify your photo collection."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"read locations from your media collection"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Allows the app to read locations from your media collection."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"Application <xliff:g id="APP">%s</xliff:g> wants to authenticate."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Biometric hardware unavailable"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Partial fingerprint detected. Please try again."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Couldn\'t process fingerprint. Please try again."</string>
@@ -1897,14 +1903,14 @@
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> auto-fill suggestions</item>
       <item quantity="one">One auto-fill suggestion</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"Save to &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Save <xliff:g id="TYPE">%1$s</xliff:g> to &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Save <xliff:g id="TYPE_0">%1$s</xliff:g> and <xliff:g id="TYPE_1">%2$s</xliff:g> to &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Save <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, and <xliff:g id="TYPE_2">%3$s</xliff:g> to &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"Update to &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Update <xliff:g id="TYPE">%1$s</xliff:g> to &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Update <xliff:g id="TYPE_0">%1$s</xliff:g> and <xliff:g id="TYPE_1">%2$s</xliff:g> to &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Update <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> and <xliff:g id="TYPE_2">%3$s</xliff:g> to &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"Save to "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"Save <xliff:g id="TYPE">%1$s</xliff:g> to "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"Save <xliff:g id="TYPE_0">%1$s</xliff:g> and <xliff:g id="TYPE_1">%2$s</xliff:g> to "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"Save <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> and <xliff:g id="TYPE_2">%3$s</xliff:g> to "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"Update in "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"Update <xliff:g id="TYPE">%1$s</xliff:g> in "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"Update <xliff:g id="TYPE_0">%1$s</xliff:g> and <xliff:g id="TYPE_1">%2$s</xliff:g> in "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"Update these items in "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> and <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Save"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"No, thanks"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"Update"</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 8592355..e102e5b 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Microphone"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"record audio"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to record audio?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"Activity recognition"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"recognise activity"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to recognise your physical activity?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Camera"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"take pictures and record video"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"Allow &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; to take pictures and record video?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"This app can pick up your location based on network sources such as phone masts and Wi-Fi networks. These location services must be turned on and available on your tablet for the app to be able to use them."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"This app can pick up your location based on network sources such as mobile towers and Wi-Fi networks. These location services must be turned on and available on your TV for the app to be able to use them."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"This app can get your location based on network sources such as phone masts and Wi-Fi networks. These location services must be turned on and available on your phone for the app to be able to use them."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"access precise location in the background"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"This app can get your exact location any time it is in the background. These location services must be turned on and available on your phone for the app to be able to use them. This may increase battery consumption."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"access location in the background"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"If this is granted additionally to the approximate or precise location access, the app can access the location while running in the background."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"change your audio settings"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Allows the app to modify global audio settings such as volume and which speaker is used for output."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"record audio"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"This app can record audio using the microphone at any time."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"send commands to the SIM"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Allows the app to send commands to the SIM. This is very dangerous."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"recognise physical activity"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"This app can recognise your physical activity."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"take pictures and videos"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"This app can take pictures and record videos using the camera at any time."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"control vibration"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Allows the app to modify your photo collection."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"read locations from your media collection"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Allows the app to read locations from your media collection."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"Application <xliff:g id="APP">%s</xliff:g> wants to authenticate."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Biometric hardware unavailable"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Partial fingerprint detected. Please try again."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Couldn\'t process fingerprint. Please try again."</string>
@@ -1897,14 +1903,14 @@
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> auto-fill suggestions</item>
       <item quantity="one">One auto-fill suggestion</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"Save to &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Save <xliff:g id="TYPE">%1$s</xliff:g> to &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Save <xliff:g id="TYPE_0">%1$s</xliff:g> and <xliff:g id="TYPE_1">%2$s</xliff:g> to &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Save <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, and <xliff:g id="TYPE_2">%3$s</xliff:g> to &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"Update to &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Update <xliff:g id="TYPE">%1$s</xliff:g> to &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Update <xliff:g id="TYPE_0">%1$s</xliff:g> and <xliff:g id="TYPE_1">%2$s</xliff:g> to &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Update <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> and <xliff:g id="TYPE_2">%3$s</xliff:g> to &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"Save to "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"Save <xliff:g id="TYPE">%1$s</xliff:g> to "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"Save <xliff:g id="TYPE_0">%1$s</xliff:g> and <xliff:g id="TYPE_1">%2$s</xliff:g> to "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"Save <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> and <xliff:g id="TYPE_2">%3$s</xliff:g> to "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"Update in "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"Update <xliff:g id="TYPE">%1$s</xliff:g> in "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"Update <xliff:g id="TYPE_0">%1$s</xliff:g> and <xliff:g id="TYPE_1">%2$s</xliff:g> in "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"Update these items in "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> and <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Save"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"No, thanks"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"Update"</string>
diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml
index 9138098..29a797b 100644
--- a/core/res/res/values-en-rXC/strings.xml
+++ b/core/res/res/values-en-rXC/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‎‏‎‎‏‏‎‎‎‎‏‎‏‏‎‏‏‏‎‏‎‏‎‎‎‎‏‎‏‏‎‎‎‏‏‎‎‏‏‎‏‎‏‏‎‏‏‎‏‎‎‎‏‎‎‏‎‎‎‎Microphone‎‏‎‎‏‎"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‎‏‏‏‎‏‏‏‏‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‎‏‏‎‏‎‏‎‎‎‎‏‏‎‎‎‎record audio‎‏‎‎‏‎"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‏‎‏‏‏‏‎‎‏‏‎‏‏‏‎‎‎‏‎‏‏‎‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‎‎‏‎‏‎‎‎‎‏‏‎‎Allow &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; to record audio?‎‏‎‎‏‎"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‏‎‏‏‎‎‏‎‎‏‎‏‏‏‎‎‎‏‎‎‏‏‎‏‏‏‏‎‏‎‎‏‎‎‎‏‎‏‎‎‏‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎Activity recognition‎‏‎‎‏‎"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‏‏‏‏‎‎‏‎‏‎‎‏‏‎‎‏‏‏‎‏‏‏‎‏‎‎‎‏‎‎‎‎‎‎‏‎‏‏‏‏‎‎‎‏‏‎‎‎‎‏‎‏‎‏‎‎recognize activity‎‏‎‎‏‎"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‎‏‎‏‏‎‏‎‎‎‏‏‏‏‏‎‎‏‎‏‏‎‏‎‎‎‏‏‎‎‏‏‎‎‏‏‏‏‏‎‎‏‎‏‎‏‎‎‎‏‎‎‎‎‏‏‏‎Allow &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; to recognize your physical activity?‎‏‎‎‏‎"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‎‏‏‏‎‎‏‎‏‎‏‏‎‎‏‏‏‎‎‏‏‏‏‏‎‏‏‎‏‏‏‏‎‏‏‎‏‏‏‎‎‎‎‏‎‎‏‎‎‏‏‏‏‎‏‏‏‎Camera‎‏‎‎‏‎"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‏‎‎‎‏‏‏‎‎‎‏‏‏‏‏‏‎‎‎‎‎‎‏‎‏‏‏‎‏‏‎‏‏‏‎‎‏‎‎‎‏‏‎‏‎‎‏‏‏‏‏‎‎‏‎‎‎‎take pictures and record video‎‏‎‎‏‎"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‎‎‎‎‎‏‎‎‏‏‏‏‎‏‏‏‏‏‏‎‎‎‎‏‏‏‏‏‎‎‎‏‎‎‏‏‎‏‏‏‎‏‏‎‎‏‎‏‏‎‏‎‎‏‏‎‎‎Allow &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt; to take pictures and record video?‎‏‎‎‏‎"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‏‎‏‏‎‏‎‎‎‎‎‏‎‎‎‎‎‎‎‏‎‎‎‎‎‎‎‏‏‏‎‏‎‏‎‎‏‎‎‎‏‏‏‎‏‏‏‏‎‎‏‎‎‏‏‎‏‎‎This app can get your location based on network sources such as cell towers and Wi-Fi networks. These location services must be turned on and available on your tablet for the app to be able to use them.‎‏‎‎‏‎"</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‎‎‎‏‎‎‏‎‏‎‏‏‎‎‏‎‎‏‎‏‎‏‏‏‎‏‎‎‎‎‎‏‏‏‎‎‏‎‎‎‎‎‏‏‎‏‏‏‎‏‎‎‏‏‏‏‏‎This app can get your location based on network sources such as cell towers and Wi-Fi networks. These location services must be turned on and available on your TV for the app to be able to use them.‎‏‎‎‏‎"</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‎‎‏‎‏‎‎‏‎‎‏‎‎‎‏‎‎‎‎‎‎‏‎‎‏‎‏‏‎‎‏‎‏‏‎‎‏‎‏‎‎‏‏‎‏‎‎‎‎‎‎‎‎‏‏‎This app can get your location based on network sources such as cell towers and Wi-Fi networks. These location services must be turned on and available on your phone for the app to be able to use them.‎‏‎‎‏‎"</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‏‏‎‏‏‎‎‎‏‎‏‎‏‎‏‏‎‏‎‏‏‏‏‏‏‏‏‎‏‏‎‏‏‏‏‏‎‏‏‎‎‏‏‎‏‏‏‎‎‎‏‎‏‏‎‎‎‎access precise location in the background‎‏‎‎‏‎"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‎‎‏‏‎‏‏‎‎‎‎‏‏‏‎‏‏‏‏‎‎‎‎‏‏‎‏‏‎‏‏‏‎‎‏‏‏‏‏‎‏‎‏‎‎‎‏‎‎‏‏‏‏‎‏‏‏‎This app can get your exact location any time it is in the background. These location services must be turned on and available on your phone for the app to be able to use them. This may increase battery consumption.‎‏‎‎‏‎"</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‏‎‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‏‎‎‏‎‏‏‎‎‎‏‏‏‏‎‎‏‏‏‎‏‎‎‎‏‏‏‎‎‎‏‎‏‎‎‎‏‏‎‎access location in the background‎‏‎‎‏‎"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‏‎‎‏‏‎‏‏‏‎‎‏‎‏‏‎‎‏‏‏‎‏‏‎‎‏‎‏‏‏‏‎‎‏‏‎‎‏‎‎‏‎‎‏‎‏‏‏‎‎‎‎‎‏‎‏‏‎If this is granted additionally to the approximate or precise location access the app can access the location while running in the background.‎‏‎‎‏‎"</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‎‏‎‎‏‏‎‎‎‏‏‎‏‏‎‎‎‎‏‎‏‎‎‎‎‏‏‎‎‎‏‎‏‏‎‎‎‏‎‏‎‏‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‎change your audio settings‎‏‎‎‏‎"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎‏‏‏‎‎‎‏‎‏‎‏‎‏‎‏‎‏‎‎‎‏‎‎‏‏‎‏‎‏‎‏‎‏‎‎‏‎‏‎‎‎‏‏‏‏‏‎‎‎‏‎‎‎‏‎‏‎Allows the app to modify global audio settings such as volume and which speaker is used for output.‎‏‎‎‏‎"</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‏‏‏‎‎‏‎‏‎‎‏‏‏‏‏‏‎‏‎‏‏‏‎‏‏‎‎‎‏‏‏‎‏‏‎‏‎‏‎‏‏‎‎‎‎‏‏‎‎‎‏‎‏‎‎‏‏‎record audio‎‏‎‎‏‎"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‏‎‏‏‏‎‏‏‎‎‏‎‎‏‎‎‏‏‎‏‎‎‎‎‎‎‏‏‎‎‎‏‏‏‎‏‎‏‏‎‏‎‎‏‏‏‏‏‎‏‎‏‎‏‏‎‎‏‎This app can record audio using the microphone at any time.‎‏‎‎‏‎"</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‎‎‏‎‏‏‏‏‏‎‎‎‏‏‏‏‏‎‎‎‎‏‏‏‎‏‎‎‏‏‎‎‏‎‏‎‏‎‎‏‎‏‏‏‏‏‎‎‏‎‎‏‏‎‎‎‎‏‎send commands to the SIM‎‏‎‎‏‎"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‏‎‏‏‏‎‎‏‏‏‏‎‏‏‎‏‎‎‏‎‏‏‏‏‏‎‏‎‏‎‎‏‏‏‎‏‏‏‏‎‎‎‏‏‏‎‎‎‏‏‏‎‎‏‎‏‎‎Allows the app to send commands to the SIM. This is very dangerous.‎‏‎‎‏‎"</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‎‎‏‏‏‎‎‎‎‏‎‏‎‏‎‎‎‏‎‎‎‏‏‏‎‏‏‎‎‏‏‎‏‎‎‎‏‎‏‏‎‎‏‏‎‎‎‎‎‎‎‏‎‎‏‎‎‎recognize physical activity‎‏‎‎‏‎"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‏‏‎‎‏‏‏‏‏‏‏‎‎‏‎‏‎‏‎‏‏‎‎‎‎‏‎‏‏‎‎‎‎‏‏‎‎‎‎‏‏‏‎‎‎‎‎‎‎‏‎‏‏‏‏‏‎‎This app can recognize your physical activity.‎‏‎‎‏‎"</string>
     <string name="permlab_camera" msgid="3616391919559751192">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‎‎‎‏‏‎‎‎‎‎‎‎‎‎‎‎‏‎‏‎‎‏‎‏‎‎‏‎‏‎‏‎‏‏‏‏‏‎‎‏‏‏‎‏‏‎‏‏‎‎‎‎‏‏‎‎‎‎take pictures and videos‎‏‎‎‏‎"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‎‏‏‎‏‎‏‎‏‎‎‎‎‏‏‏‎‎‏‎‏‎‎‎‏‎‎‎‎‏‎‎‎‏‏‎‏‎‎‏‏‎‏‎‎‎‏‏‎‎‏‎‏‏‏‏‎‎This app can take pictures and record videos using the camera at any time.‎‏‎‎‏‎"</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‏‎‎‏‏‏‏‎‎‏‏‎‎‏‏‏‎‎‏‏‎‏‎‎‏‎‎‏‏‏‏‏‏‏‎‎‎‏‎‏‎‏‏‏‎‎‏‎‏‏‎‏‎‏‎‎control vibration‎‏‎‎‏‎"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‏‎‎‎‏‎‏‎‏‎‏‎‏‏‎‎‏‎‏‏‎‎‏‏‎‎‏‎‎‏‏‏‎‏‎‎‎‏‏‎‎‎‎‏‎‏‎‎‎‏‎‏‎‎‎‏‏‏‎Allows the app to modify your photo collection.‎‏‎‎‏‎"</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‎‎‎‏‏‎‎‏‎‎‎‏‎‏‎‎‎‏‎‏‎‎‏‏‏‏‎‏‏‎‏‎‎‎‏‏‏‎‎‎‎‎‏‏‎‎‏‏‏‏‏‎‏‏‏‎‎‎‎read locations from your media collection‎‏‎‎‏‎"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‎‏‏‏‎‏‎‏‏‏‎‎‏‎‎‏‎‎‎‏‏‏‏‏‏‎‎‏‎‎‏‎‏‏‏‏‎‏‎‏‎‎Allows the app to read locations from your media collection.‎‏‎‎‏‎"</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‏‎‏‎‏‏‎‎‏‏‎‎‏‏‎‎‎‏‎‎‏‎‎‎‏‏‏‎‎‏‎‏‎‎‎‎‎‎‎‎‎‏‎‎‎‏‎‏‏‎‎‏‏‎‎‎‎‎‎Application ‎‏‎‎‏‏‎<xliff:g id="APP">%s</xliff:g>‎‏‎‎‏‏‏‎ wants to authenticate.‎‏‎‎‏‎"</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‎‏‏‏‏‎‏‏‎‎‏‎‎‎‏‏‎‏‎‎‏‏‎‏‎‏‎‏‎‎‎‏‎‎‏‏‎‎‎‏‏‎‎‎‎‎‏‎‎‏‎‏‏‏‏‎‎‎Biometric hardware unavailable‎‏‎‎‏‎"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‎‎‎‏‏‎‎‏‏‏‎‎‎‏‎‎‏‏‏‏‎‎‎‏‏‎‎‎‎‎‏‎‏‏‏‏‎‏‏‏‏‏‏‏‏‎‏‎‎‎‏‎‎‏‎‏‏‎Partial fingerprint detected. Please try again.‎‏‎‎‏‎"</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‏‏‏‎‎‏‎‏‎‎‎‏‏‎‏‏‎‎‏‎‎‎‎‎‎‏‎‏‏‏‎‎‏‏‏‏‏‏‎‎‏‎‎‎‎‎‎‎‏‏‏‎‎‏‏‏‎‎Couldn\'t process fingerprint. Please try again.‎‏‎‎‏‎"</string>
@@ -1897,14 +1903,14 @@
       <item quantity="other">‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‎‎‏‏‎‏‎‏‏‎‏‎‎‎‎‎‎‎‏‏‎‏‏‎‏‏‏‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎‎‏‏‎‎‎‏‎‏‏‎‏‎‏‎‎‎‏‎‎‏‏‎<xliff:g id="COUNT">%1$s</xliff:g>‎‏‎‎‏‏‏‎ autofill suggestions‎‏‎‎‏‎</item>
       <item quantity="one">‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‎‎‏‏‎‏‎‏‏‎‏‎‎‎‎‎‎‎‏‏‎‏‏‎‏‏‏‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎‎‏‏‎‎‎‏‎‏‏‎‏‎‏‎‎One autofill suggestion‎‏‎‎‏‎</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‏‎‎‏‏‎‏‏‎‏‏‎‏‏‎‎‏‏‎‏‎‏‏‏‎‎‏‎‏‏‎‏‏‎‏‏‎‏‎‏‏‏‎‏‏‏‎‎‏‎‏‎‏‎‏‎‎‏‎Save to &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="LABEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt;?‎‏‎‎‏‎"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‏‏‏‎‏‏‏‏‏‏‎‏‎‏‎‎‏‏‏‎‏‏‏‏‏‏‎‎‏‎‎‏‏‎‎‎‎‎‏‎‏‏‎‎‎‎‎‎‏‎‎‎‏‏‎‎‏‎Save ‎‏‎‎‏‏‎<xliff:g id="TYPE">%1$s</xliff:g>‎‏‎‎‏‏‏‎ to &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="LABEL">%2$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt;?‎‏‎‎‏‎"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‎‎‏‎‏‏‎‏‏‏‏‏‏‏‎‎‏‏‏‎‎‏‏‎‎‏‏‎‏‏‎‏‎‎‎‎‎‏‎‏‎‏‏‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎Save ‎‏‎‎‏‏‎<xliff:g id="TYPE_0">%1$s</xliff:g>‎‏‎‎‏‏‏‎ and ‎‏‎‎‏‏‎<xliff:g id="TYPE_1">%2$s</xliff:g>‎‏‎‎‏‏‏‎ to &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="LABEL">%3$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt;?‎‏‎‎‏‎"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‎‎‏‎‏‏‎‏‏‎‎‎‏‎‎‎‎‏‏‏‎‎‏‏‎‏‏‎‏‏‎‏‏‎‏‏‎‏‎‏‎‎‏‏‎‏‎‏‎‏‎‎‎‏‎‎‏‎Save ‎‏‎‎‏‏‎<xliff:g id="TYPE_0">%1$s</xliff:g>‎‏‎‎‏‏‏‎, ‎‏‎‎‏‏‎<xliff:g id="TYPE_1">%2$s</xliff:g>‎‏‎‎‏‏‏‎, and ‎‏‎‎‏‏‎<xliff:g id="TYPE_2">%3$s</xliff:g>‎‏‎‎‏‏‏‎ to &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="LABEL">%4$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt;?‎‏‎‎‏‎"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‏‏‎‏‏‏‎‎‎‎‎‎‏‎‏‎‎‏‏‎‏‏‎‎‎‏‏‎‎‎‎‎‏‏‎‎‎‏‏‏‏‎‎‏‏‎‎‎‏‎‏‎‎‎‎‏‎‎Update to &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="LABEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt;?‎‏‎‎‏‎"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‎‏‎‏‏‎‏‏‎‏‏‏‏‏‎‎‏‏‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‎‏‏‎‏‎‏‏‏‎‎‎‏‎‏‎‎‎‎‏‏‎Update ‎‏‎‎‏‏‎<xliff:g id="TYPE">%1$s</xliff:g>‎‏‎‎‏‏‏‎ to &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="LABEL">%2$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt;?‎‏‎‎‏‎"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‏‏‏‎‏‏‏‎‏‏‎‎‏‏‏‏‎‏‏‎‎‏‎‎‏‏‎‎‏‎‎‏‏‎‏‏‏‏‎‎‎‎‏‏‎‎‏‎‏‎‏‏‏‎‏‎‎‏‎Update ‎‏‎‎‏‏‎<xliff:g id="TYPE_0">%1$s</xliff:g>‎‏‎‎‏‏‏‎ and ‎‏‎‎‏‏‎<xliff:g id="TYPE_1">%2$s</xliff:g>‎‏‎‎‏‏‏‎ to &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="LABEL">%3$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt;?‎‏‎‎‏‎"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‏‎‏‏‎‏‎‏‎‏‏‎‏‎‏‎‎‏‎‎‎‎‎‏‏‎‎‎‏‎‏‎‏‎‏‎‎‏‏‎‎‎‏‏‏‎‏‏‎‏‎‏‎‎‏‏‏‎Update ‎‏‎‎‏‏‎<xliff:g id="TYPE_0">%1$s</xliff:g>‎‏‎‎‏‏‏‎, ‎‏‎‎‏‏‎<xliff:g id="TYPE_1">%2$s</xliff:g>‎‏‎‎‏‏‏‎, and ‎‏‎‎‏‏‎<xliff:g id="TYPE_2">%3$s</xliff:g>‎‏‎‎‏‏‏‎ to &lt;b&gt;‎‏‎‎‏‏‎<xliff:g id="LABEL">%4$s</xliff:g>‎‏‎‎‏‏‏‎&lt;/b&gt;?‎‏‎‎‏‎"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‎‏‎‎‎‏‎‏‏‏‎‏‎‏‎‎‎‏‏‏‎‎‏‏‏‎‎‎‏‏‎‏‏‎‎‎‏‏‏‏‎‎‏‏‏‎‎‎‏‎‎‏‎‏‎‏‏‎Save to ‎‏‎‎‏‏‎"<b>"‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="LABEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎"</b>"‎‏‎‎‏‏‏‎?‎‏‎‎‏‎"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‎‎‏‏‏‎‏‏‎‎‏‎‎‎‏‏‏‎‎‏‏‏‏‏‏‎‏‎‎‏‎‎‏‎‏‏‏‏‏‏‏‎‏‎‏‎‎‎‎‏‎‏‎‏‎‏‎‎Save ‎‏‎‎‏‏‎<xliff:g id="TYPE">%1$s</xliff:g>‎‏‎‎‏‏‏‎ to ‎‏‎‎‏‏‎"<b>"‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="LABEL">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎"</b>"‎‏‎‎‏‏‏‎?‎‏‎‎‏‎"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‎‏‏‎‎‏‏‎‏‏‏‎‏‎‎‎‏‏‎‎‏‏‎‎‎‎‏‏‎‎‎‎‎‎‏‏‏‎‏‎‏‏‏‎‏‎‎‎‎‏‏‏‎‎‎‎‎‎‎‎Save ‎‏‎‎‏‏‎<xliff:g id="TYPE_0">%1$s</xliff:g>‎‏‎‎‏‏‏‎ and ‎‏‎‎‏‏‎<xliff:g id="TYPE_1">%2$s</xliff:g>‎‏‎‎‏‏‏‎ to ‎‏‎‎‏‏‎"<b>"‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="LABEL">%3$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎"</b>"‎‏‎‎‏‏‏‎?‎‏‎‎‏‎"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‏‎‎‎‎‎‏‏‎‎‎‎‎‎‏‏‎‎‎‏‏‏‎‎‏‎‎‏‏‏‏‏‏‎‏‏‏‎‎‏‏‏‎‏‎‏‏‎‏‏‏‎‎‏‎‏‏‎Save ‎‏‎‎‏‏‎<xliff:g id="TYPE_0">%1$s</xliff:g>‎‏‎‎‏‏‏‎, ‎‏‎‎‏‏‎<xliff:g id="TYPE_1">%2$s</xliff:g>‎‏‎‎‏‏‏‎, and ‎‏‎‎‏‏‎<xliff:g id="TYPE_2">%3$s</xliff:g>‎‏‎‎‏‏‏‎ to ‎‏‎‎‏‏‎"<b>"‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="LABEL">%4$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎"</b>"‎‏‎‎‏‏‏‎?‎‏‎‎‏‎"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‏‏‎‏‎‎‎‎‏‏‏‏‎‏‎‏‏‏‏‎‏‎‏‏‎‎‎‏‎‏‎‏‏‏‎‎‎‎‎‎‏‎‏‏‎‏‎‏‎‎‎‏‏‏‏‏‏‎Update in ‎‏‎‎‏‏‎"<b>"‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="LABEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎"</b>"‎‏‎‎‏‏‏‎?‎‏‎‎‏‎"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‎‎‎‏‎‏‏‎‎‎‏‏‎‎‏‎‎‎‏‎‎‎‎‎‎‏‏‏‎‏‏‎‏‎‎‏‏‎‎‎‏‎‎‏‎‎‏‎‎‏‏‏‏‏‎‎‏‎Update ‎‏‎‎‏‏‎<xliff:g id="TYPE">%1$s</xliff:g>‎‏‎‎‏‏‏‎ in ‎‏‎‎‏‏‎"<b>"‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="LABEL">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎"</b>"‎‏‎‎‏‏‏‎?‎‏‎‎‏‎"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‏‏‏‎‏‎‏‏‏‎‏‎‎‏‎‏‎‏‎‏‎‏‏‎‏‏‎‏‎‏‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‏‎‎‎‏‏‏‎‏‎‎‎Update ‎‏‎‎‏‏‎<xliff:g id="TYPE_0">%1$s</xliff:g>‎‏‎‎‏‏‏‎ and ‎‏‎‎‏‏‎<xliff:g id="TYPE_1">%2$s</xliff:g>‎‏‎‎‏‏‏‎ in ‎‏‎‎‏‏‎"<b>"‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="LABEL">%3$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎"</b>"‎‏‎‎‏‏‏‎?‎‏‎‎‏‎"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‏‎‎‏‎‏‏‎‎‎‏‎‏‏‎‎‎‏‎‏‏‏‎‎‎‏‏‏‎‎‏‎‎‎‎‏‎‏‎‎‏‎‏‎‎‏‏‏‎‏‎‎‏‎‎Update these items in ‎‏‎‎‏‏‎"<b>"‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="LABEL">%4$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎"</b>"‎‏‎‎‏‏‏‎: ‎‏‎‎‏‏‎<xliff:g id="TYPE_0">%1$s</xliff:g>‎‏‎‎‏‏‏‎, ‎‏‎‎‏‏‎<xliff:g id="TYPE_1">%2$s</xliff:g>‎‏‎‎‏‏‏‎, and ‎‏‎‎‏‏‎<xliff:g id="TYPE_2">%3$s</xliff:g>‎‏‎‎‏‏‏‎ ?‎‏‎‎‏‎"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‎‏‏‎‎‏‎‏‎‎‏‎‏‏‎‏‎‏‏‎‏‎‏‎‏‏‎‎‏‎‏‏‏‎‏‏‏‏‎‎‎‏‎‎‏‎‎‎‏‎‏‏‎‎‎‎‏‎Save‎‏‎‎‏‎"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‎‎‏‏‎‏‏‏‎‎‏‎‏‎‏‏‏‏‏‏‎‎‎‎‏‎‏‏‏‏‎‎‏‏‏‎‎‎‎‎‏‏‏‎‏‎‎‏‏‏‏‎‏‏‎‏‏‎No thanks‎‏‎‎‏‎"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‎‎‏‎‎‏‏‏‎‏‎‎‏‏‏‎‏‎‏‎‏‎‏‎‏‎‎‏‎‎‎‎‎‎‎‏‏‎‏‎‏‎‎‏‎‎‎‏‎‎‎‎‏‏‏‏‎‎Update‎‏‎‎‏‎"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 6176b7b..254d6bb 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Micrófono"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"grabar audio"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"¿Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; grabe audio?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"Reconocimiento de actividad"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"reconocer actividad"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"¿Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; reconozca tu actividad física?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Cámara"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"tomar fotografías y grabar videos"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"¿Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tome fotos y grabe videos?"</string>
@@ -299,7 +302,7 @@
     <string name="permgroupdesc_calllog" msgid="3006237336748283775">"leer y escribir el registro de llamadas telefónicas"</string>
     <string name="permgrouprequest_calllog" msgid="8487355309583773267">"¿Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; acceda al registro de las llamadas telefónicas?"</string>
     <string name="permgrouplab_phone" msgid="5229115638567440675">"Teléfono"</string>
-    <string name="permgroupdesc_phone" msgid="6234224354060641055">"realizar y administrar llamadas telefónicas"</string>
+    <string name="permgroupdesc_phone" msgid="6234224354060641055">"hacer y administrar llamadas telefónicas"</string>
     <string name="permgrouprequest_phone" msgid="9166979577750581037">"¿Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; haga y administre las llamadas telefónicas?"</string>
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Sensores corporales"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"acceder a los datos del sensor acerca de tus signos vitales"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Esta app puede obtener tu ubicación a través de fuentes de red, como torres de telefonía móvil y redes Wi-Fi. Estos servicios de ubicación deben estar activados y disponibles en tu tablet para que la app pueda usarlos."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Esta app puede obtener tu ubicación a través de fuentes de red, telefonía móvil y redes Wi-Fi. Estos servicios de ubicación deben estar activados y disponibles en tu TV para que la app pueda usarlos."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Esta app puede obtener tu ubicación a través de fuentes de red, como torres de celulares y redes Wi-Fi. Estos servicios de ubicación deben estar activados y disponibles en tu teléfono para que la app pueda usarlos."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"acceder a la ubicación exacta en segundo plano"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"Esta app puede obtener tu ubicación exacta en cualquier momento mientras esté en segundo plano. Los servicios de ubicación deben estar activados y disponibles en el teléfono para que la app pueda usarlos. Es posible que aumente el consumo de batería."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"acceder a la ubicación en segundo plano"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Si este permiso se otorga de manera adicional para aproximar o precisar el acceso a la ubicación, la app podrá acceder a la ubicación mientras se ejecuta en segundo plano."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"cambiar tu configuración de audio"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Permite que la aplicación modifique la configuración de audio global, por ejemplo, el volumen y el altavoz de salida."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"grabar audio"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"Esta app puede grabar audio con el micrófono en cualquier momento."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"enviar comandos a la tarjeta SIM"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Permite que la aplicación envíe comandos a la tarjeta SIM. Usar este permiso es peligroso."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"reconocer actividad física"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"Esta app puede reconocer tu actividad física."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"tomar fotografías y grabar videos"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"Esta app puede tomar fotos y grabar videos con la cámara en cualquier momento."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"controlar la vibración"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Permite que la app modifique tu colección de fotos."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"leer ubicaciones de tu colección de contenido multimedia"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Permite que la app lea las ubicaciones de tu colección de contenido multimedia."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"La aplicación de <xliff:g id="APP">%s</xliff:g> quiere autenticarte"</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"No hay hardware biométrico disponible"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"La huella digital se detectó parcialmente. Vuelve a intentarlo."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"No se pudo procesar la huella digital. Vuelve a intentarlo."</string>
@@ -1897,14 +1903,14 @@
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> sugerencias de Autocompletar</item>
       <item quantity="one">Una sugerencia de Autocompletar</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"¿Quieres guardar el contenido en &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"¿Quieres guardar tu <xliff:g id="TYPE">%1$s</xliff:g> en &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"¿Quieres guardar tu <xliff:g id="TYPE_0">%1$s</xliff:g> y <xliff:g id="TYPE_1">%2$s</xliff:g> en &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"¿Quieres guardar tu <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> y <xliff:g id="TYPE_2">%3$s</xliff:g> en &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"¿Quieres actualizar los datos en &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"¿Quieres actualizar tu <xliff:g id="TYPE">%1$s</xliff:g> en &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"¿Quieres actualizar tu <xliff:g id="TYPE_0">%1$s</xliff:g> y <xliff:g id="TYPE_1">%2$s</xliff:g> en &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"¿Quieres actualizar tu <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, y <xliff:g id="TYPE_2">%3$s</xliff:g> en &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"¿Quieres guardar en "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"¿Quieres guardar <xliff:g id="TYPE">%1$s</xliff:g> en "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"¿Quieres guardar <xliff:g id="TYPE_0">%1$s</xliff:g> y <xliff:g id="TYPE_1">%2$s</xliff:g> en "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"¿Quieres guardar <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> y <xliff:g id="TYPE_2">%3$s</xliff:g> en "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"¿Quieres actualizar en "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"¿Quieres actualizar <xliff:g id="TYPE">%1$s</xliff:g> en "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"¿Quieres actualizar <xliff:g id="TYPE_0">%1$s</xliff:g> y <xliff:g id="TYPE_1">%2$s</xliff:g> en "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"¿Quieres actualizar estos elementos en "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> y <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Guardar"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"No, gracias"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"Actualizar"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index dd766f7..3ac65fd 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Micrófono"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"grabar audio"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"¿Quieres permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; grabe audio?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"reconocimiento de actividad"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"reconocer actividad"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"¿Quieres permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; reconozca tu actividad física?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Cámara"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"hacer fotos y grabar vídeos"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"¿Quieres permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; haga fotos y grabe vídeos?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Esta aplicación puede obtener tu ubicación a partir de fuentes de red como las antenas de telefonía móvil y las redes Wi-Fi. Estos servicios de ubicación deben estar activados y disponibles en tu tablet para que la aplicación pueda usarlos."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Esta aplicación puede obtener tu ubicación a partir de fuentes de red como las antenas de telefonía móvil y las redes Wi-Fi. Estos servicios de ubicación deben estar activados y disponibles en tu TV para que la aplicación pueda usarlos."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Esta aplicación puede obtener tu ubicación a partir de fuentes de red como las antenas de telefonía móvil y las redes Wi-Fi. Estos servicios de ubicación deben estar activados y disponibles en tu teléfono para que la aplicación pueda usarlos."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"acceder a la ubicación exacta en segundo plano"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"Esta aplicación puede obtener tu ubicación exacta en cualquier momento cuando está en segundo plano. Estos servicios de ubicación deben estar activados y disponibles en tu teléfono para que la aplicación pueda utilizarlos. Es posible que aumente el consumo de batería."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"acceder a la ubicación en segundo plano"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Si se concede este permiso además del acceso a la ubicación exacta o aproximada, la aplicación podrá acceder a la ubicación mientras se ejecuta en segundo plano."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"cambiar la configuración de audio"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Permite que la aplicación modifique la configuración de audio global (por ejemplo, el volumen y el altavoz de salida)."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"grabar sonido"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"Esta aplicación puede grabar audio con el micrófono en cualquier momento."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"enviar comandos a la tarjeta SIM"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Permite que la aplicación envíe comandos a la tarjeta SIM. Este permiso es muy peligroso."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"reconocer actividad física"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"Esta aplicación puede reconocer tu actividad física."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"realizar fotografías y vídeos"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"Esta aplicación puede hacer fotografías y grabar vídeos con la cámara en cualquier momento."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"controlar la vibración"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Permite que la aplicación modifique tu colección de fotos."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"leer las ubicaciones de tu colección de contenido multimedia"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Permite que la aplicación lea las ubicaciones de tu colección de contenido multimedia."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"<xliff:g id="APP">%s</xliff:g> solicita tu autenticación."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Hardware biométrico no disponible"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Se ha detectado una huella digital parcial. Vuelve a intentarlo."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"No se ha podido procesar la huella digital. Vuelve a intentarlo."</string>
@@ -1897,14 +1903,14 @@
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> sugerencias de Autocompletar</item>
       <item quantity="one">1 sugerencia de Autocompletar</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"¿Guardar en &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"¿Guardar <xliff:g id="TYPE">%1$s</xliff:g> en &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"¿Guardar <xliff:g id="TYPE_0">%1$s</xliff:g> y <xliff:g id="TYPE_1">%2$s</xliff:g> en &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"¿Guardar <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> y <xliff:g id="TYPE_2">%3$s</xliff:g> en &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"¿Quieres actualizar a &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"¿Quieres actualizar <xliff:g id="TYPE">%1$s</xliff:g> a &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"¿Quieres actualizar <xliff:g id="TYPE_0">%1$s</xliff:g> y <xliff:g id="TYPE_1">%2$s</xliff:g> a &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"¿Quieres actualizar <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> y <xliff:g id="TYPE_2">%3$s</xliff:g> a &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"¿Guardar en "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"¿Guardar <xliff:g id="TYPE">%1$s</xliff:g> en "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"¿Guardar <xliff:g id="TYPE_0">%1$s</xliff:g> y <xliff:g id="TYPE_1">%2$s</xliff:g> en "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"¿Guardar <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> y <xliff:g id="TYPE_2">%3$s</xliff:g> en "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"¿Actualizar en "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"¿Actualizar <xliff:g id="TYPE">%1$s</xliff:g> en "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"¿Actualizar <xliff:g id="TYPE_0">%1$s</xliff:g> y <xliff:g id="TYPE_1">%2$s</xliff:g> en "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"¿Actualizar estos elementos en "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" (<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> y <xliff:g id="TYPE_2">%3$s</xliff:g>)?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Guardar"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"No, gracias"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"Actualizar"</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 650fcb6..b77b772 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Mikrofon"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"heli salvestamine"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"Kas lubada rakendusel &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; salvestada heli?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"Tegevuste tuvastamine"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"tegevuste tuvastamine"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"Kas lubada rakendusel &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; teie füüsilised tegevused tuvastada?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Kaamera"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"pildistamine ja video salvestamine"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"Kas lubada rakendusel &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; jäädvustada pilte ja salvestada videoid?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"See rakendus näeb võrguallikate (nt mobiilimastid ja WiFi-võrgud) abil teie asukohta. Need asukohateenused peavad olema sisse lülitatud ja teie tahvelarvutis saadaval, et rakendus neid kasutada saaks."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"See rakendus näeb võrguallikate (nt mobiilimastid ja WiFi-võrgud) abil teie asukohta. Need asukohateenused peavad olema sisse lülitatud ja teie teleris saadaval, et rakendus neid kasutada saaks."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"See rakendus näeb võrguallikate (nt mobiilimastid ja WiFi-võrgud) abil teie asukohta. Need asukohateenused peavad olema sisse lülitatud ja teie telefonis saadaval, et rakendus neid kasutada saaks."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"juurdepääs täpsele asukohale taustal"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"See rakendus hangib teie täpse asukoha alati, kui see töötab taustal. Need asukohateenused peavad olema sisse lülitatud ja teie telefonis saadaval, et rakendus saaks neid kasutada. See võib suurendada akutoite tarbimist."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"juurdepääs asukohale taustal"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Kui see on antud ka umbkaudsele või täpsele asukohale juurdepääsu puhul, saab rakendus taustal käitamisel juurdepääsu asukohale."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"muuda heliseadeid"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Võimaldab rakendusel muuta üldiseid heliseadeid, näiteks helitugevust ja seda, millist kõlarit kasutatakse väljundiks."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"salvesta heli"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"See rakendus saab mikrofoni kasutades mis tahes ajal heli salvestada."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"SIM-kaardile käskluste saatmine"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Lubab rakendusel saata käske SIM-kaardile. See on väga ohtlik."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"füüsiliste tegevuste tuvastamine"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"See rakendus saab tuvastada teie füüsilised tegevused."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"piltide ja videote tegemine"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"See rakendus saab mis tahes ajal kaameraga pildistada ja videoid salvestada."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"juhtige vibreerimist"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Võimaldab rakendusel muuta teie fotokogu."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"Lugeda teie meediakogus olevaid asukohti"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Võimaldab rakendusel lugeda teie meediakogus olevaid asukohti."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"Rakendus <xliff:g id="APP">%s</xliff:g> soovib autentimist."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Biomeetriline riistvara ei ole saadaval"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Tuvastati osaline sõrmejälg. Proovige uuesti."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Sõrmejälge ei õnnestunud töödelda. Proovige uuesti."</string>
@@ -1897,14 +1903,14 @@
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> automaatse täitmise soovitust</item>
       <item quantity="one">Üks automaatse täitmise soovitus</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"Kas salvestada teenusesse &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Kas salvestada üksus <xliff:g id="TYPE">%1$s</xliff:g> teenusesse &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Kas salvestada üksused <xliff:g id="TYPE_0">%1$s</xliff:g> ja <xliff:g id="TYPE_1">%2$s</xliff:g> teenusesse &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Kas salvestada üksused <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ja <xliff:g id="TYPE_2">%3$s</xliff:g> teenusesse &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"Kas värskendada valikule &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Kas värskendada üksus <xliff:g id="TYPE">%1$s</xliff:g> valikule &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Kas värskendada üksused <xliff:g id="TYPE_0">%1$s</xliff:g> ja <xliff:g id="TYPE_1">%2$s</xliff:g> valikule &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Kas värskendada üksused <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ja <xliff:g id="TYPE_2">%3$s</xliff:g> valikule &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"Kas salvestada teenuses "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"Kas salvestada <xliff:g id="TYPE">%1$s</xliff:g> teenuses "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"Kas salvestada <xliff:g id="TYPE_0">%1$s</xliff:g> ja <xliff:g id="TYPE_1">%2$s</xliff:g> teenuses "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"Kas salvestada <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ja <xliff:g id="TYPE_2">%3$s</xliff:g> teenuses "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"Kas värskendada üksust teenuses "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"Kas värskendada üksust <xliff:g id="TYPE">%1$s</xliff:g> teenuses "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"Kas värskendada üksusi <xliff:g id="TYPE_0">%1$s</xliff:g> ja <xliff:g id="TYPE_1">%2$s</xliff:g> teenuses "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"Kas värskendada teenuses "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" neid üksusi: <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ja <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Salvesta"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Tänan, ei"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"Värskenda"</string>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index 6a6fdbf..26d8b31 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Mikrofonoa"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"grabatu audioa"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari audioa grabatzea baimendu nahi diozu?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"Ariketa hautematea"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"hauteman ariketa"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"Ariketa fisikoa hautematea baimendu nahi diozu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Kamera"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"atera argazkiak eta grabatu bideoak"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; aplikazioari argazkiak ateratzea eta bideoak grabatzea baimendu nahi diozu?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Aplikazioak zure kokapenaren berri izan dezake sareen iturburuak (adibidez, telefonia mugikorreko dorreak eta Wi-Fi sareak) erabilita. Kokapen-zerbitzu horiek aktibatuta eta erabilgarri izan behar dituzu tabletan, aplikazioak erabil ditzan."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Aplikazioak zure kokapenaren berri izan dezake sareen iturburuak (adibidez, telefonia mugikorreko dorreak eta Wi-Fi sareak) erabilita. Kokapen-zerbitzu horiek aktibatuta eta erabilgarri izan behar dituzu telebistan, aplikazioak erabil ditzan."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Aplikazioak zure kokapenaren berri izan dezake sareen iturburuak (adibidez, telefonia mugikorreko dorreak eta Wi-Fi sareak) erabilita. Kokapen-zerbitzu horiek aktibatuta eta erabilgarri izan behar dituzu telefonoan, aplikazioak erabil ditzan."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"lortu kokapen zehatza atzeko planoan"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"Aplikazioak zure kokapen zehatza lor dezake atzeko planoan funtzionatzen duenean. Kokapen-zerbitzu horiek aktibatuta eta erabilgarri izan behar dituzu telefonoan, aplikazioak erabil ditzan. Baliteke bateria gehiago erabiltzea."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"Atzitu kokapena atzeko planoan"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Baimen hau ematen bada kokapen zehatz edo gutxi gorabeherakorako sarbideaz gain, atzeko planoan exekutatu bitartean atzitu ahalko du aplikazioak kokapena."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"aldatu audio-ezarpenak"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Audio-ezarpen orokorrak aldatzeko baimena ematen dio; besteak beste, bolumena eta irteerarako zer bozgorailu erabiltzen den."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"grabatu audioa"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"Aplikazioak edonoiz erabil dezake mikrofonoa audioa grabatzeko."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"bidali aginduak SIM txartelera"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"SIM txartelera aginduak bidaltzeko aukera ematen die aplikazioei. Oso arriskutsua da."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"hauteman ariketa fisikoa"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"Aplikazioak ariketa fisikoa hauteman dezake."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"atera argazkiak eta grabatu bideoak"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"Aplikazioak edonoiz erabil dezake kamera argazkiak ateratzeko eta bideoak grabatzeko."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"kontrolatu dardara"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Argazki-bilduma aldatzea baimentzen die aplikazioei."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"multimedia-edukien bildumako kokapena irakurri"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Multimedia-edukien bildumako kokapena irakurtzea baimentzen die aplikazioei."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"<xliff:g id="APP">%s</xliff:g> aplikazioak autentifikatu egin nahi du."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Hardware biometrikoa ez dago erabilgarri"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Hatz-marka digitala ez da osorik hauteman. Saiatu berriro."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Ezin izan da prozesatu hatz-marka. Saiatu berriro."</string>
@@ -1898,14 +1904,14 @@
       <item quantity="other">Automatikoki betetzeko <xliff:g id="COUNT">%1$s</xliff:g> iradokizun</item>
       <item quantity="one">Automatikoki betetzeko 1 iradokizun</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; zerbitzuan gorde nahi duzu?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"<xliff:g id="TYPE">%1$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; zerbitzuan gorde nahi duzu?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"<xliff:g id="TYPE_0">%1$s</xliff:g> eta <xliff:g id="TYPE_1">%2$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; zerbitzuan gorde nahi dituzu?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> eta <xliff:g id="TYPE_2">%3$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; zerbitzuan gorde nahi dituzu?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; zerbitzuan eguneratu nahi duzu?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"<xliff:g id="TYPE">%1$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; zerbitzuan eguneratu nahi duzu?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"<xliff:g id="TYPE_0">%1$s</xliff:g> eta <xliff:g id="TYPE_1">%2$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; zerbitzuan eguneratu nahi dituzu?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> eta <xliff:g id="TYPE_2">%3$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; zerbitzuan eguneratu nahi dituzu?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" zerbitzuan gorde nahi duzu?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594"><b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" zerbitzuan gorde nahi duzu <xliff:g id="TYPE">%1$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432"><b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" zerbitzuan gorde nahi dituzu <xliff:g id="TYPE_0">%1$s</xliff:g> eta <xliff:g id="TYPE_1">%2$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555"><b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" zerbitzuan gorde nahi dituzu <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> eta <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" zerbitzuan eguneratu nahi duzu?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233"><b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" zerbitzuan eguneratu nahi duzu <xliff:g id="TYPE">%1$s</xliff:g>?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484"><b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" zerbitzuan eguneratu nahi dituzu <xliff:g id="TYPE_0">%1$s</xliff:g> eta <xliff:g id="TYPE_1">%2$s</xliff:g>?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922"><b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" zerbitzuan eguneratu nahi dituzu <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> eta <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Gorde"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Ez, eskerrik asko"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"Eguneratu"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 2310f9e..2d6c2ef 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"میکروفن"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"ضبط صدا"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"‏به &lt;/b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; اجازه داده شود صدا ضبط کند؟"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"تشخیص فعالیت"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"تشخیص فعالیت"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"‏به &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; اجازه می‌دهید فعالیت فیزیکی‌تان را تشخیص دهد؟"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"دوربین"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"عکس گرفتن و فیلم‌برداری"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"‏به &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; اجازه داده شود عکس بگیرد و ویدیو ضبط کند؟"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"‏این برنامه می‌تواند براساس منابع شبکه مانند دکل‌های مخابراتی و شبکه‌های Wi-Fi، مکان شما را تشخیص دهد. این خدمات مکان باید روشن و در رایانه لوحی شما دردسترس باشند تا برنامه بتواند از آن‌ها استفاده کند."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"‏این برنامه می‌تواند براساس منابع شبکه مانند دکل‌های مخابراتی و شبکه‌های Wi-Fi، مکان شما را تشخیص دهد. این خدمات مکان باید روشن و در تلویزیون شما دردسترس باشند تا برنامه بتواند از آن‌ها استفاده کند."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"‏این برنامه می‌تواند براساس منابع شبکه مانند دکل‌های مخابراتی و شبکه‌های Wi-Fi، مکان شما را تشخیص دهد. این خدمات مکان باید روشن و در تلفن شما دردسترس باشند تا برنامه بتواند از آن‌ها استفاده کند."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"دسترسی به موقعیت مکانی دقیق در پس‌زمینه"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"هرزمان این برنامه در پس‌زمینه باشد می‌تواند موقعیت مکانی دقیق شما را دریافت کند. برای اینکه برنامه بتواند از خدمات مکان استفاده کند، این خدمات باید در تلفنتان روشن و دردسترس باشد. ممکن است با این کار مصرف باتری افزایش یابد."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"دسترسی به مکان در پس‌زمینه"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"اگر این مجوز نیز برای دسترسی دقیق یا تقریبی به مکان داده شود، برنامه می‌تواند درحین اجرا در پس‌زمینه به مکان دسترسی پیدا کند."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"تغییر تنظیمات صوتی"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"به برنامه امکان می‌دهد تنظیمات صوتی کلی مانند میزان صدا و بلندگوی مورد استفاده برای پخش صدا را تغییر دهد."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"ضبط صدا"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"این برنامه می‌تواند در هرزمانی با استفاده از میکروفون صدا ضبط کند."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"ارسال فرمان به سیم کارت"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"به برنامه اجازه ارسال دستورات به سیم کارت را می‌دهد. این بسیار خطرناک است."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"تشخیص فعالیت فیزیکی"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"این برنامه نمی‌تواند فعالیت فیزیکی‌تان را تشخیص دهد."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"عکسبرداری و فیلمبرداری"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"این برنامه می‌تواند در هرزمانی با استفاده از دوربین عکس و فیلم بگیرد."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"کنترل لرزش"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"به برنامه اجازه می‌دهد مجموعه عکستان را تغییر دهد."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"خواندن مکان‌ها از مجموعه رسانه شما"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"به برنامه اجازه می‌دهد مکان‌ها را از مجموعه رسانه‌تان بخواند."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"برنامه <xliff:g id="APP">%s</xliff:g> می‌خواهد احراز هویت کند."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"سخت‌افزار زیست‌سنجی دردسترس نیست"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"بخشی از اثر انگشت شناسایی شد. لطفاً دوباره امتحان کنید."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"اثرانگشت پردازش نشد. لطفاً دوباره امتحان کنید."</string>
@@ -1192,7 +1198,7 @@
     <string name="volume_music" msgid="5421651157138628171">"میزان صدای رسانه"</string>
     <string name="volume_music_hint_playing_through_bluetooth" msgid="9165984379394601533">"پخش از طریق بلوتوث"</string>
     <string name="volume_music_hint_silent_ringtone_selected" msgid="8310739960973156272">"آهنگ زنگ روی بی‌صدا تنظیم شد"</string>
-    <string name="volume_call" msgid="3941680041282788711">"میزان صدای هنگام تماس"</string>
+    <string name="volume_call" msgid="3941680041282788711">"صدا حینِ تماس"</string>
     <string name="volume_bluetooth_call" msgid="2002891926351151534">"میزان صدای تماس بلوتوث"</string>
     <string name="volume_alarm" msgid="1985191616042689100">"میزان صدای هشدار"</string>
     <string name="volume_notification" msgid="2422265656744276715">"میزان صدای اعلان"</string>
@@ -1897,14 +1903,14 @@
       <item quantity="one"><xliff:g id="COUNT">%1$s</xliff:g> پیشنهاد تکمیل خودکار</item>
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> پیشنهاد تکمیل خودکار</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"‏در &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; ذخیره شود؟"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"‏<xliff:g id="TYPE">%1$s</xliff:g> در &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; ذخیره شود؟"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"‏<xliff:g id="TYPE_0">%1$s</xliff:g> و <xliff:g id="TYPE_1">%2$s</xliff:g> در &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; ذخیره شوند؟"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"‏<xliff:g id="TYPE_0">%1$s</xliff:g>، <xliff:g id="TYPE_1">%2$s</xliff:g> و <xliff:g id="TYPE_2">%3$s</xliff:g> در &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; ذخیره شوند؟"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"‏به &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; به‌روزرسانی شود؟"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"‏<xliff:g id="TYPE">%1$s</xliff:g> به &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; به‌روزرسانی شود؟"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"‏<xliff:g id="TYPE_0">%1$s</xliff:g> و <xliff:g id="TYPE_1">%2$s</xliff:g> به &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; به‌روزرسانی شود؟"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"‏<xliff:g id="TYPE_0">%1$s</xliff:g>، <xliff:g id="TYPE_1">%2$s</xliff:g>، و <xliff:g id="TYPE_2">%3$s</xliff:g> به &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; به‌روزرسانی شود؟"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"در "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" ذخیره شود؟"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"<xliff:g id="TYPE">%1$s</xliff:g> در "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" ذخیره شود؟"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"<xliff:g id="TYPE_0">%1$s</xliff:g> و <xliff:g id="TYPE_1">%2$s</xliff:g> در "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" ذخیره شود؟"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"<xliff:g id="TYPE_0">%1$s</xliff:g>، <xliff:g id="TYPE_1">%2$s</xliff:g> و <xliff:g id="TYPE_2">%3$s</xliff:g> در "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" ذخیره شود؟"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"در "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" به‌روزرسانی شود؟"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"<xliff:g id="TYPE">%1$s</xliff:g> در "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" به‌روزرسانی شود؟"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"<xliff:g id="TYPE_0">%1$s</xliff:g> و <xliff:g id="TYPE_1">%2$s</xliff:g> در "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" به‌روزرسانی شود؟"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"این موارد در "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>، <xliff:g id="TYPE_1">%2$s</xliff:g> و <xliff:g id="TYPE_2">%3$s</xliff:g> به‌روزرسانی شود؟"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"ذخیره"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"نه سپاسگزارم"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"به‌روزرسانی"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 4f2531c..39c4912 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Mikrofoni"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"tallentaa ääntä"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"Saako &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; nauhoittaa ääntä?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"Liikunnan tunnistaminen"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"tunnistaa liikunnan"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"Saako &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tunnistaa liikkumisesi?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Kamera"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"ottaa kuvia ja videoita"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"Saako &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ottaa kuvia ja nauhoittaa videoita?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Tämä sovellus voi määrittää sijaintisi matkapuhelinverkon tukiasemien, Wi-Fi-verkkojen ja muiden verkkolähteiden perusteella. Näiden sijaintipalveluiden tulee olla käytössä ja käytettävissä tabletillasi, jotta sovellus voi käyttää niitä."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Tämä sovellus voi määrittää sijaintisi matkapuhelinverkon tukiasemien, Wi-Fi-verkkojen ja muiden verkkolähteiden perusteella. Näiden sijaintipalveluiden tulee olla käytössä ja käytettävissä TV:lläsi, jotta sovellus voi käyttää niitä."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Tämä sovellus voi määrittää sijaintisi matkapuhelinverkon tukiasemien, Wi-Fi-verkkojen ja muiden verkkolähteiden perusteella. Näiden sijaintipalveluiden tulee olla käytössä ja käytettävissä puhelimellasi, jotta sovellus voi käyttää niitä."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"käyttää tarkkaa sijaintia taustalla"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"Tämä sovellus saa tarkat sijaintitietosi käyttöönsä taustalla. Näiden sijaintipalveluiden tulee olla käytössä ja käytettävissä puhelimellasi, jotta sovellus voi käyttää niitä. Tämä voi lisätä akun kulutusta."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"käytä sijaintia taustalla"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Jos tämä myönnetään karkean tai tarkan sijainnin käyttöoikeuden lisäksi, sovellus voi käyttää sijaintia toimiessaan taustalla."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"muuta ääniasetuksia"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Antaa sovelluksen muokata yleisiä ääniasetuksia, kuten äänenvoimakkuutta ja käytettävää kaiutinta."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"tallentaa ääntä"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"Tämä sovellus voi tallentaa mikrofonilla ääntä koska tahansa."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"lähettää komentoja SIM-kortille"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Antaa sovelluksen lähettää komentoja SIM-kortille. Tämä ei ole turvallista."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"tunnistaa liikkumisen"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"Sovellus voi tunnistaa liikkumisesi."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"ota kuvia ja videoita"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"Tämä sovellus voi ottaa kameralla kuvia ja videoita koska tahansa."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"hallitse värinää"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Antaa sovelluksen muokata kuvakokoelmaasi."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"lukea mediakokoelmasi sijainteja"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Antaa sovelluksen lukea mediakokoelmasi sijainteja."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"<xliff:g id="APP">%s</xliff:g> pyytää todentamista"</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Biometrinen laitteisto ei käytettävissä"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Sormenjälki havaittiin vain osittain. Yritä uudelleen."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Sormenjäljen käsittely epäonnistui. Yritä uudelleen."</string>
@@ -636,9 +642,9 @@
     <string name="permdesc_bindCarrierServices" msgid="1391552602551084192">"Antaa sovelluksen luoda sidoksen operaattorin palveluun. Ei tavallisten sovelluksien käyttöön."</string>
     <string name="permlab_access_notification_policy" msgid="4247510821662059671">"Älä häiritse -tilan käyttöoikeus"</string>
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Sallii sovelluksen lukea ja muokata Älä häiritse -tilan asetuksia."</string>
-    <string name="policylab_limitPassword" msgid="4497420728857585791">"Aseta salasanasäännöt"</string>
-    <string name="policydesc_limitPassword" msgid="2502021457917874968">"Hallinnoi ruudun ruudun lukituksen salasanoissa ja PIN-koodeissa sallittuja merkkejä ja niiden pituutta."</string>
-    <string name="policylab_watchLogin" msgid="5091404125971980158">"Tarkkaile näytön avaamisyrityksiä"</string>
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"Asentaa salasanasäännöt"</string>
+    <string name="policydesc_limitPassword" msgid="2502021457917874968">"Hallinnoida ruudun lukituksen salasanoissa ja PIN-koodeissa sallittuja merkkejä ja niiden pituutta."</string>
+    <string name="policylab_watchLogin" msgid="5091404125971980158">"Tarkkailla näytön avaamisyrityksiä"</string>
     <string name="policydesc_watchLogin" product="tablet" msgid="3215729294215070072">"Valvoo väärien salasanojen lukumäärää näytön lukituksen poistossa sekä lukitsee tablet-laitteen tai poistaa sen tiedot, jos salasana syötetään väärin liian monta kertaa."</string>
     <string name="policydesc_watchLogin" product="TV" msgid="2707817988309890256">"Valvo väärien salasanojen määrää poistettaessa näytön lukitusta ja lukitse televisio tai poista television kaikki tiedot, jos salasana kirjoitetaan väärin liian monta kertaa."</string>
     <string name="policydesc_watchLogin" product="default" msgid="5712323091846761073">"Valvoo väärien salasanojen lukumäärää näytön lukituksen poistossa ja lukitsee puhelimen tai poistaa sen kaikki tiedot, jos väärä salasana syötetään liian monta kertaa."</string>
@@ -659,14 +665,14 @@
     <string name="policydesc_wipeData_secondaryUser" product="default" msgid="6787904546711590238">"Pyyhi tämän käyttäjän tiedot puhelimesta ilman varoitusta."</string>
     <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Aseta laitteen yleinen välityspalvelin"</string>
     <string name="policydesc_setGlobalProxy" msgid="8459859731153370499">"Aseta laitteen yleinen välityspalvelin käyttöön, kun käytäntö on käytössä. Vain laitteen omistaja voi asettaa yleisen välityspalvelimen."</string>
-    <string name="policylab_expirePassword" msgid="5610055012328825874">"Määritä ruudun lukituksen salasanan viimeinen voimassaolopäivä"</string>
-    <string name="policydesc_expirePassword" msgid="5367525762204416046">"Muuta sitä, miten usein ruudun lukituksen salasana, PIN-koodi tai kuvio tulee vaihtaa."</string>
-    <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Aseta tallennustilan salaus"</string>
+    <string name="policylab_expirePassword" msgid="5610055012328825874">"Määrittää ruudun lukituksen salasanan viimeinen voimassaolopäivä"</string>
+    <string name="policydesc_expirePassword" msgid="5367525762204416046">"Muuttaa sitä, miten usein ruudun lukituksen salasana, PIN-koodi tai kuvio tulee vaihtaa."</string>
+    <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Asettaa tallennustilan salaus"</string>
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"Pakota tallennettujen sovellustietojen salaus."</string>
-    <string name="policylab_disableCamera" msgid="6395301023152297826">"Poista kamerat käytöstä"</string>
-    <string name="policydesc_disableCamera" msgid="2306349042834754597">"Estä laitteen kaikkien kameroiden käyttö."</string>
+    <string name="policylab_disableCamera" msgid="6395301023152297826">"Poistaa kamerat käytöstä"</string>
+    <string name="policydesc_disableCamera" msgid="2306349042834754597">"Estää laitteen kaikkien kameroiden käytön."</string>
     <string name="policylab_disableKeyguardFeatures" msgid="8552277871075367771">"Estää lukitun näytön toimintoja"</string>
-    <string name="policydesc_disableKeyguardFeatures" msgid="2044755691354158439">"Estä joidenkin lukitun näytön toimintojen käyttö."</string>
+    <string name="policydesc_disableKeyguardFeatures" msgid="2044755691354158439">"Estää joidenkin lukitun näytön toimintojen käytön."</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Koti"</item>
     <item msgid="869923650527136615">"Mobiili"</item>
@@ -1897,14 +1903,14 @@
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> automaattisen täytön ehdotusta</item>
       <item quantity="one">Yksi automaattisen täytön ehdotus</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"Tallennetaanko tämä palveluun &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Tallennetaanko <xliff:g id="TYPE">%1$s</xliff:g> palveluun &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Tallennetaanko <xliff:g id="TYPE_0">%1$s</xliff:g> ja <xliff:g id="TYPE_1">%2$s</xliff:g> palveluun &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Tallennetaanko <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ja <xliff:g id="TYPE_2">%3$s</xliff:g> palveluun &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"Muutetaanko tämä palvelussa &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Muutetaanko <xliff:g id="TYPE">%1$s</xliff:g>, jonka &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; on tallentanut?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Muutetaanko <xliff:g id="TYPE_0">%1$s</xliff:g> ja <xliff:g id="TYPE_1">%2$s</xliff:g>, jotka &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; on tallentanut?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Muutetaanko <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ja <xliff:g id="TYPE_2">%3$s</xliff:g>, jotka &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; on tallentanut?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"Saako "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" tallentaa tämän?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"Tallennetaanko <xliff:g id="TYPE">%1$s</xliff:g> ("<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>")?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"Tallennetaanko <xliff:g id="TYPE_0">%1$s</xliff:g> ja <xliff:g id="TYPE_1">%2$s</xliff:g> ("<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>")?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"Tallennetaanko <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ja <xliff:g id="TYPE_2">%3$s</xliff:g> ("<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>")?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"Päivitetäänkö "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"Päivitetäänkö <xliff:g id="TYPE">%1$s</xliff:g> ("<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>")?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"Päivitetäänkö <xliff:g id="TYPE_0">%1$s</xliff:g> ja <xliff:g id="TYPE_1">%2$s</xliff:g> ("<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>")?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"Päivitetäänkö nämä ("<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"): <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ja <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Tallenna"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Ei kiitos"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"Muuta"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 39889ec..a03f25f 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Microphone"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"enregistrer des fichiers audio"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"Autoriser &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&amp;gt à enregistrer l\'audio?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"Reconnaissance des activités"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"reconnaître les activités"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"Autoriser « <xliff:g id="APP_NAME">%1$s</xliff:g> » à reconnaître vos activités physiques?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Appareil photo"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"prendre des photos et filmer des vidéos"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"Autoriser « <xliff:g id="APP_NAME">%1$s</xliff:g> » à prendre des photos et à filmer des vidéos?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Cette application peut déterminer votre position à l\'aide de différentes sources de localisation sur le réseau, comme les tours de téléphonie cellulaire et les réseaux Wi-Fi. Ces services de localisation doivent être activés et accessibles sur votre tablette pour que l\'application puisse les utiliser."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Cette application peut déterminer votre position à l\'aide de différentes sources de localisation sur le réseau, comme les tours de téléphonie cellulaire et les réseaux Wi-Fi. Ces services de localisation doivent être activés et accessibles sur votre téléviseur pour que l\'application puisse les utiliser."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Cette application peut déterminer votre position à l\'aide de différentes sources de localisation sur le réseau, comme les tours de téléphonie cellulaire et les réseaux Wi-Fi. Ces services de localisation doivent être activés et accessibles sur votre téléphone pour que l\'application puisse les utiliser."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"accéder à votre position précise en arrière-plan"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"Cette application peut obtenir votre position exacte à tout moment en arrière-plan. Ces services de localisation doivent être activés et accessibles sur votre téléviseur pour que l\'application puisse les utiliser. Cela peut entraîner une utilisation accrue de la pile."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"accès à la localisation en arrière-plan"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Si cette autorisation est accordée en plus de l\'accès approximatif ou précis à la localisation, alors l\'application peut accéder à la localisation lorsqu\'elle fonctionne en arrière-plan."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"modifier vos paramètres audio"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Permet à l\'application de modifier les paramètres audio généraux, tels que le volume et la sortie audio utilisée."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"enregistrer des fichiers audio"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"Cette application peut enregistrer de l\'audio à l\'aide du microphone en tout temps."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"envoyer des commandes à la carte SIM"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Permet à l\'application d\'envoyer des commandes à la carte SIM. Cette fonctionnalité est très dangereuse."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"reconnaître les activités physiques"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"Cette application peut reconnaître vos activités physiques."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"prendre des photos et filmer des vidéos"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"Cette application peut prendre des photos et enregistrer des vidéos à l\'aide de l\'appareil photo en tout temps."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"gérer le vibreur"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Autorise l\'application à modifier votre collection de photos."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"lire les positions issues de votre collection multimédia"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Autorise l\'application à lire les positions indiquées dans votre collection multimédia."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"<xliff:g id="APP">%s</xliff:g> vous demande de vous authentifier."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Matériel biométrique indisponible"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Empreinte digitale partielle détectée. Veuillez essayer de nouveau."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Impossible de traiter les empreintes digitales. Veuillez essayer de nouveau."</string>
@@ -1897,14 +1903,14 @@
       <item quantity="one"><xliff:g id="COUNT">%1$s</xliff:g> suggestion de remplissage automatique</item>
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> suggestions de remplissage automatique</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"Enregistrer dans &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Enregistrer <xliff:g id="TYPE">%1$s</xliff:g> dans &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Enregistrer <xliff:g id="TYPE_0">%1$s</xliff:g> et <xliff:g id="TYPE_1">%2$s</xliff:g> dans &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Enregistrer <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> et <xliff:g id="TYPE_2">%3$s</xliff:g> dans &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"Mettre à jour vers &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Mettre à jour <xliff:g id="TYPE">%1$s</xliff:g> vers &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Mettre à jour <xliff:g id="TYPE_0">%1$s</xliff:g> et <xliff:g id="TYPE_1">%2$s</xliff:g> vers &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Mettre à jour <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> et <xliff:g id="TYPE_2">%3$s</xliff:g> vers &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"Enregistrer sous "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"Enregistrer <xliff:g id="TYPE">%1$s</xliff:g> sous "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"Enregistrer <xliff:g id="TYPE_0">%1$s</xliff:g> et <xliff:g id="TYPE_1">%2$s</xliff:g> sous "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"Enregistrer <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> et <xliff:g id="TYPE_2">%3$s</xliff:g> sous "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"Mettre à jour sous "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"Mettre à jour <xliff:g id="TYPE">%1$s</xliff:g> sous "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"Mettre à jour <xliff:g id="TYPE_0">%1$s</xliff:g> et <xliff:g id="TYPE_1">%2$s</xliff:g> sous "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"Mettre à jour ces éléments sous "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" : <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> et <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Enregistrer"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Non, merci"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"Mettre à jour"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 9759415..5e9d5c1 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -138,7 +138,7 @@
     <string name="wfcSpnFormat_spn_vowifi" msgid="4444638298656953681">"VoWiFi <xliff:g id="SPN">%s</xliff:g>"</string>
     <string name="wifi_calling_off_summary" msgid="8720659586041656098">"Désactivé"</string>
     <string name="wfc_mode_wifi_preferred_summary" msgid="1994113411286935263">"Wi-Fi de préférence"</string>
-    <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Priorité au mobile"</string>
+    <string name="wfc_mode_cellular_preferred_summary" msgid="1988279625335345908">"Données mobiles de préférence"</string>
     <string name="wfc_mode_wifi_only_summary" msgid="2379919155237869320">"Wi-Fi uniquement"</string>
     <string name="cfTemplateNotForwarded" msgid="1683685883841272560">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g> : non transféré"</string>
     <string name="cfTemplateForwarded" msgid="1302922117498590521">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g> : <xliff:g id="DIALING_NUMBER">{1}</xliff:g>"</string>
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Microphone"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"enregistrer des fichiers audio"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"Permettre à &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; d\'enregistrer des contenus audio ?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"Reconnaissance de l\'activité"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"reconnaître l\'activité"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"Autoriser &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; à reconnaître votre activité physique ?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Appareil photo"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"prendre des photos et enregistrer des vidéos"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"Permettre à &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; de prendre des photos et de filmer des vidéos ?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Cette application peut obtenir votre position via des sources de réseau telles que les antennes-relais et les réseaux Wi-Fi. Ces services de localisation doivent être activés et disponibles sur votre tablette pour que l\'application puisse les utiliser."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Cette application peut obtenir votre position via des sources de réseau telles que les antennes-relais et les réseaux Wi-Fi. Ces services de localisation doivent être activés et disponibles sur votre téléviseur pour que l\'application puisse les utiliser."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Cette application peut obtenir votre position via des sources de réseau telles que les antennes-relais et les réseaux Wi-Fi. Ces services de localisation doivent être activés et disponibles sur votre téléphone pour que l\'application puisse les utiliser."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"accéder à la position exacte en arrière-plan"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"Cette application peut obtenir votre position exacte à tout moment lorsqu\'elle s\'exécute en arrière-plan. Ces services de localisation doivent être activés et disponibles sur votre téléphone pour que l\'application puisse les utiliser. Ceci peut réduire l\'autonomie de la batterie."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"accéder à la position en arrière-plan"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Si vous lui accordez cette autorisation en plus de l\'accès à la position approximative ou précise, l\'application peut accéder à votre position lorsqu\'elle est s\'exécute en arrière-plan."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"modifier vos paramètres audio"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Permet à l\'application de modifier les paramètres audio généraux, tels que le volume et la sortie audio utilisée."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"enregistrer des fichiers audio"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"Cette application peut utiliser le micro pour enregistrer du contenu audio à tout moment."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"envoyer des commandes à la carte SIM"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Autoriser l\'envoi de commandes à la carte SIM via l\'application. Cette fonctionnalité est très risquée."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"reconnaître l\'activité physique"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"Cette application peut reconnaître votre activité physique."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"prendre des photos et enregistrer des vidéos"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"Cette application peut utiliser l\'appareil photo pour prendre des photos et enregistrer des vidéos à tout moment."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"contrôler le vibreur"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Autorise l\'application à modifier votre bibliothèque photo."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"consulter des positions issues de votre bibliothèque multimédia"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Autorise l\'application à consulter des positions issues de votre bibliothèque multimédia."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"L\'application <xliff:g id="APP">%s</xliff:g> veut vous authentifier."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Matériel biométrique indisponible"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Empreinte numérique partiellement détectée. Veuillez réessayer."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Impossible de reconnaître l\'empreinte numérique. Veuillez réessayer."</string>
@@ -1897,14 +1903,14 @@
       <item quantity="one"><xliff:g id="COUNT">%1$s</xliff:g> suggestion de saisie automatique</item>
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> suggestions de saisie automatique</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"Enregistrer dans &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; ?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Enregistrer <xliff:g id="TYPE">%1$s</xliff:g> dans &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; ?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Enregistrer <xliff:g id="TYPE_0">%1$s</xliff:g> et <xliff:g id="TYPE_1">%2$s</xliff:g> dans &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; ?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Enregistrer <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> et <xliff:g id="TYPE_2">%3$s</xliff:g> dans &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; ?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"Faire passer à &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; ?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Faire passer <xliff:g id="TYPE">%1$s</xliff:g> à &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; ?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Faire passer <xliff:g id="TYPE_0">%1$s</xliff:g> et <xliff:g id="TYPE_1">%2$s</xliff:g> à &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; ?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Faire passer <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> et <xliff:g id="TYPE_2">%3$s</xliff:g> à &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; ?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"Enregistrer dans "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" ?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"Enregistrer <xliff:g id="TYPE">%1$s</xliff:g> dans "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" ?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"Enregistrer <xliff:g id="TYPE_0">%1$s</xliff:g> et <xliff:g id="TYPE_1">%2$s</xliff:g> dans "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" ?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"Enregistrer <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> et <xliff:g id="TYPE_2">%3$s</xliff:g> dans "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" ?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"Mettre à jour cet élément dans "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" ?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"Mettre à jour <xliff:g id="TYPE">%1$s</xliff:g> dans "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" ?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"Mettre à jour <xliff:g id="TYPE_0">%1$s</xliff:g> et <xliff:g id="TYPE_1">%2$s</xliff:g> dans "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" ?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"Mettre à jour les éléments <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> et <xliff:g id="TYPE_2">%3$s</xliff:g> dans "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" ?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Enregistrer"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Non, merci"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"Mettre à jour"</string>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index 4d78073..d522b53 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Micrófono"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"gravar audio"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"Queres permitir que a aplicación &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; grave audio?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"Recoñecemento da actividade"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"recoñecer actividade"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"Queres permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; recoñeza a túa actividade física?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Cámara"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"tirar fotos e gravar vídeos"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"Queres permitir que a aplicación &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; realice fotos e grave vídeos?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Esta aplicación pode obter a túa localización a partir de fontes de rede como torres de telecomunicacións e redes wifi. Para que a aplicación poida utilizar os servizos de localización, deben estar activados e dispoñibles na túa tableta."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Esta aplicación pode obter a túa localización a partir de fontes de rede como torres de telecomunicacións e redes wifi. Para que a aplicación poida utilizar os servizos de localización, deben estar activados e dispoñibles na túa televisión."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Esta aplicación pode obter a túa localización a partir de fontes de rede como torres de telecomunicacións e redes wifi. Para que a aplicación poida utilizar os servizos de localización, deben estar activados e dispoñibles no teu teléfono."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"acceder á localización exacta en segundo plano"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"Esta aplicación pode obter a túa localización exacta cando estea en segundo plano. É necesario activar estes servizos de localización e deben estar dispoñibles no teléfono para que a aplicación poida utilizalos. Ademais, poden supoñer un aumento do consumo de batería."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"acceder á localización en segundo plano"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Se a aplicación ten acceso á localización aproximada ou exacta e lle concedes este permiso, poderá consultar onde te atopas cando estea en segundo plano."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"cambiar a configuración de son"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Permite á aplicación modificar a configuración de audio global, como o volume e que altofalante se utiliza para a saída."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"gravar audio"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"Esta aplicación pode utilizar o micrófono en calquera momento para gravar audio."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"enviar comandos á SIM"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Permite á aplicación enviar comandos á SIM. Isto é moi perigoso."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"recoñecer actividade física"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"Esta aplicación pode recoñecer a túa actividade física."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"facer fotos e vídeos"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"Esta aplicación pode utilizar a cámara en calquera momento para sacar fotos e gravar vídeos."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"controlar a vibración"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Permite que a aplicación modifique a túa colección de fotos."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"ler localizacións da túa colección multimedia"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Permite que a aplicación lea as localizacións da túa colección multimedia."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"A aplicación <xliff:g id="APP">%s</xliff:g> quere que te autentiques."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"O hardware biométrico non está dispoñible"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Detectouse unha impresión dixital parcial. Téntao de novo."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Non se puido procesar a impresión dixital. Téntao de novo."</string>
@@ -1898,14 +1904,14 @@
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> suxestións de autocompletar</item>
       <item quantity="one">Unha suxestión de autocompletar</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"Queres gardar o contido en: &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Queres gardar <xliff:g id="TYPE">%1$s</xliff:g> en: &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Queres gardar estes datos (<xliff:g id="TYPE_0">%1$s</xliff:g> e <xliff:g id="TYPE_1">%2$s</xliff:g>) en &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Queres gardar estes datos (<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> e <xliff:g id="TYPE_2">%3$s</xliff:g>) en &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"Queres actualizar &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; con estes datos?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Queres actualizar &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; con estes datos (<xliff:g id="TYPE">%1$s</xliff:g>)?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Queres actualizar &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; con estes datos (<xliff:g id="TYPE_0">%1$s</xliff:g> e <xliff:g id="TYPE_1">%2$s</xliff:g>)?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Queres actualizar &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; con estes datos (<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> e <xliff:g id="TYPE_2">%3$s</xliff:g>)?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"Queres gardar o contido en "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"Queres gardar <xliff:g id="TYPE">%1$s</xliff:g> en "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"Queres gardar <xliff:g id="TYPE_0">%1$s</xliff:g> e <xliff:g id="TYPE_1">%2$s</xliff:g> en "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"Queres gardar <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> e <xliff:g id="TYPE_2">%3$s</xliff:g> en "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"Queres actualizar o contido en "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"Queres actualizar <xliff:g id="TYPE">%1$s</xliff:g> en "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"Queres actualizar <xliff:g id="TYPE_0">%1$s</xliff:g> e <xliff:g id="TYPE_1">%2$s</xliff:g> en "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"Queres actualizar <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> e <xliff:g id="TYPE_2">%3$s</xliff:g> en "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Gardar"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Non, grazas"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"Actualizar"</string>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index 13090c6..9e9c21e 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"માઇક્રોફોન"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"ઑડિઓ રેકોર્ડ કરવાની"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ને ઑડિઓ રેકૉર્ડ કરવાની મંજૂરી આપીએ?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"પ્રવૃત્તિની ઓળખ"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"પ્રવૃત્તિને ઓળખો"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ને તમારી શારીરિક પ્રવૃત્તિને ઓળખવાની મંજૂરી આપવી છે?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"કૅમેરો"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"ચિત્રો લેવાની અને વીડિઓ રેકોર્ડ કરવાની"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ને ચિત્રો લેવાની અને વીડિઓ રેકૉર્ડ કરવાની મંજૂરી આપીએ?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"આ ઍપ્લિકેશન, સેલ ટાવર્સ અને વાઇ-ફાઇ નેટવર્ક્સ જેવા નેટવર્ક સ્રોતોના આધારે તમારું સ્થાન મેળવી શકે છે. ઍપ્લિકેશન દ્વારા આ સ્થાન સેવાઓનો ઉપયોગ કરવામાં સમર્થ થવા માટે તમારા ટેબ્લેટ પર આ ઉપલબ્ધ અને ચાલુ હોવી આવશ્યક છે."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"આ ઍપ્લિકેશન, સેલ ટાવર્સ અને વાઇ-ફાઇ નેટવર્ક્સ જેવા નેટવર્ક સ્રોતોના આધારે તમારું સ્થાન મેળવી શકે છે. ઍપ્લિકેશન દ્વારા આ સ્થાન સેવાઓનો ઉપયોગ કરવામાં સમર્થ થવા માટે તમારા ટીવી પર આ ઉપલબ્ધ અને ચાલુ હોવી આવશ્યક છે."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"આ ઍપ્લિકેશન, સેલ ટાવર્સ અને વાઇ-ફાઇ નેટવર્ક્સ જેવા નેટવર્ક સ્રોતોના આધારે તમારું સ્થાન મેળવી શકે છે. ઍપ્લિકેશન દ્વારા આ સ્થાન સેવાઓનો ઉપયોગ કરવામાં સમર્થ થવા માટે તમારા ફોન પર આ ઉપલબ્ધ અને ચાલુ હોવી આવશ્યક છે."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"બૅકગ્રાઉન્ડમાં ચોક્કસ સ્થાન ઍક્સેસ કરો"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"આ ઍપ બૅકગ્રાઉન્ડમાં હોય ત્યારે કોઈપણ સમયે તમારું ચોક્કસ સ્થાન મેળવી શકે છે. ઍપ આ સ્થાન સેવાઓનો ઉપયોગ કરી શકે તે માટે તમારા ફોન પર આ સેવાઓ ઉપલબ્ધ અને ચાલુ હોવી આવશ્યક છે. આ બૅટરી વપરાશ વધારી શકે છે."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"બૅકગ્રાઉન્ડમાં સ્થાન ઍક્સેસ કરો"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"જો અંદાજિત અથવા ચોક્કસ સ્થાનના ઍક્સેસ ઉપરાંત આને પરવાનગી આપવામાં આવી હશે, તો ઍપ બૅકગ્રાઉન્ડમાં ચાલતી હોય ત્યારે સ્થાનને ઍક્સેસ કરી શકશે."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"તમારી ઑડિઓ સેટિંગ્સ બદલો"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"એપ્લિકેશનને વૈશ્વિક ઑડિઓ સેટિંગ્સને સંશોધિત કરવાની મંજૂરી આપે છે, જેમ કે વૉલ્યૂમ અને આઉટપુટ માટે કયા સ્પીકરનો ઉપયોગ કરવો."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"ઑડિઓ રેકોર્ડ કરવાની"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"આ ઍપ્લિકેશન, માઇક્રોફોનનો ઉપયોગ કરીને કોઈપણ સમયે ઑડિઓ રેકોર્ડ કરી શકે છે."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"સિમ ને આદેશો મોકલો"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"એપ્લિકેશનને સિમ પરા આદેશો મોકલવાની મંજૂરી આપે છે. આ ખૂબ જ ખતરનાક છે."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"શારીરિક પ્રવૃત્તિને ઓળખો"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"આ ઍપ તમારી શારીરિક પ્રવૃત્તિને ઓળખી શકે છે."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"ચિત્રો અને વિડિઓઝ લો"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"આ ઍપ્લિકેશન, કૅમેરાનો ઉપયોગ કરીને કોઈપણ સમયે ચિત્રો લઈ અને વિડિઓઝ રેકોર્ડ કરી શકે છે."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"વાઇબ્રેશન નિયંત્રિત કરો"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"એપને તમારો ફોટો સંગ્રહ સંશોધિત કરવાની મંજૂરી આપે છે."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"આપના મીડિયા સંગ્રહમાંથી સ્થાનો વાંચવા"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"એપને તમારા મીડિયા સંગ્રહમાંથી સ્થાનો વાંચવાની મંજૂરી આપે છે."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"<xliff:g id="APP">%s</xliff:g> ઍપ પ્રમાણીકરણ કરવા માગે છે."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"બાયોમેટ્રિક હાર્ડવેર ઉપલબ્ધ નથી"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"આંશિક ફિંગરપ્રિન્ટ મળી. કૃપા કરીને ફરી પ્રયાસ કરો."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"ફિંગરપ્રિન્ટ પ્રક્રિયા કરી શકાઈ નથી. કૃપા કરીને ફરી પ્રયાસ કરો."</string>
@@ -1898,14 +1904,14 @@
       <item quantity="one">સ્વતઃભરણ વિશે <xliff:g id="COUNT">%1$s</xliff:g> સૂચન</item>
       <item quantity="other">સ્વતઃભરણ વિશે <xliff:g id="COUNT">%1$s</xliff:g> સૂચન</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;માં સાચવીએ?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"<xliff:g id="TYPE">%1$s</xliff:g>ને &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;માં સાચવીએ?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"<xliff:g id="TYPE_0">%1$s</xliff:g> અને <xliff:g id="TYPE_1">%2$s</xliff:g>ને &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;માં સાચવીએ?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> અને <xliff:g id="TYPE_2">%3$s</xliff:g>ને &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;માં સાચવીએ?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; પર અપડેટ કરવું છે?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"<xliff:g id="TYPE">%1$s</xliff:g>ને &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; પર અપડેટ કરવું છે?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"<xliff:g id="TYPE_0">%1$s</xliff:g> અને <xliff:g id="TYPE_1">%2$s</xliff:g> ને &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; પર અપડેટ કરવું છે?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> અને <xliff:g id="TYPE_2">%3$s</xliff:g>ને &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;પર અપડેટ કરવું છે?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" પર સાચવીએ?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"<xliff:g id="TYPE">%1$s</xliff:g>ને "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" પર સાચવીએ?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"<xliff:g id="TYPE_0">%1$s</xliff:g> અને <xliff:g id="TYPE_1">%2$s</xliff:g>ને "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" પર સાચવીએ?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> અને <xliff:g id="TYPE_2">%3$s</xliff:g>ને "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" પર સાચવીએ?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"માં અપડેટ કરીએ?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"<xliff:g id="TYPE">%1$s</xliff:g>ને "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"માં અપડેટ કરીએ?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"<xliff:g id="TYPE_0">%1$s</xliff:g> અને <xliff:g id="TYPE_1">%2$s</xliff:g>ને "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"માં અપડેટ કરીએ?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922"><b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"માંની: <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> અને <xliff:g id="TYPE_2">%3$s</xliff:g> બાબતોને અપડેટ કરીએ?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"સાચવો"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"ના, આભાર"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"અપડેટ કરો"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 05ec806..87b35c9 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"माइक्रोफ़ोन"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"ऑडियो रिकॉर्ड करें"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; को ऑडियो रिकॉर्ड करने की अनुमति देना चाहते हैं?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"गतिविधि की पहचान"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"गतिविधि को पहचानें"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; को अपने शरीर की गतिविधि को पहचानने की मंज़ूरी देना चाहते हैं?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"कैमरा"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"चित्र लेने और वीडियो रिकॉर्ड करने"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; को फ़ोटो खींचने और वीडियो रिकॉर्ड करने की अनुमति देना चाहते हैं?"</string>
@@ -300,7 +303,7 @@
     <string name="permgrouprequest_calllog" msgid="8487355309583773267">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; को अपने काॅल लाॅग एक्सेस करने की मंज़ूरी देना चाहते हैं?"</string>
     <string name="permgrouplab_phone" msgid="5229115638567440675">"फ़ोन"</string>
     <string name="permgroupdesc_phone" msgid="6234224354060641055">"फ़ोन कॉल करें और प्रबंधित करें"</string>
-    <string name="permgrouprequest_phone" msgid="9166979577750581037">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; को फ़ोन कॉल करने और उन्हें प्रबंधित करने की अनुमति देना चाहते हैं?"</string>
+    <string name="permgrouprequest_phone" msgid="9166979577750581037">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; को फ़ोन कॉल करने और उन्हें प्रबंधित करने की अनुमति दें?"</string>
     <string name="permgrouplab_sensors" msgid="416037179223226722">"शरीर संवेदक"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"अपने महत्वपूर्ण संकेतों के बारे में सेंसर डेटा को ऐक्सेस करें"</string>
     <string name="permgrouprequest_sensors" msgid="6349806962814556786">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; को अपने स्वास्थ्य से जुड़ी ज़रूरी जानकारी इस्तेमाल करने की अनुमति देना चाहते हैं?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"यह ऐप सेल टावर और वाई-फ़ाई नेटवर्क जैसे नेटवर्क के स्रोतों के आधार पर आपकी जगह का पता कर सकता है. ये जगह की जानकारी आपके टैबलेट पर चालू और मौजूद होनी चाहिए ताकि ऐप उनका इस्तेमाल कर सके."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"यह ऐप सेल टावर और वाई-फ़ाई नेटवर्क जैसे नेटवर्क के स्रोतों के आधार पर आपकी जगह का पता कर सकता है. ये जगह की जानकारी आपके टीवी पर चालू और मौजूद होनी चाहिए ताकि ऐप उनका इस्तेमाल कर सके."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"यह ऐप सेल टावर और वाई-फ़ाई नेटवर्क जैसे नेटवर्क के स्रोतों के आधार पर आपकी जगह का पता कर सकता है. ये जगह की जानकारी आपके फ़ोन पर चालू और मौजूद होनी चाहिए ताकि ऐप उनका इस्तेमाल कर सके."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"बैकग्राउंड में होने पर \'जगह की सटीक जानकारी\' एक्सेस करें"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"यह ऐप्लिकेशन बैकग्राउंड में चलते हुए, किसी भी समय आपकी \'जगह की सटीक जानकारी\' का इस्तेमाल कर सकता है. यह ज़रूरी है कि \'जगह की जानकारी\' वाली ये सेवाएं आपके फ़ोन में मौजूद हों और चालू की गई हों ताकि ऐप्लिकेशन उनका इस्तेमाल कर पाए. ऐसा करने से ज़्यादा बैटरी खर्च हो सकती है."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"बैकग्राउंड में जगह की जानकारी एक्सेस करना"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"अनुमानित या बिल्कुल सही जगह की जानकारी का एक्सेस करने की अनुमति अलग से दिए जाने पर, बैकग्राउंड में चलने के दौरान ऐप्लिकेशन आपकी जगह की जानकारी एक्सेस कर सकता है."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"अपनी ऑडियो सेटिंग बदलें"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"ऐप्स  को वैश्विक ऑडियो सेटिंग, जैसे वॉल्‍यूम और कौन-सा स्पीकर आउटपुट के लिए उपयोग किया गया, संशोधित करने देता है."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"ऑडियो रिकॉर्ड करने"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"यह ऐप्लिकेशन किसी भी समय माइक्रोफ़ोन का उपयोग करके ऑडियो रिकॉर्ड कर सकता है."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"सिम पर निर्देश भेजें"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"ऐप को सिम पर निर्देश भेजने देती है. यह बहुत ही खतरनाक है."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"शरीर की गतिविधि को पहचानना"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"यह ऐप्लिकेशन आपके शरीर की गतिविधि को पहचान सकता है."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"चित्र और वीडियो लें"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"यह ऐप्लिकेशन किसी भी समय कैमरे का उपयोग करके चित्र ले सकता है और वीडियो रिकॉर्ड कर सकता है."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"कंपन (वाइब्रेशन) को नियंत्रित करें"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"इससे ऐप्लिकेशन को आपके फ़ोटो संग्रह में बदलाव करने की मंज़ूरी दी जाती है."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"अपने मीडिया संग्रह से जगह की जानकारी एक्सेस करने की अनुमति दें"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"इससे ऐप्लिकेशन को आपके मीडिया संग्रह से जगह की जानकारी एक्सेस करने की अनुमति दी जाती है."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"ऐप्लिकेशन <xliff:g id="APP">%s</xliff:g> पुष्टि करना चाहता है."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"बायोमेट्रिक हार्डवेयर उपलब्ध नहीं है"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"आंशिक फ़िंगरप्रिंट की पहचान की गई. कृपया पुनः प्रयास करें."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"फ़िंगरप्रिंट संसाधित नहीं हो सका. कृपया पुन: प्रयास करें."</string>
@@ -1897,14 +1903,14 @@
       <item quantity="one">ऑटोमैटिक भरने के <xliff:g id="COUNT">%1$s</xliff:g> सुझाव</item>
       <item quantity="other">ऑटोमैटिक भरने के <xliff:g id="COUNT">%1$s</xliff:g> सुझाव</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; में सेव करें?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"<xliff:g id="TYPE">%1$s</xliff:g> को &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; में सेव करें?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"<xliff:g id="TYPE_0">%1$s</xliff:g> और <xliff:g id="TYPE_1">%2$s</xliff:g> को &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; में सेव करें?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> और <xliff:g id="TYPE_2">%3$s</xliff:g> को &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; में सेव करें?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; में अपडेट करें?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"<xliff:g id="TYPE">%1$s</xliff:g> को &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; में अपडेट करें?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"<xliff:g id="TYPE_0">%1$s</xliff:g> और <xliff:g id="TYPE_1">%2$s</xliff:g> को &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; में अपडेट करें?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> और <xliff:g id="TYPE_2">%3$s</xliff:g> को &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; में अपडेट करें?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"क्या आप "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" में सेव करना चाहते हैं?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"क्या आप "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" में <xliff:g id="TYPE">%1$s</xliff:g> सेव करना चाहते हैं?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"क्या आप "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" में <xliff:g id="TYPE_0">%1$s</xliff:g> और <xliff:g id="TYPE_1">%2$s</xliff:g> सेव करना चाहते हैं?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"क्या आप "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" में <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, और <xliff:g id="TYPE_2">%3$s</xliff:g> सेव करना चाहते हैं?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"क्या आप "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" में अपडेट करना चाहते हैं?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"क्या आप "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" में <xliff:g id="TYPE">%1$s</xliff:g> अपडेट करना चाहते हैं?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"क्या आप "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" में <xliff:g id="TYPE_0">%1$s</xliff:g> और <xliff:g id="TYPE_1">%2$s</xliff:g> अपडेट करना चाहते हैं?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"क्या आप "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" में इन आइटम को अपडेट करना चाहते हैं: <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, और <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"सेव करें"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"नहीं, धन्यवाद"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"अपडेट करें"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 839d423..7b24bba 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -124,7 +124,7 @@
     <string name="roamingTextSearching" msgid="8360141885972279963">"Pretraživanje usluge"</string>
     <string name="wfcRegErrorTitle" msgid="3855061241207182194">"Postavljanje Wi‑Fi poziva nije uspjelo"</string>
   <string-array name="wfcOperatorErrorAlertMessages">
-    <item msgid="3910386316304772394">"Da biste telefonirali i slali poruke putem Wi-Fi-ja, od mobilnog operatera morate tražiti da postavi tu uslugu. Zatim ponovo uključite Wi-Fi pozive u postavkama. (Kôd pogreške: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
+    <item msgid="3910386316304772394">"Da biste telefonirali i slali poruke putem Wi-Fija, od mobilnog operatera morate tražiti da postavi tu uslugu. Zatim ponovo uključite Wi-Fi pozive u postavkama. (Kôd pogreške: <xliff:g id="CODE">%1$s</xliff:g>)"</item>
   </string-array>
   <string-array name="wfcOperatorErrorNotificationMessages">
     <item msgid="7372514042696663278">"Poteškoća s registracijom Wi‑Fi poziva kod mobilnog operatera: <xliff:g id="CODE">%1$s</xliff:g>"</item>
@@ -295,6 +295,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Mikrofon"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"snimati zvuk"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"Želite li dopustiti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; da snima audiozapise?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"Prepoznavanje aktivnosti"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"prepoznati aktivnost"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"Želite li dopustiti da &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; prepoznaje vašu tjelesnu aktivnost?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Fotoaparat"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"snimati fotografije i videozapise"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"Želite li dopustiti aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; da snima fotografije i videozapise?"</string>
@@ -421,14 +424,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Aplikacija može dohvatiti vašu lokaciju putem mrežnih izvora poput baznih stanica i Wi-Fi mreža. Te usluge lokacije moraju biti uključene i dostupne na tabletu da bi ih aplikacija mogla upotrebljavati."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Aplikacija može dohvatiti vašu lokaciju putem mrežnih izvora poput baznih stanica i Wi-Fi mreža. Te usluge lokacije moraju biti uključene i dostupne na televizoru da bi ih aplikacija mogla upotrebljavati."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Aplikacija može dohvatiti vašu lokaciju putem mrežnih izvora poput baznih stanica i Wi-Fi mreža. Te usluge lokacije moraju biti uključene i dostupne na telefonu da bi ih aplikacija mogla upotrebljavati."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"pristupiti preciznoj lokaciji u pozadini"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"Aplikacija može dobiti vašu točnu lokaciju svaki put kada je u pozadini. Te usluge lokacije moraju biti uključene i dostupne na telefonu da bi ih aplikacija mogla upotrebljavati. To može pojačati potrošnju baterije."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"pristup lokaciji u pozadini"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Ako se ovo odobrava dodatno za pristup približnoj ili preciznoj lokaciji, aplikacija može pristupiti lokaciji tijekom rada u pozadini."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"promjena postavki zvuka"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Aplikaciji omogućuje izmjenu globalnih postavki zvuka, primjerice glasnoće i zvučnika koji se upotrebljava za izlaz."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"snimanje zvuka"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"Aplikacija u svakom trenutku može snimati zvuk mikrofonom."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"slati naredbe SIM-u"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Omogućuje aplikaciji slanje naredbi SIM-u. To je vrlo opasno."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"prepoznati tjelesnu aktivnost"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"Ova aplikacija može prepoznati vašu tjelesnu aktivnost."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"snimi fotografije i videozapise"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"Aplikacija u svakom trenutku može snimati fotografije i videozapise fotoaparatom."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"upravljanje vibracijom"</string>
@@ -521,6 +526,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Omogućuje aplikaciji izmjenu vaše zbirke fotografija."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"čitanje lokacija iz vaše medijske zbirke"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Omogućuje aplikaciji čitanje lokacija iz vaše medijske zbirke."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"Aplikacija <xliff:g id="APP">%s</xliff:g> traži autentifikaciju."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Biometrijski hardver nije dostupan"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Otkriven je djelomični otisak prsta. Pokušajte ponovo."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Obrada otiska prsta nije uspjela. Pokušajte ponovo."</string>
@@ -1538,7 +1544,7 @@
     <string name="data_usage_wifi_limit_title" msgid="5803363779034792676">"Dost. ogr. Wi-Fi prijenosa pod."</string>
     <string name="data_usage_limit_body" msgid="2908179506560812973">"Podatkovni je promet pauziran za ostatak ciklusa"</string>
     <string name="data_usage_mobile_limit_snoozed_title" msgid="3171402244827034372">"Premašen limit mobilnih podataka"</string>
-    <string name="data_usage_wifi_limit_snoozed_title" msgid="3547771791046344188">"Premašen limit podataka Wi-Fi-ja"</string>
+    <string name="data_usage_wifi_limit_snoozed_title" msgid="3547771791046344188">"Premašen limit podataka Wi-Fija"</string>
     <string name="data_usage_limit_snoozed_body" msgid="1671222777207603301">"Premašili ste postavljeno ograničenje za <xliff:g id="SIZE">%s</xliff:g>"</string>
     <string name="data_usage_restricted_title" msgid="5965157361036321914">"Pozadinski podaci ograničeni"</string>
     <string name="data_usage_restricted_body" msgid="469866376337242726">"Dodirnite i uklonite ograničenje"</string>
@@ -1932,14 +1938,14 @@
       <item quantity="few"><xliff:g id="COUNT">%1$s</xliff:g> prijedloga za automatsko popunjavanje</item>
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> prijedloga za automatsko popunjavanje</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"Želite li spremiti na uslugu &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Želite li da se podatak (<xliff:g id="TYPE">%1$s</xliff:g>) spremi na uslugu &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Želite li da se <xliff:g id="TYPE_0">%1$s</xliff:g> i <xliff:g id="TYPE_1">%2$s</xliff:g> spreme na uslugu &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Želite li da se <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> i <xliff:g id="TYPE_2">%3$s</xliff:g> spreme na uslugu &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"Želite li ažurirati na &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Želite li polje <xliff:g id="TYPE">%1$s</xliff:g> ažurirati na &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Želite li polja <xliff:g id="TYPE_0">%1$s</xliff:g> i <xliff:g id="TYPE_1">%2$s</xliff:g> ažurirati na &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Želite li polja <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> i <xliff:g id="TYPE_2">%3$s</xliff:g> ažurirati na &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"Želite li spremiti u oznaku "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"Želite li spremiti podatke <xliff:g id="TYPE">%1$s</xliff:g> u oznaku "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"Želite li spremiti podatke <xliff:g id="TYPE_0">%1$s</xliff:g> i <xliff:g id="TYPE_1">%2$s</xliff:g> u oznaku "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"Spremite podatke <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> i <xliff:g id="TYPE_2">%3$s</xliff:g> u oznaku "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"Želite li ažurirati u oznaku "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"Želite li ažurirati podatke <xliff:g id="TYPE">%1$s</xliff:g> u oznaci "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"Želite li ažurirati podatke <xliff:g id="TYPE_0">%1$s</xliff:g> i <xliff:g id="TYPE_1">%2$s</xliff:g> u oznaci "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"Želite li ažurirati ove stavke u oznaci "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> i <xliff:g id="TYPE_2">%3$s</xliff:g> ?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Spremi"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Ne, hvala"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"Ažuriraj"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index bc54bfa..b02b68b 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Mikrofon"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"hanganyag rögzítése"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"Engedélyezi a(z) &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; számára, hogy hangfelvételt készíthessen?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"Tevékenység felismerése"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"tevékenység felismerése"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"Engedélyezi a(z) &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; alkalmazásnak a testmozgás felismerését?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Fényképezőgép"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"fotók és videók készítése"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"Engedélyezi a(z) &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; számára, hogy képeket és videókat készíthessen?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Az alkalmazás hozzáférhet hálózati forrásokon (például az adótornyokon és a Wi-Fi-hálózatokon) alapuló helyadataihoz. A helyszolgáltatásoknak bekapcsolt és elérhető állapotban kell lenniük a táblagépen ahhoz, hogy az alkalmazás használhassa őket."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Az alkalmazás hozzáférhet hálózati forrásokon (például az adótornyokon és a Wi-Fi-hálózatokon) alapuló helyadataihoz. A helyszolgáltatásoknak bekapcsolt és elérhető állapotban kell lenniük a TV-n ahhoz, hogy az alkalmazás használhassa őket."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Az alkalmazás hozzáférhet hálózati forrásokon (például az adótornyokon és a Wi-Fi-hálózatokon) alapuló helyadataihoz. A helyszolgáltatásoknak bekapcsolt és elérhető állapotban kell lenniük a telefonon ahhoz, hogy az alkalmazás használhassa őket."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"pontos helyadatokhoz való hozzáférés a háttérben"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"Ez az alkalmazás bármikor hozzáférhet az eszköz pontos helyadataihoz a háttérben. A helyszolgáltatásoknak bekapcsolt és hozzáférhető állapotban kell lenniük a telefonon ahhoz, hogy az alkalmazás használhassa őket. Ez növelheti az akkumulátorhasználatot."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"Hozzáférés a helyadatokhoz a háttérben"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Ha engedélyezi ezt a hozzávetőleges vagy pontos helyadatokhoz való hozzáférés mellett, akkor az alkalmazás hozzáférhet a helyadatokhoz, miközben a háttérben fut."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"hangbeállítások módosítása"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Lehetővé teszi az alkalmazás számára az általános hangbeállítások, például a hangerő és a használni kívánt kimeneti hangszóró módosítását."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"hanganyag rögzítése"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"Az alkalmazás a mikrofon használatával bármikor készíthet hangfelvételt."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"parancsok küldése a SIM-kártyára"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Engedélyezi, hogy az alkalmazás parancsokat küldjön a SIM kártyára. Ez rendkívül veszélyes lehet."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"testmozgás felismerése"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"Az alkalmazás képes felismerni a testmozgást."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"fotók és videók készítése"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"Az alkalmazás a kamera használatával bármikor készíthet fényképeket és rögzíthet videókat."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"rezgés szabályozása"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Engedélyezi az alkalmazásnak a fényképgyűjtemény módosítását."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"helyek olvasása a médiagyűjteményből"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Engedélyezi az alkalmazásnak a helyek médiagyűjteményből való olvasását."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"A(z) <xliff:g id="APP">%s</xliff:g> alkalmazás hitelesítést kér."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Biometrikus hardver nem áll rendelkezésre"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"A rendszer az ujjlenyomatnak csak egy részletét érzékelte. Próbálkozzon újra."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Nem sikerült feldolgozni az ujjlenyomatot. Próbálkozzon újra."</string>
@@ -1897,14 +1903,14 @@
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> automatikus kitöltési javaslat</item>
       <item quantity="one">Egy automatikus kitöltési javaslat</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"Menti ide: &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Menti a következőt: <xliff:g id="TYPE">%1$s</xliff:g> ide: &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Menti a következőket: <xliff:g id="TYPE_0">%1$s</xliff:g> és <xliff:g id="TYPE_1">%2$s</xliff:g> ide: &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Menti a következőket: <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> és <xliff:g id="TYPE_2">%3$s</xliff:g> ide: &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"Frissít a következőre: &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Frissíti a következőt: <xliff:g id="TYPE">%1$s</xliff:g> erre: &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Frissíti a következőket: <xliff:g id="TYPE_0">%1$s</xliff:g> és <xliff:g id="TYPE_1">%2$s</xliff:g> erre: &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Frissíti a következőket: <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> és <xliff:g id="TYPE_2">%3$s</xliff:g> erre: &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"Menti a(z) "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" szolgáltatásba?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"Menti a(z) "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" szolgáltatásba a következőt: <xliff:g id="TYPE">%1$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"Menti a(z) "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" szolgáltatásba a következőket: <xliff:g id="TYPE_0">%1$s</xliff:g> és <xliff:g id="TYPE_1">%2$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"Menti a(z) "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" szolgáltatásba a következőket: <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> és <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"Frissíti a(z) "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" szolgáltatásban?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"Frissíti a(z) "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" szolgáltatásban a következőt: <xliff:g id="TYPE">%1$s</xliff:g>?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"Frissíti a(z) "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" szolgáltatásban a következőket: <xliff:g id="TYPE_0">%1$s</xliff:g> és <xliff:g id="TYPE_1">%2$s</xliff:g>?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"Frissíti a(z) "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" szolgáltatásban a következőket: <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> és <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Mentés"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Nem, köszönöm"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"Frissítés"</string>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index 4a828fa..90ab955 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Խոսափող"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"ձայնագրել"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"Թույլ տա՞լ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; հավելվածին կատարել ձայնագրություն:"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"Ակտիվության ճանաչում"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"ճանաչել ակտիվությունը"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"Թույլատրե՞լ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; հավելվածին ճանաչել ձեր ֆիզիկական ակտիվությունը:"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Տեսախցիկ"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"լուսանկարել և տեսագրել"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"Թույլ տա՞լ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; հավելվածին լուսանկարել և տեսանկարել:"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Այս հավելվածը կարող է ստանալ ձեր տեղադրության տվյալները ցանցային տարբեր աղբյուրներից, օրինակ՝ բջջային աշտարակներից և Wi-Fi ցանցերից: Այս տեղորոշման ծառայությունները պետք է միացված և հասանելի լինեն ձեր պլանշետում, որպեսզի հավելվածը կարողանա օգտագործել դրանք:"</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Այս հավելվածը կարող է ստանալ ձեր տեղադրության տվյալները ցանցային տարբեր աղբյուրներից, օրինակ՝ բջջային աշտարակներից և Wi-Fi ցանցերից: Այս տեղորոշման ծառայությունները պետք է միացված և հասանելի լինեն ձեր հեռուստացույցում, որպեսզի հավելվածը կարողանա օգտագործել դրանք:"</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Այս հավելվածը կարող է ստանալ ձեր տեղադրության տվյալները ցանցային տարբեր աղբյուրներից, օրինակ՝ բջջային աշտարակներից և Wi-Fi ցանցերից: Այս տեղորոշման ծառայությունները պետք է միացված և հասանելի լինեն ձեր հեռախոսում, որպեսզի հավելվածը կարողանա օգտագործել դրանք:"</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"Ֆոնային ռեժիմում տեղադրության տվյալների հասանելիություն"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"Հավելվածը կարող է ստանալ ձեր տեղադրության տվյալները ֆոնային ռեժիմում։ Այս տեղորոշման ծառայությունները պետք է միացված և հասանելի լինեն ձեր հեռախոսում, որպեսզի հավելվածը կարողանա օգտագործել դրանք: Սա կարող է արագացնել մարտկոցի լիցքի սպառումը:"</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"տեղադրության մասին տվյալների հասանելիություն ֆոնային ռեժիմում"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Եթե բացի մոտավոր կամ ճշգրիտ տեղորոշման տվյալների հասանելիությունից հավելվածին տրամադրեք այս թույլտվությունը, հավելվածին տեղադրության մասին տվյալները հասանելի կլինեն ֆոնային ռեժիմում։"</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"փոխել ձեր աուդիո կարգավորումները"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Թույլ է տալիս հավելվածին փոփոխել ձայնանյութի գլոբալ կարգավորումները, ինչպես օրինակ` ձայնը և թե որ խոսափողն է օգտագործված արտածման համար:"</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"ձայնագրել աուդիո ֆայլ"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"Այս հավելվածը ցանկացած պահի կարող է ձայնագրել խոսափողի օգնությամբ:"</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"ուղարկել հրամաններ SIM քարտին"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Թույլ է տալիս հավելվածին հրամաններ ուղարկել SIM-ին: Սա շատ վտանգավոր է:"</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"ֆիզիկական ակտիվության ճանաչում"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"Հավելվածը կարող է ճանաչել ձեր ֆիզիկական ակտիվությունը:"</string>
     <string name="permlab_camera" msgid="3616391919559751192">"լուսանկարել և տեսանկարել"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"Այս հավելվածը կարող է ցանկացած պահի լուսանկարել և տեսագրել՝ օգտագործելով տեսախցիկը:"</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"կառավարել թրթռումը"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Թույլ է տալիս հավելվածին փոփոխել ձեր լուսանկարների հավաքածուն:"</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"ճանաչել տեղադրության մասին տվյալները մեդիա բովանդակության հավաքածուից"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Թույլ է տալիս հավելվածին ճանաչել տեղադրության մասին տվյալները ձեր մեդիա բովանդակության հավաքածուից:"</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"<xliff:g id="APP">%s</xliff:g> հավելվածը նույնականացում է հարցում"</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Կենսաչափական սարքը հասանելի չէ"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Մատնահետքը հայտնաբերվել է մասամբ: Փորձեք նորից:"</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Չհաջողվեց մշակել մատնահետքը: Նորից փորձեք:"</string>
@@ -1897,14 +1903,14 @@
       <item quantity="one"><xliff:g id="COUNT">%1$s</xliff:g> ինքնալցման առաջարկ</item>
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> ինքնալցման առաջարկ</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"Պահե՞լ &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; ծառայությունում"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Պահե՞լ <xliff:g id="TYPE">%1$s</xliff:g>ը &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; ծառայությունում"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Պահե՞լ <xliff:g id="TYPE_0">%1$s</xliff:g>ն ու <xliff:g id="TYPE_1">%2$s</xliff:g>ը &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; ծառայությունում"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Պահե՞լ <xliff:g id="TYPE_0">%1$s</xliff:g>ը, <xliff:g id="TYPE_1">%2$s</xliff:g>ն ու <xliff:g id="TYPE_2">%3$s</xliff:g>ը &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; ծառայությունում"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"Թարմացնե՞լ &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; ծառայության տվյալները"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Թարմացնե՞լ &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; ծառայության տվյալները (<xliff:g id="TYPE">%1$s</xliff:g>)"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Թարմացնե՞լ &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; ծառայության տվյալները (<xliff:g id="TYPE_0">%1$s</xliff:g> և <xliff:g id="TYPE_1">%2$s</xliff:g>)"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Թարմացնե՞լ &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; ծառայության տվյալները (<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> և <xliff:g id="TYPE_2">%3$s</xliff:g>)"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"Պահե՞լ "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" ծառայությունում"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"Պահե՞լ տվյալները (<xliff:g id="TYPE">%1$s</xliff:g>) "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" ծառայությունում"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"Պահե՞լ տվյալները (<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>) "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" ծառայությունում"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"Պահե՞լ տվյալները (<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g>) "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" ծառայությունում"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"Թարմացնե՞լ "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" ծառայությունում"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"Թարմացնե՞լ տվյալները (<xliff:g id="TYPE">%1$s</xliff:g>) "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" ծառայությունում"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"Թարմացնե՞լ տվյալները (<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>) "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" ծառայությունում"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"Թարմացնե՞լ տվյալները (<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g>) "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" ծառայությունում"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Պահել"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Ոչ"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"Թարմացնել"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 167082d..924b264 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Mikrofon"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"merekam audio"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"Izinkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; merekam audio?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"Pengenalan aktivitas"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"kenali aktivitas"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"Izinkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengenali aktivitas fisik Anda?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Kamera"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"mengambil gambar dan merekam video"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"Izinkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengambil gambar dan merekam video?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Aplikasi ini dapat memperoleh lokasi Anda berdasarkan sumber jaringan seperti menara seluler dan jaringan Wi-Fi. Layanan lokasi ini harus diaktifkan dan tersedia di tablet agar aplikasi dapat menggunakannya."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Aplikasi ini dapat memperoleh lokasi Anda berdasarkan sumber jaringan seperti menara seluler dan jaringan Wi-Fi. Layanan lokasi ini harus diaktifkan dan tersedia di TV agar aplikasi dapat menggunakannya."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Aplikasi ini dapat memperoleh lokasi Anda berdasarkan sumber jaringan seperti menara seluler dan jaringan Wi-Fi. Layanan lokasi ini harus diaktifkan dan tersedia di ponsel agar aplikasi dapat menggunakannya."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"akses lokasi pasti saat di latar belakang"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"Aplikasi ini bisa mendapatkan lokasi pasti Anda kapan pun aplikasi ada di latar belakang. Fitur layanan lokasi ini harus diaktifkan dan tersedia di ponsel agar dapat digunakan oleh aplikasi. Fitur ini dapat meningkatkan konsumsi baterai."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"akses lokasi di latar belakang"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Jika aplikasi diberi izin tambahan ke akses lokasi perkiraan atau akurat, aplikasi dapat mengakses lokasi saat bekerja di latar belakang."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"ubah setelan audio Anda"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Memungkinkan aplikasi mengubah setelan audio global, misalnya volume dan pengeras suara mana yang digunakan untuk keluaran."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"rekam audio"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"Aplikasi ini dapat merekam audio menggunakan mikrofon kapan saja."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"kirimkan perintah ke SIM"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Mengizinkan aplikasi mengirim perintah ke SIM. Ini sangat berbahaya."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"kenali aktivitas fisik"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"Aplikasi ini dapat mengenali aktivitas fisik Anda."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"ambil gambar dan video"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"Aplikasi ini dapat mengambil foto dan merekam video menggunakan kamera kapan saja."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"kontrol getaran"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Mengizinkan aplikasi untuk memodifikasi koleksi foto Anda."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"membaca lokasi dari koleksi media Anda"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Mengizinkan aplikasi untuk membaca lokasi dari koleksi media Anda."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"Aplikasi <xliff:g id="APP">%s</xliff:g> meminta autentikasi."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Hardware biometrik tidak tersedia"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Sebagian sidik jari terdeteksi. Coba lagi."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Tidak dapat memproses sidik jari. Coba lagi."</string>
@@ -1897,14 +1903,14 @@
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> saran IsiOtomatis</item>
       <item quantity="one">1 saran IsiOtomatis</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"Simpan ke &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Simpan <xliff:g id="TYPE">%1$s</xliff:g> ke &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Simpan <xliff:g id="TYPE_0">%1$s</xliff:g> dan <xliff:g id="TYPE_1">%2$s</xliff:g> ke &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Simpan <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, dan <xliff:g id="TYPE_2">%3$s</xliff:g> ke &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"Update ke &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Update <xliff:g id="TYPE">%1$s</xliff:g> ke &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Update <xliff:g id="TYPE_0">%1$s</xliff:g> dan <xliff:g id="TYPE_1">%2$s</xliff:g> ke &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Update <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, dan <xliff:g id="TYPE_2">%3$s</xliff:g> ke &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"Simpan ke "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"Simpan <xliff:g id="TYPE">%1$s</xliff:g> ke "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"Simpan <xliff:g id="TYPE_0">%1$s</xliff:g> dan <xliff:g id="TYPE_1">%2$s</xliff:g> ke "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"Simpan <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, dan <xliff:g id="TYPE_2">%3$s</xliff:g> ke "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"Perbarui di "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"Perbarui <xliff:g id="TYPE">%1$s</xliff:g> di "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"Perbarui <xliff:g id="TYPE_0">%1$s</xliff:g> dan <xliff:g id="TYPE_1">%2$s</xliff:g> di "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"Perbarui item-item berikut di "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, dan <xliff:g id="TYPE_2">%3$s</xliff:g> ?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Simpan"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Lain kali"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"Update"</string>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index 0c7e6b8..1be394a 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Hljóðnemi"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"taka upp hljóð"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"Viltu leyfa &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; að taka upp hljóð?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"Greining á hreyfingu"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"greina hreyfingu"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"Viltu leyfa &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; að greina hreyfingu þína?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Myndavél"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"taka myndir og taka upp myndskeið"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"Viltu leyfa &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; að taka myndir og myndskeið?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Þetta forrit getur séð staðsetningu þína út frá netkerfum á borð við farsímasenda og Wi-Fi net. Það verður að vera kveikt á slíkri staðsetningarþjónustu og hún þarf að vera aðgengileg spjaldtölvunni til að forritið geti notað hana."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Þetta forrit getur séð staðsetningu þína út frá netkerfum á borð við farsímasenda og Wi-Fi net. Það verður að vera kveikt á slíkri staðsetningarþjónustu og hún þarf að vera aðgengileg sjónvarpinu til að forritið geti notað hana."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Þetta forrit getur séð staðsetningu þína út frá netkerfum á borð við farsímasenda og Wi-Fi net. Það verður að vera kveikt á slíkri staðsetningarþjónustu og hún þarf að vera aðgengileg símanum til að forritið geti notað hana."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"aðgangur að nákvæmri staðsetningu í bakgrunni"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"Þetta forrit getur séð nákvæma staðsetningu þína hvenær sem það er í bakgrunninum. Það verður að vera kveikt á þessari staðsetningarþjónustu og hún þarf að vera aðgengileg í símanum til að forritið geti notað hana. Þetta getur aukið rafhlöðunotkun."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"aðgangur að staðsetningu í bakgrunni"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Ef þetta er veitt til viðbótar við aðgang að áætlaðri eða nákvæmri staðsetningu getur forritið fengið aðgang að staðsetningu á meðan það keyrir í bakgrunni."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"breyta hljóðstillingum"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Leyfir forriti að breyta altækum hljóðstillingum, s.s. hljóðstyrk og hvaða hátalari er notaður sem úttak."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"taka upp hljóð"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"Þetta forrit getur tekið upp hljóð með hljóðnemanum hvenær sem er."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"senda skipanir til SIM-kortsins"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Leyfir forriti að senda SIM-kortinu skipanir. Þetta er mjög hættulegt."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"greina hreyfingu"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"Þetta forrit getur greint hreyfingu þína."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"taka myndir og myndskeið"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"Þetta forrit getur tekið myndir og tekið upp myndskeið með myndavélinni hvenær sem er."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"stjórna titringi"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Leyfir forritinu að breyta myndasafninu þínu."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"lesa staðsetningar úr efnissafninu þínu"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Leyfir forritinu að lesa staðsetningar úr efnissafninu þínu."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"<xliff:g id="APP">%s</xliff:g> forritið vill staðfestingu."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Lífkennavélbúnaður ekki tiltækur"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Hluti fingrafars greindist. Reyndu aftur."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Ekki var hægt að vinna úr fingrafarinu. Reyndu aftur."</string>
@@ -1898,14 +1904,14 @@
       <item quantity="one"><xliff:g id="COUNT">%1$s</xliff:g> tillaga fyrir sjálfvirka útfyllingu</item>
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> tillögur fyrir sjálfvirka útfyllingu</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"Vista á &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Vista <xliff:g id="TYPE">%1$s</xliff:g> á &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Vista <xliff:g id="TYPE_0">%1$s</xliff:g> og <xliff:g id="TYPE_1">%2$s</xliff:g> á &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Vista <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> og <xliff:g id="TYPE_2">%3$s</xliff:g> á &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"Viltu uppfæra í &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Viltu uppfæra <xliff:g id="TYPE">%1$s</xliff:g> í &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Viltu uppfæra <xliff:g id="TYPE_0">%1$s</xliff:g> og <xliff:g id="TYPE_1">%2$s</xliff:g> í &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Viltu uppfæra <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> og <xliff:g id="TYPE_2">%3$s</xliff:g> í &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"Vista í "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"Vista <xliff:g id="TYPE">%1$s</xliff:g> í "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"Vista <xliff:g id="TYPE_0">%1$s</xliff:g> og <xliff:g id="TYPE_1">%2$s</xliff:g> í "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"Vista <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> og <xliff:g id="TYPE_2">%3$s</xliff:g> í "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"Uppfæra í "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"Uppfæra <xliff:g id="TYPE">%1$s</xliff:g> í "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"Uppfæra <xliff:g id="TYPE_0">%1$s</xliff:g> og <xliff:g id="TYPE_1">%2$s</xliff:g> í "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"Uppfæra þessi atriði í "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> og <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Vista"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Nei, takk"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"Uppfæra"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index a6d5d23..a3b9835 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Microfono"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"registrare audio"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"Consentire all\'app &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; di registrare audio?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"Riconoscimento di attività"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"riconoscere l\'attività"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"Vuoi consentire a &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; di riconoscere la tua attività fisica?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Fotocamera"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"scattare foto e registrare video"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"Consentire a &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; di scattare foto e registrare video?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Questa app può accedere alla tua posizione tramite fonti di rete come antenne di telefonia mobile e reti Wi-Fi. Tali servizi di geolocalizzazione devono essere attivati e disponibili sul tablet per consentire all\'app di utilizzarli."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Questa app può accedere alla tua posizione tramite fonti di rete come antenne di telefonia mobile e reti Wi-Fi. Tali servizi di geolocalizzazione devono essere attivati e disponibili sulla TV per consentire all\'app di utilizzarli."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Questa app può accedere alla tua posizione tramite fonti di rete come antenne di telefonia mobile e reti Wi-Fi. Tali servizi di geolocalizzazione devono essere attivati e disponibili sul telefono per consentire all\'app di utilizzarli."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"Accesso alla posizione esatta in background"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"Questa app può recuperare la tua posizione esatta quando è in background. Questi servizi di geolocalizzazione devono essere attivi e disponibili sul telefono affinché l\'app possa usarli. Potrebbe aumentare il consumo della batteria."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"accesso alla posizione in background"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Se concedi l\'autorizzazione insieme all\'accesso alla posizione precisa o approssimativa, l\'app potrà accedere alla posizione mentre viene eseguita in background."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"modifica impostazioni audio"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Consente all\'applicazione di modificare le impostazioni audio globali, come il volume e quale altoparlante viene utilizzato per l\'uscita."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"registrare audio"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"Questa app può registrare audio tramite il microfono in qualsiasi momento."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"invio di comandi alla SIM"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Consente all\'app di inviare comandi alla SIM. Questo è molto pericoloso."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"riconoscimento dell\'attività fisica"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"Questa app può riconoscere la tua attività fisica."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"acquisizione di foto e video"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"Questa app può scattare foto e registrare video tramite la fotocamera in qualsiasi momento."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"controllo vibrazione"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Consente all\'app di modificare la tua raccolta di foto."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"Lettura delle posizioni dalla tua raccolta multimediale"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Consente all\'app di leggere le posizioni dalla tua raccolta multimediale."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"L\'app <xliff:g id="APP">%s</xliff:g> richiede l\'autenticazione."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Hardware biometrico non disponibile"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Rilevata impronta digitale parziale. Riprova."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Impossibile elaborare l\'impronta digitale. Riprova."</string>
@@ -1174,7 +1180,7 @@
     <string name="app_upgrading_toast" msgid="3008139776215597053">"Upgrade dell\'app <xliff:g id="APPLICATION">%1$s</xliff:g>…"</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Ottimizzazione applicazione <xliff:g id="NUMBER_0">%1$d</xliff:g> di <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="android_preparing_apk" msgid="8162599310274079154">"<xliff:g id="APPNAME">%1$s</xliff:g> in preparazione."</string>
-    <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Avvio applicazioni."</string>
+    <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Avvio app."</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"Conclusione dell\'avvio."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> in esecuzione"</string>
     <string name="heavy_weight_notification_detail" msgid="2304833848484424985">"Tocca per tornare al gioco"</string>
@@ -1802,7 +1808,7 @@
     <string name="zen_mode_rule_name_combination" msgid="191109939968076477">"<xliff:g id="FIRST">%1$s</xliff:g>/<xliff:g id="REST">%2$s</xliff:g>"</string>
     <string name="toolbar_collapse_description" msgid="2821479483960330739">"Comprimi"</string>
     <string name="zen_mode_feature_name" msgid="5254089399895895004">"Non disturbare"</string>
-    <string name="zen_mode_downtime_feature_name" msgid="2626974636779860146">"Tempo di inattività"</string>
+    <string name="zen_mode_downtime_feature_name" msgid="2626974636779860146">"Tempo di riposo"</string>
     <string name="zen_mode_default_weeknights_name" msgid="3081318299464998143">"Notte di un giorno feriale"</string>
     <string name="zen_mode_default_weekends_name" msgid="2786495801019345244">"Fine settimana"</string>
     <string name="zen_mode_default_events_name" msgid="8158334939013085363">"Evento"</string>
@@ -1897,14 +1903,14 @@
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> suggerimenti di Compilazione automatica</item>
       <item quantity="one">Un suggerimento di Compilazione automatica</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"Salvare in &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Salvare <xliff:g id="TYPE">%1$s</xliff:g> in &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Salvare <xliff:g id="TYPE_0">%1$s</xliff:g> e <xliff:g id="TYPE_1">%2$s</xliff:g> in &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Salvare <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> e <xliff:g id="TYPE_2">%3$s</xliff:g> in &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"Vuoi eseguire l\'aggiornamento a &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Vuoi eseguire l\'aggiornamento di <xliff:g id="TYPE">%1$s</xliff:g> a &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Vuoi eseguire l\'aggiornamento di <xliff:g id="TYPE_0">%1$s</xliff:g> e <xliff:g id="TYPE_1">%2$s</xliff:g> a &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Vuoi eseguire l\'aggiornamento di <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> e <xliff:g id="TYPE_2">%3$s</xliff:g> a &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"Vuoi salvare su "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"Vuoi salvare <xliff:g id="TYPE">%1$s</xliff:g> su "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"Vuoi salvare <xliff:g id="TYPE_0">%1$s</xliff:g> e <xliff:g id="TYPE_1">%2$s</xliff:g> su "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"Vuoi salvare <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> e <xliff:g id="TYPE_2">%3$s</xliff:g> su "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"Vuoi aggiornare su "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"Vuoi aggiornare <xliff:g id="TYPE">%1$s</xliff:g> su "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"Vuoi aggiornare <xliff:g id="TYPE_0">%1$s</xliff:g> e <xliff:g id="TYPE_1">%2$s</xliff:g> su "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"Vuoi aggiornare questi elementi su "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> e <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Salva"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"No, grazie"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"Aggiorna"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 48933f9..5bf5704 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -251,7 +251,7 @@
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Voice Assist"</string>
     <string name="global_action_lockdown" msgid="1099326950891078929">"נעילה"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
-    <string name="notification_hidden_text" msgid="6351207030447943784">"הודעה חדשה"</string>
+    <string name="notification_hidden_text" msgid="6351207030447943784">"התראה חדשה"</string>
     <string name="notification_channel_virtual_keyboard" msgid="6969925135507955575">"מקלדת וירטואלית"</string>
     <string name="notification_channel_physical_keyboard" msgid="7297661826966861459">"מקלדת פיזית"</string>
     <string name="notification_channel_security" msgid="7345516133431326347">"אבטחה"</string>
@@ -298,6 +298,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"מיקרופון"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"הקלטת אודיו"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"‏לתת לאפליקציה &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; הרשאה להקליט אודיו?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"זיהוי פעילות"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"זיהוי פעילות"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"‏האם לאפשר ל-&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; לזהות את הפעילות הגופנית שלך?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"מצלמה"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"צילום תמונות והקלטת וידאו"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"‏לתת לאפליקציה &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; הרשאה לצלם תמונות וסרטונים?"</string>
@@ -424,14 +427,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"‏אפליקציה זו יכולה לזהות את המיקום שלך על סמך מקורות מיקום ברשת, כגון אנטנות סלולריות ורשתות Wi-Fi. שירותי מיקום אלה חייבים להיות מופעלים וזמינים בטאבלט שלך כדי שהאפליקציה תוכל להשתמש בהם."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"‏אפליקציה זו יכולה לזהות את המיקום שלך על סמך מקורות מיקום ברשת, כגון אנטנות סלולריות ורשתות Wi-Fi. שירותי מיקום אלה חייבים להיות מופעלים וזמינים בטלוויזיה שלך כדי שהאפליקציה תוכל להשתמש בהם."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"‏אפליקציה זו יכולה לזהות את המיקום שלך על סמך מקורות מיקום ברשת, כגון אנטנות סלולריות ורשתות Wi-Fi. שירותי מיקום אלה חייבים להיות מופעלים וזמינים בטלפון שלך כדי שהאפליקציה תוכל להשתמש בהם."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"קבלת גישה למיקום מדויק ברקע"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"אפליקציה זו יכולה לזהות את המיקום המדויק שלך בכל זמן שהיא פועלת ברקע. כדי שהאפליקציה תוכל להשתמש בשירותי המיקום, עליהם להיות מופעלים וזמינים בטלפון. ייתכן שפעולה זו תגביר את צריכת הסוללה."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"גישה למיקום ברקע"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"אם מתקבל אישור, בנוסף לגישה למיקום משוער או מדויק, תהיה לאפליקציה גישה למיקום גם כשהיא פועלת ברקע."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"שנה את הגדרות האודיו שלך"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"מאפשר לאפליקציה לשנות הגדרות אודיו גלובליות כמו עוצמת קול ובחירת הרמקול המשמש לפלט."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"הקלט אודיו"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"אפליקציה זו יכולה להשתמש במיקרופון כדי להקליט אודיו בכל עת."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"‏שליחת פקודות אל ה-SIM"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"‏מאפשרת ליישום לשלוח פקודות ל-SIM. זוהי הרשאה מסוכנת מאוד."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"זיהוי הפעילות הגופנית"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"האפליקציה מזהה את הפעילות הגופנית שלך."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"צלם תמונות וסרטונים"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"אפליקציה זו יכולה להשתמש במצלמה כדי לצלם תמונות ולהקליט סרטונים בכל עת."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"שליטה ברטט"</string>
@@ -524,6 +529,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"מאפשרת לאפליקציה לשנות את אוסף התמונות שלך."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"לקרוא מיקומים מאוסף המדיה שלך"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"מאפשרת לאפליקציה לקרוא מיקומים מאוסף המדיה שלך."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"האפליקציה <xliff:g id="APP">%s</xliff:g> רוצה לבצע אימות."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"חומרה ביומטרית לא זמינה"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"זוהתה טביעת אצבע חלקית. נסה שוב."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"לא ניתן היה לעבד את טביעת האצבע. נסה שוב."</string>
@@ -654,7 +660,7 @@
     <string name="policylab_resetPassword" msgid="4934707632423915395">"שינוי נעילת המסך"</string>
     <string name="policydesc_resetPassword" msgid="1278323891710619128">"שינוי של נעילת המסך."</string>
     <string name="policylab_forceLock" msgid="2274085384704248431">"נעילת המסך"</string>
-    <string name="policydesc_forceLock" msgid="1141797588403827138">"שליטה באופן ובתזמון של נעילת המסך"</string>
+    <string name="policydesc_forceLock" msgid="1141797588403827138">"שליטה באופן ובתזמון של נעילת המסך."</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"מחיקת כל הנתונים"</string>
     <string name="policydesc_wipeData" product="tablet" msgid="4306184096067756876">"מחק את נתוני הטאבלט ללא אזהרה על ידי ביצוע איפוס נתוני יצרן."</string>
     <string name="policydesc_wipeData" product="tv" msgid="5816221315214527028">"מחיקה של נתוני הטלוויזיה ללא אזהרה, על ידי ביצוע איפוס לנתוני היצרן."</string>
@@ -1247,7 +1253,7 @@
     <string name="ringtone_silent" msgid="7937634392408977062">"ללא"</string>
     <string name="ringtone_picker_title" msgid="3515143939175119094">"רינגטונים"</string>
     <string name="ringtone_picker_title_alarm" msgid="6473325356070549702">"צלילי התראה"</string>
-    <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"צלילי הודעה"</string>
+    <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"צלילי התראה"</string>
     <string name="ringtone_unknown" msgid="3914515995813061520">"לא ידוע"</string>
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
       <item quantity="two">‏יש רשתות Wi-Fi זמינות</item>
@@ -1460,7 +1466,7 @@
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"מאזין להתראות"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"‏VR ליסנר"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"ספק תנאי"</string>
-    <string name="notification_ranker_binding_label" msgid="774540592299064747">"שירות של דירוג הודעות"</string>
+    <string name="notification_ranker_binding_label" msgid="774540592299064747">"שירות של דירוג התראות"</string>
     <string name="vpn_title" msgid="19615213552042827">"‏VPN מופעל"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"‏VPN מופעל על ידי <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="1610714069627824309">"הקש כדי לנהל את הרשת."</string>
@@ -1903,7 +1909,7 @@
       <item quantity="one">בחרת <xliff:g id="COUNT_0">%1$d</xliff:g></item>
     </plurals>
     <string name="default_notification_channel_label" msgid="5929663562028088222">"ללא שיוך לקטגוריה"</string>
-    <string name="importance_from_user" msgid="7318955817386549931">"אתה מגדיר את החשיבות של ההודעות האלה."</string>
+    <string name="importance_from_user" msgid="7318955817386549931">"עליך להגדיר את החשיבות של ההתראות האלה."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"ההודעה חשובה בשל האנשים המעורבים."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"האם לאפשר ל-<xliff:g id="APP">%1$s</xliff:g> ליצור משתמש חדש לחשבון <xliff:g id="ACCOUNT">%2$s</xliff:g> ?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"האם לאפשר ל-<xliff:g id="APP">%1$s</xliff:g> ליצור משתמש חדש לחשבון <xliff:g id="ACCOUNT">%2$s</xliff:g> (כבר קיים משתמש לחשבון הזה) ?"</string>
@@ -1967,14 +1973,14 @@
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> הצעות של מילוי אוטומטי</item>
       <item quantity="one">הצעה אחת של מילוי אוטומטי</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"‏לשמור בשירות &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"‏האם לשמור <xliff:g id="TYPE">%1$s</xliff:g> בשירות &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"‏האם לשמור <xliff:g id="TYPE_0">%1$s</xliff:g> ו<xliff:g id="TYPE_1">%2$s</xliff:g> בשירות &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"‏האם לשמור <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ו<xliff:g id="TYPE_2">%3$s</xliff:g> בשירות &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"‏האם לעדכן בשירות &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"‏האם לעדכן את <xliff:g id="TYPE">%1$s</xliff:g> בשירות &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"‏האם לעדכן את <xliff:g id="TYPE_0">%1$s</xliff:g> ואת <xliff:g id="TYPE_1">%2$s</xliff:g> בשירות &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"‏האם לעדכן את <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ו<xliff:g id="TYPE_2">%3$s</xliff:g> בשירות &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"לשמור ב-"<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"האם לשמור את <xliff:g id="TYPE">%1$s</xliff:g> ב-"<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"האם לשמור את <xliff:g id="TYPE_0">%1$s</xliff:g> ואת <xliff:g id="TYPE_1">%2$s</xliff:g> ב-"<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"האם לשמור את <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ו-<xliff:g id="TYPE_2">%3$s</xliff:g> ב-"<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"האם לעדכן ב-"<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"האם לעדכן את <xliff:g id="TYPE">%1$s</xliff:g> ב-"<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"האם לעדכן את <xliff:g id="TYPE_0">%1$s</xliff:g> ואת <xliff:g id="TYPE_1">%2$s</xliff:g> ב-"<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"האם לעדכן פריטים אלה ב-"<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ו-<xliff:g id="TYPE_2">%3$s</xliff:g> ?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"שמירה"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"לא, תודה"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"עדכון"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 994039c..a9f94c9 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"マイク"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"音声の録音"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"音声の録音を &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; に許可しますか?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"運動の認識"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"運動を認識します"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"運動の認識を &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; に許可しますか?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"カメラ"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"写真と動画の撮影"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"写真と動画の撮影を &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; に許可しますか?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"このアプリは、ネットワーク位置情報源(携帯基地局や Wi-Fi ネットワークなど)に基づいて、ユーザーの位置情報を取得します。これらの位置情報サービスは ON の状態にして、タブレットでアプリがサービスを利用できるようにする必要があります。"</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"このアプリは、ネットワーク位置情報源(携帯基地局や Wi-Fi ネットワークなど)に基づいて、ユーザーの位置情報を取得します。これらの位置情報サービスは ON の状態にして、テレビでアプリがサービスを利用できるようにする必要があります。"</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"このアプリは、ネットワーク位置情報源(携帯基地局や Wi-Fi ネットワークなど)に基づいて、ユーザーの位置情報を取得します。これらの位置情報サービスは ON の状態にして、スマートフォンでアプリがサービスを利用できるようにする必要があります。"</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"バックグラウンドで正確な位置情報にアクセス"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"このアプリは、バックグラウンド状態でも常にユーザーの正確な位置情報を取得できます。この位置情報サービスは ON の状態にして、スマートフォンでアプリがサービスを利用できるようにする必要があります。これにより、電池の消費量が増える可能性があります。"</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"バックグラウンドでの位置情報へのアクセス"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"これが、おおよその位置情報または正確な位置情報へのアクセスの追加権限の場合、アプリはバックグラウンドでの実行中も位置情報にアクセスできます。"</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"音声設定の変更"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"音声全般の設定(音量、出力に使用するスピーカーなど)の変更をアプリに許可します。"</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"録音"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"このアプリは、いつでもマイクを使用して録音できます。"</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"SIMへのコマンド送信"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"SIMにコマンドを送信することをアプリに許可します。この許可は非常に危険です。"</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"運動の認識"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"このアプリで運動が認識されるようにします。"</string>
     <string name="permlab_camera" msgid="3616391919559751192">"写真と動画の撮影"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"このアプリは、いつでもカメラを使用して写真や動画を撮影できます。"</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"バイブレーションの制御"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"写真コレクションの変更をアプリに許可します。"</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"メディア コレクションの位置情報の読み取り"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"メディア コレクションの位置情報の読み取りをアプリに許可します。"</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"アプリ <xliff:g id="APP">%s</xliff:g> が認証を求めています。"</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"生体認証ハードウェアが利用できません"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"指紋を一部しか検出できませんでした。もう一度お試しください。"</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"指紋を処理できませんでした。もう一度お試しください。"</string>
@@ -1897,14 +1903,14 @@
       <item quantity="other">自動入力の候補 <xliff:g id="COUNT">%1$s</xliff:g> 件</item>
       <item quantity="one">自動入力の候補 1 件</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; に保存しますか?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"<xliff:g id="TYPE">%1$s</xliff:g>を &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; に保存しますか?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"<xliff:g id="TYPE_0">%1$s</xliff:g>、<xliff:g id="TYPE_1">%2$s</xliff:g>を &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; に保存しますか?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"<xliff:g id="TYPE_0">%1$s</xliff:g>、<xliff:g id="TYPE_1">%2$s</xliff:g>、<xliff:g id="TYPE_2">%3$s</xliff:g>を &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; に保存しますか?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; に更新しますか?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"<xliff:g id="TYPE">%1$s</xliff:g>を &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; に更新しますか?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"<xliff:g id="TYPE_0">%1$s</xliff:g>と<xliff:g id="TYPE_1">%2$s</xliff:g>を &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; に更新しますか?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"<xliff:g id="TYPE_0">%1$s</xliff:g>、<xliff:g id="TYPE_1">%2$s</xliff:g>、<xliff:g id="TYPE_2">%3$s</xliff:g>を &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; に更新しますか?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" に保存しますか?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"<xliff:g id="TYPE">%1$s</xliff:g>を "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" に保存しますか?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"<xliff:g id="TYPE_0">%1$s</xliff:g>、<xliff:g id="TYPE_1">%2$s</xliff:g>を "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" に保存しますか?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"<xliff:g id="TYPE_0">%1$s</xliff:g>、<xliff:g id="TYPE_1">%2$s</xliff:g>、<xliff:g id="TYPE_2">%3$s</xliff:g>を "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" に保存しますか?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" で更新しますか?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"<xliff:g id="TYPE">%1$s</xliff:g>を "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" で更新しますか?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"<xliff:g id="TYPE_0">%1$s</xliff:g>、<xliff:g id="TYPE_1">%2$s</xliff:g>を "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" で更新しますか?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"<xliff:g id="TYPE_0">%1$s</xliff:g>、<xliff:g id="TYPE_1">%2$s</xliff:g>、<xliff:g id="TYPE_2">%3$s</xliff:g>を "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" で更新しますか?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"はい"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"いいえ"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"更新"</string>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index a9ce748..e776289 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"მიკროფონი"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"აუდიოს ჩაწერა"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"გსურთ, მიანიჭოთ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>-ს&lt;/b&gt; აუდიოს ჩაწერის ნებართვა?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"აქტივობის ამოცნობა"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"აქტივობის ამოცნობა"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"გსურთ, მიანიჭოთ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-ს თქვენი ფიზიკური აქტივობის ამოცნობის ნებართვა?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"კამერა"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"ფოტოებისა და ვიდეოების გადაღება"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"გსურთ, მიანიჭოთ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>-ს&lt;/b&gt; სურათების გადაღების და ვიდეოების ჩაწერის ნებართვა?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"ამ აპს თქვენი მდებარეობის შესახებ ინფორმაციის მიღება ისეთი წყაროების მეშვეობით შეუძლია, როგორიცაა მობილური კავშირგაბმულობის ანძები და Wi-Fi ქსელები. მდებარეობის აღნიშნული სერვისები თქვენს ტაბლეტზე ჩართული და ხელმისაწვდომი უნდა იყოს, რათა აპმა მათი გამოყენება შეძლოს."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"ამ აპს თქვენი მდებარეობის შესახებ ინფორმაციის მიღება ისეთი წყაროების მეშვეობით შეუძლია, როგორიცაა მობილური კავშირგაბმულობის ანძები და Wi-Fi ქსელები. მდებარეობის აღნიშნული სერვისები თქვენს ტელევიზორზე ჩართული და ხელმისაწვდომი უნდა იყოს, რათა აპმა მათი გამოყენება შეძლოს."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"ამ აპს თქვენი მდებარეობის შესახებ ინფორმაციის მიღება ისეთი წყაროების მეშვეობით შეუძლია, როგორიცაა მობილური კავშირგაბმულობის ანძები და Wi-Fi ქსელები. მდებარეობის აღნიშნული სერვისები თქვენს ტელეფონზე ჩართული და ხელმისაწვდომი უნდა იყოს, რათა აპმა მათი გამოყენება შეძლოს."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"ზუსტ მდებარეობაზე წვდომა ფონურ რეჟიმში"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"ამ აპს შეუძლია თქვენი ზუსტი მდებარეობის შესახებ ინფორმაციის მიღება ყოველთვის, როცა გაშვებულია ფონურ რეჟიმში. თქვენს ტელეფონზე ჩართული და ხელმისაწვდომი უნდა იყოს მდებარეობის სერვისები, აპმა მათი გამოყენება რომ შეძლოს. ამან შეიძლება გაზარდოს ბატარეის მოხმარება."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"მდებარეობაზე წვდომა ფონურ რეჟიმში"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"ამ ნებართვის მიახლოებით ან ზუსტ მდებარეობაზე წვდომის ნებართვასთან ერთად მინიჭების შემთხვევაში, აპს შეეძლება მდებარეობაზე წვდომა ფონურ რეჟიმში."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"თქვენი აუდიო პარამეტრების შეცვლა"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"აპს შეეძლება აუდიოს გლობალური პარამეტრების შეცვლა. მაგ.: ხმის სიმაღლე და რომელი დინამიკი გამოიყენება სიგნალის გამოსტანად."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"აუდიოს ჩაწერა"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"ამ აპს ნებისმიერ დროს შეუძლია მიკროფონით აუდიოს ჩაწერა."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"ბრძანებების SIM-ზე გაგზავნა"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"აპისთვის ნების დართვა გაუგზავნოს ბრძანებები SIM-ბარათს. ეს ძალიან საშიშია."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"ფიზიკური აქტივობის ამოცნობა"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"ამ აპს შეუძლია თქვენი ფიზიკური აქტივობის ამოცნობა."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"სურათებისა და ვიდეოების გადაღება"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"ამ აპს ნებისმიერ დროს შეუძლია კამერით სურათების გადაღება და ვიდეოების ჩაწერა."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"ვიბრაციის კონტროლი"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"აპი შეძლებს თქვენი ფოტოკოლექციის შეცვლას."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"მდებარეობების გაცნობა თქვენი მედიაკოლექციიდან"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"აპი შეძლებს მდებარეობების გაცნობას თქვენი მედიაკოლექციიდან."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"აპლიკაცია <xliff:g id="APP">%s</xliff:g> ითხოვს ავტორიზაციას."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"ბიომეტრიული აპარატურა მიუწვდომელია"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"აღმოჩენილია თითის ნაწილობრივი ანაბეჭდი. გთხოვთ, სცადოთ ხელახლა."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"თითის ანაბეჭდი ვერ მუშავდება. გთხოვთ, სცადოთ ხელახლა."</string>
@@ -1897,14 +1903,14 @@
       <item quantity="other">ავტომატური შევსების <xliff:g id="COUNT">%1$s</xliff:g> შემოთავაზება</item>
       <item quantity="one">ავტომატური შევსების ერთი შემოთავაზება</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"გსურთ, შეინახოთ &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>-ში&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"გსურთ, შეინახოთ <xliff:g id="TYPE">%1$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>-ში&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"გსურთ, შეინახოთ <xliff:g id="TYPE_0">%1$s</xliff:g> და <xliff:g id="TYPE_1">%2$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>-ში&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"გსურთ, შეინახოთ <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, და <xliff:g id="TYPE_2">%3$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>-ში&lt;/b&gt;?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"გსურთ, განაახლოთ &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;-ზე?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"გსურთ, განაახლოთ <xliff:g id="TYPE">%1$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;-ზე?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"გსურთ, განაახლოთ <xliff:g id="TYPE_0">%1$s</xliff:g> და <xliff:g id="TYPE_1">%2$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;-ზე?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"გსურთ, განაახლოთ <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> და <xliff:g id="TYPE_2">%3$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;-ზე?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"გსურთ "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"-ში შენახვა?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"გსურთ, "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"-ში შეინახოთ <xliff:g id="TYPE">%1$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"გსურთ, "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"-ში შეინახოთ <xliff:g id="TYPE_0">%1$s</xliff:g> და <xliff:g id="TYPE_1">%2$s</xliff:g>?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"გსურთ, "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"-ში შეინახოთ <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> და <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"გსურთ "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"-ში განახლება?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"გსურთ, "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"-ში განაახლოთ <xliff:g id="TYPE">%1$s</xliff:g>?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"გსურთ, "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"-ში განაახლოთ <xliff:g id="TYPE_0">%1$s</xliff:g> და <xliff:g id="TYPE_1">%2$s</xliff:g>?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"გსურთ, "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"-ში განაახლოთ <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> და <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"შენახვა"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"არა, გმადლობთ"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"განახლება"</string>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index a8b527b..375aa82 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Микрофон"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"аудио жазу"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; қолданбасына аудиомазмұн жазуға рұқсат берілсін бе?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"Әрекетті тану"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"әрекетті тану"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; қолданбасына физикалық әрекетті тануға рұқсат етілсін бе?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Камера"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"суретке түсіріп, бейне жазу"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; қолданбасына суретке түсіруге және бейне жазуға рұқсат берілсін бе?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Бұл қолданба орналасқан жеріңізді ұялы байланыс мұнаралары мен Wi-Fi желілері сияқты желі көздерінің негізінде анықтайды. Қолданба бұл орынды анықтау қызметтерін пайдалана алуы үшін олар қосулы әрі планшетте қолжетімді болуы керек."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Бұл қолданба орналасқан жеріңізді ұялы байланыс мұнаралары мен Wi-Fi желілері сияқты желі көздерінің негізінде анықтайды. Қолданба бұл орынды анықтау қызметтерін пайдалана алуы үшін олар қосулы әрі теледидарда қолжетімді болуы керек."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Бұл қолданба орналасқан жеріңізді ұялы байланыс мұнаралары мен Wi-Fi желілері сияқты желі көздерінің негізінде анықтайды. Қолданба бұл орынды анықтау қызметтерін пайдалана алуы үшін олар қосулы әрі телефонда қолжетімді болуы керек."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"геодеректерге фондық режимде кіру"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"Бұл қолданба нақты орналасқан жеріңіз туралы ақпаратты фондық режимде де анықтай алады. Қолданба бұл орынды анықтау қызметтерін пайдалана алуы үшін, олар қосулы әрі телефонда қолжетімді болуы керек. Батарея көбірек тұтынылуы мүмкін."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"геодеректерді фондық режимде пайдалану"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Егер ол шамамен есептегендегі немесе нақты орынды пайдалануға рұқсат алса, қолданба фондық режимде жұмыс істеп тұрып-ақ геодеректерді пайдалана алады."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"аудио параметрлерін өзгерту"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Қолданбаға дыбыс қаттылығы және аудио шығыс үндеткішін таңдау сияқты жаһандық аудио параметрлерін өзгерту мүмкіндігін береді."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"аудио жазу"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"Бұл қолданба кез келген уақытта микрофон арқылы аудиомазмұн жаза алады."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"SIM картасына пәрмендер жіберу"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Қолданбаға SIM картасына пәрмен жіберу мүмкіндігін береді. Бұл өте қауіпті."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"физикалық әрекетті тану"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"Бұл қолданба физикалық әрекетті тани алады."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"фотосурет жасау және бейне жазу"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"Бұл қолданба кез келген уақытта камерамен суретке түсіруі және бейнелерді жазуы мүмкін."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"тербелісті басқару"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Қолданбаға суреттер жинағын өзгертуге мүмкіндік береді."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"медиамазмұн жинағынан геодеректерді оқу"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Қолданбаға медиамазмұн жинағынан геодеректерді оқуға мүмкіндік береді."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"<xliff:g id="APP">%s</xliff:g> қолданбасына аутентификация қажет."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Биометрикалық жабдық жоқ"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Саусақ ізі ішінара анықталды. Әрекетті қайталаңыз."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Саусақ ізін өңдеу мүмкін емес. Әрекетті қайталаңыз."</string>
@@ -1898,14 +1904,14 @@
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> автотолтыру ұсынысы</item>
       <item quantity="one">Бір автотолтыру ұсынысы</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"\"<xliff:g id="LABEL">%1$s</xliff:g>\" қызметінде сақталсын ба?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"<xliff:g id="TYPE">%1$s</xliff:g> \"<xliff:g id="LABEL">%2$s</xliff:g>\" қызметінде сақталсын ба?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"<xliff:g id="TYPE_0">%1$s</xliff:g> және <xliff:g id="TYPE_1">%2$s</xliff:g> \"<xliff:g id="LABEL">%3$s</xliff:g>\" қызметінде сақталсын ба?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> және <xliff:g id="TYPE_2">%3$s</xliff:g> \"<xliff:g id="LABEL">%4$s</xliff:g>\" қызметінде сақталсын ба?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; қызметінде жаңартылсын ба?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"<xliff:g id="TYPE">%1$s</xliff:g> мәліметі &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; қызметінде жаңартылсын ба?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"<xliff:g id="TYPE_0">%1$s</xliff:g> және <xliff:g id="TYPE_1">%2$s</xliff:g> мәліметі &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; қызметінде жаңартылсын ба?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> және <xliff:g id="TYPE_2">%3$s</xliff:g> мәліметі &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; қызметінде жаңартылсын ба?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" қызметіне сақталсын ба?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"<xliff:g id="TYPE">%1$s</xliff:g> деректері "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" қызметіне сақталсын ба?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"<xliff:g id="TYPE_0">%1$s</xliff:g> және <xliff:g id="TYPE_1">%2$s</xliff:g> деректері "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" қызметіне сақталсын ба?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> және <xliff:g id="TYPE_2">%3$s</xliff:g> деректері "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" қызметіне сақталсын ба?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" қызметінде жаңартылсын ба?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"<xliff:g id="TYPE">%1$s</xliff:g> деректері "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" қызметінде жаңартылсын ба?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"<xliff:g id="TYPE_0">%1$s</xliff:g> және <xliff:g id="TYPE_1">%2$s</xliff:g> деректері "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" қызметінде жаңартылсын ба?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922"><b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" қызметіндегі <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> және <xliff:g id="TYPE_2">%3$s</xliff:g> деректері жаңартылсын ба?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Сақтау"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Жоқ, рақмет"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"Жаңарту"</string>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index 2620ce4..b9cf1eb 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"មីក្រូ​ហ្វូន"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"ថតសំឡេង"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"អនុញ្ញាតឱ្យ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ថតសំឡេង?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"ការសម្គាល់​សកម្មភាព"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"ស្គាល់​សកម្មភាព"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"អនុញ្ញាតឱ្យ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ស្គាល់​សកម្មភាព​រាងកាយ​របស់អ្នក?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"កាមេរ៉ា"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"ថតរូប និងថតវីដេអូ"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"អនុញ្ញាតឱ្យ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ថតរូប និងថត​វីដេអូ?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"កម្មវិធី​នេះ​អាច​ទទួល​បាន​ទីតាំង​របស់​អ្នក​ ដោយ​ផ្អែក​លើ​ប្រភព​បណ្តាញ​ ដូចជា​៖​ អង់តែន​ និង​បណ្តាញ​ Wi-Fi​ ។​ សេវាកម្ម​ទីតាំង​ទាំងនេះ​ត្រូវតែ​បើក​ និង​ត្រូវតែ​មាន​នៅ​លើ​ថេប្លេត​របស់​អ្នក ដើម្បី​ឲ្យ​កម្មវិធី​នេះ​អាច​ប្រើ​វា​បាន​។"</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"កម្មវិធី​នេះ​អាច​ទទួល​បាន​ទីតាំង​របស់​អ្នក​ ដោយ​ផ្អែក​លើ​ប្រភព​បណ្តាញ​ ដូចជា​៖​ អង់តែន​ និង​បណ្តាញ​ Wi-Fi​ ។​ សេវាកម្ម​ទីតាំង​ទាំងនេះ​ត្រូវតែ​បើក​ និង​ត្រូវតែ​មាន​នៅ​លើ​ទូរទស្សន៍​របស់​អ្នក ដើម្បី​ឲ្យ​កម្មវិធី​នេះ​អាច​ប្រើ​វា​បាន​។"</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"កម្មវិធី​នេះ​អាច​ទទួល​បាន​ទីតាំង​របស់​អ្នក​ ដោយ​ផ្អែក​លើ​ប្រភព​បណ្តាញ​ ដូចជា​៖​ អង់តែន​ និង​បណ្តាញ​ Wi-Fi​ ។​ សេវាកម្ម​ទីតាំង​ទាំងនេះ​ត្រូវតែ​បើក​ និង​ត្រូវតែ​មាន​នៅ​លើ​ទូរសព្ទ​របស់​អ្នក ដើម្បី​ឲ្យ​កម្មវិធី​នេះ​អាច​ប្រើ​វា​បាន​។"</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"ចូលប្រើ​ទីតាំង​ជាក់លាក់​នៅផ្ទៃ​ខាងក្រោយ"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"កម្មវិធីនេះ​អាចទទួល​បានទីតាំង​ពិតប្រាកដ​របស់អ្នក​គ្រប់ពេល​ដែលវា​ស្ថិតនៅ​ផ្ទៃខាងក្រោយ។ សេវាកម្ម​ទីតាំង​ទាំងនេះ​ត្រូវតែ​បើក និងមាន​នៅលើ​ទូរសព្ទ​របស់អ្នក ដើម្បីឱ្យ​កម្មវិធី​នេះអាចប្រើ​ពួកវាបាន។ វាអាចប្រើ​ថាមពល​ច្រើន​ជាងមុន។"</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"ចូល​ប្រើ​ទីតាំង​នៅ​ផ្ទៃខាងក្រោយ"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"ប្រសិនបើ​ផ្ដល់​ការអនុញ្ញាត​នេះ​បន្ថែម​ពីលើ​ការចូលប្រើទីតាំងជាក់លាក់ ឬប្រហាក់ប្រហែល កម្មវិធី​នឹងអាចចូលប្រើទីតាំងនោះ ខណៈពេលដំណើរការនៅផ្ទៃខាងក្រោយ។"</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"ប្ដូរ​ការ​កំណត់​អូឌីយូ​របស់​អ្នក"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"ឲ្យ​កម្មវិធី​កែ​ការ​កំណត់​សំឡេង​សកល ដូច​ជា​កម្រិត​សំឡេង និង​អូប៉ាល័រ​ដែល​បាន​ប្រើ​សម្រាប់​លទ្ធផល។"</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"ថត​សំឡេង"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"កម្មវិធី​នេះ​អាច​ថត​សំឡេង​ដោយ​ប្រើ​មីក្រូហ្វូន​បាន​គ្រប់​ពេល។"</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"ផ្ញើពាក្យបញ្ជាទៅស៊ីមកាត"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"ឲ្យ​កម្មវិធី​ផ្ញើ​ពាក្យ​បញ្ជា​ទៅ​ស៊ីម​កាត។ វា​គ្រោះ​ថ្នាក់​ណាស់។"</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"ស្គាល់​សកម្មភាព​រាងកាយ"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"កម្មវិធីនេះ​អាចស្គាល់សកម្មភាព​រាងកាយ​របស់អ្នក។"</string>
     <string name="permlab_camera" msgid="3616391919559751192">"ថត​រូប និងវីដេអូ"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"កម្មវិធី​នេះ​អាច​ថត​រូប​ និង​ថត​វីដេអូ​ ដោយ​ប្រើ​កាមេរ៉ា​បាន​គ្រប់​ពេល​។"</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"ពិនិត្យ​ការ​ញ័រ"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"អនុញ្ញាតឱ្យ​កម្មវិធី​កែប្រែ​បណ្ដុំ​រូបថត​របស់​អ្នក។"</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"អាន​ទីតាំង​ពី​បណ្ដុំ​មេឌៀ​របស់​អ្នក"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"អនុញ្ញាតឱ្យ​កម្មវិធី​អាន​ទីតាំង​ពីបណ្ដុំ​មេឌៀ​របស់​អ្នក។"</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"កម្មវិធី <xliff:g id="APP">%s</xliff:g> ចង់​ធ្វើ​កា​រផ្ទៀងផ្ទាត់។"</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"មិនអាច​ប្រើឧបករណ៍​ស្កេន​ស្នាមម្រាមដៃ​បានទេ"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"បានផ្តិតយកស្នាមម្រាមដៃមិនពេញលក្ខណៈ។ សូមព្យាយាមម្តងទៀត។"</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"មិនអាចដំណើរការស្នាមម្រាមដៃបានទេ។ សូមព្យាយាមម្តងទៀត។"</string>
@@ -1899,14 +1905,14 @@
       <item quantity="other">ការណែនាំអំពីការបំពេញដោយស្វ័យប្រវត្តិ <xliff:g id="COUNT">%1$s</xliff:g></item>
       <item quantity="one">ការណែនាំអំពីការបំពេញដោយស្វ័យប្រវត្តិមួយ</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"រក្សាទុក​ទៅក្នុង &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"រក្សាទុក <xliff:g id="TYPE">%1$s</xliff:g> ទៅក្នុង &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"រក្សាទុក <xliff:g id="TYPE_0">%1$s</xliff:g> និង <xliff:g id="TYPE_1">%2$s</xliff:g> ទៅក្នុង &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"រក្សាទុក <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, និង <xliff:g id="TYPE_2">%3$s</xliff:g> ទៅក្នុង &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"ធ្វើ​បច្ចុប្បន្នភាព​ទៅ &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"ធ្វើ​បច្ចុប្បន្នភាព <xliff:g id="TYPE">%1$s</xliff:g> ទៅ &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"ធ្វើ​បច្ចុប្បន្នភាព <xliff:g id="TYPE_0">%1$s</xliff:g> និង <xliff:g id="TYPE_1">%2$s</xliff:g> ទៅ &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"ធ្វើ​បច្ចុប្បន្នភាព <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> និង <xliff:g id="TYPE_2">%3$s</xliff:g> ទៅ &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"រក្សាទុក​ទៅក្នុង "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"រក្សាទុក <xliff:g id="TYPE">%1$s</xliff:g> ទៅក្នុង "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"រក្សាទុក​ <xliff:g id="TYPE_0">%1$s</xliff:g> និង <xliff:g id="TYPE_1">%2$s</xliff:g> ទៅ​ក្នុង "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"រក្សាទុក​ <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> និង <xliff:g id="TYPE_2">%3$s</xliff:g> ទៅក្នុង "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"ធ្វើ​បច្ចុប្បន្នភាព​នៅក្នុង "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"ធ្វើ​បច្ចុប្បន្នភាព <xliff:g id="TYPE">%1$s</xliff:g> នៅក្នុង "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"ធ្វើ​បច្ចុប្បន្នភាព​ <xliff:g id="TYPE_0">%1$s</xliff:g> និង <xliff:g id="TYPE_1">%2$s</xliff:g> នៅក្នុង "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"ធ្វើ​បច្ចុប្បន្នភាព​ធាតុ​ទាំងនេះ​នៅក្នុង "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> និង <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"រក្សាទុក"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"ទេ អរគុណ"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"ធ្វើ​បច្ចុប្បន្នភាព"</string>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index 1b83ec2..2a480cd 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"ಮೈಕ್ರೋಫೋನ್‌"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"ಆಡಿಯೊ ರೆಕಾರ್ಡ್ ಮಾಡಿ"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"ಆಡಿಯೋ ರೆಕಾರ್ಡ್‌ ಮಾಡಲು &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ಗೆ ಅನುಮತಿಸಬೇಕೇ?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"ಚಟುವಟಿಕೆಯನ್ನು ಗುರುತಿಸುವಿಕೆ"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"ಚಟುವಟಿಕೆಯನ್ನು ಗುರುತಿಸಿ"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"ನಿಮ್ಮ ದೈಹಿಕ ಚಟುವಟಿಕೆಯನ್ನು ಗುರುತಿಸಲು &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ಗೆ ಅನುಮತಿಸುವುದೇ?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"ಕ್ಯಾಮರಾ"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"ಚಿತ್ರಗಳನ್ನು ತೆಗೆಯಲು, ವೀಡಿಯೊ ರೆಕಾರ್ಡ್ ಮಾಡಲು"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"ಚಿತ್ರಗಳನ್ನು ಸೆರೆಹಿಡಿಯಲು ಮತ್ತು ವೀಡಿಯೊ ರೆಕಾರ್ಡ್‌ ಮಾಡಲು &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ಗೆ ಅನುಮತಿಸಬೇಕೇ?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"ಈ ಅಪ್ಲಿಕೇಶನ್ ನಿಮ್ಮ ಸ್ಥಳವನ್ನು ಸೆಲ್ ಟವರ್‌ಗಳು ಮತ್ತು ವೈ-ಫೈ ನೆಟ್‍‍ವರ್ಕ್‌ನಂತಹ ನೆಟ್‍‍ವರ್ಕ್ ಮೂಲಗಳ ಆಧಾರದ ಮೇಲೆ ಪಡೆಯಬಹುದು. ಈ ಸ್ಥಳ ಸೇವೆಗಳನ್ನು ಆನ್ ಮಾಡಿರಬೇಕು ಮತ್ತು ಅವುಗಳನ್ನು ಬಳಸಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಸಾಧ್ಯವಾಗುವಂತೆ ನಿಮ್ಮ ಟ್ಯಾಬ್ಲೆಟ್‌ನಲ್ಲಿ ಅವುಗಳು ಲಭ್ಯವಿರಬೇಕು."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"ಈ ಅಪ್ಲಿಕೇಶನ್ ನಿಮ್ಮ ಸ್ಥಳವನ್ನು ಸೆಲ್ ಟವರ್‌ಗಳು ಮತ್ತು ವೈ-ಫೈ ನೆಟ್‍‍ವರ್ಕ್‌ನಂತಹ ನೆಟ್‍‍ವರ್ಕ್ ಮೂಲಗಳ ಆಧಾರದ ಮೇಲೆ ಪಡೆಯಬಹುದು. ಈ ಸ್ಥಳ ಸೇವೆಗಳನ್ನು ಆನ್ ಮಾಡಿರಬೇಕು ಮತ್ತು ಅವುಗಳನ್ನು ಬಳಸಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಸಾಧ್ಯವಾಗುವಂತೆ ನಿಮ್ಮ ಟಿವಿಯಲ್ಲಿ ಅವುಗಳು ಲಭ್ಯವಿರಬೇಕು."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"ಈ ಅಪ್ಲಿಕೇಶನ್ ನಿಮ್ಮ ಸ್ಥಳವನ್ನು ಸೆಲ್ ಟವರ್‌ಗಳು ಮತ್ತು ವೈ-ಫೈ ನೆಟ್‍‍ವರ್ಕ್‌ನಂತಹ ನೆಟ್‍‍ವರ್ಕ್ ಮೂಲಗಳ ಆಧಾರದ ಮೇಲೆ ಪಡೆಯಬಹುದು. ಈ ಸ್ಥಳ ಸೇವೆಗಳನ್ನು ಆನ್ ಮಾಡಿರಬೇಕು ಮತ್ತು ಅವುಗಳನ್ನು ಬಳಸಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಸಾಧ್ಯವಾಗುವಂತೆ ನಿಮ್ಮ ಫೋನ್‌ನಲ್ಲಿ ಅವುಗಳು ಲಭ್ಯವಿರಬೇಕು."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"ಹಿನ್ನೆಲೆಯಲ್ಲಿ ನಿಖರ ಸ್ಥಳವನ್ನು ಪ್ರವೇಶಿಸಿ"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"ಈ ಅಪ್ಲಿಕೇಶನ್ ಹಿನ್ನೆಲೆಯಲ್ಲಿದೆಯಾದರೂ ನಿಮ್ಮ ಸರಿಯಾದ ಸ್ಥಳವನ್ನು ಪಡೆಯಬಹುದು. ಈ ಸ್ಥಳ ಸೇವೆಗಳನ್ನು ಆನ್ ಮಾಡಿರಬೇಕು ಮತ್ತು ಅವುಗಳನ್ನು ಬಳಸಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಸಾಧ್ಯವಾಗುವಂತೆ ನಿಮ್ಮ ಫೋನ್‌ನಲ್ಲಿ ಅವುಗಳು ಲಭ್ಯವಿರಬೇಕು."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"ಹಿನ್ನೆಲೆಯಲ್ಲಿ ಸ್ಥಳವನ್ನು ಪ್ರವೇಶಿಸಿ"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"ಇದನ್ನು ಅಂದಾಜು ಅಥವಾ ನಿಖರವಾದ ಸ್ಥಳ ಪ್ರವೇಶಕ್ಕೆ ಹೆಚ್ಚುವರಿಯಾಗಿ ಅನುಮತಿಸಿದರೆ, ಆ್ಯಪ್ ಹಿನ್ನೆಲೆಯಲ್ಲಿ ರನ್ ಆಗುತ್ತಿರುವಾಗ ಅದು ಸ್ಥಳವನ್ನು ಪ್ರವೇಶಿಸಬಹುದು."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"ನಿಮ್ಮ ಆಡಿಯೊ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಬದಲಾಯಿಸಿ"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"ವಾಲ್ಯೂಮ್ ರೀತಿಯ ಮತ್ತು ಔಟ್‍‍ಪುಟ್‍‍ಗಾಗಿ ಯಾವ ಸ್ಪೀಕರ್ ಬಳಸಬೇಕು ಎಂಬ ರೀತಿಯ ಜಾಗತಿಕ ಆಡಿಯೊ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಮಾರ್ಪಡಿಸಲು ಅಪ್ಲಿಕೇಶನ್‍‍ಗೆ ಅವಕಾಶ ಮಾಡಿಕೊಡುತ್ತದೆ."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"ಆಡಿಯೊ ರೆಕಾರ್ಡ್ ಮಾಡಿ"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"ಈ ಅಪ್ಲಿಕೇಶನ್ ಮೈಕ್ರೋಫೋನ್ ಬಳಸುವ ಮೂಲಕ ಯಾವುದೇ ಸಮಯದಲ್ಲಾದರೂ ಆಡಿಯೊ ರೆಕಾರ್ಡ್ ಮಾಡಬಹುದು."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"ಸಿಮ್‌ಗೆ ಆಜ್ಞೆಗಳನ್ನು ಕಳುಹಿಸಿ"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"ಸಿಮ್‌ ಗೆ ಆದೇಶಗಳನ್ನು ಕಳುಹಿಸಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ. ಇದು ತುಂಬಾ ಅಪಾಯಕಾರಿ."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"ದೈಹಿಕ ಚಟುವಟಿಕೆಯನ್ನು ಗುರುತಿಸಿ"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"ಈ ಆ್ಯಪ್‌ ನಿಮ್ಮ ದೈಹಿಕ ಚಟುವಟಿಕೆಯನ್ನು ಗುರುತಿಸಬಹುದು."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"ಚಿತ್ರಗಳು ಮತ್ತು ವೀಡಿಯೊಗಳನ್ನು ಸೆರೆಹಿಡಿಯಿರಿ"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"ಈ ಅಪ್ಲಿಕೇಶನ್ ಯಾವ ಸಮಯದಲ್ಲಾದರೂ ಕ್ಯಾಮರಾ ಬಳಸಿಕೊಂಡು ಚಿತ್ರಗಳು ಮತ್ತು ವಿಡಿಯೋಗಳನ್ನು ರೆಕಾರ್ಡ್ ಮಾಡಬಹುದು."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"ವೈಬ್ರೇಷನ್‌‌ ನಿಯಂತ್ರಿಸಿ"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"ನಿಮ್ಮ ಫೋಟೋ ಸಂಗ್ರಹಣೆಯನ್ನು ಮಾರ್ಪಡಿಸಲು ಆ್ಯಪ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"ನಿಮ್ಮ ಮೀಡಿಯಾ ಸಂಗ್ರಹಣೆಯಿಂದ ಸ್ಥಳಗಳನ್ನು ಓದಿ"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"ನಿಮ್ಮ ಮೀಡಿಯಾ ಸಂಗ್ರಹಣೆಯಿಂದ ಸ್ಥಳಗಳನ್ನು ಓದಲು ಆ್ಯಪ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"<xliff:g id="APP">%s</xliff:g> ಆ್ಯಪ್‌ಗೆ ದೃಢೀಕರಣದ ಅಗತ್ಯವಿದೆ."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"ಬಯೋಮೆಟ್ರಿಕ್ ಹಾರ್ಡ್‌ವೇರ್‌ ಲಭ್ಯವಿಲ್ಲ"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"ಭಾಗಶಃ ಬೆರಳಚ್ಚು ಪತ್ತೆಯಾಗಿದೆ. ದಯವಿಟ್ಟು ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"ಬೆರಳಚ್ಚು ಪ್ರಕ್ರಿಯೆಗೊಳಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ. ದಯವಿಟ್ಟು ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
@@ -1898,14 +1904,14 @@
       <item quantity="one"><xliff:g id="COUNT">%1$s</xliff:g> ಸ್ವಯಂಭರ್ತಿ ಸಲಹೆಗಳು</item>
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> ಸ್ವಯಂಭರ್ತಿ ಸಲಹೆಗಳು</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;ನಲ್ಲಿ ಉಳಿಸುವುದೇ?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"<xliff:g id="TYPE">%1$s</xliff:g> ಅನ್ನು &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;ನಲ್ಲಿ ಉಳಿಸುವುದೇ?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"<xliff:g id="TYPE_0">%1$s</xliff:g> ಹಾಗೂ <xliff:g id="TYPE_1">%2$s</xliff:g> ಅನ್ನು &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;ನಲ್ಲಿ ಉಳಿಸುವುದೇ?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, ಹಾಗೂ <xliff:g id="TYPE_2">%3$s</xliff:g> ಅನ್ನು &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;ನಲ್ಲಿ ಉಳಿಸುವುದೇ?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;ಗೆ ಅಪ್‌ಡೇಟ್‌ ಮಾಡುವುದೇ?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"<xliff:g id="TYPE">%1$s</xliff:g> ಅನ್ನು &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;ಗೆ ಅಪ್‌ಡೇಟ್‌ ಮಾಡುವುದೇ?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"<xliff:g id="TYPE_0">%1$s</xliff:g> ಹಾಗೂ <xliff:g id="TYPE_1">%2$s</xliff:g> ಅನ್ನು &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;ಗೆ ಅಪ್‌ಡೇಟ್‌ ಮಾಡುವುದೇ?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, ಹಾಗೂ <xliff:g id="TYPE_2">%3$s</xliff:g> ಅನ್ನು &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;ಗೆ ಅಪ್‌ಡೇಟ್‌ ಮಾಡುವುದೇ?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" ನಲ್ಲಿ ಉಳಿಸುವುದೇ?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"<xliff:g id="TYPE">%1$s</xliff:g> ಅನ್ನು "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" ನಲ್ಲಿ ಉಳಿಸುವುದೇ?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"<xliff:g id="TYPE_0">%1$s</xliff:g> ಮತ್ತು <xliff:g id="TYPE_1">%2$s</xliff:g> ಅನ್ನು "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" ನಲ್ಲಿ ಉಳಿಸುವುದೇ?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ಮತ್ತು <xliff:g id="TYPE_2">%3$s</xliff:g> ಅನ್ನು "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" ನಲ್ಲಿ ಉಳಿಸುವುದೇ?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" ನಲ್ಲಿ ಅಪ್‌ಡೇಟ್ ಮಾಡುವುದೇ?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"<xliff:g id="TYPE">%1$s</xliff:g> ಅನ್ನು "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" ನಲ್ಲಿ ಅಪ್‌ಡೇಟ್ ಮಾಡುವುದೇ?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"<xliff:g id="TYPE_0">%1$s</xliff:g> ಮತ್ತು <xliff:g id="TYPE_1">%2$s</xliff:g> ಅನ್ನು "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" ನಲ್ಲಿ ಅಪ್‌ಡೇಟ್ ಮಾಡುವುದೇ?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"ಈ ಮುಂದಿನ ಐಟಂಗಳನ್ನು "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" ನಲ್ಲಿ ಅಪ್‌ಡೇಟ್ ಮಾಡುವುದೇ: <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ಮತ್ತು <xliff:g id="TYPE_2">%3$s</xliff:g> ?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"ಉಳಿಸಿ"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"ಬೇಡ"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"ಅಪ್‌ಡೇಟ್"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 6223dab..b66cbf4 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"마이크"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"오디오 녹음"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;에서 오디오를 녹음하도록 허용하시겠습니까?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"활동 감지"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"활동 확인"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;에서 내 신체 활동을 확인하도록 허용하시겠습니까?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"카메라"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"사진 및 동영상 촬영"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;에서 사진을 촬영하고 동영상을 녹화하도록 허용하시겠습니까?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"이 앱은 기지국 및 Wi-Fi 네트워크와 같은 네트워크 소스를 통해 내 위치를 알 수 있습니다. 앱에서 위치 서비스를 사용하려면 태블릿에서 위치 서비스가 사용 설정되어 있으며 사용 가능해야 합니다."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"이 앱은 기지국 및 Wi-Fi 네트워크와 같은 네트워크 소스를 통해 내 위치를 알 수 있습니다. 앱에서 위치 서비스를 사용하려면 TV에서 위치 서비스가 사용 설정되어 있으며 사용 가능해야 합니다."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"이 앱은 기지국 및 Wi-Fi 네트워크와 같은 네트워크 소스를 통해 내 위치를 알 수 있습니다. 앱에서 위치 서비스를 사용하려면 휴대전화에서 위치 서비스가 사용 설정되어 있으며 사용 가능해야 합니다."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"백그라운드에서 정확한 위치에 액세스"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"이 앱은 백그라운드에서 언제든지 나의 정확한 위치를 알 수 있습니다. 앱에서 위치 서비스를 사용하려면 휴대전화에서 위치 서비스가 사용 설정되어 있으며 사용할 수 있어야 합니다. 배터리 사용량이 늘어날 수 있습니다."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"백그라운드에서 위치 정보 액세스"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"이 권한이 대략적인 위치 정보 또는 정확한 위치 정보 액세스 권한에 추가적으로 부여되면 앱이 백그라운드에서 실행되는 동안 위치에 액세스할 수 있습니다."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"오디오 설정 변경"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"앱이 음량이나 출력을 위해 사용하는 스피커 등 전체 오디오 설정을 변경할 수 있도록 허용합니다."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"오디오 녹음"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"이 앱은 언제든지 마이크를 사용하여 오디오를 녹음할 수 있습니다."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"SIM 카드로 명령 전송"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"앱이 SIM에 명령어를 전송할 수 있도록 허용합니다. 이 기능은 매우 신중히 허용해야 합니다."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"신체 활동 확인"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"이 앱에서 내 신체 활동을 확인할 수 있습니다."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"사진과 동영상 찍기"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"이 앱은 언제든지 카메라를 사용하여 사진을 촬영하고 동영상을 녹화할 수 있습니다."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"진동 제어"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"앱에서 사진 컬렉션을 수정하도록 허용합니다."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"미디어 컬렉션에서 위치 읽기"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"앱에서 미디어 컬렉션의 위치를 읽도록 허용합니다."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"<xliff:g id="APP">%s</xliff:g> 애플리케이션에서 인증을 요청합니다"</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"생체 인식 하드웨어를 사용할 수 없음"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"지문이 일부만 인식되었습니다. 다시 시도해 주세요."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"지문을 인식할 수 없습니다. 다시 시도해 주세요."</string>
@@ -1897,14 +1903,14 @@
       <item quantity="other">자동완성 추천 <xliff:g id="COUNT">%1$s</xliff:g>개</item>
       <item quantity="one">자동완성 추천 1개</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;에 저장하시겠습니까?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"<xliff:g id="TYPE">%1$s</xliff:g>을(를) &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;에 저장하시겠습니까?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"<xliff:g id="TYPE_0">%1$s</xliff:g> 및 <xliff:g id="TYPE_1">%2$s</xliff:g>을(를) &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;에 저장하시겠습니까?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g>을(를) &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;에 저장하시겠습니까?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;(으)로 업데이트하시겠습니까?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"<xliff:g id="TYPE">%1$s</xliff:g>을(를) &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;(으)로 업데이트하시겠습니까?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"<xliff:g id="TYPE_0">%1$s</xliff:g> 및 <xliff:g id="TYPE_1">%2$s</xliff:g>을(를) &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;(으)로 업데이트하시겠습니까?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g>을(를) &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;(으)로 업데이트하시겠습니까?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"에 저장하시겠습니까?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"<xliff:g id="TYPE">%1$s</xliff:g>을(를) "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"에 저장하시겠습니까?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"<xliff:g id="TYPE_0">%1$s</xliff:g> 및 <xliff:g id="TYPE_1">%2$s</xliff:g>을(를) "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"에 저장하시겠습니까?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> 및 <xliff:g id="TYPE_2">%3$s</xliff:g>을(를) "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"에 저장하시겠습니까?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"에서 업데이트하시겠습니까?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233"><b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"에서 <xliff:g id="TYPE">%1$s</xliff:g>을(를) 업데이트하시겠습니까?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484"><b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"에서 <xliff:g id="TYPE_0">%1$s</xliff:g> 및 <xliff:g id="TYPE_1">%2$s</xliff:g>을(를) 업데이트하시겠습니까?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922"><b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"에서 <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> 및 <xliff:g id="TYPE_2">%3$s</xliff:g> 업데이트"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"저장"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"사용 안함"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"업데이트"</string>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index f49746f..de3bcd2 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Микрофон"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"аудио жаздыруу"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; колдонмосуна аудио файлдарды жаздырууга уруксат берилсинби?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"Кыймыл-аракетти аныктоо"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"кыймыл-аракетти аныктоо"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; колдонмосуна кыймыл-аракетиңизди аныктоого уруксат бересизби?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Камера"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"сүрөт жана видео тартууга"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; колдонмосуна сүрөттөрдү тартып, видеолорду жаздырууга уруксат берилсинби?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Бул колдонмо байланыш мунаралары жана Wi-Fi сыяктуу тармактык булактар аркылуу жайгашкан жериңизди аныктай алат. Колдонмо бул кызматтарды пайдаланышы үчүн, аларды күйгүзүп, планшетиңизге туташтырып коюшуңуз керек."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Бул колдонмо байланыш мунаралары жана Wi-Fi сыяктуу тармактык булактар аркылуу жайгашкан жериңизди аныктай алат. Колдонмо бул кызматтарды пайдаланышы үчүн, аларды күйгүзүп, сыналгыңызга туташтырып коюшуңуз керек."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Бул колдонмо байланыш мунаралары жана Wi-Fi сыяктуу тармактык булактар аркылуу жайгашкан жериңизди аныктай алат. Колдонмо бул кызматтарды пайдаланышы үчүн, аларды күйгүзүп, телефонуңузга туташтырып коюшуңуз керек."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"так аныкталган жайгашкан жерге фондук режимде кирүүгө уруксат берүү"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"Бул колдонмо фондук режимде сиздин кайда жүргөнүңүздү көрүп турат. Ал үчүн жайгашкан жерди аныктоо функциясын иштетишиңиз керек. Эскерте кетүүчү нерсе, батареяңыз тез отуруп калышы мүмкүн."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"жайгашкан жерди фондо аныктоо"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Эгер колдонмого жайгашкан жерди болжолдуу же так аныктоого уруксат берилсе, ал фондо иштеп жатып эле жайгашкан жерди аныктап турат."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"аудио жөндөөлөрүңүздү өзгөртүңүз"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Колдонмого үн деңгээли жана кайсы динамик аркылуу үн чыгарылышы керек сыяктуу түзмөктүн аудио тууралоолорун өзгөртүүгө уруксат берет."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"аудио жаздыруу"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"Бул колдонмо каалаган убакта микрофон менен аудио файлдарды жаздыра алат."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"SIM-картага буйруктарды жөнөтүү"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Колдонмого SIM-картага буйруктарды жөнөтүү мүмкүнчүлүгүн берет. Бул абдан кооптуу."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"кыймыл-аракетти аныктоо"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"Бул колдонмо кыймыл-аракетиңизди аныктап турат."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"сүрөт жана видео тартуу"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"Бул колдонмо каалаган убакта камера менен сүрөт же видеолорду тарта алат."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"титирөөнү башкаруу"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Колдонмого сүрөт жыйнагыңызды өзгөртүүгө мүмкүнчүлүк берет."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"медиа жыйнагыңыз сакталган жерлерди окуу"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Колдонмого медиа жыйнагыңыз сакталган жерлерди окууга мүмкүнчүлүк берет."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"<xliff:g id="APP">%s</xliff:g> колдонмосунда аутентификациядан өтүңүз."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Биометрикалык аппарат жеткиликсиз"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Манжа изи жарым-жартылай аныкталды. Кайра аракет кылыңыз."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Манжа изи иштелбей койду. Кайра аракет кылыңыз."</string>
@@ -1899,14 +1905,14 @@
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> автотолтуруу сунушу бар</item>
       <item quantity="one">Бир автотолтуруу сунушу бар</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; кызматында сакталсынбы?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"<xliff:g id="TYPE">%1$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; кызматында сакталсынбы?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"<xliff:g id="TYPE_0">%1$s</xliff:g> жана <xliff:g id="TYPE_1">%2$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; кызматында сакталсынбы?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> жана <xliff:g id="TYPE_2">%3$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; кызматында сакталсынбы?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; кызматына жаңыртылсынбы?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"<xliff:g id="TYPE">%1$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; кызматына жаңыртылсынбы?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"<xliff:g id="TYPE_0">%1$s</xliff:g> жана <xliff:g id="TYPE_1">%2$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; кызматына жаңыртылсынбы?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> жана <xliff:g id="TYPE_2">%3$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; кызматына жаңыртылсынбы?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" кызматына сакталсынбы?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"<xliff:g id="TYPE">%1$s</xliff:g> "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" кызматына сакталсынбы?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"<xliff:g id="TYPE_0">%1$s</xliff:g> жана <xliff:g id="TYPE_1">%2$s</xliff:g> "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" кызматына сакталсынбы?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> жана <xliff:g id="TYPE_2">%3$s</xliff:g> "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" кызматына сакталсынбы?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" кызматында жаңыртылсынбы?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233"><b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" кызматындагы <xliff:g id="TYPE">%1$s</xliff:g> жаңыртылсын?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484"><b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" кызматындагы <xliff:g id="TYPE_0">%1$s</xliff:g> жана <xliff:g id="TYPE_1">%2$s</xliff:g> жаңыртылсынбы?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922"><b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" кызматындагы төмөнкүлөр жаңыртылсынбы: <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> жана <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Сактоо"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Жок, рахмат"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"Жаңыртуу"</string>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index 9fc6033..9fb0adb 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"ໄມໂຄຣໂຟນ"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"ບັນທຶກສຽງ"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"ອະນຸຍາດ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ໃຫ້ບັນທຶກສຽງບໍ?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"ການຈຳແນກການເຄື່ອນໄຫວ"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"ຈຳແນກການເຄື່ອນໄຫວ"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"ອະນຸຍາດໃຫ້ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ຈຳແນກກິດຈະກຳທາງກາຍຂອງທ່ານບໍ?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"ກ້ອງ"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"ຖ່າຍ​ຮູບ ແລະ​ບັນ​ທຶກວິ​ດີ​ໂອ"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"ອະນຸຍາດ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ໃຫ້ຖ່າຍຮູບ ແລະ ບັນທຶກວິດີໂອບໍ?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"This app can get your location based on network sources such as cell towers and Wi-Fi networks. These location services must be turned on and available on your tablet for the app to be able to use them."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"This app can get your location based on network sources such as cell towers and Wi-Fi networks. These location services must be turned on and available on your TV for the app to be able to use them."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"This app can get your location based on network sources such as cell towers and Wi-Fi networks. These location services must be turned on and available on your phone for the app to be able to use them."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"ເຂົ້າເຖິງສະຖານທີ່ແນ່ນອນໃນພື້ນຫຼັງ"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"ແອັບນີ້ສາມາດຮັບເອົາສະຖານທີ່ແນ່ນອນຂອງທ່ານໄດ້ທຸກເວລາທີ່ມັນຢູ່ໃນພື້ນຫຼັງ. ການບໍລິການສະຖານທີ່ເຫຼົ່ານີ້ຕ້ອງເປີດຢູ່ ແລະ ສາມາດໃຊ້ໄດ້ໃນໂທລະສັບຂອງທ່ານເພື່ອໃຫ້ແອັບສາມາດໃຊ້ພວກມັນໄດ້. ນີ້ອາດຈະເຮັດໃຫ້ການໃຊ້ແບັດເຕີຣີເພີ່ມຂຶ້ນ."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"ເຂົ້າເຖິງສະຖານທີ່ໃນພື້ນຫຼັງ"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"ຖ້າອະນຸຍາດສິ່ງນີ້ນອກຈາກການເຂົ້າເຖິງສະຖານທີ່ໂດຍປະມານ ຫຼື ທີ່ແນ່ນອນ ແອັບສາມາດເຂົ້າເຖິງສະຖານທີ່ໄດ້ໃນຂະນະທີ່ເປີດໃຊ້ໃນພື້ນຫຼັງ."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"ປ່ຽນການຕັ້ງຄ່າສຽງຂອງທ່ານ"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"ອະນຸຍາດໃຫ້ແອັບຯແກ້ໄຂການຕັ້ງຄ່າສຽງສ່ວນກາງ ເຊັ່ນ: ລະດັບສຽງ ແລະລຳໂພງໃດທີ່ຖືກໃຊ້ສົ່ງສຽງອອກ."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"ບັນທຶກສຽງ"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"This app can record audio using the microphone at any time."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"ສົ່ງ​ຄຳ​ສັ່ງ​ຫາ SIM"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"ອະນຸຍາດໃຫ້ແອັບຯສົ່ງຄຳສັ່ງຫາ SIM. ສິ່ງນີ້ອັນຕະລາຍຫຼາຍ."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"ຈຳແນກກິດຈະກຳທາງກາຍ"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"ແອັບນີ້ສາມາດຈັດລະບຽບການເຄື່ອນໄຫວທາງກາຍຂອງທ່ານໄດ້."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"ຖ່າຍຮູບ ແລະວິດີໂອ"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"This app can take pictures and record videos using the camera at any time."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"ຄວບຄຸມການສັ່ນ"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"ອະນຸຍາດໃຫ້ແອັບແກ້ໄຂຄໍເລັກຊັນຮູບຂອງທ່ານ."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"ອ່ານສະຖານທີ່ຈາກຄໍເລັກຊັນມີເດຍຂອງທ່ານ"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"ອະນຸຍາດໃຫ້ແອັບອ່ານສະຖານທີ່ຈາກຄໍເລັກຊັນມີເດຍຂອງທ່ານ."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"ແອັບພລິເຄຊັນ <xliff:g id="APP">%s</xliff:g> ຕ້ອງການກວດຮັບຮອງຄວາມຖືກຕ້ອງ."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"ຮາດແວຊີວະມິຕິບໍ່ສາມາດໃຊ້ໄດ້"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"ກວດ​ພົບ​ລາຍ​ນີ້ວ​ມື​ບາງ​ສ່ວນ​ແລ້ວ. ກະ​ລຸ​ນາ​ລອງ​ໃໝ່​ອີກ."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"ບໍ່​ສາ​ມາດ​ດຳ​ເນີນ​ການ​ລາຍ​ນີ້ວ​ມື​ໄດ້. ກະ​ລຸ​ນາ​ລອງ​ໃໝ່​ອີກ."</string>
@@ -1897,14 +1903,14 @@
       <item quantity="other">ການແນະນຳແບບຕື່ມຂໍ້ມູນແບບອັນຕະໂນມັດ <xliff:g id="COUNT">%1$s</xliff:g> ອັນ</item>
       <item quantity="one">ການແນະນຳແບບຕື່ມຂໍ້ມູນແບບອັນຕະໂນມັດອັນດຽວ</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"ບັນທຶກໃສ່ &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; ບໍ?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"ບັນທຶກ <xliff:g id="TYPE">%1$s</xliff:g> ໃສ່ &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; ບໍ?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"ບັນທຶກ <xliff:g id="TYPE_0">%1$s</xliff:g> ແລະ <xliff:g id="TYPE_1">%2$s</xliff:g> ໃສ່ &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; ບໍ?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"ບັນທຶກ <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ແລະ <xliff:g id="TYPE_2">%3$s</xliff:g> ໃສ່ &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; ບໍ?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"ອັບເດດ &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; ບໍ?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"ອັບເດດ <xliff:g id="TYPE">%1$s</xliff:g> ໃສ່ &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; ບໍ?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"ອັບເດດ <xliff:g id="TYPE_0">%1$s</xliff:g> ແລະ <xliff:g id="TYPE_1">%2$s</xliff:g> ໃສ່ &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; ບໍ?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"ອັບເດດ <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ແລະ <xliff:g id="TYPE_2">%3$s</xliff:g> ໃສ່ &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; ບໍ?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"ບັນທຶກໄວ້ໃນ "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" ບໍ?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"ບັນທຶກ <xliff:g id="TYPE">%1$s</xliff:g> ໄວ້ໃນ "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" ບໍ?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"ບັນທຶກ <xliff:g id="TYPE_0">%1$s</xliff:g> ແລະ <xliff:g id="TYPE_1">%2$s</xliff:g> ໄວ້ໃນ "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" ບໍ?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"ບັນທຶກ <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ແລະ <xliff:g id="TYPE_2">%3$s</xliff:g> ໄວ້ໃນ "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" ບໍ?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"ອັບເດດໃນ "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" ບໍ?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"ອັບເດດ <xliff:g id="TYPE">%1$s</xliff:g> ໃນ "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" ບໍ?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"ອັບເດດ <xliff:g id="TYPE_0">%1$s</xliff:g> ແລະ <xliff:g id="TYPE_1">%2$s</xliff:g> ໃນ "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" ບໍ?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"ອັບເດດລາຍການເຫຼົ່ານີ້ໃນ "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ແລະ <xliff:g id="TYPE_2">%3$s</xliff:g> ບໍ?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"ບັນທຶກ"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"ບໍ່, ຂອບໃຈ"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"ອັບເດດ"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index f1dc8d1..f5225c5 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -298,6 +298,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Mikrofonas"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"įrašyti garso įrašą"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"Leisti &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; įrašyti garsą?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"Veiklos atpažinimas"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"atpažinti veiklą"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"Leisti programai &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; atpažinti jūsų fizinę veiklą?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Fotoaparatas"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"fotografuoti ir filmuoti"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"Leisti &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; fotografuoti ir įrašyti vaizdo įrašus?"</string>
@@ -424,14 +427,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Ši programa gali gauti jūsų vietos informaciją naudodamasi tinklo šaltinių, pvz., mobiliojo ryšio bokštų ir „Wi-Fi“ tinklų, duomenimis. Šios vietovės paslaugos turi būti įjungtos ir pasiekiamos planšetiniame kompiuteryje, kad programa galėtų jas naudoti."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Ši programa gali gauti jūsų vietos informaciją naudodamasi tinklo šaltinių, pvz., mobiliojo ryšio bokštų ir „Wi-Fi“ tinklų, duomenimis. Šios vietovės paslaugos turi būti įjungtos ir pasiekiamos TV, kad programa galėtų jas naudoti."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Ši programa gali gauti jūsų vietos informaciją naudodamasi tinklo šaltinių, pvz., mobiliojo ryšio bokštų ir „Wi-Fi“ tinklų, duomenimis. Šios vietovės paslaugos turi būti įjungtos ir pasiekiamos telefone, kad programa galėtų jas naudoti."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"pasiekti tikslią vietovę, kai programa veikia fone"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"Ši programa gali gauti tikslius jūsų vietovės duomenis bet kuriuo metu, kai veikia fone. Šios vietovės paslaugos turi būti įjungtos ir pasiekiamos telefone, kad programa galėtų jas naudoti. Tai gali padidinti akumuliatoriaus energijos suvartojimą."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"prieiga prie vietovės fone"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Jei papildomai suteikiama prieiga prie apytikslės arba tikslios vietovės, programa gali pasiekti vietovės duomenis veikdama fone."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"keisti garso nustatymus"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Leidžiama programai keisti visuotinius garso nustatymus, pvz., garsumą ir tai, kuris garsiakalbis naudojamas išvesčiai."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"įrašyti garsą"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"Ši programa gali bet kada įrašyti garsą naudodama mikrofoną."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"siųsti komandas į SIM kortelę"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Programai leidžiama siųsti komandas į SIM kortelę. Tai labai pavojinga."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"atpažinti fizinę veiklą"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"Ši programa gali atpažinti jūsų fizinę veiklą."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"fotografuoti ir filmuoti"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"Ši programa gali bet kada fotografuoti ir įrašyti vaizdo įrašų naudodama fotoaparatą."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"valdyti vibraciją"</string>
@@ -524,6 +529,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Programai leidžiama keisti nuotraukų kolekciją."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"skaityti vietoves iš medijos kolekcijos"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Programai leidžiama skaityti vietoves iš medijos kolekcijos."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"Programa „<xliff:g id="APP">%s</xliff:g>“ nori jus autentifikuoti."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Biometrinė aparatinė įranga nepasiekiama"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Aptiktas dalinis piršto antspaudas. Bandykite dar kartą."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Nepavyko apdoroti piršto antspaudo. Bandykite dar kartą."</string>
@@ -1967,14 +1973,14 @@
       <item quantity="many"><xliff:g id="COUNT">%1$s</xliff:g> automatinio pildymo pasiūlymo</item>
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> automatinio pildymo pasiūlymų</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"Išsaugoti sistemoje &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Išsaugoti <xliff:g id="TYPE">%1$s</xliff:g> sistemoje &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Išsaugoti <xliff:g id="TYPE_0">%1$s</xliff:g> ir <xliff:g id="TYPE_1">%2$s</xliff:g> sistemoje &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Išsaugoti <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ir <xliff:g id="TYPE_2">%3$s</xliff:g> sistemoje &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"Atnaujinti paslaugoje &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Atnaujinti <xliff:g id="TYPE">%1$s</xliff:g> paslaugoje &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Atnaujinti <xliff:g id="TYPE_0">%1$s</xliff:g> ir <xliff:g id="TYPE_1">%2$s</xliff:g> paslaugoje &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Atnaujinti <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ir <xliff:g id="TYPE_2">%3$s</xliff:g> paslaugoje &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"Išsaugoti paslaugoje "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"Išsaugoti <xliff:g id="TYPE">%1$s</xliff:g> paslaugoje "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"Išsaugoti <xliff:g id="TYPE_0">%1$s</xliff:g> ir <xliff:g id="TYPE_1">%2$s</xliff:g> paslaugoje "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"Išsaugoti <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ir <xliff:g id="TYPE_2">%3$s</xliff:g> paslaugoje "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"Atnaujinti paslaugoje "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"Atnaujinti <xliff:g id="TYPE">%1$s</xliff:g> paslaugoje "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"Atnaujinti <xliff:g id="TYPE_0">%1$s</xliff:g> ir <xliff:g id="TYPE_1">%2$s</xliff:g> paslaugoje "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"Atnaujinti šiuos elementus paslaugoje "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ir <xliff:g id="TYPE_2">%3$s</xliff:g> ?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Išsaugoti"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Ne, ačiū"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"Atnaujinti"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 156a1a9..d0c16d8 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -222,7 +222,7 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"Tālruņa opcijas"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"Ekrāna bloķētājs"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"Strāvas padeve ir izslēgta."</string>
-    <string name="global_action_emergency" msgid="7112311161137421166">"Ārkārtas"</string>
+    <string name="global_action_emergency" msgid="7112311161137421166">"Ārkārtas situācija"</string>
     <string name="global_action_bug_report" msgid="7934010578922304799">"Kļūdu ziņojums"</string>
     <string name="global_action_logout" msgid="935179188218826050">"Beigt sesiju"</string>
     <string name="global_action_screenshot" msgid="8329831278085426283">"Ekrānuzņēmums"</string>
@@ -295,6 +295,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Mikrofons"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"ierakstīt audio"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"Vai atļaut lietotnei &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ierakstīt audio?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"Aktivitātes noteikšana"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"noteikt aktivitātes"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"Vai atļaut lietotnei &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; noteikt jūsu fiziskās aktivitātes?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Kamera"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"uzņemt attēlus un ierakstīt videoklipus"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"Vai atļaut lietotnei &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uzņemt fotoattēlus un ierakstīt videoklipus?"</string>
@@ -421,14 +424,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Šī lietotne var iegūt jūsu atrašanās vietu, pamatojoties uz tīkla avotiem, piemēram, mobilo sakaru torņiem un Wi-Fi tīkliem. Šiem atrašanās vietu pakalpojumiem ir jābūt ieslēgtiem un pieejamiem jūsu planšetdatorā, lai lietotne tos varētu izmantot."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Šī lietotne var iegūt jūsu atrašanās vietu, pamatojoties uz tīkla avotiem, piemēram, mobilo sakaru torņiem un Wi-Fi tīkliem. Šiem atrašanās vietu pakalpojumiem ir jābūt ieslēgtiem un pieejamiem jūsu televizorā, lai lietotne tos varētu izmantot."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Šī lietotne var iegūt jūsu atrašanās vietu, pamatojoties uz tīkla avotiem, piemēram, mobilo sakaru torņiem un Wi-Fi tīkliem. Šiem atrašanās vietu pakalpojumiem ir jābūt ieslēgtiem un pieejamiem jūsu tālrunī, lai lietotne tos varētu izmantot."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"Piekļuve precīzai atrašanās vietai, darbojoties fonā"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"Šī lietotne var iegūt precīzu jūsu atrašanās vietu jebkurā laikā, darbojoties fonā. Šiem atrašanās vietu pakalpojumiem ir jābūt ieslēgtiem un pieejamiem jūsu tālrunī, lai lietotne varētu tos izmantot. Tādējādi var palielināties akumulatora jaudas patēriņš."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"piekļūt atrašanās vietai fonā"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Ja šī atļauja tiek piešķirta līdz ar piekļuvi aptuvenai vai precīzai atrašanās vietai, lietotne var piekļūt atrašanās vietai, darbojoties fonā."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"mainīt audio iestatījumus"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Ļauj lietotnei mainīt globālos audio iestatījumus, piemēram, skaļumu un izejai izmantoto skaļruni."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"ierakstīt audio"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"Šī lietotne jebkurā brīdī var ierakstīt audio, izmantojot mikrofonu."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"Sūtīt komandas SIM kartei"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Ļauj lietotnei sūtīt komandas uz SIM karti. Tas ir ļoti bīstami!"</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"noteikt fiziskās aktivitātes"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"Šī lietotne var noteikt jūsu fiziskās aktivitātes."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"uzņemt attēlus un videoklipus"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"Šī lietotne jebkurā brīdī var uzņemt attēlus un ierakstīt videoklipus, izmantojot kameru."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"kontrolēt vibrosignālu"</string>
@@ -521,6 +526,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Ļauj lietotnei pārveidot jūsu fotoattēlu kolekciju."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"Lasīt atrašanās vietas no jūsu multivides kolekcijas"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Ļauj lietotnei lasīt atrašanās vietas no jūsu multivides kolekcijas."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"Lietotne <xliff:g id="APP">%s</xliff:g> pieprasa autentificēt."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Biometrisko datu aparatūra nav pieejama"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Noteikts daļējs pirksta nospiedums. Lūdzu, mēģiniet vēlreiz."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Nevarēja apstrādāt pirksta nospiedumu. Lūdzu, mēģiniet vēlreiz."</string>
@@ -799,7 +805,7 @@
     <string name="lockscreen_instructions_when_pattern_enabled" msgid="46154051614126049">"Nospiediet Izvēlne, lai atbloķētu, vai veiciet ārkārtas zvanu."</string>
     <string name="lockscreen_instructions_when_pattern_disabled" msgid="686260028797158364">"Lai atbloķētu, nospiediet vienumu Izvēlne."</string>
     <string name="lockscreen_pattern_instructions" msgid="7478703254964810302">"Zīmējiet kombināciju, lai atbloķētu."</string>
-    <string name="lockscreen_emergency_call" msgid="5298642613417801888">"Ārkārtas"</string>
+    <string name="lockscreen_emergency_call" msgid="5298642613417801888">"Ārkārtas situācija"</string>
     <string name="lockscreen_return_to_call" msgid="5244259785500040021">"Atpakaļ pie zvana"</string>
     <string name="lockscreen_pattern_correct" msgid="9039008650362261237">"Pareizi!"</string>
     <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"Mēģināt vēlreiz"</string>
@@ -1932,14 +1938,14 @@
       <item quantity="one"><xliff:g id="COUNT">%1$s</xliff:g> automātiskās aizpildes ieteikums</item>
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> automātiskās aizpildes ieteikumi</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"Vai saglabāt pakalpojumā &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Vai saglabāt vienumu “<xliff:g id="TYPE">%1$s</xliff:g>” pakalpojumā &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Vai saglabāt vienumus “<xliff:g id="TYPE_0">%1$s</xliff:g>” un “<xliff:g id="TYPE_1">%2$s</xliff:g>” pakalpojumā &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Vai saglabāt vienumus “<xliff:g id="TYPE_0">%1$s</xliff:g>”, “<xliff:g id="TYPE_1">%2$s</xliff:g>” un “<xliff:g id="TYPE_2">%3$s</xliff:g>” pakalpojumā &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"Vai atjaunināt pakalpojumā &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Vai atjaunināt vienumu “<xliff:g id="TYPE">%1$s</xliff:g>” pakalpojumā &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Vai atjaunināt vienumus “<xliff:g id="TYPE_0">%1$s</xliff:g>” un “<xliff:g id="TYPE_1">%2$s</xliff:g>” pakalpojumā &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Vai atjaunināt vienumus “<xliff:g id="TYPE_0">%1$s</xliff:g>”, “<xliff:g id="TYPE_1">%2$s</xliff:g>” un “<xliff:g id="TYPE_2">%3$s</xliff:g>” pakalpojumā &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"Vai saglabāt pakalpojumā "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"Vai saglabāt informāciju <xliff:g id="TYPE">%1$s</xliff:g> pakalpojumā "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"Vai saglabāt informāciju <xliff:g id="TYPE_0">%1$s</xliff:g> un <xliff:g id="TYPE_1">%2$s</xliff:g> pakalpojumā "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"Vai saglabāt informāciju <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> un <xliff:g id="TYPE_2">%3$s</xliff:g> pakalpojumā "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"Vai atjaunināt informāciju pakalpojumā "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"Vai atjaunināt informāciju <xliff:g id="TYPE">%1$s</xliff:g> pakalpojumā "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"Vai atjaunināt informāciju <xliff:g id="TYPE_0">%1$s</xliff:g> un <xliff:g id="TYPE_1">%2$s</xliff:g> pakalpojumā "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"Vai atjaunināt šos vienumus pakalpojumā "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> un <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Saglabāt"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Nē, paldies"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"Atjaunināt"</string>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index 8bca75e..4b3a53e 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Микрофон"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"снима аудио"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"Дали да се дозволи &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да снима аудио?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"Препознавање активност"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"препознавај ја активноста"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"Дозволувате ли &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да ја препознава вашата физичка активност?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Камера"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"фотографира и снима видео"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"Дали да се дозволи &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; да фотографира и да снима видео?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Апликацијава може да ја добие вашата локација од мрежните извори како што се репетиторите за мобилни мрежи и Wi-Fi мрежите. Овие услуги за локација мора да се вклучени и достапни на таблетот за да може да ги користи апликацијата."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Апликацијава може да ја добие вашата локација од мрежните извори како што се репетиторите за мобилни мрежи и Wi-Fi мрежите. Овие услуги за локација мора да се вклучени и достапни на телевизорот за да може да ги користи апликацијата."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Апликацијава може да ја добие вашата локација од мрежните извори како што се репетиторите за мобилни мрежи и Wi-Fi мрежите. Овие услуги за локација мора да се вклучени и достапни на телефонот за да може да ги користи апликацијата."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"пристап до прецизната локација во заднина"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"Апликацијава може да ја добие вашата точна локација секогаш кога е во заднина. Услугиве според локација мора да се вклучени и достапни на телефонот за да може да ги користи апликацијата. Ова може да го зголеми трошењето на батеријата."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"пристап до локацијата во заднина"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Ако покрај дозволата за пристап до приближната или прецизната локација е доделена и оваа дозвола, тогаш апликацијата ќе може да пристапува до локацијата додека се извршува во заднина."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"менува аудио поставки"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Овозможува апликацијата да ги менува глобалните аудио поставки, како што се јачината на звукот и кој звучник се користи за излез."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"снимај аудио"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"Апликацијава може да снима аудио со микрофонот во секое време."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"испраќање наредби до SIM-картичката"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Овозможува апликацијата да испраќа наредби до SIM картичката. Ова е многу опасно."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"препознавајте ја физичката активност"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"Апликацијава може да ја препознава вашата физичка активност."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"снимај слики и видеа"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"Апликацијава може да фотографира и да снима видеа со камерата во секое време."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"контролирај вибрации"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Дозволува апликацијата да ја менува вашата збирка на фотографии."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"да чита локации од вашата збирка на аудиовизуелни содржини"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Дозволува апликацијата да чита локации од вашата збирка на аудиовизуелни содржини."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"Апликацијата <xliff:g id="APP">%s</xliff:g> сака да ве провери."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Биометрискиот хардвер е недостапен"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Откриен е делумен отпечаток. Обидете се повторно."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Отпечатокот не можеше да се обработи. Обидете се повторно."</string>
@@ -1900,14 +1906,14 @@
       <item quantity="one"><xliff:g id="COUNT">%1$s</xliff:g> предлог за автоматско пополнување</item>
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> предлози за автоматско пополнување</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"Да се зачува во &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Да се зачува <xliff:g id="TYPE">%1$s</xliff:g> во &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Да се зачуваат <xliff:g id="TYPE_0">%1$s</xliff:g> и <xliff:g id="TYPE_1">%2$s</xliff:g> во &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Да се зачуваат <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> и <xliff:g id="TYPE_2">%3$s</xliff:g> во &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"Дали да се ажурира на &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Дали да се ажурира <xliff:g id="TYPE">%1$s</xliff:g> на &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Дали да се ажурираат <xliff:g id="TYPE_0">%1$s</xliff:g> и <xliff:g id="TYPE_1">%2$s</xliff:g> на &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Дали да се ажурираат <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> и <xliff:g id="TYPE_2">%3$s</xliff:g> на &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"Да се зачува во "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"Да се зачува <xliff:g id="TYPE">%1$s</xliff:g> во "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"Да се зачуваат <xliff:g id="TYPE_0">%1$s</xliff:g> и <xliff:g id="TYPE_1">%2$s</xliff:g> во "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"Да се зачуваат <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> и <xliff:g id="TYPE_2">%3$s</xliff:g> во "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"Да се ажурира во "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"Да се ажурира <xliff:g id="TYPE">%1$s</xliff:g> во "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"Да се ажурираат <xliff:g id="TYPE_0">%1$s</xliff:g> и <xliff:g id="TYPE_1">%2$s</xliff:g> во "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"Да се ажурираат овие ставки во "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> и <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Зачувај"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Не, фала"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"Ажурирај"</string>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index 1efdc72..2184af0 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"മൈക്രോഫോണ്‍"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"ഓഡിയോ റെക്കോർഡ് ചെയ്യുക"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"ഓഡിയോ റെക്കോർഡ് ചെയ്യാൻ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ആപ്പിനെ അനുവദിക്കണോ?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"പ്രവർത്തനം തിരിച്ചറിയൽ"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"പ്രവർത്തനം തിരിച്ചറിയുക"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>-&lt;/b&gt;നെ നിങ്ങളുടെ ശാരീരിക പ്രവർത്തനം തിരിച്ചറിയാൻ അനുവദിക്കണോ?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"ക്യാമറ"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"ചിത്രങ്ങളെടുത്ത് വീഡിയോ റെക്കോർഡുചെയ്യുക"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"ചിത്രം എടുക്കാനും വീഡിയോ റെക്കോർഡ് ചെയ്യാനും &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ആപ്പിനെ അനുവദിക്കണോ?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"സെൽ ടവറുകളും വൈഫൈ നെറ്റ്‌വർക്കുകളും പോലുള്ള നെറ്റ്‌വർക്ക് ഉറവിടങ്ങളെ അടിസ്ഥാനമാക്കിക്കൊണ്ട് ഈ ആപ്പിന് നിങ്ങളുടെ ലൊക്കേഷൻ അനുമാനിക്കാൻ കഴിയും. നിങ്ങളുടെ ടാബ്‌ലെറ്റിൽ ഈ ലൊക്കേഷൻ സേവനങ്ങൾ ഓൺ ചെയ്തിട്ടുണ്ടെങ്കിൽ മാത്രമാണ് ആപ്പിന് അവ ഉപയോഗിക്കാൻ കഴിയുക."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"സെൽ ടവറുകളും വൈഫൈ നെറ്റ്‌വർക്കുകളും പോലുള്ള നെറ്റ്‌വർക്ക് ഉറവിടങ്ങളെ അടിസ്ഥാനമാക്കിക്കൊണ്ട് ഈ ആപ്പിന് നിങ്ങളുടെ ലൊക്കേഷൻ അനുമാനിക്കാൻ കഴിയും. നിങ്ങളുടെ ടിവിയിൽ ഈ ലൊക്കേഷൻ സേവനങ്ങൾ ഓൺ ചെയ്തിട്ടുണ്ടെങ്കിൽ മാത്രമാണ് ആപ്പിന് അവ ഉപയോഗിക്കാൻ കഴിയുക."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"സെൽ ടവറുകളും വൈഫൈ നെറ്റ്‌വർക്കുകളും പോലുള്ള നെറ്റ്‌വർക്ക് ഉറവിടങ്ങളെ അടിസ്ഥാനമാക്കിക്കൊണ്ട് ഈ ആപ്പിന് നിങ്ങളുടെ ലൊക്കേഷൻ അനുമാനിക്കാൻ കഴിയും. നിങ്ങളുടെ ഫോണിൽ ഈ ലൊക്കേഷൻ സേവനങ്ങൾ ഓൺ ചെയ്തിട്ടുണ്ടെങ്കിൽ മാത്രമാണ് ആപ്പിന് അവ ഉപയോഗിക്കാൻ കഴിയുക."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"പശ്ചാത്തലത്തിൽ കൃത്യമായ ലൊക്കേഷൻ ആക്‌സസ് ചെയ്യുക"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"ഈ ആപ്പ് പശ്ചാത്തലത്തിൽ ഉള്ളപ്പോൾ എപ്പോൾ വേണമെങ്കിലും ഇതിന് നിങ്ങളുടെ കൃത്യമായ ലൊക്കേഷൻ നേടാനാവും. ആപ്പിന് ഉപയോഗിക്കാനായി, ഈ ലൊക്കേഷൻ സേവനങ്ങൾ ഓണായിരിക്കുകയും നിങ്ങളുടെ ഫോണിൽ ലഭ്യമാവുകയും വേണം. ഇതിലൂടെ ബാറ്ററി ഉപഭോഗം വർദ്ധിച്ചേക്കാം."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"പശ്ചാത്തലത്തിൽ ലൊക്കേഷൻ ആക്‌സസ് ചെയ്യുക"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"ഏകദേശം അല്ലെങ്കിൽ കൃത്യമായ ലൊക്കേഷൻ ആക്‌സസിന് ഇത് അധികമായി അനുവദിച്ചതാണെങ്കിൽ, പശ്ചാത്തലത്തിൽ റൺ ചെയ്യുമ്പോഴും ആപ്പിന് ലൊക്കേഷൻ ആക്‌സസ് ചെയ്യാനാവും."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"നിങ്ങളുടെ ഓഡിയോ ക്രമീകരണങ്ങൾ മാറ്റുക"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"വോളിയവും ഔട്ട്പുട്ടിനായി ഉപയോഗിച്ച സ്‌പീക്കറും പോലുള്ള ആഗോള ഓഡിയോ ക്രമീകരണങ്ങൾ പരിഷ്‌ക്കരിക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"ഓഡിയോ റെക്കോർഡ് ചെയ്യുക"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"ഈ ആപ്പിന് ഏത് സമയത്തും മൈക്രോഫോൺ ഉപയോഗിച്ചുകൊണ്ട് ഓഡിയോ റെക്കോർഡുചെയ്യാൻ കഴിയും."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"SIM-ലേക്ക് കമാൻഡുകൾ അയയ്ക്കുക"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"സിമ്മിലേക്ക് കമാൻഡുകൾ അയയ്‌ക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. ഇത് വളരെ അപകടകരമാണ്."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"ശാരീരിക പ്രവർത്തനം തിരിച്ചറിയുക"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"നിങ്ങളുടെ ശാരീരിക പ്രവർത്തനം ഈ ആപ്പിന് തിരിച്ചറിയാനാവും."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"ചിത്രങ്ങളും വീഡിയോകളും എടുക്കുക"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"ഏതുസമയത്തും ക്യാമറ ഉപയോഗിച്ചുകൊണ്ട് ചിത്രങ്ങൾ എടുക്കാനും വീഡിയോകൾ റെക്കോർഡുചെയ്യാനും ഈ ആപ്പിന് കഴിയും."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"വൈബ്രേറ്റുചെയ്യൽ നിയന്ത്രിക്കുക"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"നിങ്ങളുടെ ഫോട്ടോ ശേഖരം പരിഷ്‌ക്കരിക്കുന്നതിന് ആപ്പിനെ അനുവദിക്കുന്നു."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"നിങ്ങളുടെ മീഡിയ ശേഖരത്തിൽ നിന്നും ലൊക്കേഷനുകൾ റീഡ് ചെയ്യുക"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"നിങ്ങളുടെ മീഡിയ ശേഖരത്തിൽ നിന്നും ലൊക്കേഷനുകൾ റീഡ് ചെയ്യുന്നതിന് ആപ്പിനെ അനുവദിക്കുന്നു."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"<xliff:g id="APP">%s</xliff:g> ആപ്പിന് നിങ്ങളെ പരിശോധിച്ചുറപ്പിക്കണം."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"ബയോമെട്രിക് ഹാർ‌ഡ്‌വെയർ ലഭ്യമല്ല"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"വിരലടയാളം ഭാഗികമായി തിരിച്ചറിഞ്ഞു. വീണ്ടും ശ്രമിക്കുക."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"വിരലടയാളം പ്രോസസ്സ് ചെയ്യാനായില്ല. വീണ്ടും ശ്രമിക്കുക."</string>
@@ -1898,14 +1904,14 @@
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> സ്വയമേവ പൂരിപ്പിക്കൽ നിർദ്ദേശങ്ങൾ</item>
       <item quantity="one">ഒരു സ്വയമേവ പൂരിപ്പിക്കൽ നിർദ്ദേശം</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;എന്നതിലേക്ക് സംരക്ഷിക്കണോ?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"<xliff:g id="TYPE">%1$s</xliff:g> എന്നതിനെ &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;എന്നതിലേക്ക് സംരക്ഷിക്കണോ?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> എന്നിവ&lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;എന്നതിലേക്ക് സംരക്ഷിക്കണോ?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> എന്നിവ&lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;എന്നതിലേക്ക് സംരക്ഷിക്കണോ?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; എന്നതിലേക്ക് അപ്ഡേറ്റ് ചെയ്യണോ?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"<xliff:g id="TYPE">%1$s</xliff:g> എന്നതിനെ &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; എന്നതിലേക്ക് അപ്ഡേറ്റ് ചെയ്യണോ?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"&lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; എന്നതിലേക്ക് <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> അപ്ഡേറ്റ് ചെയ്യുക?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> എന്നിവയെ &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; എന്നതിലേക്ക് അപ്ഡേറ്റ് ചെയ്യണോ?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" എന്നതിൽ സംരക്ഷിക്കണോ?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"<xliff:g id="TYPE">%1$s</xliff:g>, "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" എന്നതിൽ സംരക്ഷിക്കണോ?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> എന്നിവ "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" എന്നതിൽ സംരക്ഷിക്കണോ?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> എന്നിവ "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" എന്നതിൽ സംരക്ഷിക്കണോ?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" എന്നതിൽ അപ്‌ഡേറ്റ് ചെയ്യണോ?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"<xliff:g id="TYPE">%1$s</xliff:g>, "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" എന്നതിൽ അപ്‌ഡേറ്റ് ചെയ്യണോ?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> എന്നിവ "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" എന്നതിൽ അപ്‌ഡേറ്റ് ചെയ്യണോ?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"ഇനിപ്പറയുന്ന ഇനങ്ങൾ "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" എന്നതിൽ അപ്‌ഡേറ്റ് ചെയ്യണോ: <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> ?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"സംരക്ഷിക്കുക"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"വേണ്ട, നന്ദി"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"അപ്ഡേറ്റ് ചെയ്യുക"</string>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 86ae178..45e118f 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Микрофон"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"дуу хураах"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-д аудио бичихийг зөвшөөрөх үү?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"Үйл ажиллагааны зөвшөөрөл"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"хөдөлгөөн таних"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>-д&lt;/b&gt; таны биеийн дасгал хөдөлгөөн танихыг зөвшөөрөх үү?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Камер"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"зураг авах, бичлэг хийх"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;-д зураг авах, видео хийхийг зөвшөөрөх үү?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Энэ апп үүрэн цамхаг, Wi-Fi сүлжээ зэрэг сүлжээний байршлын эх сурвалжийг ашиглан таны байршлыг мэдэх боломжтой. Эдгээр байршлын үйлчилгээ нь таны таблетад асаалттай байх ёстой ба апп ашиглах боломжтой байх ёстой."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Энэ апп үүрэн цамхаг, Wi-Fi сүлжээ зэрэг сүлжээний байршлын эх сурвалжийг ашиглан таны байршлыг мэдэх боломжтой. Эдгээр байршлын үйлчилгээ нь таны ТВ-д асаалттай байх ёстой ба апп ашиглах боломжтой байх ёстой."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Энэ апп үүрэн цамхаг, Wi-Fi сүлжээ зэрэг сүлжээний байршлын эх сурвалжийг ашиглан таны байршлыг мэдэх боломжтой. Эдгээр байршлын үйлчилгээ нь таны утсанд асаалттай байх ёстой ба апп ашиглах боломжтой байх ёстой."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"нарийвчилсан байршилд арын дэвсгэрт хандах"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"Энэ апп нь ард ажиллах үедээ таны байршлыг ямар ч үед нарийн тогтоох боломжтой. Апп эдгээр байршлын үйлчилгээг ашиглахын тулд эдгээрийг таны утсан дээр асааж идэвхтэй байлгах шаардлагатай. Энэ нь батарейны хэрэглээг ихэсгэж болзошгүй."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"байршилд ард хандах"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Хэрэв үүнийг ойролцоо эсвэл нарийвчилсан байршлын хандалтад нэмэлтээр зөвшөөрсөн бол энэ апп ард ажиллах явцдаа байршилд хандаж болно."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"Аудио тохиргоо солих"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Апп нь дууны хэмжээ, спикерын гаралтад ашиглагдах глобал аудио тохиргоог өөрчлөх боломжтой."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"аудио бичих"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"Энэ апп ямар ч үед микрофон ашиглан аудио бичих боломжтой."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"SIM картад тушаал илгээх"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Апп-д SIM рүү комманд илгээхийг зөвшөөрнө. Энэ маш аюултай."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"биеийн дасгал хөдөлгөөн таних"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"Энэ апп таны биеийн дасгал хөдөлгөөнийг таних боломжтой."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"зураг авах болон видео бичих"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"Энэ апп ямар ч үед камер ашиглан зураг авж, видео хийх боломжтой."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"чичиргээг удирдах"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Таны зургийн цуглуулгыг тохируулах зөвшөөрлийг аппад олгодог."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"медиа цуглуулгаасаа байршлыг унших"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Таны медиа цуглуулгаас байршлыг унших зөвшөөрлийг аппад олгодог."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"<xliff:g id="APP">%s</xliff:g> апп баталгаажуулахыг хүсэж байна."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Биометрийн техник хангамж боломжгүй байна"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Хурууны хээг дутуу уншуулсан байна. Дахин оролдоно уу."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Хурууны хээ боловсруулж чадахгүй байна. Дахин оролдоно уу."</string>
@@ -1897,14 +1903,14 @@
       <item quantity="other">автоматаар бөглөх хэсгийн <xliff:g id="COUNT">%1$s</xliff:g> зөвлөмж</item>
       <item quantity="one">Автоматаар бөглөх хэсгийн 1 зөвлөмж</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;-д хадгалах уу?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"<xliff:g id="TYPE">%1$s</xliff:g>-г &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;-д хадгалах уу?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>-г &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;-д хадгалах уу?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g>-г &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;-д хадгалах уу?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;-д шинэчлэх үү?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"<xliff:g id="TYPE">%1$s</xliff:g>-г &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;-д шинэчлэх үү?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>-г &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;-д шинэчлэх үү?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g>-г &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;-д шинэчлэх үү?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"-д хадгалах уу?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"<xliff:g id="TYPE">%1$s</xliff:g>-г "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"-д хадгалах уу?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"<xliff:g id="TYPE_0">%1$s</xliff:g> болон <xliff:g id="TYPE_1">%2$s</xliff:g>-г "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"-д хадгалах уу?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> болон <xliff:g id="TYPE_2">%3$s</xliff:g>-г "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"-д хадгалах уу?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"-д шинэчлэх үү?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"<xliff:g id="TYPE">%1$s</xliff:g>-г "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"-д шинэчлэх үү?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"<xliff:g id="TYPE_0">%1$s</xliff:g> болон <xliff:g id="TYPE_1">%2$s</xliff:g>-г "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"-д шинэчлэх үү?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"Эдгээр зүйлийг буюу <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> болон <xliff:g id="TYPE_2">%3$s</xliff:g>-г "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"-д шинэчлэх үү?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Хадгалах"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Үгүй, баярлалаа"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"Шинэчлэх"</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index 70ed012..fb4c408 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -206,10 +206,10 @@
     <string name="reboot_to_reset_title" msgid="4142355915340627490">"फॅक्‍टरी डेटा रीसेट"</string>
     <string name="reboot_to_reset_message" msgid="2432077491101416345">"रीस्टार्ट करत आहे..."</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"बंद होत आहे…"</string>
-    <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"आपला टॅबलेट बंद होईल."</string>
-    <string name="shutdown_confirm" product="tv" msgid="476672373995075359">"आपला टीव्ही बंद होईल."</string>
+    <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"तुमचा टॅबलेट बंद होईल."</string>
+    <string name="shutdown_confirm" product="tv" msgid="476672373995075359">"तुमचा टीव्ही बंद होईल."</string>
     <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"तुमचे घड्याळ बंद होईल."</string>
-    <string name="shutdown_confirm" product="default" msgid="649792175242821353">"आपला फोन बंद होईल."</string>
+    <string name="shutdown_confirm" product="default" msgid="649792175242821353">"तुमचा फोन बंद होईल."</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"तुम्ही बंद करू इच्छिता?"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"सुरक्षित मोडमध्ये रीबूट करा"</string>
     <string name="reboot_safemode_confirm" msgid="55293944502784668">"तुम्ही सुरक्षित मोडमध्ये रीबूट करू इच्छिता? हे तुम्ही इंस्टॉल केलेले सर्व तृतीय पक्ष अॅप्लिकेशन अक्षम करेल. तुम्ही पुन्हा रीबूट करता तेव्हा ते पुनर्संचयित केले जातील."</string>
@@ -227,7 +227,7 @@
     <string name="bugreport_title" msgid="2667494803742548533">"बग रीपोर्ट घ्या"</string>
     <string name="bugreport_message" msgid="398447048750350456">"ई-मेल मेसेज म्हणून पाठविण्यासाठी, हे तुमच्या सद्य डिव्हाइस स्थितीविषयी माहिती संकलित करेल. बग रीपोर्ट सुरू करण्यापासून तो पाठविण्यापर्यंत थोडा वेळ लागेल; कृपया धीर धरा."</string>
     <string name="bugreport_option_interactive_title" msgid="8635056131768862479">"परस्परसंवादी अहवाल"</string>
-    <string name="bugreport_option_interactive_summary" msgid="229299488536107968">"बहुतांश प्रसंगांमध्ये याचा वापर करा. ते आपल्याला अहवालाच्या प्रगतीचा मागोवा घेण्याची, समस्येविषयी आणखी तपाशील एंटर करण्याची आणि स्क्रीनशॉट घेण्याची अनुमती देते. ते कदाचित अहवाल देण्यासाठी बराच वेळ घेणारे कमी-वापरलेले विभाग वगळू शकते."</string>
+    <string name="bugreport_option_interactive_summary" msgid="229299488536107968">"बहुतांश प्रसंगांमध्ये याचा वापर करा. ते तुम्हाला अहवालाच्या प्रगतीचा मागोवा घेण्याची, समस्येविषयी आणखी तपाशील एंटर करण्याची आणि स्क्रीनशॉट घेण्याची अनुमती देते. ते कदाचित अहवाल देण्यासाठी बराच वेळ घेणारे कमी-वापरलेले विभाग वगळू शकते."</string>
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"संपूर्ण अहवाल"</string>
     <string name="bugreport_option_full_summary" msgid="7210859858969115745">"तुमचे डिव्हाइस प्रतिसाद देत नाही किंवा खूप धीमे असते किंवा तुम्हाला सर्व अहवाल विभागांची आवश्यकता असते तेव्हा कमीतकमी सिस्टम हस्तक्षेपासाठी या पर्यायाचा वापर करा. तुम्हाला आणखी तपशील एंटर करण्याची किंवा अतिरिक्त स्क्रीनशॉट घेण्याची अनुमती देत नाही."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"मायक्रोफोन"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"ऑडिओ रेकॉर्ड"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ला ऑडिओ रेकॉर्ड करू द्यायचे?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"अॅक्टिव्हिटी ओळख"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"अॅक्टिव्हिटी ओळखा"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ला तुमची शारीरिक अॅक्टिव्हिटी ओळखण्याची अनुमती द्यायची का?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"कॅमेरा"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"चित्रे घेण्याची आणि व्हिडिओ रेकॉर्ड"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ला फोटो घेऊ आणि व्हिडिओ रेकॉर्ड करू द्यायचे?"</string>
@@ -339,9 +342,9 @@
     <string name="permlab_receiveSms" msgid="8673471768947895082">"मजकूर मेसेज मिळवा (SMS)"</string>
     <string name="permdesc_receiveSms" msgid="6424387754228766939">"SMS मेसेज प्राप्त करण्याची आणि त्यावर प्रक्रिया करण्याची अॅप ला अनुमती देते. म्हणजेच अॅप आपल्या डीव्हाइसवर पाठविलेले मेसेज तुम्हाला न दर्शवता त्यांचे परीक्षण करू किंवा ते हटवू शकतो."</string>
     <string name="permlab_receiveMms" msgid="1821317344668257098">"मजकूर मेसेज मिळवा (MMS)"</string>
-    <string name="permdesc_receiveMms" msgid="533019437263212260">"MMS मेसेज प्राप्त करण्यास आणि त्यावर प्रक्रिया करण्यास अॅप ला अनुमती देते. म्हणजेच अॅप आपल्या डिव्हाइसवर पाठविलेले मेसेज आपल्याला न दर्शवता त्यांचे परीक्षण करू किंवा ते हटवू शकतो."</string>
+    <string name="permdesc_receiveMms" msgid="533019437263212260">"MMS मेसेज प्राप्त करण्यास आणि त्यावर प्रक्रिया करण्यास अॅप ला अनुमती देते. म्हणजेच अॅप आपल्या डिव्हाइसवर पाठविलेले मेसेज तुम्हाला न दर्शवता त्यांचे परीक्षण करू किंवा ते हटवू शकतो."</string>
     <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"सेल प्रसारण मेसेज वाचा"</string>
-    <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"आपल्या डिव्हाइसद्वारे प्राप्त केलेले सेल प्रसारण मेसेज वाचण्यासाठी अॅप ला अनुमती देते. काही स्थानांमध्ये आपल्याला आणीबाणीच्या परिस्थितीची चेतावणी देण्यासाठी सेल प्रसारण सूचना वितरीत केल्या जातात. आणीबाणी सेल प्रसारण प्राप्त होते तेव्हा आपल्या डिव्हाइसच्या कार्यप्रदर्शनात किंवा कार्यात दुर्भावनापूर्ण अॅप्स व्यत्यय आणू शकतात."</string>
+    <string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"आपल्या डिव्हाइसद्वारे प्राप्त केलेले सेल प्रसारण मेसेज वाचण्यासाठी अॅप ला अनुमती देते. काही स्थानांमध्ये तुम्हाला आणीबाणीच्या परिस्थितीची चेतावणी देण्यासाठी सेल प्रसारण सूचना वितरीत केल्या जातात. आणीबाणी सेल प्रसारण प्राप्त होते तेव्हा आपल्या डिव्हाइसच्या कार्यप्रदर्शनात किंवा कार्यात दुर्भावनापूर्ण अॅप्स व्यत्यय आणू शकतात."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"सदस्यता घेतलेली फीड वाचा"</string>
     <string name="permdesc_subscribedFeedsRead" msgid="5557058907906144505">"सध्या संकालित केलेल्या फीडविषयी तपशील मिळविण्यासाठी अॅप ला अनुमती देते."</string>
     <string name="permlab_sendSms" msgid="7544599214260982981">"SMS मेसेज पाठवणे आणि पाहणे"</string>
@@ -351,7 +354,7 @@
     <string name="permdesc_readSms" product="tv" msgid="5796670395641116592">"हा अॅप तुमच्या टीव्हीवर स्टोअर केलेले सर्व SMS (मजकूर) मेसेज वाचू शकतो."</string>
     <string name="permdesc_readSms" product="default" msgid="6826832415656437652">"हा अॅप तुमच्या फोनवर स्टोअर केलेले सर्व SMS (मजकूर) मेसेज वाचू शकतो."</string>
     <string name="permlab_receiveWapPush" msgid="5991398711936590410">"मजकूर मेसेज मिळवा (WAP)"</string>
-    <string name="permdesc_receiveWapPush" msgid="748232190220583385">"WAP मेसेज प्राप्त करण्यास आणि त्यावर प्रक्रिया करण्यासाठी अॅप ला अनुमती देते. ही परवानगी आपल्याला पाठविलेले मेसेज आपल्याला न दर्शविता त्यांचे परीक्षण करण्याची आणि ते हटविण्याची क्षमता समाविष्ट करते."</string>
+    <string name="permdesc_receiveWapPush" msgid="748232190220583385">"WAP मेसेज प्राप्त करण्यास आणि त्यावर प्रक्रिया करण्यासाठी अॅप ला अनुमती देते. ही परवानगी तुम्हाला पाठविलेले मेसेज तुम्हाला न दर्शविता त्यांचे परीक्षण करण्याची आणि ते हटविण्याची क्षमता समाविष्ट करते."</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"चालणारे अॅप्स पुनर्प्राप्त करा"</string>
     <string name="permdesc_getTasks" msgid="7454215995847658102">"सध्या आणि अलीकडे चालणार्‍या कार्यांविषयी माहिती पुनर्प्राप्त करण्यासाठी अॅप ला अनुमती देते. हे डिव्हाइसवर कोणते अॅप्लिकेशन वापरले जात आहेत त्याविषयी माहिती शोधण्यासाठी अॅप ला अनुमती देऊ शकतात."</string>
     <string name="permlab_manageProfileAndDeviceOwners" msgid="7918181259098220004">"प्रोफाईल आणि डिव्हाइस मालक व्यवस्थापित करा"</string>
@@ -387,25 +390,25 @@
     <string name="permdesc_broadcastSticky" product="tv" msgid="6839285697565389467">"रोचक प्रसारणे पाठविण्यास अॅपला अनुमती देते, जे प्रसारण समाप्त झाल्यानंतर तसेच रहाते. अतिरिक्त वापर टीव्ही धीमा किंवा यासाठी बरीच मेमरी वापरली जात असल्यामुळे तो अस्थिर करू शकतो."</string>
     <string name="permdesc_broadcastSticky" product="default" msgid="2825803764232445091">"रोचक प्रसारणे पाठविण्यासाठी अॅप ला अनुमती देते, जे प्रसारण समाप्त झाल्यानंतर देखील तसेच राहते. अत्याधिक वापरामुळे बरीच मेमरी वापरली जाऊन तो फोनला धीमा किंवा अस्थिर करू शकतो."</string>
     <string name="permlab_readContacts" msgid="8348481131899886131">"तुमचे संपर्क वाचा"</string>
-    <string name="permdesc_readContacts" product="tablet" msgid="5294866856941149639">"तुम्ही कॉल केलेल्या, ईमेल केलेल्या किंवा विशिष्ट लोकांशी अन्य मार्गांनी संवाद प्रस्थापित केलेल्या लोकांच्या फ्रिक्वेन्सीसह, आपल्या टॅब्लेटवर स्टोअर केलेल्या आपल्या संपर्कांविषयीचा डेटा वाचण्यासाठी अॅप ला अनुमती देते. ही परवानगी आपला संपर्क डेटा सेव्ह करण्याची अॅप्स ला अनुमती देते आणि दुर्भावनापूर्ण अॅप्स आपल्या माहितीशिवाय संपर्क डेटा सामायिक करू शकतात."</string>
-    <string name="permdesc_readContacts" product="tv" msgid="1839238344654834087">"तुम्ही विशिष्ट लोकांना इतर मार्गांनी कॉल केलेल्या, ईमेल केलेल्या किंवा संप्रेषित केलेल्या फ्रिक्वेन्सीसह, आपल्या टीव्हीवर स्टोअर केलेल्या आपल्या संपर्कांविषयीचा डेटा वाचण्यासाठी अॅप्सला अनुमती देतात. ही परवागनी अॅप्सला आपला संपर्क डेटा सेव्ह करण्यासाठी अनुमती देते आणि दुर्भावनापूर्ण अॅप्स आपल्याला न कळविता संपर्क डेटा सामायिक करू शकतात."</string>
-    <string name="permdesc_readContacts" product="default" msgid="8440654152457300662">"तुम्ही कॉल केलेल्या, ईमेल केलेल्या किंवा विशिष्ट लोकांशी अन्य मार्गांनी संवाद प्रस्थापित केलेल्या लोकांच्या फ्रिक्वेन्सीसह, आपल्या फोनवर स्टोअर केलेल्या आपल्या संपर्कांविषयीचा डेटा वाचण्यासाठी अॅप ला अनुमती देते. ही परवानगी आपला संपर्क डेटा सेव्ह करण्याची अॅप्स ला अनुमती देते आणि दुर्भावनापूर्ण अॅप्स आपल्या माहितीशिवाय संपर्क डेटा सामायिक करू शकतात."</string>
+    <string name="permdesc_readContacts" product="tablet" msgid="5294866856941149639">"तुम्ही कॉल केलेल्या, ईमेल केलेल्या किंवा विशिष्ट लोकांशी अन्य मार्गांनी संवाद प्रस्थापित केलेल्या लोकांच्या फ्रिक्वेन्सीसह, आपल्या टॅब्लेटवर स्टोअर केलेल्या आपल्या संपर्कांविषयीचा डेटा वाचण्यासाठी अॅप ला अनुमती देते. ही परवानगी तुमचा संपर्क डेटा सेव्ह करण्याची अॅप्स ला अनुमती देते आणि दुर्भावनापूर्ण अॅप्स आपल्या माहितीशिवाय संपर्क डेटा शेअर करू शकतात."</string>
+    <string name="permdesc_readContacts" product="tv" msgid="1839238344654834087">"तुम्ही विशिष्ट लोकांना इतर मार्गांनी कॉल केलेल्या, ईमेल केलेल्या किंवा संप्रेषित केलेल्या फ्रिक्वेन्सीसह, आपल्या टीव्हीवर स्टोअर केलेल्या आपल्या संपर्कांविषयीचा डेटा वाचण्यासाठी अॅप्सला अनुमती देतात. ही परवागनी अॅप्सला तुमचा संपर्क डेटा सेव्ह करण्यासाठी अनुमती देते आणि दुर्भावनापूर्ण अॅप्स तुम्हाला न कळविता संपर्क डेटा शेअर करू शकतात."</string>
+    <string name="permdesc_readContacts" product="default" msgid="8440654152457300662">"तुम्ही कॉल केलेल्या, ईमेल केलेल्या किंवा विशिष्ट लोकांशी अन्य मार्गांनी संवाद प्रस्थापित केलेल्या लोकांच्या फ्रिक्वेन्सीसह, आपल्या फोनवर स्टोअर केलेल्या आपल्या संपर्कांविषयीचा डेटा वाचण्यासाठी अॅप ला अनुमती देते. ही परवानगी तुमचा संपर्क डेटा सेव्ह करण्याची अॅप्स ला अनुमती देते आणि दुर्भावनापूर्ण अॅप्स आपल्या माहितीशिवाय संपर्क डेटा शेअर करू शकतात."</string>
     <string name="permlab_writeContacts" msgid="5107492086416793544">"तुमचे संपर्क सुधारित करा"</string>
     <string name="permdesc_writeContacts" product="tablet" msgid="897243932521953602">"तुम्ही विशिष्ट संपर्कांशी अन्य मार्गांनी कॉल केलेल्या, ईमेल केलेल्या किंवा संवाद प्रस्थापित केलेल्या फ्रिक्वेन्सीसह, आपल्या टॅब्लेटवर स्टोअर केलेल्या आपल्या संपर्कांविषयीचा डेटा सुधारित करण्यासाठी अॅप ला अनुमती देते. ही परवानगी संपर्क डेटा हटविण्यासाठी अॅप ला अनुमती देते."</string>
     <string name="permdesc_writeContacts" product="tv" msgid="5438230957000018959">"तुम्ही विशिष्ट संपर्कांशी अन्य मार्गांनी कॉल केलेल्या, ईमेल केलेल्या किंवा संवाद प्रस्थापित केलेल्या फ्रिक्वेन्सीसह, आपल्या टीव्हीवर स्टोअर केलेल्या आपल्या संपर्कांविषयीचा डेटा सुधारित करण्यासाठी अॅपला अनुमती देते. ही परवानगी संपर्क डेटा हटविण्यासाठी अॅपला अनुमती देते."</string>
     <string name="permdesc_writeContacts" product="default" msgid="589869224625163558">"तुम्ही विशिष्ट संपर्कांशी अन्य मार्गांनी कॉल केलेल्या, ईमेल केलेल्या किंवा संवाद प्रस्थापित केलेल्या फ्रिक्वेन्सीसह, आपल्या फोनवर स्टोअर केलेल्या आपल्या संपर्कांविषयीचा डेटा सुधारित करण्यासाठी अॅप ला अनुमती देते. ही परवानगी संपर्क डेटा हटविण्यासाठी अॅप ला अनुमती देते."</string>
     <string name="permlab_readCallLog" msgid="3478133184624102739">"कॉल लॉग वाचा"</string>
-    <string name="permdesc_readCallLog" msgid="3204122446463552146">"हा अॅप आपला कॉल इतिहास वाचू शकता."</string>
+    <string name="permdesc_readCallLog" msgid="3204122446463552146">"हा अॅप तुमचा कॉल इतिहास वाचू शकता."</string>
     <string name="permlab_writeCallLog" msgid="8552045664743499354">"कॉल लॉग लिहा"</string>
-    <string name="permdesc_writeCallLog" product="tablet" msgid="6661806062274119245">"येणार्‍या आणि केल्या जाणार्‍या कॉलविषयीच्या डेटासह, आपल्या टॅब्लेटचा कॉल लॉग सुधारित करण्यासाठी अॅप ला अनुमती देते. दुर्भावनापूर्ण अॅप्स आपला कॉल लॉग मिटवण्यासाठी किंवा सुधारित करण्यासाठी याचा वापर करू शकतात."</string>
-    <string name="permdesc_writeCallLog" product="tv" msgid="4225034892248398019">"येणार्‍या आणि केल्या जाणार्‍या कॉलविषयीच्या डेटासह, आपल्या टीव्हीचा कॉल लॉग सुधारित करण्यासाठी अॅपला अनुमती देते. दुर्भावनापूर्ण अॅप्स आपला कॉल लॉग मिटवण्यासाठी किंवा सुधारित करण्यासाठी याचा वापर करू शकतात."</string>
-    <string name="permdesc_writeCallLog" product="default" msgid="683941736352787842">"येणार्‍या आणि केल्या जाणार्‍या कॉलविषयीच्या डेटासह, आपल्या फोनचा कॉल लॉग सुधारित करण्यासाठी अॅप ला अनुमती देते. दुर्भावनापूर्ण अॅप्स आपला कॉल लॉग मिटवण्यासाठी किंवा सुधारित करण्यासाठी याचा वापर करू शकतात."</string>
+    <string name="permdesc_writeCallLog" product="tablet" msgid="6661806062274119245">"येणार्‍या आणि केल्या जाणार्‍या कॉलविषयीच्या डेटासह, आपल्या टॅब्लेटचा कॉल लॉग सुधारित करण्यासाठी अॅप ला अनुमती देते. दुर्भावनापूर्ण अॅप्स तुमचा कॉल लॉग मिटवण्यासाठी किंवा सुधारित करण्यासाठी याचा वापर करू शकतात."</string>
+    <string name="permdesc_writeCallLog" product="tv" msgid="4225034892248398019">"येणार्‍या आणि केल्या जाणार्‍या कॉलविषयीच्या डेटासह, आपल्या टीव्हीचा कॉल लॉग सुधारित करण्यासाठी अॅपला अनुमती देते. दुर्भावनापूर्ण अॅप्स तुमचा कॉल लॉग मिटवण्यासाठी किंवा सुधारित करण्यासाठी याचा वापर करू शकतात."</string>
+    <string name="permdesc_writeCallLog" product="default" msgid="683941736352787842">"येणार्‍या आणि केल्या जाणार्‍या कॉलविषयीच्या डेटासह, आपल्या फोनचा कॉल लॉग सुधारित करण्यासाठी अॅप ला अनुमती देते. दुर्भावनापूर्ण अॅप्स तुमचा कॉल लॉग मिटवण्यासाठी किंवा सुधारित करण्यासाठी याचा वापर करू शकतात."</string>
     <string name="permlab_bodySensors" msgid="4683341291818520277">"शरीर सेंसर (हृदय गती मॉनिटरसारखे) अॅक्सेस करा"</string>
     <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"हृदय गती सारख्या, आपल्या शारीरिक स्थितीचे नियंत्रण करणार्‍या सेन्सरवरून डेटामध्ये प्रवेश करण्यासाठी अॅपला अनुमती देते."</string>
     <string name="permlab_readCalendar" msgid="6716116972752441641">"कॅलेंडर इव्हेंट आणि तपशील वाचा"</string>
-    <string name="permdesc_readCalendar" product="tablet" msgid="4993979255403945892">"हा अॅप आपल्या टॅब्लेटवर स्टोअर केलेले सर्व कॅलेंडर इव्हेंट वाचू आणि सामायिक करू शकतो किंवा आपला कॅलेंडर डेटा सेव्ह करू शकतो."</string>
-    <string name="permdesc_readCalendar" product="tv" msgid="8837931557573064315">"हा अॅप आपल्या टीव्हीवर स्टोअर केलेले सर्व कॅलेंडर इव्हेंट वाचू आणि सामायिक करू शकतो किंवा आपला कॅलेंडर डेटा सेव्ह करू शकतो."</string>
-    <string name="permdesc_readCalendar" product="default" msgid="4373978642145196715">"हा अॅप आपल्या फोनवर स्टोअर केलेले सर्व कॅलेंडर इव्हेंट वाचू आणि सामायिक करू शकतो किंवा आपला कॅलेंडर डेटा सेव्ह करू शकतो."</string>
+    <string name="permdesc_readCalendar" product="tablet" msgid="4993979255403945892">"हा अॅप आपल्या टॅब्लेटवर स्टोअर केलेले सर्व कॅलेंडर इव्हेंट वाचू आणि शेअर करू शकतो किंवा तुमचा कॅलेंडर डेटा सेव्ह करू शकतो."</string>
+    <string name="permdesc_readCalendar" product="tv" msgid="8837931557573064315">"हा अॅप आपल्या टीव्हीवर स्टोअर केलेले सर्व कॅलेंडर इव्हेंट वाचू आणि शेअर करू शकतो किंवा तुमचा कॅलेंडर डेटा सेव्ह करू शकतो."</string>
+    <string name="permdesc_readCalendar" product="default" msgid="4373978642145196715">"हा अॅप आपल्या फोनवर स्टोअर केलेले सर्व कॅलेंडर इव्हेंट वाचू आणि शेअर करू शकतो किंवा तुमचा कॅलेंडर डेटा सेव्ह करू शकतो."</string>
     <string name="permlab_writeCalendar" msgid="8438874755193825647">"कॅलेंडर इव्हेंट जोडा किंवा बदला आणि मालकाला न कळवता अतिथींना ईमेल पाठवा"</string>
     <string name="permdesc_writeCalendar" product="tablet" msgid="1675270619903625982">"हा अॅप आपल्या टॅब्लेटवर कॅलेंडर इव्हेंट जोडू, काढू किंवा बदलू शकतो. हा अॅप कॅलेंडर मालकांकडून येत आहेत असे वाटणारे मेसेज पाठवू किंवा त्यांच्या मालकांना सूचित केल्याशिवाय इव्हेंट बदलू शकतो."</string>
     <string name="permdesc_writeCalendar" product="tv" msgid="9017809326268135866">"हा अॅप आपल्या टीव्हीवर कॅलेंडर इव्हेंट जोडू, काढू किंवा बदलू शकतो. हा अॅप कॅलेंडर मालकांकडून येत आहेत असे वाटणारे मेसेज पाठवू किंवा त्यांच्या मालकांना सूचित केल्याशिवाय इव्हेंट बदलू शकतो."</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"हा अॅप सेल टॉवर आणि वाय-फाय नेटवर्क सारख्या नेटवर्क स्रोतांच्या आधारावर तुमचे स्थान मिळवू शकतो. अॅपला या स्थान सेवा वापरण्यास सक्षम असण्यासाठी तुमच्या टॅब्लेटवर त्या चालू केलेल्या आणि उपलब्ध असणे आवश्यक आहे."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"हा अॅप सेल टॉवर आणि वाय-फाय नेटवर्क सारख्या नेटवर्क स्रोतांच्या आधारावर तुमचे स्थान मिळवू शकतो. अॅपला या स्थान सेवा वापरण्यास सक्षम असण्यासाठी तुमच्या टीव्हीवर त्या चालू केलेल्या आणि उपलब्ध असणे आवश्यक आहे."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"हा अॅप सेल टॉवर आणि वाय-फाय नेटवर्क सारख्या नेटवर्क स्रोतांच्या आधारावर तुमचे स्थान मिळवू शकतो. अॅपला या स्थान सेवा वापरण्यास सक्षम असण्यासाठी तुमच्या फोनवर त्या चालू केलेल्या आणि उपलब्ध असणे आवश्यक आहे."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"बॅकग्राउंडमध्ये अचूक स्थान अ‍ॅक्सेस करा"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"हे अ‍ॅप बॅकग्राउंडमध्ये असताना अचूक स्थान कधीही मिळवू शकते. या स्थान सेवा सुरू करणे आणि त्या वापरण्यासाठी अ‍ॅपसाठी तुमच्या फोनवर उपलब्ध करणे आवश्यक आहे, यामुळे बॅटरी वापर वाढू शकतो."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"बॅकग्राउंडमध्ये स्थान अॅक्सेस करू शकतो"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"याला अंदाजे किंवा अचूक स्थान अॅक्सेस करण्यास अतिरिक्त मंजूरी दिल्यास, बॅकग्राउंडमध्ये चालतांना अॅप स्थान अॅक्सेस करू शकतो."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"आपल्या ऑडिओ सेटिंग्ज बदला"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"व्हॉल्यूम आणि आउटपुटसाठी कोणता स्पीकर वापरला आहे यासारख्या समग्र ऑडिओ सेटिंग्ज सुधारित करण्यासाठी अॅप ला अनुमती देते."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"ऑडिओ रेकॉर्ड"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"हा अॅप कोणत्याही वेळी मायक्रोफोन वापरून ऑडिओ रेकॉर्ड करू शकता."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"सिम वर कमांड पाठवा"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"अ‍ॅप ला सिम वर कमांड पाठविण्‍याची अनुमती देते. हे खूप धोकादायक असते."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"शारीरिक अॅक्टिव्हिटी ओळखा"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"हे अॅप तुमच्या शारीरिक अॅक्टिव्हिटी ओळखू शकते."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"चित्रे आणि व्हिडिओ घ्या"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"हा अॅप कोणत्याही वेळी कॅमेरा वापरून चित्रेे घेऊ आणि व्ह‍िडिअो रेकॉर्ड करू शकतो."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"व्हायब्रेट नियंत्रित करा"</string>
@@ -454,7 +459,7 @@
     <string name="permdesc_transmitIr" product="default" msgid="7957763745020300725">"अ‍ॅप ला फोनच्‍या इन्‍फ्रारेड ट्रान्‍समीटरचा वापर करण्‍याची अनुमती देते."</string>
     <string name="permlab_setWallpaper" msgid="6627192333373465143">"वॉलपेपर सेट करा"</string>
     <string name="permdesc_setWallpaper" msgid="7373447920977624745">"सिस्टम वॉलपेपर सेट करण्यासाठी अॅप ला अनुमती देते."</string>
-    <string name="permlab_setWallpaperHints" msgid="3278608165977736538">"आपला वॉलपेपर आकार समायोजित करा"</string>
+    <string name="permlab_setWallpaperHints" msgid="3278608165977736538">"तुमचा वॉलपेपर आकार समायोजित करा"</string>
     <string name="permdesc_setWallpaperHints" msgid="8235784384223730091">"सिस्टम वॉलपेपर आकार सूचना सेट करण्यासाठी अॅप ला अनुमती देते."</string>
     <string name="permlab_setTimeZone" msgid="2945079801013077340">"टाइम झोन सेट करा"</string>
     <string name="permdesc_setTimeZone" product="tablet" msgid="1676983712315827645">"टॅब्लेटचा टाइम झोन बदलण्यासाठी अॅप ला अनुमती देते."</string>
@@ -478,7 +483,7 @@
     <string name="permdesc_changeWifiState" msgid="7137950297386127533">"वाय-फाय अॅक्सेस बिंदूंवर कनेक्ट करण्यासाठी आणि त्यावरून डिस्कनेक्ट करण्यासाठी आणि वाय-फाय नेटवर्कसाठी डिव्हाइस कॉंफिगरेशनमध्ये बदल करण्यासाठी अॅपला अनुमती देते."</string>
     <string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"वाय-फाय मल्‍टिकास्‍ट रिसेप्‍शनला अनुमती द्या"</string>
     <string name="permdesc_changeWifiMulticastState" product="tablet" msgid="7969774021256336548">"मल्टिकास्ट पत्ते वापरून फक्त तुमच्या टॅब्लेटवर नाही, तर वाय-फाय नेटवर्कवरील सर्व डीव्हाइसवर पाठविलेले पॅकेट प्राप्त करण्यासाठी अॅप ला अनुमती देते. हे मल्टिकास्टखेरिज इतर मोडसाठी अधिक पॉवर वापरते."</string>
-    <string name="permdesc_changeWifiMulticastState" product="tv" msgid="9031975661145014160">"केवळ आपला टीव्ही न वापरता, एकाधिक पत्ते वापरून एका वाय-फाय नेटवकवरील सर्व डीव्हाइसवर पाठविलेली पॅकेट प्राप्त करण्यासाठी अॅपला अनुमती देते."</string>
+    <string name="permdesc_changeWifiMulticastState" product="tv" msgid="9031975661145014160">"केवळ तुमचा टीव्ही न वापरता, एकाधिक पत्ते वापरून एका वाय-फाय नेटवकवरील सर्व डीव्हाइसवर पाठविलेली पॅकेट प्राप्त करण्यासाठी अॅपला अनुमती देते."</string>
     <string name="permdesc_changeWifiMulticastState" product="default" msgid="6851949706025349926">"मल्टिकास्ट पत्ते वापरून फक्त तुमच्या फोनवर नाही, तर वाय-फाय नेटवर्कवरील सर्व डीव्हाइसवर पाठविलेले पॅकेट प्राप्त करण्यासाठी अॅप ला अनुमती देते. हे मल्टिकास्टखेरिज इतर मोडसाठी अधिक पॉवर वापरते."</string>
     <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"ब्लूटूथ सेटिंग्ज अॅक्सेस करा"</string>
     <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"स्थानिक ब्लूटूथ टॅबलेट कॉंफिगर करण्याकरिता आणि दूरस्थ डिव्हाइस शोधण्यासाठी आणि त्यासह जोडण्यासाठी अॅप ला अनुमती देते."</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"अॅपला तुमच्या फोटो संग्रहामध्ये सुधारणा करण्याची अनुमती देते."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"तुमच्या मीडिया संग्रहातून स्थाने वाचा"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"अॅपला तुमच्या मीडिया संग्रहामध्येील स्थाने वाचण्यासाठी अनुमती देते."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"अॅप्लिकेशन <xliff:g id="APP">%s</xliff:g>ला ऑथेंटिकेट करायचे आहे."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"बायोमेट्रिक हार्डवेअर उपलब्ध नाही"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"आंशिक फिंगरप्रिंट आढळली. कृपया पुन्हा प्रयत्न करा."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"फिंगरप्रिंटवर प्रक्रिया करणे शक्य झाले नाही. कृपया पुन्हा प्रयत्न करा."</string>
@@ -824,12 +830,12 @@
     <string name="lockscreen_sim_puk_locked_instructions" msgid="8127916255245181063">"वापरकर्ता मार्गदर्शक पहा किंवा कस्टमर केअरशी संपर्क साधा."</string>
     <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"सिम कार्ड लॉक केलेले आहे."</string>
     <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"सिम कार्ड अनलॉक करत आहे…"</string>
-    <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6481623830344107222">"तुम्ही आपला अनलॉक पॅटर्न <xliff:g id="NUMBER_0">%1$d</xliff:g> वेळा अयोग्यरितीने काढला. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> सेकंदांमध्ये पुन्हा प्रयत्न करा."</string>
-    <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="2725973286239344555">"तुम्ही आपला पासवर्ड <xliff:g id="NUMBER_0">%1$d</xliff:g> वेळा अयोग्यरितीने टाइप केला आहे. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> सेकंदांमध्ये पुन्हा प्रयत्न करा."</string>
-    <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6216672706545696955">"तुम्ही आपला पिन <xliff:g id="NUMBER_0">%1$d</xliff:g> वेळा अयोग्यरितीने टाइप केला आहे. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> सेकंदांमध्ये पुन्हा प्रयत्न करा."</string>
-    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="9191611984625460820">"तुम्ही आपला अनलॉक पॅटर्न <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="lockscreen_failed_attempts_almost_glogin" product="tv" msgid="5316664559603394684">"तुम्ही <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="lockscreen_failed_attempts_almost_glogin" product="default" msgid="2590227559763762751">"तुम्ही आपला अनलॉक पॅटर्न <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="lockscreen_too_many_failed_attempts_dialog_message" msgid="6481623830344107222">"तुम्ही तुमचा अनलॉक पॅटर्न <xliff:g id="NUMBER_0">%1$d</xliff:g> वेळा अयोग्यरितीने काढला. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> सेकंदांमध्ये पुन्हा प्रयत्न करा."</string>
+    <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="2725973286239344555">"तुम्ही तुमचा पासवर्ड <xliff:g id="NUMBER_0">%1$d</xliff:g> वेळा अयोग्यरितीने टाइप केला आहे. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> सेकंदांमध्ये पुन्हा प्रयत्न करा."</string>
+    <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6216672706545696955">"तुम्ही तुमचा पिन <xliff:g id="NUMBER_0">%1$d</xliff:g> वेळा अयोग्यरितीने टाइप केला आहे. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> सेकंदांमध्ये पुन्हा प्रयत्न करा."</string>
+    <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="9191611984625460820">"तुम्ही तुमचा अनलॉक पॅटर्न <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="lockscreen_failed_attempts_almost_glogin" product="tv" msgid="5316664559603394684">"तुम्ही <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="lockscreen_failed_attempts_almost_glogin" product="default" msgid="2590227559763762751">"तुम्ही तुमचा अनलॉक पॅटर्न <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="lockscreen_failed_attempts_almost_at_wipe" product="tablet" msgid="6128106399745755604">"तुम्ही <xliff:g id="NUMBER_0">%1$d</xliff:g> वेळा टॅबलेट अनलॉक करण्याचे चुकीचे प्रयत्न केले. आणखी <xliff:g id="NUMBER_1">%2$d</xliff:g> अयशस्वी प्रयत्नांनंतर, टॅबलेट फॅक्टरी डीफॉल्टवर रीसेट केला जाईल आणि सर्व वापरकर्ता डेटा गमावला जाईल."</string>
     <string name="lockscreen_failed_attempts_almost_at_wipe" product="tv" msgid="950408382418270260">"तुम्ही <xliff:g id="NUMBER_0">%1$d</xliff:g> वेळा टीव्ही अनलॉक करण्याचा अयोग्यरित्या प्रयत्न केला. आणखी <xliff:g id="NUMBER_1">%2$d</xliff:g> अयशस्वी प्रयत्नांनंतर, टीव्ही फॅक्टरी डीफॉल्टवर रीसेट केला जाईल आणि सर्व वापरकर्ता डेटा गमावेल."</string>
     <string name="lockscreen_failed_attempts_almost_at_wipe" product="default" msgid="8603565142156826565">"तुम्ही <xliff:g id="NUMBER_0">%1$d</xliff:g> वेळा फोन अनलॉक करण्याचे चुकीचे प्रयत्न केले. आणखी <xliff:g id="NUMBER_1">%2$d</xliff:g> अयशस्वी प्रयत्नांनंतर, फोन फॅक्टरी डीफॉल्टवर रीसेट केला जाईल आणि सर्व वापरकर्ता डेटा गमावला जाईल."</string>
@@ -894,7 +900,7 @@
     <string name="js_dialog_title_default" msgid="6961903213729667573">"Javascript"</string>
     <string name="js_dialog_before_unload_title" msgid="2619376555525116593">"नेव्हिगेशनची पुष्टी करा"</string>
     <string name="js_dialog_before_unload_positive_button" msgid="3112752010600484130">"हे पृष्ठ सोडा"</string>
-    <string name="js_dialog_before_unload_negative_button" msgid="5614861293026099715">"या पृष्ठावर रहा"</string>
+    <string name="js_dialog_before_unload_negative_button" msgid="5614861293026099715">"या पेजवर रहा"</string>
     <string name="js_dialog_before_unload" msgid="3468816357095378590">"<xliff:g id="MESSAGE">%s</xliff:g>\n\nआपल्‍याला खात्री आहे की तुम्ही या पृष्‍ठावरून नेव्‍हिगेट करू इच्‍छिता?"</string>
     <string name="save_password_label" msgid="6860261758665825069">"पुष्टी करा"</string>
     <string name="double_tap_toast" msgid="4595046515400268881">"टीप: झूम कमी करण्यासाठी आणि वाढवण्यासाठी दोनदा-टॅप करा."</string>
@@ -933,7 +939,7 @@
     <string name="save_password_notnow" msgid="6389675316706699758">"आत्ता नाही"</string>
     <string name="save_password_remember" msgid="6491879678996749466">"लक्षात ठेवा"</string>
     <string name="save_password_never" msgid="8274330296785855105">"कधीही नाही"</string>
-    <string name="open_permission_deny" msgid="7374036708316629800">"आपल्याला हे पृष्ठ उघडण्याची परवानगी नाही."</string>
+    <string name="open_permission_deny" msgid="7374036708316629800">"तुम्हाला हे पृष्ठ उघडण्याची परवानगी नाही."</string>
     <string name="text_copied" msgid="4985729524670131385">"मजकूर क्लिपबोर्डवर कॉपी केला."</string>
     <string name="more_item_label" msgid="4650918923083320495">"अधिक"</string>
     <string name="prepend_shortcut_label" msgid="2572214461676015642">"मेनू+"</string>
@@ -1185,8 +1191,8 @@
     <string name="new_app_description" msgid="5894852887817332322">"<xliff:g id="OLD_APP">%1$s</xliff:g> सेव्ह न करता बंद होईल"</string>
     <string name="dump_heap_notification" msgid="2618183274836056542">"<xliff:g id="PROC">%1$s</xliff:g> ने मेमेरी मर्यादा वाढविली"</string>
     <string name="dump_heap_notification_detail" msgid="3993078784053054141">"हीप डंप गोळा केले. शेअर करण्यासाठी टॅप करा."</string>
-    <string name="dump_heap_title" msgid="5864292264307651673">"हीप डंप सामायिक करायचे?"</string>
-    <string name="dump_heap_text" msgid="4809417337240334941">"<xliff:g id="PROC">%1$s</xliff:g> प्रक्रियेने त्याची <xliff:g id="SIZE">%2$s</xliff:g> ची प्रक्रिया मेमरी मर्यादा ओलांडली आहे. त्याच्या विकासकासह सामायिक करण्यासाठी तुमच्यासाठी हीप डंप उपलब्ध आहे. सावधगिरी बाळगा: या हीप डंपमध्ये तुमची कोणतीही वैयक्तिक माहिती असू शकते ज्यात अॅप्लिकेशन प्रवेश करू शकतो."</string>
+    <string name="dump_heap_title" msgid="5864292264307651673">"हीप डंप शेअर करायचे?"</string>
+    <string name="dump_heap_text" msgid="4809417337240334941">"<xliff:g id="PROC">%1$s</xliff:g> प्रक्रियेने त्याची <xliff:g id="SIZE">%2$s</xliff:g> ची प्रक्रिया मेमरी मर्यादा ओलांडली आहे. त्याच्या विकासकासह शेअर करण्यासाठी तुमच्यासाठी हीप डंप उपलब्ध आहे. सावधगिरी बाळगा: या हीप डंपमध्ये तुमची कोणतीही वैयक्तिक माहिती असू शकते ज्यात अॅप्लिकेशन प्रवेश करू शकतो."</string>
     <string name="sendText" msgid="5209874571959469142">"मजकुरासाठी क्रिया निवडा"</string>
     <string name="volume_ringtone" msgid="6885421406845734650">"रिंगर व्हॉल्यूम"</string>
     <string name="volume_music" msgid="5421651157138628171">"मीडिया व्हॉल्यूम"</string>
@@ -1322,7 +1328,7 @@
     <string name="adb_active_notification_message" msgid="7463062450474107752">"USB डीबगिंग बंद करण्यासाठी टॅप करा"</string>
     <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"USB डीबगिंग बंद करण्यासाठी निवडा."</string>
     <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"बग रीपोर्ट घेत आहे..."</string>
-    <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"बग अहवाल सामायिक करायचा?"</string>
+    <string name="share_remote_bugreport_notification_title" msgid="4987095013583691873">"बग अहवाल शेअर करायचा?"</string>
     <string name="sharing_remote_bugreport_notification_title" msgid="7572089031496651372">"बग रीपोर्ट शेअर करत आहे..."</string>
     <string name="share_remote_bugreport_notification_message_finished" msgid="6029609949340992866">"आपल्या प्रशासकाने या डिव्हाइसचे समस्या निवारण करण्यात मदत करण्यासाठी दोष अहवालाची विनंती केली. अॅप्स आणि डेटा शेअर केले जाऊ शकतात."</string>
     <string name="share_remote_bugreport_action" msgid="6249476773913384948">"शेअर करा"</string>
@@ -1441,7 +1447,7 @@
     <string name="next_button_label" msgid="1080555104677992408">"पुढील"</string>
     <string name="skip_button_label" msgid="1275362299471631819">"वगळा"</string>
     <string name="no_matches" msgid="8129421908915840737">"कोणत्याही जुळण्या नाहीत"</string>
-    <string name="find_on_page" msgid="1946799233822820384">"पृष्ठावर शोधा"</string>
+    <string name="find_on_page" msgid="1946799233822820384">"पेजवर शोधा"</string>
     <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
       <item quantity="one"><xliff:g id="TOTAL">%d</xliff:g> पैकी <xliff:g id="INDEX">%d</xliff:g></item>
       <item quantity="other"><xliff:g id="TOTAL">%d</xliff:g> पैकी <xliff:g id="INDEX">%d</xliff:g></item>
@@ -1503,7 +1509,7 @@
     <string name="action_menu_overflow_description" msgid="2295659037509008453">"अधिक पर्याय"</string>
     <string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
     <string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
-    <string name="storage_internal" msgid="3570990907910199483">"अंतर्गत सामायिक केलेला स्टोरेज"</string>
+    <string name="storage_internal" msgid="3570990907910199483">"अंतर्गत शेअर केलेला स्टोरेज"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"SD कार्ड"</string>
     <string name="storage_sd_card_label" msgid="6347111320774379257">"<xliff:g id="MANUFACTURER">%s</xliff:g> SD कार्ड"</string>
     <string name="storage_usb_drive" msgid="6261899683292244209">"USB ड्राइव्‍ह"</string>
@@ -1601,18 +1607,18 @@
     <string name="kg_login_invalid_input" msgid="5754664119319872197">"अवैध वापरकर्तानाव किंवा पासवर्ड."</string>
     <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"तुमचे वापरकर्तानाव किंवा पासवर्ड विसरलात?\n "<b>"google.com/accounts/recovery"</b>" ला भेट द्या."</string>
     <string name="kg_login_checking_password" msgid="1052685197710252395">"खाते तपासत आहे…"</string>
-    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"तुम्ही आपला पिन <xliff:g id="NUMBER_0">%1$d</xliff:g> वेळा अयोग्यरितीने टाइप केला आहे. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> सेकंदांमध्ये पुन्हा प्रयत्न करा."</string>
-    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"तुम्ही आपला पासवर्ड <xliff:g id="NUMBER_0">%1$d</xliff:g> वेळा अयोग्यरितीने टाइप केला आहे. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> सेकंदांमध्ये पुन्हा प्रयत्न करा."</string>
-    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"तुम्ही आपला अनलॉक पॅटर्न <xliff:g id="NUMBER_0">%1$d</xliff:g> वेळा अयोग्यरितीने काढला. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> सेकंदांमध्ये पुन्हा प्रयत्न करा."</string>
+    <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"तुम्ही तुमचा पिन <xliff:g id="NUMBER_0">%1$d</xliff:g> वेळा अयोग्यरितीने टाइप केला आहे. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> सेकंदांमध्ये पुन्हा प्रयत्न करा."</string>
+    <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"तुम्ही तुमचा पासवर्ड <xliff:g id="NUMBER_0">%1$d</xliff:g> वेळा अयोग्यरितीने टाइप केला आहे. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> सेकंदांमध्ये पुन्हा प्रयत्न करा."</string>
+    <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"तुम्ही तुमचा अनलॉक पॅटर्न <xliff:g id="NUMBER_0">%1$d</xliff:g> वेळा अयोग्यरितीने काढला. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> सेकंदांमध्ये पुन्हा प्रयत्न करा."</string>
     <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"तुम्ही <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="tv" msgid="5621231220154419413">"तुम्ही <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="4051015943038199910">"तुम्ही <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="2072996269148483637">"तुम्ही <xliff:g id="NUMBER">%d</xliff:g> वेळा टॅबलेट अनलॉक करण्याचा अयोग्यपणे प्रयत्न केला. टॅबलेट आता फॅक्टरी डीफॉल्ट वर रीसेट केला जाईल."</string>
     <string name="kg_failed_attempts_now_wiping" product="tv" msgid="4987878286750741463">"तुम्ही <xliff:g id="NUMBER">%d</xliff:g> वेळा टीव्ही अनलॉक करण्याचा अयोग्यरित्या प्रयत्न केला. टीव्ही आता फॅक्टरी डीफॉल्टवर रीसेट केला जाईल."</string>
     <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"तुम्ही <xliff:g id="NUMBER">%d</xliff:g> वेळा फोन अनलॉक करण्याचा अयोग्यपणे प्रयत्न केला. फोन आता फॅक्टरी डीफॉल्ट वर रीसेट केला जाईल."</string>
-    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"तुम्ही आपला अनलॉक पॅटर्न <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="tv" msgid="4224651132862313471">"तुम्ही <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="1437638152015574839">"तुम्ही आपला अनलॉक पॅटर्न <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="tablet" msgid="3253575572118914370">"तुम्ही तुमचा अनलॉक पॅटर्न <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="tv" msgid="4224651132862313471">"तुम्ही <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="1437638152015574839">"तुम्ही तुमचा अनलॉक पॅटर्न <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="4160700433287233771">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"काढा"</string>
     <string name="safe_media_volume_warning" product="default" msgid="2276318909314492312">"शिफारस केलेल्‍या पातळीच्या वर आवाज वाढवायचा?\n\nउच्च आवाजात दीर्घ काळ ऐकण्‍याने आपल्‍या श्रवणशक्तीची हानी होऊ शकते."</string>
@@ -1809,7 +1815,7 @@
     <string name="zen_mode_default_events_name" msgid="8158334939013085363">"इव्‍हेंट"</string>
     <string name="zen_mode_default_every_night_name" msgid="3012363838882944175">"निष्क्रिय आहे"</string>
     <string name="muted_by" msgid="5942954724562097128">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> काही ध्‍वनी म्‍यूट करत आहे"</string>
-    <string name="system_error_wipe_data" msgid="6608165524785354962">"आपल्‍या डिव्‍हाइसमध्‍ये अंतर्गत समस्‍या आहे आणि आपला फॅक्‍टरी डेटा रीसेट होईपर्यंत ती अस्‍थिर असू शकते."</string>
+    <string name="system_error_wipe_data" msgid="6608165524785354962">"आपल्‍या डिव्‍हाइसमध्‍ये अंतर्गत समस्‍या आहे आणि तुमचा फॅक्‍टरी डेटा रीसेट होईपर्यंत ती अस्‍थिर असू शकते."</string>
     <string name="system_error_manufacturer" msgid="8086872414744210668">"आपल्‍या डिव्‍हाइसमध्‍ये अंतर्गत समस्‍या आहे. तपशीलांसाठी आपल्‍या निर्मात्याशी संपर्क साधा."</string>
     <string name="stk_cc_ussd_to_dial" msgid="5214333646366591205">"USSD विनंती नियमित कॉलवर बदलली"</string>
     <string name="stk_cc_ussd_to_ss" msgid="4884994189414782605">"USSD विनंती SS विनंतीवर बदलली"</string>
@@ -1898,14 +1904,14 @@
       <item quantity="one">आपोआप भरण्याची <xliff:g id="COUNT">%1$s</xliff:g> सूचना</item>
       <item quantity="other">आपोआप भरण्याच्या <xliff:g id="COUNT">%1$s</xliff:g> सूचना</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; मध्ये सेव्ह करायचे का?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"&lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;मध्ये <xliff:g id="TYPE">%1$s</xliff:g> सेव्ह करायची?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"&lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;मध्ये <xliff:g id="TYPE_0">%1$s</xliff:g> आणि <xliff:g id="TYPE_1">%2$s</xliff:g> सेव्ह करायची?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"&lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;मध्ये <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> आणि <xliff:g id="TYPE_2">%3$s</xliff:g> सेव्ह करायची?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; वर अपडेट करायचे आहे का?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"<xliff:g id="TYPE">%1$s</xliff:g>&lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g> &lt;/b&gt; वर अपडेट करायचे आहे का?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"<xliff:g id="TYPE_0">%1$s</xliff:g> आणि <xliff:g id="TYPE_1">%2$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; वर अपडेट करायचा आहे का?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> आणि <xliff:g id="TYPE_2">%3$s</xliff:g>&lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;वर अपडेट करायचा आहे का?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" मध्ये सेव्ह करायचे का?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"<xliff:g id="TYPE">%1$s</xliff:g>, "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" मध्ये सेव्ह करायचे का?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"<xliff:g id="TYPE_0">%1$s</xliff:g> आणि <xliff:g id="TYPE_1">%2$s</xliff:g>, "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" मध्ये सेव्ह करायचे का?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> आणि <xliff:g id="TYPE_2">%3$s</xliff:g>, "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" मध्ये सेव्ह करायचे का?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" मध्ये अपडेट करायचे का?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"<xliff:g id="TYPE">%1$s</xliff:g>, "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" मध्ये अपडेट करायचे का?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"<xliff:g id="TYPE_0">%1$s</xliff:g> आणि <xliff:g id="TYPE_1">%2$s</xliff:g>, "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" मध्ये अपडेट करायचे का?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"हे आयटम "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> आणि <xliff:g id="TYPE_2">%3$s</xliff:g> मध्ये अपडेट करायचे का?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"सेव्ह करा"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"नाही, नको"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"अपडेट करा"</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 208fed6..2896923 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Mikrofon"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"rakam audio"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"Benarkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; merakam audio?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"Pengecaman aktiviti"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"camkan aktiviti"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"Benarkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengecam aktiviti fizikal anda?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Kamera"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"ambil gambar dan rakam video"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"Benarkan &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; mengambil gambar dan merakam video?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Apl ini boleh mendapatkan lokasi anda berdasarkan sumber rangkaian seperti menara selular dan rangkaian Wi-Fi. Perkhidmatan lokasi ini mesti dihidupkan dan tersedia pada tablet anda untuk membolehkan apl menggunakan perkhidmatan tersebut."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Apl ini boleh mendapatkan lokasi anda berdasarkan sumber rangkaian seperti menara selular dan rangkaian Wi-Fi. Perkhidmatan lokasi ini mesti dihidupkan dan tersedia pada TV anda untuk membolehkan apl menggunakan perkhidmatan tersebut."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Apl ini boleh mendapatkan lokasi anda berdasarkan sumber rangkaian seperti menara selular dan rangkaian Wi-Fi. Perkhidmatan lokasi ini mesti dihidupkan dan tersedia pada telefon anda untuk membolehkan apl menggunakan perkhidmatan tersebut."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"akses lokasi tepat di latar belakang"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"Apl ini boleh mendapatkan lokasi tepat anda setiap kali apl tersebut berada di latar belakang. Perkhidmatan lokasi ini mesti dihidupkan dan tersedia pada telefon anda untuk membolehkan apl menggunakan perkhidmatan tersebut. Tindakan ini mungkin meningkatkan penggunaan bateri."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"akses lokasi di latar belakang"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Jika tindakan ini dibenarkan bagi akses lokasi anggaran atau lokasi tepat, apl tersebut boleh mengakses lokasi itu semasa berjalan di latar belakang."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"tukar tetapan audio anda"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Membenarkan apl untuk mengubah suai tetapan audio global seperti kelantangan dan pembesar suara mana digunakan untuk output."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"rakam audio"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"Apl ini boleh merakam audio menggunakan mikrofon pada bila-bila masa."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"hantar perintah ke SIM"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Membenarkan apl menghantar arahan kepada SIM. Ini amat berbahaya."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"camkan aktiviti fizikal"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"Apl ini dapat mengecam aktiviti fizikal anda."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"ambil gambar dan video"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"Apl ini boleh mengambil gambar dan merakam video menggunakan kamera pada bila-bila masa."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"kawal getaran"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Membenarkan apl mengubah suai koleksi foto anda."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"baca lokasi daripada koleksi media anda"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Membenarkan apl membaca lokasi daripada koleksi media anda."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"Aplikasi <xliff:g id="APP">%s</xliff:g> mahu membuat pengesahan."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Perkakasan biometrik tidak tersedia"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Cap jari separa dikesan. Sila cuba lagi."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Tidak dapat memproses cap jari. Sila cuba lagi."</string>
@@ -1897,14 +1903,14 @@
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> cadangan autolengkap</item>
       <item quantity="one">Satu cadangan autolengkap</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"Simpan ke &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Simpan <xliff:g id="TYPE">%1$s</xliff:g> ke &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Simpan <xliff:g id="TYPE_0">%1$s</xliff:g> dan <xliff:g id="TYPE_1">%2$s</xliff:g> ke &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Simpan <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> dan <xliff:g id="TYPE_2">%3$s</xliff:g> ke &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"Kemas kini ke &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Kemas kini <xliff:g id="TYPE">%1$s</xliff:g> ke &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Kemas kini <xliff:g id="TYPE_0">%1$s</xliff:g> dan <xliff:g id="TYPE_1">%2$s</xliff:g> ke &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Kemas kini <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> dan <xliff:g id="TYPE_2">%3$s</xliff:g> ke &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"Simpan pada "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"Simpan <xliff:g id="TYPE">%1$s</xliff:g> pada "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"Simpan <xliff:g id="TYPE_0">%1$s</xliff:g> dan <xliff:g id="TYPE_1">%2$s</xliff:g> pada "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"Simpan <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> dan <xliff:g id="TYPE_2">%3$s</xliff:g> pada "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"Kemas kini dalam "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"Kemas kini <xliff:g id="TYPE">%1$s</xliff:g> dalam "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"Kemas kini <xliff:g id="TYPE_0">%1$s</xliff:g> dan <xliff:g id="TYPE_1">%2$s</xliff:g> dalam "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"Kemas kini item ini dalam "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> dan <xliff:g id="TYPE_2">%3$s</xliff:g> ?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Simpan"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Tidak, terima kasih"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"Kemas kini"</string>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index 71dd4b6..e509577 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"မိုက်ခရိုဖုန်း"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"အသံဖမ်းခြင်း"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; အား အသံဖမ်းယူခွင့် ပေးလိုပါသလား။"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"လှုပ်ရှားမှုကို မှတ်သားပါ"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"လှုပ်ရှားမှုကို မှတ်သားခြင်း"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; အား သင်၏ကိုယ်လက်လှုပ်ရှားမှုကို မှတ်သားခွင့်ပေးလိုပါသလား။"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"ကင်မရာ"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"ဓာတ်ပုံ ရိုက်ပြီးနောက် ဗွီဒီယို မှတ်တမ်းတင်ရန်"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; အား ဓာတ်ပုံနှင့် ဗီဒီယိုရိုက်ကူးခွင့် ပေးလိုပါသလား။"</string>
@@ -387,9 +390,9 @@
     <string name="permdesc_broadcastSticky" product="tv" msgid="6839285697565389467">"ထုတ်လွှင့်ခြင်းများ ပြီးဆုံးသည့်နောက် ဆက်လက်ရှိနေသည့်၊ တည်မြဲ ထုတ်လွှင့်မှုများပို့ရန် အက်ပ်အား ခွင့်ပြုပါ။ အလွန်အကျွံ လုပ်ဆောင်ပါက တီဗွီ နှေးသွားခြင်း သို့မဟုတ် မှတ်ဉာဏ်အသုံးများမှုကြောင့် မတည်မငြိမ်ဖြစ်ခြင်းများ ဖြစ်တတ်၏။"</string>
     <string name="permdesc_broadcastSticky" product="default" msgid="2825803764232445091">"အက်ပ်အား ကြာရှည်ခံ ထုတ်လွှင့်မှု ပြုပါ။ ဤထုတ်လွှင့်မှုများဟာ ထုတ်လွှင့်မှု ပြီးဆုံးပြီးသွားတည့်တိုင် ကျန်နေမည် ဖြစ်ပါသည်။ အလွန်အကျွံသုံးခြင်းကြောင့် မှတ်ဉာဏ်အသုံးများပြီး ဖုန်းနှေးခြင်း၊ မတည်ငြိမ်ခြင်း ဖြစ်နိုင်ပါသည်"</string>
     <string name="permlab_readContacts" msgid="8348481131899886131">"အဆက်အသွယ်များအား ဖတ်ခြင်း"</string>
-    <string name="permdesc_readContacts" product="tablet" msgid="5294866856941149639">"အပလီကေးရှင်းအား ခေါ်ဆိုသော အကြိမ်ရေ၊ အီးမေးလ်အကြိမ်ရေ၊ တခြားဆက်သွယ်မှုများစသည်ကဲ့သို့ သင့်တက်ဘလက်မှာ သိမ်းဆည်းထားသော အဆက်အသွယ်များရဲ့ အချက်အလက်ကို ဖတ်ခွင့်ပြုပါ။ ဤသို့ခွင့်ပြုခြင်းအားဖြင့် အပလီကေးရှင်းများကို သင့် အဆက်အသွယ်၏ အချက်မလက်များကို သိမ်းဆည်းရန် ခွင့်ပြုပြီး အန္တရာယ်ရှိသော အပလီကေးရှင်းများမှ ထိုအချက်အလက်များ ကို သင် မသိစေပဲ ဖြန့်ဝေနိုင််မည် ဖြစ်ပါသည်။"</string>
-    <string name="permdesc_readContacts" product="tv" msgid="1839238344654834087">"တစ်ဦးတစ်​ယောက်ထံ သင်ခေါ်ထားသော၊ အီးမေးိပု့ထားသော၊ သို့မဟုတ် တစ်ခြားနည်းဖြင့် အဆက်အသွယ်ပြုထားသော အကြိမ်အရေအတွက် အပါအဝင်၊ သင့်တီဗွီတွင် သိမ်းထားသည့် အဆက်အသွယ်ဆိုင်ရာ အချက်အလက်များ ဖတ်ရန် အက်ပ်အား ခွင့်ပြုပါ။ ဤနည်းဖြင့် သင့် အဆက်အသွယ် အချက်အလက်များအား သိမ်းဆည်းရန် အက်ပ်အား ခွင့်ပြုထားခြင်းဖြစ်ပြီး၊  အဆက်အသွယ် အချက်အလက်များအား အန္တရာယ်ရှိသော အက်ပ်များက သင်မသိဘဲ ဝေမျှနိုင်သည်။"</string>
-    <string name="permdesc_readContacts" product="default" msgid="8440654152457300662">"အပလီကေးရှင်းအား ခေါ်ဆိုသော အကြိမ်ရေ၊ အီးမေးလ်အကြိမ်ရေ၊ တခြားဆက်သွယ်မှုများစသည်ကဲ့သို့ သင့်ဖုန်းမှာ သိမ်းဆည်းထားသော အဆက်အသွယ်များရဲ့ အချက်အလက်ကို ဖတ်ခွင့်ပြုပါ။ ဤသို့ခွင့်ပြုခြင်းအားဖြင့် အပလီကေးရှင်းများကို သင့် အဆက်အသွယ်၏ အချက်မလက်များကို သိမ်းဆည်းရန် ခွင့်ပြုပြီး အန္တရာယ်ရှိသော အပလီကေးရှင်းများမှ ထိုအချက်အလက်များ ကို သင် မသိစေပဲ ဖြန့်ဝေနိုင််မည် ဖြစ်ပါသည်။"</string>
+    <string name="permdesc_readContacts" product="tablet" msgid="5294866856941149639">"အပလီကေးရှင်းအား ခေါ်ဆိုသော အကြိမ်ရေ၊ အီးမေးလ်အကြိမ်ရေ၊ တခြားဆက်သွယ်မှုများစသည်ကဲ့သို့ သင့်တက်ဘလက်မှာ သိမ်းဆည်းထားသော အဆက်အသွယ်များရဲ့ အချက်အလက်ကို ဖတ်ခွင့်ပြုပါ။ ဤသို့ခွင့်ပြုခြင်းအားဖြင့် အပလီကေးရှင်းများကို သင့် အဆက်အသွယ်၏ အချက်မလက်များကို သိမ်းရန် ခွင့်ပြုပြီး အန္တရာယ်ရှိသော အပလီကေးရှင်းများမှ ထိုအချက်အလက်များ ကို သင် မသိစေပဲ ဖြန့်ဝေနိုင််မည် ဖြစ်ပါသည်။"</string>
+    <string name="permdesc_readContacts" product="tv" msgid="1839238344654834087">"တစ်ဦးတစ်​ယောက်ထံ သင်ခေါ်ထားသော၊ အီးမေးိပု့ထားသော၊ သို့မဟုတ် တစ်ခြားနည်းဖြင့် အဆက်အသွယ်ပြုထားသော အကြိမ်အရေအတွက် အပါအဝင်၊ သင့်တီဗွီတွင် သိမ်းထားသည့် အဆက်အသွယ်ဆိုင်ရာ အချက်အလက်များ ဖတ်ရန် အက်ပ်အား ခွင့်ပြုပါ။ ဤနည်းဖြင့် သင့် အဆက်အသွယ် အချက်အလက်များအား သိမ်းရန် အက်ပ်အား ခွင့်ပြုထားခြင်းဖြစ်ပြီး၊  အဆက်အသွယ် အချက်အလက်များအား အန္တရာယ်ရှိသော အက်ပ်များက သင်မသိဘဲ ဝေမျှနိုင်သည်။"</string>
+    <string name="permdesc_readContacts" product="default" msgid="8440654152457300662">"အပလီကေးရှင်းအား ခေါ်ဆိုသော အကြိမ်ရေ၊ အီးမေးလ်အကြိမ်ရေ၊ တခြားဆက်သွယ်မှုများစသည်ကဲ့သို့ သင့်ဖုန်းမှာ သိမ်းဆည်းထားသော အဆက်အသွယ်များရဲ့ အချက်အလက်ကို ဖတ်ခွင့်ပြုပါ။ ဤသို့ခွင့်ပြုခြင်းအားဖြင့် အပလီကေးရှင်းများကို သင့် အဆက်အသွယ်၏ အချက်မလက်များကို သိမ်းရန် ခွင့်ပြုပြီး အန္တရာယ်ရှိသော အပလီကေးရှင်းများမှ ထိုအချက်အလက်များ ကို သင် မသိစေပဲ ဖြန့်ဝေနိုင််မည် ဖြစ်ပါသည်။"</string>
     <string name="permlab_writeContacts" msgid="5107492086416793544">"အဆက်အသွယ်များအား ပြင်ဆင်ခြင်း"</string>
     <string name="permdesc_writeContacts" product="tablet" msgid="897243932521953602">"အပလီကေးရှင်းအား သင့်တက်ဘလက်မှာ သိမ်းဆည်းထားသော အဆက်အသွယ်များရဲ့ အချက်အလက် (အထူးအဆက်အသွယ်များအား ခေါ်ဆိုသော အကြိမ်ရေ၊ အီးမေးလ်ပို့သောအကြိမ်ရေ သို့ အခြားနည်းလမ်းဖြင့်ဆက်သွယ်မှုများ) ကို ပြင်ဆင်ခွင့်ပြုခြင်း။ ဒီခွင့်ပြုချက်က အပလီကေးရှင်းများအား အဆက်အသွယ် အချက်အလက်များ ဖျက်စီးခြင်း လုပ်ဆောင်စေနိုင်မှာ ဖြစ်ပါသည်။"</string>
     <string name="permdesc_writeContacts" product="tv" msgid="5438230957000018959">"အထူးအဆက်အသွယ်များအား ခေါ်ဆိုသော အကြိမ်ရေ၊ အီးမေးလ်ပို့သောအကြိမ်ရေ သို့ အခြားနည်းလမ်းဖြင့်ဆက်သွယ်မှုများ အပါအဝင်၊ သင့်တီဗွီတွင် သိမ်းဆည်းထားသော အဆက်အသွယ်များ၏ အချက်အလက်အား ပြင်ဆင်ရန် အပလီကေးရှင်းအား ခွင့်ပြုပါ။ ဤသို့ ခွင့်ပြုခြင်းသည် အဆက်အသွယ် အချက်အလက်များ ဖျက်ဆီးရန် အပလီကေးရှင်းများအား  ခွင့်ပြုခြင်းဖြစ်၏။"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"ဤအက်ပ်သည် ဆဲလ်တာဝါများနှင့် Wi-Fi ကွန်ရက်များကဲ့သို့ ကွန်ရက်အရင်းအမြစ်ပေါ် အခြေခံပြီး သင့်တည်နေရာအချက်အလက်ကို ရယူနိုင်ပါသည်။ အက်ပ်က အသုံးပြုနိုင်ရန်အတွက် ဤတည်နေရာ ဝန်ဆောင်မှုများကို ဖွင့်ထားရမည် ဖြစ်ပြီး သင့်တက်ဘလက်ပေါ်တွင် ရရှိနိုင်ရပါမည်။"</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"ဤအက်ပ်သည် ဆဲလ်တာဝါများနှင့် Wi-Fi ကွန်ရက်များကဲ့သို့ ကွန်ရက်အရင်းအမြစ်ပေါ် အခြေခံပြီး သင့်တည်နေရာအချက်အလက်ကို ရယူနိုင်ပါသည်။ အက်ပ်က အသုံးပြုနိုင်ရန်အတွက် ဤတည်နေရာ ဝန်ဆောင်မှုများကို ဖွင့်ထားရမည် ဖြစ်ပြီး သင့်တီဗီပေါ်တွင် ရရှိနိုင်ရပါမည်။"</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"ဤအက်ပ်သည် ဆဲလ်တာဝါများနှင့် Wi-Fi ကွန်ရက်များကဲ့သို့ ကွန်ရက်အရင်းအမြစ်ပေါ် အခြေခံပြီး သင့်တည်နေရာအချက်အလက်ကို ရယူနိုင်ပါသည်။ အက်ပ်က အသုံးပြုနိုင်ရန်အတွက် ဤတည်နေရာ ဝန်ဆောင်မှုများကို ဖွင့်ထားရမည် ဖြစ်ပြီး သင့်ဖုန်းပေါ်တွင် ရရှိနိုင်ရပါမည်။"</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"နောက်ခံတွင် တည်နေရာအတိအကျ အသုံးပြုခြင်း"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"နောက်ခံတွင် ဖွင့်ထားသည့်အခါတိုင်း ဤအက်ပ်က သင်၏တည်နေရာအတိအကျကို ရယူနိုင်ပါသည်။ သင်၏ဖုန်းတွင် အက်ပ်ကအသုံးပြုရန်အတွက် ဤတည်နေရာဝန်ဆောင်မှုများကို ဖွင့်ထားပြီး အသုံးပြု၍ ရပါမည်။ ၎င်းက ဘက်ထရီ ပိုကုန်နိုင်ပါသည်။"</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"နောက်ခံတွင် တည်နေရာကို အသုံးပြုရန်"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"ခန့်မှန်းခြေ သို့မဟုတ် တိကျသော တည်နေရာ ဝင်သုံးခွင့်အတွက် ၎င်းကို နောက်ဆက်တွဲ ခွင့်ပြုထားပါက နောက်ခံတွင် လုပ်ဆောင်နေစဉ် အက်ပ်က တည်နေရာကို ရယူအသုံးပြုနိုင်ပါသည်။"</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"သင့်အသံအပြင်အဆင်အားပြောင်းခြင်း"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"အပလီကေးရှင်းအား အသံအတိုးအကျယ်နှင့် အထွက်ကို မည်သည့်စပီကာကို သုံးရန်စသည်ဖြင့် စက်တစ်ခုလုံးနှင့်ဆိုင်သော အသံဆိုင်ရာ ဆက်တင်များ ပြင်ဆင်ခွင့် ပြုရန်"</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"အသံဖမ်းခြင်း"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"ဤအက်ပ်သည် မိုက်ခရိုဖုန်းကို အသုံးပြုပြီး အချိန်မရွေး အသံသွင်းနိုင်ပါသည်။"</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"SIM ထံသို့ ညွှန်ကြားချက်များကို ပို့ပါ"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"အက်ပ်အား ဆင်းမ်ကဒ်ဆီသို့ အမိန့်များ ပေးပို့ခွင့် ပြုခြင်း။ ဤခွင့်ပြုမှုမှာ အန္တရာယ်အလွန် ရှိပါသည်။"</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"ကိုယ်လက်လှုပ်ရှားမှုကို မှတ်သားပါ"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"ဤအက်ပ်က သင်၏ကိုယ်လက်လှုပ်ရှားမှုကို မှတ်သားနိုင်ပါသည်။"</string>
     <string name="permlab_camera" msgid="3616391919559751192">"ဓါတ်ပုံနှင့်ဗွီဒီယိုရိုက်ခြင်း"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"ဤအက်ပ်သည် ကင်မရာကို အသုံးပြု၍ ဓာတ်ပုံနှင့် ဗီဒီယိုများကို အချိန်မရွေး ရိုက်ကူးနိုင်ပါသည်။"</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"တုန်ခုန်မှုအား ထိန်းချုပ်ခြင်း"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"အက်ပ်အား သင့်ဓာတ်ပုံစုစည်းမှုကို ပြုပြင်ခွင့်ပေးသည်။"</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"သင့်မီဒီယာစုစည်းမှုမှ တည်နေရာများကို ဖတ်ခြင်း"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"အက်ပ်အား သင့်မီဒီယာစုစည်းမှုမှ တည်နေရာများကို ဖတ်ခွင့်ပေးသည်။"</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"အပလီကေးရှင်း <xliff:g id="APP">%s</xliff:g> က အထောက်အထားစိစစ်လိုသည်။"</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"ဇီဝအချက်အလက်သုံး ကွန်ပျူတာစက်ပစ္စည်း မရရှိနိုင်ပါ"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"လက်ဗွေရဦ တစ်ပိုင်းတစ်စ တွေ့ရှိသည်။ ကျေးဇူးပြု၍ ထပ်မံကြိုးစားပါ။"</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"လက်ဗွေရာယူခြင်း မဆောင်ရွက်နိုင်ပါ။ ထပ်မံကြိုးစားပါ။"</string>
@@ -1898,14 +1904,14 @@
       <item quantity="other">အော်တိုဖြည့်အကြံပြုချက် <xliff:g id="COUNT">%1$s</xliff:g> ခု</item>
       <item quantity="one">အော်တိုဖြည့်အကြံပြုချက် တစ်ခု</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; တွင် သိမ်းဆည်းလိုပါသလား။"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"<xliff:g id="TYPE">%1$s</xliff:g> ကို &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; တွင် သိမ်းဆည်းလိုပါသလား။"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"<xliff:g id="TYPE_0">%1$s</xliff:g> နှင့် <xliff:g id="TYPE_1">%2$s</xliff:g> ကို &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; တွင် သိမ်းဆည်းလိုပါသလား။"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"<xliff:g id="TYPE_0">%1$s</xliff:g>၊ <xliff:g id="TYPE_1">%2$s</xliff:g>  နှင့် <xliff:g id="TYPE_2">%3$s</xliff:g> ကို &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; တွင် သိမ်းဆည်းလိုပါသလား။"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; သို့ အပ်ဒိတ်လုပ်လိုပါသလား။"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"<xliff:g id="TYPE">%1$s</xliff:g> ကို &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; သို့ အပ်ဒိတ်လုပ်လိုပါသလား။"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"<xliff:g id="TYPE_0">%1$s</xliff:g> နှင့် <xliff:g id="TYPE_1">%2$s</xliff:g> ကို &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; သို့ အပ်ဒိတ်လုပ်လိုပါသလား။"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"<xliff:g id="TYPE_0">%1$s</xliff:g>၊ <xliff:g id="TYPE_1">%2$s</xliff:g> နှင့် <xliff:g id="TYPE_2">%3$s</xliff:g> ကို &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; သို့ အပ်ဒိတ်လုပ်လိုပါသလား။"</string>
+    <string name="autofill_save_title" msgid="327541108460384555"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"တွင် သိမ်းလိုပါသလား။"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"<xliff:g id="TYPE">%1$s</xliff:g> ကို "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"တွင် သိမ်းဆည်းလိုပါသလား။"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"<xliff:g id="TYPE_0">%1$s</xliff:g> နှင့် <xliff:g id="TYPE_1">%2$s</xliff:g> ကို "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"တွင် သိမ်းလိုပါသလား။"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"<xliff:g id="TYPE_0">%1$s</xliff:g>၊ <xliff:g id="TYPE_1">%2$s</xliff:g> နှင့် <xliff:g id="TYPE_2">%3$s</xliff:g> ကို "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"တွင် သိမ်းဆည်းလိုပါသလား။"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"တွင် အပ်ဒိတ်လုပ်လိုပါသလား။"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"<xliff:g id="TYPE">%1$s</xliff:g> ကို "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" တွင် အပ်ဒိတ်လုပ်လိုပါသလား။"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"<xliff:g id="TYPE_0">%1$s</xliff:g> နှင့် <xliff:g id="TYPE_1">%2$s</xliff:g> ကို "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"တွင် အပ်ဒိတ်လုပ်လိုပါသလား။"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"ဤအချက်အလက်များကို "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"တွင် အပ်ဒိတ်လုပ်လိုပါသလား- <xliff:g id="TYPE_0">%1$s</xliff:g>၊ <xliff:g id="TYPE_1">%2$s</xliff:g> နှင့် <xliff:g id="TYPE_2">%3$s</xliff:g>။"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"သိမ်းရန်"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"မလိုပါ"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"အပ်ဒိတ်လုပ်ရန်"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 28e7d33..b47c965 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Mikrofon"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"ta opp lyd"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"Vil du la &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ta opp lyd?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"Aktivitetsgjenkjenning"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"gjenkjenn aktivitet"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"Vil du la &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; gjenkjenne den fysiske aktiviteten din?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Kamera"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"ta bilder og ta opp video"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"Vil du la &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ta bilder og spille inn video?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Denne appen kan få posisjonen din fra nettverkskilder som mobilmaster og Wi-Fi-nettverk. Disse posisjonstjenestene må være slått på og tilgjengelige på nettbrettet ditt for at appen skal kunne bruke dem."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Denne appen kan få posisjonen din fra nettverkskilder som mobilmaster og Wi-Fi-nettverk. Disse posisjonstjenestene må være slått på og tilgjengelige på TV-en din for at appen skal kunne bruke dem."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Denne appen kan få posisjonen din fra nettverkskilder som mobilmaster og Wi-Fi-nettverk. Disse posisjonstjenestene må være slått på og tilgjengelige på telefonen din for at appen skal kunne bruke dem."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"tilgang til nøyaktig posisjon i bakgrunnen"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"Denne appen kan få den nøyaktige posisjonen din når den er på i bakgrunnen. Disse posisjonstjenestene må være slått på og tilgjengelige på telefonen din for at appen skal kunne bruke dem. Dette kan øke batteriforbruket."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"tilgang til posisjon i bakgrunnen"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Hvis du gir denne tillatelsen, får appen tilgang til posisjonen mens den kjører i bakgrunnen, i tillegg til tilgang til omtrentlig eller presis posisjon."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"endre lydinnstillinger"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Lar appen endre globale lydinnstillinger slik som volum og hvilken høyttaler som brukes for lydavspilling."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"ta opp lyd"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"Denne appen kan når som helst ta opp lyd med mikrofonen."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"sende kommandoer til SIM-kortet"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Lar appen sende kommandoer til SIM-kortet. Dette er veldig farlig."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"gjenkjenn fysisk aktivitet"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"Denne appen kan gjenkjenne den fysiske aktiviteten din."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"ta bilder og videoer"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"Denne appen kan når som helst ta bilder og spille inn videoer ved hjelp av kameraet."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"kontrollere vibreringen"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Lar appen gjøre endringer i bildesamlingen din."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"lese posisjoner fra mediesamlingen din"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Lar appen lese posisjoner fra mediesamlingen din."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"Appen <xliff:g id="APP">%s</xliff:g> vil autentisere."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Biometrisk maskinvare er utilgjengelig"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Deler av fingeravtrykket er registrert. Prøv på nytt."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Kunne ikke registrere fingeravtrykket. Prøv på nytt."</string>
@@ -1897,14 +1903,14 @@
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> forslag til autofyll</item>
       <item quantity="one">Ett forslag til autofyll</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"Vil du lagre i &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Vil du lagre <xliff:g id="TYPE">%1$s</xliff:g> i &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Vil du lagre <xliff:g id="TYPE_0">%1$s</xliff:g> og <xliff:g id="TYPE_1">%2$s</xliff:g> i &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Vil du lagre <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> og <xliff:g id="TYPE_2">%3$s</xliff:g> i &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"Vil du oppdatere til &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Vil du oppdatere <xliff:g id="TYPE">%1$s</xliff:g> til &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Vil du oppdatere <xliff:g id="TYPE_0">%1$s</xliff:g> og <xliff:g id="TYPE_1">%2$s</xliff:g> til &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Vil du oppdatere <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> og <xliff:g id="TYPE_2">%3$s</xliff:g> til &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"Vil du lagre i "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"Vil du lagre <xliff:g id="TYPE">%1$s</xliff:g> i "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"Vil du lagre <xliff:g id="TYPE_0">%1$s</xliff:g> og <xliff:g id="TYPE_1">%2$s</xliff:g> i "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"Vil du lagre <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> og <xliff:g id="TYPE_2">%3$s</xliff:g> i "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"Vil du oppdatere i "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"Vil du oppdatere <xliff:g id="TYPE">%1$s</xliff:g> i "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"Vil du oppdatere <xliff:g id="TYPE_0">%1$s</xliff:g> og <xliff:g id="TYPE_1">%2$s</xliff:g> i "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"Vil du oppdatere disse elementene i "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> og <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Lagre"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Nei takk"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"Oppdater"</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index 875f87d..47d4d6a 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"माइक्रोफोन"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"अडियो रेकर्ड गर्नुहोस्"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; लाई अडियो रेकर्ड गर्न दिने हो?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"गतिविधिको पहिचान"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"गतिविधि पहिचान गर्नुहोस्‌"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; लाई तपाईंको गतिविधि पहिचान गर्न अनुमति दिने हो?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"क्यामेरा"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"तस्बिर खिच्नुका साथै भिडियो रेकर्ड गर्नुहोस्"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; लाई तस्बिरहरू खिच्न र भिडियो रेकर्ड गर्न दिने हो?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"यस अनुप्रयोगले सेलका टावर र Wi-Fi नेटवर्कहरू जस्ता नेटवर्कका स्रोतहरूको आधारमा तपाईंको स्थान बारे जानकारी प्राप्त गर्न सक्छ। यो अनुप्रयोग ती स्रोतहरूको प्रयोग गर्न सक्षम होस् भन्नका खातिर यी स्थान सम्बन्धी सेवाहरूलाई अनिवार्य रूपमा सक्रिय पार्नुपर्छ र यी तपाईंको ट्याब्लेटमा उपलब्ध हुनु पर्छ।"</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"यस अनुप्रयोगले सेलका टावर र Wi-Fi नेटवर्कहरू जस्ता नेटवर्कका स्रोतहरूको आधारमा तपाईंको स्थान बारे जानकारी प्राप्त गर्न सक्छ। यो अनुप्रयोग ती स्रोतहरूको प्रयोग गर्न सक्षम होस् भन्नका खातिर यी स्थान सम्बन्धी सेवाहरूलाई अनिवार्य रूपमा सक्रिय पार्नुपर्छ र यी तपाईंको TV मा उपलब्ध हुनु पर्छ।"</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"यस अनुप्रयोगले सेलका टावर र Wi-Fi नेटवर्कहरू जस्ता नेटवर्कका स्रोतहरूको आधारमा तपाईंको स्थान बारे जानकारी प्राप्त गर्न सक्छ। यो अनुप्रयोग ती स्रोतहरूको प्रयोग गर्न सक्षम होस् भन्नका खातिर यी स्थान सम्बन्धी सेवाहरूलाई अनिवार्य रूपमा सक्रिय पार्नुपर्छ र यी तपाईंको फोनमा उपलब्ध हुनु पर्छ।"</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"पृष्ठभूमिमा सटीक स्थानमाथि पहुँच राख्नुहोस्"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"यो अनुप्रयोगले पृष्ठभूमिमा चलिरहेको अवस्थामा तपाईंलाई जुनसुकै बेला स्थानको सटिक जानकारी दिन सक्छ। यी स्थानसम्बन्धी सेवाहरू अनिवार्य रूपमा सक्रिय गरिएका हुनु पर्छ र अनुप्रयोगले यिनीहरूको प्रयोग गर्न सकोस् भन्नाका खातिर तपाईंको फोनमै उपलब्ध हुन्छन्। यस कार्यले गर्दा ब्याट्री बढी खर्च हुन सक्छ।"</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"पृष्ठभूमिमा स्थानसम्बन्धी पहुँच"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"यसका अतिरिक्त यसलाई अनुमानित वा सटिक स्थानमाथि पहुँच राख्ने अनुमति दिइएको छ भने उक्त अनुप्रयोगले पृष्ठभूमिमा चलिरहेको बेला स्थानमाथि पहुँच राख्न सक्छ।"</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"तपाईँका अडियो सेटिङहरू परिवर्तन गर्नुहोस्"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"अनुप्रयोगलाई ग्लोबल अडियो सेटिङहरू परिमार्जन गर्न अनुमति दिन्छ, जस्तै आवाजको मात्रा र आउटपुटको लागि कुन स्पिकर प्रयोग गर्ने।"</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"अडियो रेकर्ड गर्नुहोस्"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"यस अनुप्रयोगले जुनसुकै समय माइक्रोफोनको प्रयोग गरी अडियो रेकर्ड गर्न सक्छ।"</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"SIM मा आदेशहरू पठाउन दिनुहोस्"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"SIM लाई आदेश पठाउन अनुप्रयोगलाई अनुमति दिन्छ। यो निकै खतरनाक हुन्छ।"</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"शारीरिक गतिविधि पहिचान गर्नुहोस्‌"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"यो अनुप्रयोगले तपाईंको शारीरिक गतिविधिको पहिचान गर्न सक्छ।"</string>
     <string name="permlab_camera" msgid="3616391919559751192">"तस्बिरहरू र भिडियोहरू लिनुहोस्।"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"यस अनुप्रयोगले जुनसुकै समय क्यामेराको प्रयोग गरी तस्बिर खिच्न र भिडियो रेकर्ड गर्न सक्छ।"</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"कम्पन नियन्त्रण गर्नुहोस्"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"यसले अनुप्रयोगलाई तपाईंको तस्बिरको सङ्ग्रह परिमार्जन गर्न दिन्छ।"</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"आफ्नो मिडियाको सङ्ग्रहका स्थानहरू पढ्नुहोस्‌"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"यसले अनुप्रयोगलाई तपाईंको मिडिया सङ्ग्रहका स्थानहरू पढ्न दिन्छ।"</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"अनुप्रयोग <xliff:g id="APP">%s</xliff:g> ले प्रमाणीकरण गर्न चाहन्छ।"</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"बायोमेट्रिक हार्डवेयर उपलब्ध छैन"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"आंशिक औठाछाप पत्ता लाग्यो। कृपया फेरि प्रयास गर्नुहोस्।"</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"औठाछाप प्रशोधन गर्न सकिएन। कृपया फेरि प्रयास गर्नुहोस्।"</string>
@@ -1903,14 +1909,14 @@
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> स्वत: भरण सुझावहरू</item>
       <item quantity="one">एउटा स्वत: भरण सुझाव</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; मा सुरक्षित गर्ने हो?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"<xliff:g id="TYPE">%1$s</xliff:g> लाई &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; मा सुरक्षित गर्ने हो?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"<xliff:g id="TYPE_0">%1$s</xliff:g> र <xliff:g id="TYPE_1">%2$s</xliff:g> लाई  &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; मा सुरक्षित गर्ने हो?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> र <xliff:g id="TYPE_2">%3$s</xliff:g> लाई to &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; मा सुरक्षित गर्ने हो?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; मा अद्यावधिक गर्ने हो?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"<xliff:g id="TYPE">%1$s</xliff:g> लाई &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; मा अद्यावधिक गर्ने हो?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"<xliff:g id="TYPE_0">%1$s</xliff:g> र <xliff:g id="TYPE_1">%2$s</xliff:g> लाई &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; मा अद्यावधिक गर्ने हो?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> र <xliff:g id="TYPE_2">%3$s</xliff:g> लाई to &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; मा अद्यावधिक गर्ने हो?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" मा सुरक्षित गर्ने हो?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"<xliff:g id="TYPE">%1$s</xliff:g> लाई "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" मा सुरक्षित गर्ने हो?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"<xliff:g id="TYPE_0">%1$s</xliff:g> र <xliff:g id="TYPE_1">%2$s</xliff:g> लाई "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" मा सुरक्षित गर्ने हो?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> र <xliff:g id="TYPE_2">%3$s</xliff:g> लाई "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" मा सुरक्षित गर्ने हो?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" मा अद्यावधिक गर्ने हो?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"<xliff:g id="TYPE">%1$s</xliff:g> लाई "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" मा अद्यावधिक गर्ने हो?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"<xliff:g id="TYPE_0">%1$s</xliff:g> र <xliff:g id="TYPE_1">%2$s</xliff:g> लाई "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" मा अद्यावधिक गर्ने हो?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"यी वस्तुहरू "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" मा अद्यावधिक गर्नुहोस्‌: <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> र <xliff:g id="TYPE_2">%3$s</xliff:g> हो?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"सुरक्षित गर्नुहोस्"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"पर्दैन, धन्यवाद"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"अद्यावधिक गर्नुहोस्"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index b95ba19..ed79f7b 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Microfoon"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"audio opnemen"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toestaan om audio op te nemen?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"Activiteitsherkenning"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"activiteit herkennen"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"Toestaan dat &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; je fysieke activiteit herkent?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Camera"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"foto\'s maken en video opnemen"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; toestaan om foto\'s te maken en video op te nemen?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Deze app kan je locatie ophalen op basis van netwerkbronnen zoals zendmasten en wifi-netwerken. De app kan alleen gebruikmaken van deze locatieservices als ze zijn ingeschakeld en beschikbaar zijn op je tablet."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Deze app kan je locatie ophalen op basis van netwerkbronnen zoals zendmasten en wifi-netwerken. De app kan alleen gebruikmaken van deze locatieservices als ze zijn ingeschakeld en beschikbaar zijn op je tv."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Deze app kan je locatie ophalen op basis van netwerkbronnen zoals zendmasten en wifi-netwerken. De app kan alleen gebruikmaken van deze locatieservices als ze zijn ingeschakeld en beschikbaar zijn op je telefoon."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"toegang tot precieze locatie op de achtergrond"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"Deze app kan je exacte locatie ophalen wanneer de app op de achtergrond wordt uitgevoerd. De app kan alleen gebruikmaken van deze locatieservices als ze zijn ingeschakeld en beschikbaar zijn op je telefoon. Hierdoor kan het batterijverbruik toenemen."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"toegang tot locatie op de achtergrond"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Als dit wordt verleend als aanvulling op toegang tot de geschatte of precieze locatie, kan de app toegang tot de locatie krijgen terwijl de app actief is op de achtergrond."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"je audio-instellingen wijzigen"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Hiermee kan de app algemene audio-instellingen wijzigen zoals het volume en welke luidspreker wordt gebruikt voor de uitvoer."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"audio opnemen"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"Deze app kan op elk moment audio opnemen met de microfoon."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"opdrachten verzenden naar de simkaart"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Hiermee kan de app opdrachten verzenden naar de simkaart. Dit is erg gevaarlijk."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"fysieke activiteit herkennen"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"Deze app kan je fysieke activiteit herkennen."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"foto\'s en video\'s maken"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"Deze app kan op elk moment foto\'s maken en video\'s opnemen met de camera."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"trilling beheren"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Hiermee sta je de app toe je fotocollectie aan te passen."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"locaties van je mediacollecties bekijken"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Hiermee sta je de app toe locaties van je mediacollectie te bekijken."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"App <xliff:g id="APP">%s</xliff:g> wil een verificatie uitvoeren."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Biometrische hardware niet beschikbaar"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Gedeeltelijke vingerafdruk gedetecteerd. Probeer het opnieuw."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Kan vingerafdruk niet verwerken. Probeer het opnieuw."</string>
@@ -1897,14 +1903,14 @@
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> suggesties van Automatisch aanvullen</item>
       <item quantity="one">Eén suggestie van Automatisch aanvullen</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"Opslaan in &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"<xliff:g id="TYPE">%1$s</xliff:g> opslaan in &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"<xliff:g id="TYPE_0">%1$s</xliff:g> en <xliff:g id="TYPE_1">%2$s</xliff:g> opslaan in &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> en <xliff:g id="TYPE_2">%3$s</xliff:g> opslaan in &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"Updaten naar &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"<xliff:g id="TYPE">%1$s</xliff:g> updaten naar &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"<xliff:g id="TYPE_0">%1$s</xliff:g> en <xliff:g id="TYPE_1">%2$s</xliff:g> updaten naar &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> en <xliff:g id="TYPE_2">%3$s</xliff:g> updaten naar &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"Opslaan in "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"<xliff:g id="TYPE">%1$s</xliff:g> opslaan in "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"<xliff:g id="TYPE_0">%1$s</xliff:g> en <xliff:g id="TYPE_1">%2$s</xliff:g> opslaan in "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> en <xliff:g id="TYPE_2">%3$s</xliff:g> opslaan in "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"Updaten in "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"<xliff:g id="TYPE">%1$s</xliff:g> updaten in "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"<xliff:g id="TYPE_0">%1$s</xliff:g> en <xliff:g id="TYPE_1">%2$s</xliff:g> updaten in "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"Deze items updaten in "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> en <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Opslaan"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Nee, bedankt"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"Updaten"</string>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index 9d3fa8e..031cacb 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"ମାଇକ୍ରୋଫୋନ୍"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"ଅଡିଓ ରେକର୍ଡ କରେ"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ ଅଡିଓ ରେକର୍ଡ କରିବା ପାଇଁ ଅନୁମତି ଦେବେ କି?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"ଗତିବିଧି ଚିହ୍ନଟକରଣ"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"ଗତିବିଧିକୁ ଚିହ୍ନଟ କରିପାରେ"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"ଆପଣଙ୍କ ଶାରୀରିକ ଗତିବିଧି ଚିହ୍ନଟ କରିବା ପାଇଁ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ଅନୁମତି କରିବେ?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"କ୍ୟାମେରା"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"ଫଟୋ ନିଏ ଓ ଭିଡିଓ ରେକର୍ଡ କରେ"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;କୁ ଫଟୋ ଉଠାଇବାକୁ ଏବଂ ଭିଡିଓ ରେକର୍ଡ କରିବାକୁ ଅନୁମତି ଦେବେ କି?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"ଏହି ଆପ୍‍, ନେଟ୍‌ୱର୍କ ସୋର୍ସ ଉପରେ ଆଧାର କରି ଆପଣଙ୍କ ଲୋକେଶନ୍‍ ପ୍ରାପ୍ତ କରିପାରେ, ଯେପରିକି ସେଲ୍‍ ଟାୱାର୍‍ ଓ ୱାଇ-ଫାଇ ନେଟ୍‌ୱର୍କ। ଏହି ଲୋକେଶନ୍‌ ସେବା, ଆପଣଙ୍କ ଟାବଲେଟ୍‌ରେ ଅନ୍‍ ରହିଥିବା ଓ ଉପଲବ୍ଧ ଥିବା ଦରକାର, ଯେଉଁଥିରୁ ଆପ୍‌ ସେଗୁଡ଼ିକର ବ୍ୟବହାର କରିପାରିବ।"</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"ଏହି ଆପ୍‍, ନେଟ୍‌ୱର୍କ ସୋର୍ସ ଉପରେ ଆଧାର କରି ଆପଣଙ୍କ ଲୋକେଶନ୍‍ ପ୍ରାପ୍ତ କରିପାରେ, ଯେପରିକି ସେଲ୍‍ ଟାୱାର୍‍ ଓ ୱାଇ-ଫାଇ ନେଟ୍‌ୱର୍କ। ଏହି ଲୋକେଶନ୍‌ ସେବା, ଆପଣଙ୍କ ଟିଭିରେ ଅନ୍‍ ରହିଥିବା ଓ ଉପଲବ୍ଧ ଥିବା ଦରକାର, ଯେଉଁଥିରୁ ଆପ୍‌ ସେଗୁଡ଼ିକର ବ୍ୟବହାର କରିପାରିବ।"</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"ସେଲ୍‍ ଟାୱାର ଓ ୱାଇ-ଫାଇ ନେଟ୍‌ୱର୍କ ପରି ସୋର୍ସକୁ ଆଧାର କରି ଏହି ଆପ୍‍ ଆପଣଙ୍କ ଲୋକେଶନ୍‍ ପ୍ରାପ୍ତ କରିପାରିବ। ଏହି ଲୋକେଶନ୍‍ ସେବାଗୁଡ଼ିକର ବ୍ୟବହାର କରିବାକୁ ସେଗୁଡ଼ିକ ଅନ୍‍ କରାଯିବା ଏବଂ ଆପଣଙ୍କ ଫୋନ୍‌ରେ ଉପଲବ୍ଧ ଥିବା ଜରୁରୀ"</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"ପୃଷ୍ଠପଟରେ ସଠିକ୍‍ ଲୋକେଶନ୍‍ର ଆକ୍ସେସ୍‍"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"ଏହି ଆପ୍‍ ପୃଷ୍ଠପଟରେ ରହିଥିବାବେଳେ ଯେକୌଣସି ସମୟରେ ଆପଣଙ୍କର ଲୋକେଶନ୍‍ ପ୍ରାପ୍ତ କରିପାରିବ। ଏହି ଲୋକେଶନ୍‍ ସେବାଗୁଡ଼ିକ ନିଶ୍ଚିତରୂପେ ଅନ୍‍ ରହିବା ଦରକାର ଏବଂ ଆପ୍‍ର ବ୍ୟବହାର ପାଇଁ ଫୋନ୍‍ରେ ଉପଲବ୍ଧ ଥିବା ଦରକାର। ଏହା ବ୍ୟାଟେରୀ ଅଧିକା ଖର୍ଚ୍ଚ କରିପାରେ।"</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"ବ୍ୟାକ୍‌ଗ୍ରାଉଣ୍ଡ୍‌ରେ ଲୋକେସନ୍ ଆକ୍ସେସ୍ କରନ୍ତୁ"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"ଅନୁମାନିତ କିମ୍ବା ବିଲ୍‌କୁଲ୍ ସଠିକ୍ ସ୍ଥାନ ଆକ୍ସେସ୍ କରିବାର ଅନୁମତି ଅତିରିକ୍ତ ଭାବରେ ଦିଆଗଲେ, ବ୍ୟାକ୍‌ଗ୍ରାଉଣ୍ଡରେ ଚାଲୁଥିବା ସମୟରେ ଆପ୍ ଆପଣଙ୍କର ସ୍ଥାନର ଆକ୍ସେସ୍ କରିପାରିବ।"</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"ଆପଣଙ୍କ ଅଡିଓ ସେଟିଙ୍ଗକୁ ପରିବର୍ତ୍ତନ କରନ୍ତୁ"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"ଆପ୍‌କୁ ଗ୍ଲୋବାଲ୍ ଅଡିଓ ସେଟିଙ୍ଗ, ଯେପରିକି ଭଲ୍ୟୁମ୍‌କୁ ସଂଶୋଧିତ କରିବାକୁ ଏବଂ ଆଉଟପୁଟ୍ ପାଇଁ ସ୍ପିକର୍‌ ବ୍ୟବହାର କରିବାକୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"ଅଡିଓ ରେକର୍ଡ କରନ୍ତୁ"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"ଏହି ଆପ୍‍ ଯେକୌଣସି ସମୟରେ ମାଇକ୍ରୋଫୋନ୍‍ ବ୍ୟବହାର କରି ଅଡିଓ ରେକର୍ଡ କରିପାରିବ।"</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"SIMକୁ କମାଣ୍ଡ ପଠାନ୍ତୁ"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"SIMକୁ କମାଣ୍ଡ ପଠାଇବା ପାଇଁ ଆପ୍‍କୁ ଅନୁମତି ଦେଇଥାଏ। ଏହା ବହୁତ ବିପଦପୂର୍ଣ୍ଣ।"</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"ଶାରୀରିକ ଗତିବିଧି ଚିହ୍ନଟକରେ"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"ଏହି ଆପ୍‍ଣ ଆପଣଙ୍କ ଶାରୀରିକ ଗତିବିଧିକୁ ଚିହ୍ନଟ କରିପାରେ"</string>
     <string name="permlab_camera" msgid="3616391919559751192">"ଫଟୋ ଓ ଭିଡିଓଗୁଡ଼ିକୁ ନିଅନ୍ତୁ"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"ଏହି ଆପ୍‍ ଯେକୌଣସି ସମୟରେ କ୍ୟାମେରା ବ୍ୟବହାର କରି ଫଟୋ ଉଠାଇପାରେ ଏବଂ ଭିଡିଓ ରେକର୍ଡ କରିପାରେ।"</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"କମ୍ପନ ନିୟନ୍ତ୍ରଣ କରନ୍ତୁ"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"ଆପଣଙ୍କ ଫଟୋ ସଂଗ୍ରହ ପରିବର୍ତ୍ତନ କରିବାକୁ ଆପ୍‍ ଅନୁମତି ଦେଇଥାଏ।"</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"ଆପଣଙ୍କ ମିଡିଆ ସଂଗ୍ରହ ଠାରୁ ଲୋକେସନ୍‍ଗୁଡିକୁ ପଢନ୍ତୁ"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"ଆପଣଙ୍କ ମିଡିଆ ସଂଗ୍ରହ ଠାରୁ ଅବସ୍ଥାନଗୁଡିକୁ ପଢିବାକୁ ଆପ୍‍ ଅନୁମତି ଦେଇଥାଏ।"</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"ଆପ୍ଲିକେସନ୍ <xliff:g id="APP">%s</xliff:g> ପ୍ରମାଣିତକୃତ କରିବାକୁ ଚାହୁଁଛି।"</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"ବାୟୋମେଟ୍ରିକ୍‌ ହାର୍ଡୱେର୍‌ ଉପଲବ୍ଧ ନାହିଁ"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"ଆଙ୍ଗୁଠି ଚିହ୍ନ ଆଂଶିକ ଚିହ୍ନଟ ହେଲା। ଦୟାକରି ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"ଆଙ୍ଗୁଠି ଚିହ୍ନ ପ୍ରୋସେସ୍‍ କରାଯାଇପାରିଲା ନାହିଁ। ଦୟାକରି ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
@@ -1898,14 +1904,14 @@
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g>ଟି ଅଟୋଫିଲ୍‍ ପରାମର୍ଶ</item>
       <item quantity="one">ଗୋଟିଏ ଅଟୋଫିଲ୍‍ ପରାମର୍ଶ</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;ରେ ସେଭ୍‍ କରିବେ?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"<xliff:g id="TYPE">%1$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;ରେ ସେଭ୍‍ କରିବେ?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"<xliff:g id="TYPE_0">%1$s</xliff:g> ଏବଂ <xliff:g id="TYPE_1">%2$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;ରେ ସେଭ୍‍ କରିବେ?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, ଏବଂ <xliff:g id="TYPE_2">%3$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;ରେ ସେଭ୍‍ କରିବେ?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;କୁ ଅପ୍‍ଡେଟ୍‍ କରିବେ?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"<xliff:g id="TYPE">%1$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;କୁ ଅପ୍‍ଡେଟ୍‍ କରିବେ?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"<xliff:g id="TYPE_0">%1$s</xliff:g> ଏବଂ <xliff:g id="TYPE_1">%2$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;କୁ ଅପ୍‍ଡେଟ୍‍ କରିବେ?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, ଏବଂ <xliff:g id="TYPE_2">%3$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;କୁ ଅପ୍‍ଡେଟ୍‍ କରିବେ?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"କୁ ସେଭ୍ କରିବେ?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594"><b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"କୁ <xliff:g id="TYPE">%1$s</xliff:g> ସେଭ୍ କରିବେ?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432"><b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"କୁ <xliff:g id="TYPE_0">%1$s</xliff:g> ଏବଂ <xliff:g id="TYPE_1">%2$s</xliff:g> ସେଭ୍ କରିବେ?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555"><b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"କୁ <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ଏବଂ <xliff:g id="TYPE_2">%3$s</xliff:g> ସେଭ୍ କରିବେ?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"ରେ ଅପ୍‌ଡେଟ୍ କରିବେ?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233"><b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"ରେ <xliff:g id="TYPE">%1$s</xliff:g>କୁ ଅପ୍‌ଡେଟ୍ କରିବେ।"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484"><b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"ରେ <xliff:g id="TYPE_0">%1$s</xliff:g> ଏବଂ <xliff:g id="TYPE_1">%2$s</xliff:g> ଅପ୍‌ଡେଟ୍ କରିବେ?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922"><b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"ରେ: <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ଏବଂ <xliff:g id="TYPE_2">%3$s</xliff:g> ଆଇଟମ୍‌ଗୁଡ଼ିକ ଅପ୍‌ଡେଟ୍ କରିବେ?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"ସେଭ୍‌ କରନ୍ତୁ"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"ନାଁ, ପଚାରିଥିବାରୁ ଧନ୍ୟବାଦ"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"ଅପ୍‍ଡେଟ୍‌ କରନ୍ତୁ"</string>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index 6e615a8..2b30459 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"ਮਾਈਕ੍ਰੋਫੋਨ"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">" ਆਡੀਓ  ਰਿਕਾਰਡ ਕਰਨ"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"ਕੀ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ਨੂੰ ਆਡੀਓ ਰਿਕਾਰਡ ਕਰਨ ਦੇਣੀ ਹੈ?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"ਸਰਗਰਮੀ ਦੀ ਪਛਾਣ"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"ਸਰਗਰਮੀ ਨੂੰ ਪਛਾਣੋ"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"ਕੀ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ਨੂੰ ਆਪਣੇ ਸਰੀਰਕ ਸਰਗਰਮੀ ਦੀ ਪਛਾਣ ਕਰਨ ਦੇਣੀ ਹੈ?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"ਕੈਮਰਾ"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"ਤਸਵੀਰਾਂ ਲੈਣ ਅਤੇ ਵੀਡੀਓ ਰਿਕਾਰਡ ਕਰਨ"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"ਕੀ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ਨੂੰ ਤਸਵੀਰਾਂ ਖਿੱਚਣ ਅਤੇ ਵੀਡੀਓ ਰਿਕਾਰਡ ਕਰਨ ਦੇਣਾ ਹੈ?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"ਇਹ ਐਪ ਨੈੱਟਵਰਕ ਸਰੋਤਾਂ ਜਿਵੇਂ ਕਿ ਸੈੱਲ ਟਾਵਰਾਂ ਅਤੇ ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕਾਂ \'ਤੇ ਆਧਾਰਿਤ ਤੁਹਾਡਾ ਟਿਕਾਣਾ ਪਤਾ ਕਰ ਸਕਦੀ ਹੈ। ਐਪ ਦੁਆਰਾ ਟਿਕਾਣਾ ਸੇਵਾਵਾਂ ਦੀ ਵਰਤੋਂ ਕੀਤੇ ਜਾਣ ਦੇ ਯੋਗ ਹੋਣ ਲਈ ਇਹ ਸੇਵਾਵਾਂ ਤੁਹਾਡੇ ਟੈਬਲੈੱਟ \'ਤੇ ਉਪਲਬਧ ਹੋਣੀਆਂ ਅਤੇ ਚਾਲੂ ਕੀਤੀਆਂ ਹੋਣੀਆਂ ਲਾਜ਼ਮੀ ਹਨ।"</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"ਇਹ ਐਪ ਨੈੱਟਵਰਕ ਸਰੋਤਾਂ ਜਿਵੇਂ ਕਿ ਸੈੱਲ ਟਾਵਰਾਂ ਅਤੇ ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕਾਂ \'ਤੇ ਆਧਾਰਿਤ ਤੁਹਾਡਾ ਟਿਕਾਣਾ ਪਤਾ ਕਰ ਸਕਦੀ ਹੈ। ਐਪ ਵੱਲੋਂ ਟਿਕਾਣਾ ਸੇਵਾਵਾਂ ਦੀ ਵਰਤੋਂ ਕੀਤੇ ਜਾਣ ਦੇ ਯੋਗ ਹੋਣ ਲਈ ਇਹ ਸੇਵਾਵਾਂ ਤੁਹਾਡੇ ਟੀਵੀ \'ਤੇ ਉਪਲਬਧ ਹੋਣੀਆਂ ਅਤੇ ਚਾਲੂ ਕੀਤੀਆਂ ਹੋਣੀਆਂ ਲਾਜ਼ਮੀ ਹਨ।"</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"ਇਹ ਐਪ ਨੈੱਟਵਰਕ ਸਰੋਤਾਂ ਜਿਵੇਂ ਕਿ ਸੈੱਲ ਟਾਵਰਾਂ ਅਤੇ ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕਾਂ \'ਤੇ ਆਧਾਰਿਤ ਤੁਹਾਡਾ ਟਿਕਾਣਾ ਪਤਾ ਕਰ ਸਕਦੀ ਹੈ। ਐਪ ਵੱਲੋਂ ਟਿਕਾਣਾ ਸੇਵਾਵਾਂ ਦੀ ਵਰਤੋਂ ਕੀਤੇ ਜਾਣ ਦੇ ਯੋਗ ਹੋਣ ਲਈ ਇਹ ਸੇਵਾਵਾਂ ਤੁਹਾਡੇ ਫ਼ੋਨ \'ਤੇ ਉਪਲਬਧ ਹੋਣੀਆਂ ਅਤੇ ਚਾਲੂ ਕੀਤੀਆਂ ਹੋਣੀਆਂ ਲਾਜ਼ਮੀ ਹਨ।"</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"ਬੈਕਗ੍ਰਾਉਂਡ ਵਿੱਚ ਸਟੀਕ ਟਿਕਾਣੇ ਤੱਕ ਪਹੁੰਚ ਕਰੋ"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"ਇਹ ਐਪ ਬੈਕਗ੍ਰਾਉਂਡ ਵਿੱਚ ਹੋਣ \'ਤੇ ਕਿਸੇ ਵੇਲੇ ਵੀ ਤੁਹਾਡਾ ਸਟੀਕ ਟਿਕਾਣਾ ਪਤਾ ਕਰ ਸਕਦੀ ਹੈ। ਐਪ ਵੱਲੋਂ ਟਿਕਾਣਾ ਸੇਵਾਵਾਂ ਦੀ ਵਰਤੋਂ ਕਰਨ ਲਈ ਇਹ ਸੇਵਾਵਾਂ ਤੁਹਾਡੇ ਫ਼ੋਨ \'ਤੇ ਉਪਲਬਧ ਹੋਣੀਆਂ ਅਤੇ ਚਾਲੂ ਕੀਤੀਆਂ ਹੋਣੀਆਂ ਲਾਜ਼ਮੀ ਹਨ। ਇਸ ਨਾਲ ਬੈਟਰੀ ਦੀ ਖਪਤ ਵਧ ਸਕਦੀ ਹੈ।"</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"ਬੈਕਗ੍ਰਾਊਂਡ ਵਿੱਚ ਟਿਕਾਣੇ ਤੱਕ ਪਹੁੰਚ"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"ਐਪ ਨੂੰ ਵਧੀਕ ਤੌਰ \'ਤੇ ਅਨੁਮਾਨਿਤ ਜਾਂ ਸਟੀਕ ਟਿਕਾਣੇ ਤੱਕ ਪਹੁੰਚ ਦੇਣ \'ਤੇ ਇਹ ਬੈਕਗ੍ਰਾਊਂਡ ਵਿੱਚ ਚੱਲਣ ਵੇਲੇ ਟਿਕਾਣੇ ਤੱਕ ਪਹੁੰਚ ਕਰ ਸਕਦੀ ਹੈ।"</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"ਆਪਣੀਆਂ ਆਡੀਓ ਸੈਟਿੰਗਾਂ ਬਦਲੋ"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"ਐਪ ਨੂੰ ਗਲੋਬਲ ਆਡੀਓ ਸੈਟਿੰਗਾਂ ਸੰਸ਼ੋਧਿਤ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ ਜਿਵੇਂ ਅਵਾਜ਼ ਅਤੇ ਆਊਟਪੁਟ ਲਈ ਕਿਹੜਾ ਸਪੀਕਰ ਵਰਤਿਆ ਜਾਂਦਾ ਹੈ।"</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">" ਆਡੀਓ  ਰਿਕਾਰਡ ਕਰਨ"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"ਇਹ ਐਪ ਕਿਸੇ ਵੀ ਸਮੇਂ ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਦੀ ਵਰਤੋਂ ਕਰਕੇ  ਆਡੀਓ  ਫ਼ਾਈਲ ਰਿਕਾਰਡ ਕਰ ਸਕਦੀ ਹੈ।"</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"SIM ਨੂੰ ਕਮਾਂਡਾਂ ਭੇਜੋ"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"ਐਪ ਨੂੰ SIM ਨੂੰ ਕਮਾਂਡਾਂ ਭੇਜਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਹ ਬਹੁਤ ਘਾਤਕ ਹੈ।"</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"ਸਰੀਰਕ ਸਰਗਰਮੀ ਨੂੰ ਪਛਾਣਨਾ"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"ਇਹ ਐਪ ਤੁਹਾਡੀ ਸਰੀਰਕ ਸਰਗਰਮੀ ਨੂੰ ਪਛਾਣ ਸਕਦੀ ਹੈ।"</string>
     <string name="permlab_camera" msgid="3616391919559751192">"ਤਸਵੀਰਾਂ ਅਤੇ ਵੀਡੀਓ ਬਣਾਓ"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"ਇਹ ਐਪ ਕਿਸੇ ਵੀ ਸਮੇਂ ਕੈਮਰੇ ਨੂੰ ਵਰਤ ਕੇ ਤਸਵੀਰਾਂ ਖਿੱਚ ਸਕਦੀ ਹੈ ਅਤੇ ਵੀਡੀਓ ਫ਼ਾਈਲਾਂ ਰਿਕਾਰਡ ਕਰ ਸਕਦੀ ਹੈ।"</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"ਵਾਈਬ੍ਰੇਸ਼ਨ ਤੇ ਨਿਯੰਤਰਣ ਪਾਓ"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"ਐਪ ਨੂੰ ਤੁਹਾਡੇ ਫ਼ੋਟੋ ਸੰਗ੍ਰਹਿ ਨੂੰ ਸੋਧਣ ਦਿੰਦੀ ਹੈ।"</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"ਤੁਹਾਡੇ ਮੀਡੀਆ ਸੰਗ੍ਰਹਿ ਦੇ ਟਿਕਾਣਿਆਂ ਨੂੰ ਪੜ੍ਹਨਾ"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"ਐਪ ਨੂੰ ਤੁਹਾਡੇ ਮੀਡੀਆ ਸੰਗ੍ਰਹਿ ਦੇ ਟਿਕਾਣਿਆਂ ਨੂੰ ਪੜ੍ਹਨ ਦਿੰਦੀ ਹੈ।"</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"ਐਪਲੀਕੇਸ਼ਨ <xliff:g id="APP">%s</xliff:g> ਪ੍ਰਮਾਣੀਕਰਨ ਕਰਨਾ ਚਾਹੁੰਦੀ ਹੈ।"</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"ਬਾਇਓਮੈਟ੍ਰਿਕ ਹਾਰਡਵੇਅਰ ਉਪਲਬਧ ਨਹੀਂ ਹੈ"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"ਅਧੂਰਾ ਫਿੰਗਰਪ੍ਰਿਟ ਮਿਲਿਆ। ਕਿਰਪਾ ਕਰਕੇ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਦੀ ਪ੍ਰਕਿਰਿਆ ਨਹੀਂ ਕਰ ਸਕਿਆ। ਕਿਰਪਾ ਕਰਕੇ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
@@ -1874,7 +1880,7 @@
     <string name="conference_call" msgid="3751093130790472426">"ਕਾਨਫਰੰਸ ਕਾਲ"</string>
     <string name="tooltip_popup_title" msgid="5253721848739260181">"ਟੂਲ-ਟਿੱਪ"</string>
     <string name="app_category_game" msgid="5431836943981492993">"ਗੇਮਾਂ"</string>
-    <string name="app_category_audio" msgid="1659853108734301647">"ਸੰਗੀਤ ਅਤੇ  ਆਡੀਓ"</string>
+    <string name="app_category_audio" msgid="1659853108734301647">"ਸੰਗੀਤ ਅਤੇ ਆਡੀਓ"</string>
     <string name="app_category_video" msgid="2728726078629384196">"ਮੂਵੀਆਂ ਅਤੇ ਵੀਡੀਓ"</string>
     <string name="app_category_image" msgid="4867854544519846048">"ਫ਼ੋਟੋਆਂ ਅਤੇ ਚਿੱਤਰ"</string>
     <string name="app_category_social" msgid="5842783057834965912">"ਸਮਾਜਕ ਅਤੇ ਸੰਚਾਰ"</string>
@@ -1898,14 +1904,14 @@
       <item quantity="one"><xliff:g id="COUNT">%1$s</xliff:g> ਆਟੋਫਿਲ ਸੁਝਾਅ</item>
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> ਆਟੋਫਿਲ ਸੁਝਾਅ</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"ਕੀ &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; ਵਿੱਚ ਰੱਖਿਅਤ ਕਰਨਾ ਹੈ?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"ਕੀ <xliff:g id="TYPE">%1$s</xliff:g> ਨੂੰ &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; ਵਿੱਚ ਰੱਖਿਅਤ ਕਰਨਾ ਹੈ?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"ਕੀ <xliff:g id="TYPE_0">%1$s</xliff:g> ਅਤੇ <xliff:g id="TYPE_1">%2$s</xliff:g> ਨੂੰ &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; ਵਿੱਚ ਰੱਖਿਅਤ ਕਰਨਾ ਹੈ?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"ਕੀ <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, ਅਤੇ <xliff:g id="TYPE_2">%3$s</xliff:g> ਨੂੰ &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; ਵਿੱਚ ਰੱਖਿਅਤ ਕਰਨਾ ਹੈ?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"ਕੀ &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; ਵਿੱਚ ਅੱਪਡੇਟ ਕਰਨਾ ਹੈ?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"ਕੀ <xliff:g id="TYPE">%1$s</xliff:g> ਨੂੰ &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; ਵਿੱਚ ਅੱਪਡੇਟ ਕਰਨਾ ਹੈ?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"ਕੀ <xliff:g id="TYPE_0">%1$s</xliff:g> ਅਤੇ <xliff:g id="TYPE_1">%2$s</xliff:g> ਨੂੰ &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; ਵਿੱਚ ਅੱਪਡੇਟ ਕਰਨਾ ਹੈ?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"ਕੀ <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ਅਤੇ <xliff:g id="TYPE_2">%3$s</xliff:g> ਨੂੰ &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; ਵਿੱਚ ਅੱਪਡੇਟ ਕਰਨਾ ਹੈ?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"ਕੀ ਤੁਸੀਂ "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" ਵਿੱਚ ਰੱਖਿਅਤ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"ਕੀ ਤੁਸੀਂ "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" ਵਿੱਚ <xliff:g id="TYPE">%1$s</xliff:g> ਨੂੰ ਰੱਖਿਅਤ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"ਕੀ ਤੁਸੀਂ "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" ਵਿੱਚ <xliff:g id="TYPE_0">%1$s</xliff:g> ਅਤੇ <xliff:g id="TYPE_1">%2$s</xliff:g> ਨੂੰ ਰੱਖਿਅਤ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"ਕੀ ਤੁਸੀਂ "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" ਵਿੱਚ <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ਅਤੇ <xliff:g id="TYPE_2">%3$s</xliff:g> ਨੂੰ ਰੱਖਿਅਤ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"ਕੀ ਤੁਸੀਂ "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" ਵਿੱਚ ਅੱਪਡੇਟ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"ਕੀ ਤੁਸੀਂ "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" ਵਿੱਚ <xliff:g id="TYPE">%1$s</xliff:g> ਨੂੰ ਅੱਪਡੇਟ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"ਕੀ ਤੁਸੀਂ "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" ਵਿੱਚ <xliff:g id="TYPE_0">%1$s</xliff:g> ਅਤੇ <xliff:g id="TYPE_1">%2$s</xliff:g> ਨੂੰ ਅੱਪਡੇਟ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"ਕੀ ਤੁਸੀਂ "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" ਵਿੱਚ ਇਹਨਾਂ ਆਈਟਮਾਂ ਨੂੰ ਅੱਪਡੇਟ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ: <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, ਅਤੇ <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"ਰੱਖਿਅਤ ਕਰੋ"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"ਨਹੀਂ ਧੰਨਵਾਦ"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"ਅੱਪਡੇਟ ਕਰੋ"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 81a869a..7ef4907 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -298,6 +298,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Mikrofon"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"nagrywanie dźwięku"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"Zezwolić aplikacji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na nagrywanie dźwięku?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"Rozpoznawanie aktywności"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"rozpoznawanie aktywności"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"Zezwolić aplikacji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na rozpoznawanie Twojej aktywności fizycznej?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Aparat"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"robienie zdjęć i nagrywanie filmów"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"Zezwolić aplikacji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na robienie zdjęć i nagrywanie filmów?"</string>
@@ -424,14 +427,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Ta aplikacja może określać Twoją lokalizację na podstawie źródeł sieciowych, takich jak stacje bazowe i sieci Wi-Fi. Te usługi lokalizacyjne muszą być włączone i dostępne na tablecie, by aplikacja mogła z nich korzystać."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Ta aplikacja może określać Twoją lokalizację na podstawie źródeł sieciowych, takich jak stacje bazowe i sieci Wi-Fi. Te usługi lokalizacyjne muszą być włączone i dostępne na telewizorze, by aplikacja mogła z nich korzystać."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Ta aplikacja może określać Twoją lokalizację na podstawie źródeł sieciowych, takich jak stacje bazowe i sieci Wi-Fi. Te usługi lokalizacyjne muszą być włączone i dostępne na telefonie, by aplikacja mogła z nich korzystać."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"dostęp do dokładnej lokalizacji w tle"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"Ta aplikacja może określić Twoją dokładną lokalizację w dowolnym momencie, działając w tle. Te usługi lokalizacyjne muszą być włączone i dostępne na telefonie, by aplikacja mogła z nich korzystać. Może to zwiększyć zużycie baterii."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"dostęp do lokalizacji w tle"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Jeśli te uprawnienia zostaną przyznane wraz z dostępem do dokładnej lub przybliżonej lokalizacji, aplikacja będzie mogła uzyskiwać dostęp do lokalizacji podczas działania w tle."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"zmienianie ustawień audio"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Pozwala aplikacji na modyfikowanie globalnych ustawień dźwięku, takich jak głośność oraz urządzenie wyjściowe."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"nagrywanie dźwięku"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"Ta aplikacja może w dowolnym momencie nagrać dźwięk przez mikrofon."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"wysyłanie poleceń do karty SIM"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Pozwala aplikacji na wysyłanie poleceń do karty SIM. To bardzo niebezpieczne."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"rozpoznawanie aktywności fizycznej"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"Ta aplikacja może rozpoznawać Twoją aktywność fizyczną."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"wykonywanie zdjęć i filmów wideo"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"Ta aplikacja może w dowolnym momencie robić zdjęcia i nagrywać filmy przy użyciu aparatu."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"sterowanie wibracjami"</string>
@@ -524,6 +529,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Zezwala aplikacji na modyfikowanie kolekcji zdjęć."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"odczytywanie lokalizacji z kolekcji multimediów"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Zezwala aplikacji na odczytywanie lokalizacji z kolekcji multimediów."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"Aplikacja <xliff:g id="APP">%s</xliff:g> wymaga uwierzytelnienia."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Sprzęt biometryczny niedostępny"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Odcisk palca został odczytany tylko częściowo. Spróbuj ponownie."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Nie udało się przetworzyć odcisku palca. Spróbuj ponownie."</string>
@@ -1967,14 +1973,14 @@
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> sugestii autouzupełniania</item>
       <item quantity="one">Jedna sugestia autouzupełniania</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"Zapisać w: &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"<xliff:g id="TYPE">%1$s</xliff:g> – zapisać w: &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"<xliff:g id="TYPE_0">%1$s</xliff:g> i <xliff:g id="TYPE_1">%2$s</xliff:g> – zapisać w: &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> i <xliff:g id="TYPE_2">%3$s</xliff:g> – zapisać w: &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"Zaktualizować do &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Zaktualizować <xliff:g id="TYPE">%1$s</xliff:g> do &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Zaktualizować <xliff:g id="TYPE_0">%1$s</xliff:g> i <xliff:g id="TYPE_1">%2$s</xliff:g> do &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Zaktualizować <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, i <xliff:g id="TYPE_2">%3$s</xliff:g> do &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"Zapisać w: "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"Zapisać: <xliff:g id="TYPE">%1$s</xliff:g> w "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"Zapisać: <xliff:g id="TYPE_0">%1$s</xliff:g> i <xliff:g id="TYPE_1">%2$s</xliff:g> w: "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"Zapisać: <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> i <xliff:g id="TYPE_2">%3$s</xliff:g> w: "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"Zaktualizować w: "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"Zaktualizować: <xliff:g id="TYPE">%1$s</xliff:g> w: "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"Zaktualizować: <xliff:g id="TYPE_0">%1$s</xliff:g> i <xliff:g id="TYPE_1">%2$s</xliff:g> w: "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"Zaktualizować w: "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" te elementy: <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> i <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Zapisz"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Nie, dziękuję"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"Zaktualizuj"</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index 5ac7c2e..5ab4fce 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Microfone"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"grave áudio"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; grave áudio?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"Reconhecimento de atividade"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"reconhecer atividade"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"Permitir que o &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; reconheça sua atividade física?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Câmera"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"tire fotos e grave vídeos"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tire fotos e grave vídeos?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Este app pode ver seu local com base nas fontes de rede, como torres de celular e redes Wi-Fi. Esses serviços de localização precisam estar ativados e disponíveis no seu tablet para que o app possa usá-los."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Este app pode ver seu local com base nas fontes de rede, como torres de celular e redes Wi-Fi. Esses serviços de localização precisam estar ativados e disponíveis na sua TV para que o app possa usá-los."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Este app pode ver seu local com base nas fontes de rede, como torres de celular e redes Wi-Fi. Esses serviços de localização precisam estar ativados e disponíveis no seu smartphone para que o app possa usá-los."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"acessar localização precisa em segundo plano"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"Este app pode ver sua localização exata a qualquer momento quando está em segundo plano. Esses serviços de localização precisam estar ativados e disponíveis no seu smartphone para que o app possa usá-los. Isso pode aumentar o consumo de bateria."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"acessar a localização em segundo plano"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Se essa permissão for concedida, além do acesso à localização precisa ou aproximada, o app poderá acessar a localização durante a execução em segundo plano."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"alterar as suas configurações de áudio"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Permite que o app modifique configurações de áudio globais como volume e alto-falantes de saída."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"gravar áudio"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"Este app pode gravar áudio usando o microfone a qualquer momento."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"enviar comandos para o chip"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Permite que o app envie comandos ao chip. Muito perigoso."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"reconhecer atividade física"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"Este app pode reconhecer sua atividade física."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"tirar fotos e gravar vídeos"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"Este app pode tirar fotos e gravar vídeos usando a câmera a qualquer momento."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"controlar vibração"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Permite que o app modifique sua coleção de fotos."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"ler locais na sua coleção de mídias"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Permite que o app leia os locais na sua coleção de mídias."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"O app <xliff:g id="APP">%s</xliff:g> está solicitando autenticação."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Hardware biométrico indisponível"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Impressão digital parcial detectada. Tente novamente."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Não foi possível processar a impressão digital. Tente novamente."</string>
@@ -1826,7 +1832,7 @@
     <string name="usb_midi_peripheral_manufacturer_name" msgid="7176526170008970168">"Android"</string>
     <string name="usb_midi_peripheral_product_name" msgid="4971827859165280403">"Porta USB periférica"</string>
     <string name="floating_toolbar_open_overflow_description" msgid="4797287862999444631">"Mais opções"</string>
-    <string name="floating_toolbar_close_overflow_description" msgid="559796923090723804">"Fechar barra flutuante"</string>
+    <string name="floating_toolbar_close_overflow_description" msgid="559796923090723804">"Fechar menu flutuante"</string>
     <string name="maximize_button_text" msgid="7543285286182446254">"Maximizar"</string>
     <string name="close_button_text" msgid="3937902162644062866">"Fechar"</string>
     <string name="notification_messaging_title_template" msgid="3452480118762691020">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
@@ -1897,14 +1903,14 @@
       <item quantity="one"><xliff:g id="COUNT">%1$s</xliff:g> sugestão de preenchimento automático</item>
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> sugestões de preenchimento automático</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"Salvar em &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Salvar <xliff:g id="TYPE">%1$s</xliff:g> em &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Salvar <xliff:g id="TYPE_0">%1$s</xliff:g> e <xliff:g id="TYPE_1">%2$s</xliff:g> em &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Salvar <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> e <xliff:g id="TYPE_2">%3$s</xliff:g> em &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"Atualizar no &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Atualizar <xliff:g id="TYPE">%1$s</xliff:g> no &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Atualizar <xliff:g id="TYPE_0">%1$s</xliff:g> e <xliff:g id="TYPE_1">%2$s</xliff:g> no &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Atualizar <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> e <xliff:g id="TYPE_2">%3$s</xliff:g> no &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"Salvar em "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"Salvar <xliff:g id="TYPE">%1$s</xliff:g> em "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"Salvar <xliff:g id="TYPE_0">%1$s</xliff:g> e <xliff:g id="TYPE_1">%2$s</xliff:g> em "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"Salvar <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> e <xliff:g id="TYPE_2">%3$s</xliff:g> em "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"Atualizar em "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"Atualizar <xliff:g id="TYPE">%1$s</xliff:g> em "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"Atualizar <xliff:g id="TYPE_0">%1$s</xliff:g> e <xliff:g id="TYPE_1">%2$s</xliff:g> em "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"Atualizar estes itens em "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> e <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Salvar"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Não, obrigado"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"Atualizar"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 52f067f..ec853bb 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Microfone"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"gravar áudio"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"Pretende permitir que a aplicação &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; grave áudio?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"Reconhecimento da atividade"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"reconhecer a atividade"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"Pretende permitir que a aplicação &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; reconheça a sua atividade física?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Câmara"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"tirar fotos e gravar vídeos"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"Pretende permitir que a aplicação &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tire fotos e grave vídeo?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Esta aplicação pode obter a sua localização com base em fontes de rede, tais como torres de redes móveis e redes Wi-Fi. É necessário que estes serviços de localização estejam ativados e disponíveis no seu tablet para que a aplicação os possa utilizar."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Esta aplicação pode obter a sua localização com base em fontes de rede, tais como torres de redes móveis e redes Wi-Fi. É necessário que estes serviços de localização estejam ativados e disponíveis na sua TV para que a aplicação os possa utilizar."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Esta aplicação pode obter a sua localização com base em fontes de rede, tais como torres de redes móveis e redes Wi-Fi. É necessário que estes serviços de localização estejam ativados e disponíveis no seu telemóvel para que a aplicação os possa utilizar."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"aceder à localização exata em segundo plano"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"Esta aplicação pode obter a sua localização exata sempre que estiver em segundo plano. É necessário que estes Serviços de localização estejam ativados e disponíveis no seu telemóvel para que a aplicação os possa utilizar. Esta ação pode aumentar o consumo da bateria."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"aceder à localização em segundo plano"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Se tal for concedido em conjunto com o acesso à localização aproximada ou exata, a aplicação pode aceder à localização mesmo estando em segundo plano."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"alterar as suas definições de áudio"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Permite que a aplicação modifique definições de áudio globais, tais como o volume e qual o altifalante utilizado para a saída de som."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"gravar áudio"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"Esta aplicação pode gravar áudio através do microfone em qualquer altura."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"enviar comandos para o SIM"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Permite que a aplicação envie comandos para o SIM. Esta ação é muito perigosa."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"reconhecer a atividade física"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"Esta aplicação consegue reconhecer a sua atividade física."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"tirar fotos e vídeos"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"Esta aplicação pode tirar fotos e gravar vídeos através da câmara em qualquer altura."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"controlar vibração"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Permite que a aplicação modifique a sua coleção de fotos."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"ler as localizações a partir da sua coleção de multimédia"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Permite que a aplicação leia as localizações a partir da sua coleção de multimédia."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"A aplicação <xliff:g id="APP">%s</xliff:g> pretende uma autenticação"</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Hardware biométrico indisponível."</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Impressão digital detetada. Tente novamente."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Não foi possível processar a impressão digital. Tente novamente."</string>
@@ -1897,14 +1903,14 @@
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> sugestões do preenchimento automático</item>
       <item quantity="one">Uma sugestão do preenchimento automático</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"Pretende guardar no &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Pretende guardar <xliff:g id="TYPE">%1$s</xliff:g> no &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Pretende guardar <xliff:g id="TYPE_0">%1$s</xliff:g> e <xliff:g id="TYPE_1">%2$s</xliff:g> no &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Pretende guardar <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> e <xliff:g id="TYPE_2">%3$s</xliff:g> no &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"Pretende atualizar para o &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Pretende atualizar <xliff:g id="TYPE">%1$s</xliff:g> para o &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Pretende atualizar <xliff:g id="TYPE_0">%1$s</xliff:g> e <xliff:g id="TYPE_1">%2$s</xliff:g> para o &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Pretende atualizar <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> e <xliff:g id="TYPE_2">%3$s</xliff:g> para o &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"Pretende guardar em "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"Pretende guardar <xliff:g id="TYPE">%1$s</xliff:g> em "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"Pretende guardar <xliff:g id="TYPE_0">%1$s</xliff:g> e <xliff:g id="TYPE_1">%2$s</xliff:g> em "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"Pretende guardar <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> e <xliff:g id="TYPE_2">%3$s</xliff:g> em "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"Pretende atualizar em "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"Pretende atualizar <xliff:g id="TYPE">%1$s</xliff:g> em "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"Pretende atualizar <xliff:g id="TYPE_0">%1$s</xliff:g> e <xliff:g id="TYPE_1">%2$s</xliff:g> em "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"Pretende atualizar estes itens em "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> e <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Guardar"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Não, obrigado"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"Atualizar"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 5ac7c2e..5ab4fce 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Microfone"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"grave áudio"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; grave áudio?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"Reconhecimento de atividade"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"reconhecer atividade"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"Permitir que o &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; reconheça sua atividade física?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Câmera"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"tire fotos e grave vídeos"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"Permitir que &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; tire fotos e grave vídeos?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Este app pode ver seu local com base nas fontes de rede, como torres de celular e redes Wi-Fi. Esses serviços de localização precisam estar ativados e disponíveis no seu tablet para que o app possa usá-los."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Este app pode ver seu local com base nas fontes de rede, como torres de celular e redes Wi-Fi. Esses serviços de localização precisam estar ativados e disponíveis na sua TV para que o app possa usá-los."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Este app pode ver seu local com base nas fontes de rede, como torres de celular e redes Wi-Fi. Esses serviços de localização precisam estar ativados e disponíveis no seu smartphone para que o app possa usá-los."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"acessar localização precisa em segundo plano"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"Este app pode ver sua localização exata a qualquer momento quando está em segundo plano. Esses serviços de localização precisam estar ativados e disponíveis no seu smartphone para que o app possa usá-los. Isso pode aumentar o consumo de bateria."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"acessar a localização em segundo plano"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Se essa permissão for concedida, além do acesso à localização precisa ou aproximada, o app poderá acessar a localização durante a execução em segundo plano."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"alterar as suas configurações de áudio"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Permite que o app modifique configurações de áudio globais como volume e alto-falantes de saída."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"gravar áudio"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"Este app pode gravar áudio usando o microfone a qualquer momento."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"enviar comandos para o chip"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Permite que o app envie comandos ao chip. Muito perigoso."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"reconhecer atividade física"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"Este app pode reconhecer sua atividade física."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"tirar fotos e gravar vídeos"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"Este app pode tirar fotos e gravar vídeos usando a câmera a qualquer momento."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"controlar vibração"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Permite que o app modifique sua coleção de fotos."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"ler locais na sua coleção de mídias"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Permite que o app leia os locais na sua coleção de mídias."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"O app <xliff:g id="APP">%s</xliff:g> está solicitando autenticação."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Hardware biométrico indisponível"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Impressão digital parcial detectada. Tente novamente."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Não foi possível processar a impressão digital. Tente novamente."</string>
@@ -1826,7 +1832,7 @@
     <string name="usb_midi_peripheral_manufacturer_name" msgid="7176526170008970168">"Android"</string>
     <string name="usb_midi_peripheral_product_name" msgid="4971827859165280403">"Porta USB periférica"</string>
     <string name="floating_toolbar_open_overflow_description" msgid="4797287862999444631">"Mais opções"</string>
-    <string name="floating_toolbar_close_overflow_description" msgid="559796923090723804">"Fechar barra flutuante"</string>
+    <string name="floating_toolbar_close_overflow_description" msgid="559796923090723804">"Fechar menu flutuante"</string>
     <string name="maximize_button_text" msgid="7543285286182446254">"Maximizar"</string>
     <string name="close_button_text" msgid="3937902162644062866">"Fechar"</string>
     <string name="notification_messaging_title_template" msgid="3452480118762691020">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
@@ -1897,14 +1903,14 @@
       <item quantity="one"><xliff:g id="COUNT">%1$s</xliff:g> sugestão de preenchimento automático</item>
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> sugestões de preenchimento automático</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"Salvar em &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Salvar <xliff:g id="TYPE">%1$s</xliff:g> em &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Salvar <xliff:g id="TYPE_0">%1$s</xliff:g> e <xliff:g id="TYPE_1">%2$s</xliff:g> em &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Salvar <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> e <xliff:g id="TYPE_2">%3$s</xliff:g> em &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"Atualizar no &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Atualizar <xliff:g id="TYPE">%1$s</xliff:g> no &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Atualizar <xliff:g id="TYPE_0">%1$s</xliff:g> e <xliff:g id="TYPE_1">%2$s</xliff:g> no &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Atualizar <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> e <xliff:g id="TYPE_2">%3$s</xliff:g> no &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"Salvar em "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"Salvar <xliff:g id="TYPE">%1$s</xliff:g> em "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"Salvar <xliff:g id="TYPE_0">%1$s</xliff:g> e <xliff:g id="TYPE_1">%2$s</xliff:g> em "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"Salvar <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> e <xliff:g id="TYPE_2">%3$s</xliff:g> em "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"Atualizar em "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"Atualizar <xliff:g id="TYPE">%1$s</xliff:g> em "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"Atualizar <xliff:g id="TYPE_0">%1$s</xliff:g> e <xliff:g id="TYPE_1">%2$s</xliff:g> em "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"Atualizar estes itens em "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> e <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Salvar"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Não, obrigado"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"Atualizar"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 0c945f7..7c4a571 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -295,6 +295,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Microfon"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"înregistreze sunet"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"Pemiteți &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; să înregistreze conținut audio?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"Recunoașterea activității"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"recunoașterea activității"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"Permiteți aplicației &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; să vă recunoască activitatea fizică?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Camera foto"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"fotografieze și să înregistreze videoclipuri"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"Permiteți &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; să facă fotografii și să înregistreze videoclipuri?"</string>
@@ -421,14 +424,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Această aplicație vă poate obține locația cu ajutorul surselor rețelei, cum ar fi turnurile de telefonie mobilă și rețelele Wi-Fi. Aceste servicii de localizare trebuie să fie activate și disponibile pe tabletă pentru ca aplicația să le poată folosi."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Această aplicație vă poate obține locația cu ajutorul surselor rețelei, cum ar fi turnurile de telefonie mobilă și rețelele Wi-Fi. Aceste servicii de localizare trebuie să fie activate și disponibile pe televizor pentru ca aplicația să le poată folosi."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Această aplicație vă poate obține locația cu ajutorul surselor rețelei, cum ar fi turnurile de telefonie mobilă și rețelele Wi-Fi. Aceste servicii de localizare trebuie să fie activate și disponibile pe telefon pentru ca aplicația să le poată folosi."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"să acceseze locația exactă în fundal"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"Aplicația vă poate obține locația exactă ori de câte ori rulează în fundal. Serviciile de localizare trebuie să fie activate și disponibile pe telefon pentru ca aplicația să le poată folosi. Acest lucru poate accelera descărcarea bateriei."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"accesați locația în fundal"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Dacă se acordă în plus față de accesul la locație aproximativă sau exactă, aplicația poate accesa locația în timp ce rulează în fundal."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"modificare setări audio"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Permite aplicației să modifice setările audio globale, cum ar fi volumul și difuzorul care este utilizat pentru ieșire."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"înregistreze sunet"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"Această aplicație poate înregistra conținut audio folosind microfonul în orice moment."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"să trimită comenzi către SIM"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Permite aplicației să trimită comenzi pe cardul SIM. Această permisiune este foarte periculoasă."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"recunoașterea activității fizice"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"Această aplicație vă poate recunoaște activitatea fizică."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"realizarea de fotografii și videoclipuri"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"Această aplicație poate să facă fotografii și să înregistreze videoclipuri folosind camera foto în orice moment."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"controlează vibrarea"</string>
@@ -521,6 +526,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Permite aplicației să vă modifice colecția de fotografii."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"citiți locațiile din colecția media"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Permite aplicației să citească locațiile din colecția dvs. media."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"Aplicația <xliff:g id="APP">%s</xliff:g> dorește să se autentifice."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Hardware biometric indisponibil"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"S-a detectat parțial amprenta. Încercați din nou."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Amprenta nu a putut fi procesată. Încercați din nou."</string>
@@ -639,9 +645,9 @@
     <string name="permdesc_bindCarrierServices" msgid="1391552602551084192">"Permite aplicației să se conecteze la serviciile operatorului. Nu ar trebui să fie niciodată necesară pentru aplicațiile obișnuite."</string>
     <string name="permlab_access_notification_policy" msgid="4247510821662059671">"accesează Nu deranja"</string>
     <string name="permdesc_access_notification_policy" msgid="3296832375218749580">"Permite aplicației să citească și să scrie configurația Nu deranja."</string>
-    <string name="policylab_limitPassword" msgid="4497420728857585791">"Setați reguli pentru parolă"</string>
+    <string name="policylab_limitPassword" msgid="4497420728857585791">"Să seteze reguli pentru parolă"</string>
     <string name="policydesc_limitPassword" msgid="2502021457917874968">"Stabiliți lungimea și tipul de caractere permise pentru parolele și codurile PIN de blocare a ecranului."</string>
-    <string name="policylab_watchLogin" msgid="5091404125971980158">"Monitorizați încercările de deblocare a ecranului"</string>
+    <string name="policylab_watchLogin" msgid="5091404125971980158">"Să monitorizeze încercările de deblocare a ecranului"</string>
     <string name="policydesc_watchLogin" product="tablet" msgid="3215729294215070072">"Monitorizați numărul de parole incorecte introduse la deblocarea ecranului și blocați tableta sau ștergeți datele acesteia dacă sunt introduse prea multe parole incorecte."</string>
     <string name="policydesc_watchLogin" product="TV" msgid="2707817988309890256">"Monitorizați numărul de parole incorecte introduse la deblocarea ecranului și blocați televizorul sau ștergeți toate datele acestuia dacă sunt introduse prea multe parole incorecte."</string>
     <string name="policydesc_watchLogin" product="default" msgid="5712323091846761073">"Monitorizați numărul de parole incorecte introduse la deblocarea ecranului și blocați telefonul sau ștergeți toate datele acestuia dacă sunt introduse prea multe parole incorecte."</string>
@@ -664,9 +670,9 @@
     <string name="policydesc_setGlobalProxy" msgid="8459859731153370499">"Setați serverul proxy global pentru dispozitiv, care să fie utilizat cât timp politica este activă. Numai proprietarul dispozitivului poate seta serverul proxy global."</string>
     <string name="policylab_expirePassword" msgid="5610055012328825874">"Setați expirarea parolei pentru blocarea ecranului"</string>
     <string name="policydesc_expirePassword" msgid="5367525762204416046">"Modificați frecvența cu care trebuie să se schimbe parola, codul PIN sau modelul pentru blocarea ecranului."</string>
-    <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Setați criptarea stocării"</string>
+    <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Să seteze criptarea stocării"</string>
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"Necesită ca datele aplicației stocate să fie criptate."</string>
-    <string name="policylab_disableCamera" msgid="6395301023152297826">"Dezactivați camerele foto"</string>
+    <string name="policylab_disableCamera" msgid="6395301023152297826">"Să dezactiveze camerele foto"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"Împiedicați utilizarea camerelor foto de pe dispozitiv."</string>
     <string name="policylab_disableKeyguardFeatures" msgid="8552277871075367771">"Să oprească funcții de blocare ecran"</string>
     <string name="policydesc_disableKeyguardFeatures" msgid="2044755691354158439">"Împiedicați folosirea unor funcții de blocare a ecranului."</string>
@@ -1932,14 +1938,14 @@
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> de sugestii de completare automată</item>
       <item quantity="one">O sugestie de completare automată</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"Salvați în &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Salvați <xliff:g id="TYPE">%1$s</xliff:g> în &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Salvați <xliff:g id="TYPE_0">%1$s</xliff:g> și <xliff:g id="TYPE_1">%2$s</xliff:g> în &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Salvați <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> și <xliff:g id="TYPE_2">%3$s</xliff:g> în &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"Actualizați la &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Actualizați <xliff:g id="TYPE">%1$s</xliff:g> la &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Actualizați <xliff:g id="TYPE_0">%1$s</xliff:g> și <xliff:g id="TYPE_1">%2$s</xliff:g> la &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Actualizați <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> și <xliff:g id="TYPE_2">%3$s</xliff:g> la &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"Salvați în "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"Salvați <xliff:g id="TYPE">%1$s</xliff:g> în "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"Salvați <xliff:g id="TYPE_0">%1$s</xliff:g> și <xliff:g id="TYPE_1">%2$s</xliff:g> în "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"Salvați <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> și <xliff:g id="TYPE_2">%3$s</xliff:g> în "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"Actualizați în "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"Actualizați <xliff:g id="TYPE">%1$s</xliff:g> în "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"Actualizați <xliff:g id="TYPE_0">%1$s</xliff:g> și <xliff:g id="TYPE_1">%2$s</xliff:g> în "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"Actualizați aceste articole în "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> și <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Salvați"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Nu, mulțumesc"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"Actualizați"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index fd70e9c..ece22b1 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -298,6 +298,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Микрофон"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"записывать аудио"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"Разрешить приложению &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; записывать аудио?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"Распознавание активности"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"распознавать активность"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"Разрешить приложению &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; распознавать физическую активность?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Камера"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"снимать фото и видео"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"Разрешить приложению &lt;b&gt;\"<xliff:g id="APP_NAME">%1$s</xliff:g>\"&lt;/b&gt; снимать фото и видео?"</string>
@@ -424,14 +427,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Приложение может получать сведения о вашем местоположении от сетевых источников, таких как вышки сотовой связи и точки доступа Wi-Fi. Необходимо включить соответствующие параметры на планшете и разрешить приложению использовать геоданные."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Приложение может получать сведения о вашем местоположении от сетевых источников, таких как вышки сотовой связи и точки доступа Wi-Fi. Необходимо включить соответствующие параметры на телевизоре и разрешить приложению использовать геоданные."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Приложение может получать сведения о вашем местоположении от сетевых источников, таких как вышки сотовой связи и точки доступа Wi-Fi. Необходимо включить соответствующие параметры на телефоне и разрешить приложению использовать геоданные."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"Доступ к геоданным в фоновом режиме"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"Приложение может получать сведения о вашем точном местоположении в фоновом режиме. Для этого необходимо включить соответствующие параметры на телефоне и разрешить использовать геоданные. Может увеличиться расход заряда батареи."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"доступ к геоданным в фоновом режиме"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Если помимо доступа к данным о точном или приблизительном местоположении вы предоставите это разрешение, приложение сможет получать доступ к геоданным в фоновом режиме."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"Изменение настроек аудио"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Приложение сможет изменять системные настройки звука, например уровень громкости и активный динамик."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"Запись аудио"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"Приложение может в любое время записывать аудио с помощью микрофона."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"Отправка команд SIM-карте"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Приложение сможет отправлять команды SIM-карте (данное разрешение представляет большую угрозу)."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"распознавать физическую активность"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"Приложение может распознавать физическую активность."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"Фото- и видеосъемка"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"Приложение может в любое время делать фотографии и снимать видео с помощью камеры."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"Управление функцией вибросигнала"</string>
@@ -524,6 +529,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Приложение сможет вносить изменения в вашу фотоколлекцию."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"доступ к геоданным в медиаколлекции"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Приложение получит доступ к геоданным в вашей медиаколлекции."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"Приложение \"<xliff:g id="APP">%s</xliff:g>\" запрашивает аутентификацию"</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Биометрическое оборудование недоступно"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Отсканирована только часть пальца. Повторите попытку."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Не удалось распознать отпечаток. Повторите попытку."</string>
@@ -1967,14 +1973,14 @@
       <item quantity="many"><xliff:g id="COUNT">%1$s</xliff:g> вариантов автозаполнения</item>
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> варианта автозаполнения</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"Сохранить в &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Сохранить <xliff:g id="TYPE">%1$s</xliff:g> в &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Сохранить <xliff:g id="TYPE_0">%1$s</xliff:g> и <xliff:g id="TYPE_1">%2$s</xliff:g> в &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Сохранить <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> и <xliff:g id="TYPE_2">%3$s</xliff:g> в &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"Обновить данные в &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Обновить данные (<xliff:g id="TYPE">%1$s</xliff:g>) в &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Обновить данные (<xliff:g id="TYPE_0">%1$s</xliff:g> и <xliff:g id="TYPE_1">%2$s</xliff:g>) в &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Обновить данные (<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> и <xliff:g id="TYPE_2">%3$s</xliff:g>) в &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"Сохранить в сервисе "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"Сохранить данные (<xliff:g id="TYPE">%1$s</xliff:g>) в сервисе "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"Сохранить данные (<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>) в сервисе "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"Сохранить данные (<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g>) в сервисе "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"Обновить в сервисе "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"Обновить данные (<xliff:g id="TYPE">%1$s</xliff:g>) в сервисе "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"Обновить данные (<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>) в сервисе "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"Обновить данные (<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g>) в сервисе "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Сохранить"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Нет, спасибо"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"Обновить"</string>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index 3bd8ceb..ed3d0f5 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"මයික්‍රොෆෝනය"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"ශ්‍රව්‍ය පටිගත කරන්න"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;b&gt; වෙත ශබ්දය පටි ගත කිරීමට ඉඩ දෙන්නද?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"ක්‍රියාකාරකම් හැඳුනුම"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"ක්‍රියාකාරකම හඳුනා ගන්න"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"ඔබේ ශාරීරික ක්‍රියාකාරකම හඳුනා ගැනීමට &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ඉඩ දෙන්නද?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"කැමරාව"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"පින්තූර ගැනීම සහ වීඩියෝ පටිගත කිරීම"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;b&gt; වෙත පින්තූර සහ වීඩියෝ ගැනීමට ඉඩ දෙන්නද?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"මෙම යෙදුමට ජංගම දුරකථන කුළුණු සහ Wi-Fi ජාල වැනි ජාල මූලාශ්‍ර පදනම්ව ඔබගේ ස්ථානය ලබා ගත හැකිය. යෙදුමට ඒවා භාවිත කිරීමට හැකි වීමට මෙම ස්ථාන සේවා ක්‍රියාත්මක කර සහ ඔබේ ටැබ්ලට් පරිගණකය මත ලබා ගත හැකිව තිබිය යුතුය."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"මෙම යෙදුමට ජංගම දුරකථන කුළුණු සහ Wi-Fi ජාල වැනි ජාල මූලාශ්‍ර පදනම්ව ඔබගේ ස්ථානය ලබා ගත හැකිය. යෙදුමට ඒවා භාවිත කිරීමට හැකි වීමට මෙම ස්ථාන සේවා ක්‍රියාත්මක කර සහ ඔබේ TV මත ලබා ගත හැකිව තිබිය යුතුය."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"මෙම යෙදුමට ජංගම දුරකථන කුළුණු සහ Wi-Fi ජාල වැනි ජාල මූලාශ්‍ර පදනම්ව ඔබගේ ස්ථානය ලබා ගත හැකිය. යෙදුමට ඒවා භාවිත කිරීමට හැකි වීමට මෙම ස්ථාන සේවා ක්‍රියාත්මක කර සහ ඔබේ දුරකථනය මත ලබා ගත හැකිව තිබිය යුතුය."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"පසුබිම තුළ නිශ්චිත ස්ථානය වෙත පිවිසෙන්න"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"මෙම යෙදුම පසුබිම තුළ ඇති ඕනෑම අවස්ථාවක එයට ඔබේ නිශ්චිත ස්ථානය ලබා ගත හැකිය. යෙදුමට ඒවා භාවිත කිරීමට හැකි වීමට මෙම ස්ථාන සේවා ක්‍රියාත්මක කර සහ ඔබේ දුරකථනය මත ලබා ගත හැකිව තිබිය යුතුය. මෙය බැටරි පරිභෝජනය වැඩි කළ හැකිය."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"පසුබිමේ ස්ථානය ප්‍රවේශ කිරීම"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"මෙය ආසන්න වශයෙන් හෝ නිශ්චිත ස්ථානයක ප්‍රවේශය ලබා දෙන්නේ නම් පසුබිම් ධාවන අතරතුරදී යෙදුමට ස්ථානය වෙත ප්‍රවේශය විය හැක."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"ඔබගේ ශ්‍රව්‍ය සැකසීම් වෙනස් කරන්න"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"ශබ්දය ආදී ගෝලීය ශබ්ද සැකසීම් වෙනස් කිරීමට සහ ප්‍රතිදානය සඳහා භාවිත කරන්නේ කුමන නාදකය දැයි තේරීමට යෙදුමට අවසර දෙන්න."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"ශබ්ද පටිගත කරන්න"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"මෙම යෙදුමට ඕනෑම වේලාවක මයික්‍රෆෝනය භාවිතයෙන් ශ්‍රව්‍ය පටිගත කිරීමට හැකිය."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"SIM වෙත විධාන යැවීම"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"SIM වෙත විධාන ගෙන යාමට යෙදුමට අවසර දෙයි. මෙය ඉතා භයානක වේ."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"ශාරීරික ක්‍රියාකාරකම හඳුනා ගන්න"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"මෙම යෙදුමට ඔබේ ශාරීරික ක්‍රියාකාරකම හඳුනා ගැනීමට නොහැකිය"</string>
     <string name="permlab_camera" msgid="3616391919559751192">"පින්තූර සහ වීඩියෝ ගන්න"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"මෙම යෙදුමට ඕනෑම වේලාවක කැමරාව භාවිත කර පින්තූර ගැනීමට සහ වීඩියෝ පටිගත කිරීමට හැකිය."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"කම්පනය පාලනය කිරීම"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"ඔබගේ ඡායාරූප එකතුව වෙනස් කිරීමට යෙදුමට ඉඩ දෙයි."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"ඔබගේ මාධ්‍ය එකතුවෙන් ස්ථාන කියවන්න"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"ඔබගේ මාධ්‍ය එකතුවෙන් ස්ථාන කියවීමට යෙදුමට ඉඩ දෙයි."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"<xliff:g id="APP">%s</xliff:g> යෙදුම වෙත සත්‍යාපනය කිරීමට අවශ්‍යයි."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"ජීවමිතික දෘඪාංග ලබා ගත නොහැකිය"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"ඇඟිලි සලකුණ අඩ වශයෙන් අනාවරණය කර ගැනිණි. කරුණාකර නැවත උත්සාහ කරන්න."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"ඇඟිලි සලකුණ පිරිසැකසීමට නොහැකි විය. කරුණාකර නැවත උත්සාහ කරන්න."</string>
@@ -1899,14 +1905,14 @@
       <item quantity="one">ස්වයං පිරවුම් යෝජනා <xliff:g id="COUNT">%1$s</xliff:g></item>
       <item quantity="other">ස්වයං පිරවුම් යෝජනා <xliff:g id="COUNT">%1$s</xliff:g></item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; වෙත සුරකින්නද?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"<xliff:g id="TYPE">%1$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; වෙත සුරකින්නද?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"<xliff:g id="TYPE_0">%1$s</xliff:g> සහ <xliff:g id="TYPE_1">%2$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; වෙත සුරකින්නද?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, සහ <xliff:g id="TYPE_2">%3$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; වෙත සුරකින්නද?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; වෙත යාවත්කාලීන කරන්නද?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"<xliff:g id="TYPE">%1$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; වෙත යාවත්කාලීන කරන්නද?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"<xliff:g id="TYPE_0">%1$s</xliff:g> සහ <xliff:g id="TYPE_1">%2$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; වෙත යාවත්කාලීන කරන්නද?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, සහ <xliff:g id="TYPE_2">%3$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; වෙත යාවත්කාලීන කරන්නද?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" වෙත සුරකින්නද?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594"><b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" වෙත <xliff:g id="TYPE">%1$s</xliff:g> සුරකින්නද?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432"><b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" වෙත <xliff:g id="TYPE_0">%1$s</xliff:g> සහ <xliff:g id="TYPE_1">%2$s</xliff:g> සුරකින්නද?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555"><b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" වෙත <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, සහ <xliff:g id="TYPE_2">%3$s</xliff:g> සුරකින්න?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" තුළ යාවත්කාලීන කරන්නද?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233"><b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" තුළ <xliff:g id="TYPE">%1$s</xliff:g> යාවත්කාලීන කරන්නද?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484"><b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" තුළ <xliff:g id="TYPE_0">%1$s</xliff:g> සහ <xliff:g id="TYPE_1">%2$s</xliff:g> යාවත්කාලීන කරන්නද?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922"><b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" තුළ යාවත්කාලීන කරන්නද?: <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, සහ <xliff:g id="TYPE_2">%3$s</xliff:g> ?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"සුරකින්න"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"එපා ස්තූතියි"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"යාවත්කාලීන කරන්න"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index c0981ce..525fcde 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -298,6 +298,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Mikrofón"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"nahrávanie zvuku"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"Povoliť aplikácii &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; zaznamenávať zvuk?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"rozpoznávanie aktivity"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"rozpoznanie aktivity"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"Chcete povoliť aplikácii &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; rozpoznávať vašu fyzickú aktivitu?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Fotoaparát"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"fotenie a natáčanie videí"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"Povoliť aplikácii &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; snímať fotky a zaznamenávať video?"</string>
@@ -424,14 +427,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Táto aplikácia môže získať údaje o vašej polohe na základe sieťových zdrojov, ako sú mobilné veže a siete Wi‑Fi. Na to, aby aplikácia mohla používať služby určovania polohy, musia byť tieto služby zapnuté a k dispozícii na tablete."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Táto aplikácia môže získať údaje o vašej polohe na základe sieťových zdrojov, ako sú mobilné veže a siete Wi‑Fi. Na to, aby aplikácia mohla používať služby určovania polohy, musia byť tieto služby zapnuté a k dispozícii na televízore."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Táto aplikácia môže získať údaje o vašej polohe na základe sieťových zdrojov, ako sú mobilné veže a siete Wi‑Fi. Na to, aby aplikácia mohla používať služby určovania polohy, musia byť tieto služby zapnuté a k dispozícii na telefóne."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"prístup k presnej polohe na pozadí"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"Táto aplikácia dokáže kedykoľvek získať vašu presnú polohu, keď je spustená na pozadí. Na to, aby mohla používať služby určovania polohy, musia byť tieto služby zapnuté a k dispozícii v telefóne. Môže to zvýšiť spotebu batérie."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"prístup k polohe na pozadí"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Ak okrem prístupu k približnej alebo presnej polohe udelíte aj toto povolenie, aplikácia bude môcť používať polohu, keď bude spustená na pozadí."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"meniť nastavenia zvuku"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Umožňuje aplikácii upraviť globálne nastavenia zvuku, ako je hlasitosť, alebo určiť, z ktorého reproduktora bude zvuk vychádzať."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"nahrávať zvuk"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"Táto aplikácia môže kedykoľvek zaznamenávať zvuk pomocou mikrofónu."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"posielanie príkazov do SIM karty"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Umožňuje aplikácii odosielať príkazy na SIM kartu. Toto je veľmi nebezpečné povolenie."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"rozpoznávanie fyzickej aktivity"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"Táto aplikácia dokáže rozpoznať vašu fyzickú aktivitu."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"fotiť a nakrúcať videá"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"Táto aplikácia môže kedykoľvek fotografovať a zaznamenávať videá pomocou fotoaparátu."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"ovládať vibrovanie"</string>
@@ -524,6 +529,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Umožňuje aplikácii upravovať zbierku fotiek."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"čítať polohy zo zbierky médií"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Umožňuje aplikácii čítať polohy zo zbierky médií."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"Aplikácia <xliff:g id="APP">%s</xliff:g> chce overiť totožnosť"</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Biometrický hardvér nie je k dispozícii"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Podarilo sa rozpoznať iba časť odtlačku prsta. Skúste to znova."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Odtlačok prsta sa nepodarilo spracovať. Skúste to znova."</string>
@@ -1967,14 +1973,14 @@
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> návrhov automatického dopĺňania</item>
       <item quantity="one">Jeden návrh automatického dopĺňania</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"Uložiť do služby &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Uložiť <xliff:g id="TYPE">%1$s</xliff:g> do služby &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Uložiť <xliff:g id="TYPE_0">%1$s</xliff:g> a <xliff:g id="TYPE_1">%2$s</xliff:g> do služby &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Uložiť <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> a <xliff:g id="TYPE_2">%3$s</xliff:g> do služby &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"Nahrať do služby &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Chcete nahrať <xliff:g id="TYPE">%1$s</xliff:g> do služby &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Chcete nahrať <xliff:g id="TYPE_0">%1$s</xliff:g> a <xliff:g id="TYPE_1">%2$s</xliff:g> do služby &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Chcete nahrať <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> a <xliff:g id="TYPE_2">%3$s</xliff:g> do služby &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"Uložiť do služby "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"Chcete položku <xliff:g id="TYPE">%1$s</xliff:g> uložiť do služby "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"Chcete položky <xliff:g id="TYPE_0">%1$s</xliff:g> a <xliff:g id="TYPE_1">%2$s</xliff:g> uložiť do služby "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"Chcete položky <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> a <xliff:g id="TYPE_2">%3$s</xliff:g> uložiť do služby "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"Aktualizovať v službe "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"Chcete údaje <xliff:g id="TYPE">%1$s</xliff:g> aktualizovať v službe "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"Chcete položky <xliff:g id="TYPE_0">%1$s</xliff:g> a <xliff:g id="TYPE_1">%2$s</xliff:g> aktualizovať v službe "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"Chcete tieto položky aktualizovať v službe "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> a <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Uložiť"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Nie, vďaka"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"Aktualizovať"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 261e6ed..252246a 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -298,6 +298,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Mikrofon"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"snemanje zvoka"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"Želite aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; omogočiti snemanje zvoka?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"Prepoznavanje dejavnosti"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"prepoznavanje dejavnosti"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"Želite aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; omogočiti prepoznavanje svoje telesne dejavnosti?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Fotoaparat"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"fotografiranje in snemanje videoposnetkov"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"Želite aplikaciji &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; omogočiti fotografiranje in snemanje videoposnetkov?"</string>
@@ -424,14 +427,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Ta aplikacija lahko pridobi vašo lokacijo na podlagi omrežnih virov, kot so bazne postaje in omrežja Wi-Fi. Če želite aplikaciji omogočiti uporabo teh lokacijskih storitev, morajo biti te vklopljene in na voljo v tabličnem računalniku."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Ta aplikacija lahko pridobi vašo lokacijo na podlagi omrežnih virov, kot so bazne postaje in omrežja Wi-Fi. Če želite aplikaciji omogočiti uporabo teh lokacijskih storitev, morajo biti te vklopljene in na voljo v televizorju."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Ta aplikacija lahko pridobi vašo lokacijo na podlagi omrežnih virov, kot so bazne postaje in omrežja Wi-Fi. Če želite aplikaciji omogočiti uporabo teh lokacijskih storitev, morajo biti te vklopljene in na voljo v telefonu."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"dostop do točne lokacije, ko deluje v ozadju"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"Ta aplikacija lahko pridobi vašo točno lokacijo, ko deluje v ozadju. Če želite aplikaciji omogočiti uporabo teh lokacijskih storitev, morajo biti te vklopljene in na voljo v telefonu. Poraba energije akumulatorja bo morda večja."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"dostop do lokacije med izvajanjem v ozadju"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Če to dovolite poleg dostopa do približne ali natančne lokacije, lahko aplikacija dostopa do lokacije, medtem ko se izvaja v ozadju."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"spreminjanje nastavitev zvoka"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Aplikaciji omogoča spreminjanje splošnih zvočnih nastavitev, na primer glasnost in kateri zvočnik se uporablja."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"snemanje zvoka"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"Ta aplikacija lahko poljubno uporablja mikrofon za snemanje zvoka."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"pošiljanje ukazov na kartico SIM"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Aplikaciji dovoli pošiljanje ukazov kartici SIM. To je lahko zelo nevarno."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"prepoznavanje telesne dejavnosti"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"Ta aplikacija lahko prepoznava vašo telesno dejavnost."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"fotografiranje in snemanje videoposnetkov"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"Ta aplikacija lahko poljubno uporablja fotoaparat za snemanje fotografij ali videoposnetkov."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"nadzor vibriranja"</string>
@@ -524,6 +529,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Aplikaciji omogoča spreminjanje zbirke fotografij."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"branje lokacij v predstavnostni zbirki"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Aplikaciji omogoča branje lokacij v predstavnostni zbirki."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"Aplikacija <xliff:g id="APP">%s</xliff:g> želi preveriti pristnost."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Strojna oprema za biometrične podatke ni na voljo"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Zaznan delni prstni odtis. Poskusite znova."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Prstnega odtisa ni bilo mogoče obdelati. Poskusite znova."</string>
@@ -669,7 +675,7 @@
     <string name="policydesc_expirePassword" msgid="5367525762204416046">"Spreminjanje tega, kako pogosto je treba spremeniti geslo, kodo PIN ali vzorec za zaklepanje zaslona."</string>
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Nastavitev šifriranja shrambe"</string>
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"Shranjeni podatki aplikacije morajo biti šifrirani."</string>
-    <string name="policylab_disableCamera" msgid="6395301023152297826">"Onemogoči fotoaparate"</string>
+    <string name="policylab_disableCamera" msgid="6395301023152297826">"Onemogočanje fotoaparatov"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"Prepreči uporabo vseh fotoaparatov v napravi."</string>
     <string name="policylab_disableKeyguardFeatures" msgid="8552277871075367771">"Onemogočanje nekaterih funkcij zaklepanja zaslona"</string>
     <string name="policydesc_disableKeyguardFeatures" msgid="2044755691354158439">"Prepreči uporabo nekaterih funkcij zaklepanja zaslona."</string>
@@ -1967,14 +1973,14 @@
       <item quantity="few"><xliff:g id="COUNT">%1$s</xliff:g> predlogi za samodejno izpolnjevanje</item>
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> predlogov za samodejno izpolnjevanje</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"Želite shraniti pod oznako &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Želite <xliff:g id="TYPE">%1$s</xliff:g> shraniti pod oznako &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Želite <xliff:g id="TYPE_0">%1$s</xliff:g> in <xliff:g id="TYPE_1">%2$s</xliff:g> shraniti pod oznako &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Želite <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> in <xliff:g id="TYPE_2">%3$s</xliff:g> shraniti pod oznako &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"Želite posodobiti na oznako &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Želite <xliff:g id="TYPE">%1$s</xliff:g> posodobiti na oznako &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Želite <xliff:g id="TYPE_0">%1$s</xliff:g> in <xliff:g id="TYPE_1">%2$s</xliff:g> posodobiti na oznako &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Želite <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> in <xliff:g id="TYPE_2">%3$s</xliff:g> posodobiti na oznako &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"Želite shraniti v aplikacijo "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"Želite shraniti element <xliff:g id="TYPE">%1$s</xliff:g> v aplikacijo "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"Želite shraniti elementa <xliff:g id="TYPE_0">%1$s</xliff:g> in <xliff:g id="TYPE_1">%2$s</xliff:g> v aplikacijo "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"Želite shraniti elemente <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> in <xliff:g id="TYPE_2">%3$s</xliff:g> v aplikacijo "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"Želite posodobiti v aplikaciji "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"Želite posodobiti element <xliff:g id="TYPE">%1$s</xliff:g> v aplikaciji "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"Želite posodobiti elementa <xliff:g id="TYPE_0">%1$s</xliff:g> in <xliff:g id="TYPE_1">%2$s</xliff:g> v aplikaciji "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"Želite posodobiti te elemente v aplikaciji "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> in <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Shrani"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Ne, hvala"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"Posodobi"</string>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index 4b6cb09..9062f29 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Mikrofoni"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"regjistro audio"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"Të lejohet që &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; të regjistrojë audio?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"Njohja e aktivitetit"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"njih aktivitetin"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"Të lejohet që &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; të njohë aktivitetin tënd fizik?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Kamera"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"bëj fotografi dhe regjistro video"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"Të lejohet që &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; të nxjerrë fotografi dhe të regjistrojë video?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Ky aplikacion mund të marrë vendndodhjen tënde bazuar në burimet e rrjetit si antenat e operatorëve celulare dhe rrjetet Wi-Fi. Këto shërbime të vendndodhjes duhet të jenë të aktivizuara dhe në dispozicion në tabletin tënd që aplikacioni të mund t\'i përdorë."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Ky aplikacion mund të marrë vendndodhjen tënde bazuar në burimet e rrjetit si antenat e operatorëve celulare dhe rrjetet Wi-Fi. Këto shërbime të vendndodhjes duhet të jenë të aktivizuara dhe në dispozicion në televizorin tënd që aplikacioni të mund t\'i përdorë."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Ky aplikacion mund të marrë vendndodhjen tënde bazuar në burimet e rrjetit si antenat e operatorëve celulare dhe rrjetet Wi-Fi. Këto shërbime të vendndodhjes duhet të jenë të aktivizuara dhe në dispozicion në telefonin tënd që aplikacioni të mund t\'i përdorë."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"qasu në vendndodhjen e saktë në sfond"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"Ky aplikacion mund të marrë vendndodhjen tënde të saktë në çdo kohë kur është në sfond. Këto shërbime të vendndodhjes duhet të jenë të aktivizuara dhe në dispozicion në telefonin tënd që aplikacioni të mund t\'i përdorë. Kjo gjë mund të rritë konsumin e baterisë."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"qasje te vendndodhja në sfond"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Nëse kjo jepet përveç qasjes te vendndodhja e përafërt ose të saktë, aplikacioni mund të qaset te vendndodhja ndërkohë që ekzekutohet në sfond."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"ndrysho cilësimet e audios"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Lejon aplikacionin të modifikojë cilësimet globale të audios siç është volumi dhe se cili altoparlant përdoret për daljen."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"regjistro audio"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"Ky aplikacion mund të regjistrojë audio me mikrofonin në çdo kohë."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"dërgo komanda te karta SIM"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Lejon aplikacionin t\'i dërgojë komanda kartës SIM. Kjo është shumë e rrezikshme."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"njih aktivitetin fizik"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"Ky aplikacion mund të njohë aktivitetin tënd fizik."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"bëj fotografi dhe video"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"Ky aplikacion mund të nxjerrë fotografi dhe të regjistrojë video me kamerën tënde në çdo kohë."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"kontrollo dridhjen"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Lejon aplikacionin të modifikojë koleksionin tënd të fotografive."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"lexo vendndodhjet nga koleksioni yt i medias"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Lejon aplikacionin të lexojë vendndodhjet nga koleksioni yt i medias."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"Aplikacioni <xliff:g id="APP">%s</xliff:g> dëshiron të vërtetojë."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Nuk ofrohet harduer biometrik"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"U zbulua një gjurmë gishti e pjesshme. Provo përsëri."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Gjurma e gishtit nuk mund të përpunohej. Provo përsëri."</string>
@@ -1898,14 +1904,14 @@
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> sugjerime për plotësim automatik</item>
       <item quantity="one">Një sugjerim për plotësim automatik</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"Të ruhet te &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Të ruhet <xliff:g id="TYPE">%1$s</xliff:g> te &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Të ruhen <xliff:g id="TYPE_0">%1$s</xliff:g> dhe <xliff:g id="TYPE_1">%2$s</xliff:g> te &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Të ruhen <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> dhe <xliff:g id="TYPE_2">%3$s</xliff:g> te &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"Të përditësohet te &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Të përditësohet <xliff:g id="TYPE">%1$s</xliff:g> te &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Të përditësohen <xliff:g id="TYPE_0">%1$s</xliff:g> dhe <xliff:g id="TYPE_1">%2$s</xliff:g> te &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Të përditësohen <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> dhe <xliff:g id="TYPE_2">%3$s</xliff:g> te &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"Të ruhet te "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"Të ruhet <xliff:g id="TYPE">%1$s</xliff:g> te "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"Të ruhet <xliff:g id="TYPE_0">%1$s</xliff:g> dhe <xliff:g id="TYPE_1">%2$s</xliff:g> te "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"Të ruhet <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> dhe <xliff:g id="TYPE_2">%3$s</xliff:g> te "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"Të përditësohet në "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"Të përditësohet <xliff:g id="TYPE">%1$s</xliff:g> në "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"Të përditësohet <xliff:g id="TYPE_0">%1$s</xliff:g> dhe <xliff:g id="TYPE_1">%2$s</xliff:g> në "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"Të përditësohen këta artikuj në "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> dhe <xliff:g id="TYPE_2">%3$s</xliff:g> ?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Ruaj"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Jo, faleminderit"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"Përditëso"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 449fdfc..642e12e 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -295,6 +295,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Микрофон"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"снима звук"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"Желите ли да омогућите да &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; снима звук?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"Препознавање активности"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"препознавање активности"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"Желите ли да омогућите да &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; препознаје физичке активности?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Камера"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"снима слике и видео"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"Желите ли да омогућите да &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; снима слике и видео снимке?"</string>
@@ -421,14 +424,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Ова апликација може да приступи вашој локацији помоћу извора мреже, као што су мобилни предајници и Wi-Fi мреже. Ове услуге локације морају да буду укључене и доступне на таблету да би апликација могла да их користи."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Ова апликација може да приступи вашој локацији помоћу извора мреже, као што су мобилни предајници и Wi-Fi мреже. Ове услуге локације морају да буду укључене и доступне на ТВ-у да би апликација могла да их користи."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Ова апликација може да приступи вашој локацији помоћу извора мреже, као што су мобилни предајници и Wi-Fi мреже. Ове услуге локације морају да буду укључене и доступне на телефону да би апликација могла да их користи."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"приступ прецизној локацији у позадини"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"Ова апликација може да одреди вашу тачну локацију сваки пут када ради у позадини. Ове услуге локације морају да буду укључене и доступне на телефону да би апликација могла да их користи. То може да повећа потрошњу батерије."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"приступ локацији у позадини"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Ако се поред приближног или прецизног приступа локација одобри и овај, апликација може да приступа локацији док је покренута у позадини."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"промена аудио подешавања"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Дозвољава апликацији да мења глобална аудио подешавања као што су јачина звука и избор звучника који се користи као излаз."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"снимање аудио записа"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"Ова апликација може да снима звук помоћу микрофона у било ком тренутку."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"слање команди на SIM"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Омогућава апликацији да шаље команде SIM картици. То је веома опасно."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"препознавање физичких активности"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"Ова апликација може да препозна физичке активности."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"снимање фотографија и видео снимака"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"Ова апликација може да снима фотографије и видео снимке помоћу камере у било ком тренутку."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"контрола вибрације"</string>
@@ -521,6 +526,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Дозвољава апликацији да мења колекцију слика."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"читање локација из медијске колекције"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Дозвољава апликацији да чита локације из медијске колекције."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"Апликација <xliff:g id="APP">%s</xliff:g> жели да потврди ваш идентитет."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Биометријски хардвер није доступан"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Откривен је делимични отисак прста. Пробајте поново."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Није успела обрада отиска прста. Пробајте поново."</string>
@@ -1932,14 +1938,14 @@
       <item quantity="few"><xliff:g id="COUNT">%1$s</xliff:g> аутоматски попуњена предлога</item>
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> аутоматски попуњених предлога</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"Желите ли да сачувате у: &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Желите ли да сачувате ставку <xliff:g id="TYPE">%1$s</xliff:g> у: &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Желите ли да сачувате ставке <xliff:g id="TYPE_0">%1$s</xliff:g> и <xliff:g id="TYPE_1">%2$s</xliff:g> у: &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Желите ли да сачувате ставке <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> и <xliff:g id="TYPE_2">%3$s</xliff:g> у: &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"Желите ли да ажурирате на &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Желите ли да ажурирате ставку <xliff:g id="TYPE">%1$s</xliff:g> на &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Желите ли да ажурирате ставке <xliff:g id="TYPE_0">%1$s</xliff:g> и <xliff:g id="TYPE_1">%2$s</xliff:g> на &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Желите ли да ажурирате ставке <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> и <xliff:g id="TYPE_2">%3$s</xliff:g> на &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"Желите ли да сачувате у услузи "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"Желите ли да сачувате ставку <xliff:g id="TYPE">%1$s</xliff:g> у услузи "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"Желите ли да сачувате ставке <xliff:g id="TYPE_0">%1$s</xliff:g> и <xliff:g id="TYPE_1">%2$s</xliff:g> у услузи "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"Желите ли да сачувате ставке <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> и <xliff:g id="TYPE_2">%3$s</xliff:g> у услузи "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"Желите ли да ажурирате у услузи "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"Желите ли да ажурирате ставку <xliff:g id="TYPE">%1$s</xliff:g> у услузи "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"Желите ли да ажурирате ставке <xliff:g id="TYPE_0">%1$s</xliff:g> и <xliff:g id="TYPE_1">%2$s</xliff:g> у услузи "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"Желите ли да ажурирате ове ставке у услузи "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> и <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Сачувај"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Не, хвала"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"Ажурирај"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 9f46514..2ace15c 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Mikrofon"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"spela in ljud"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"Vill du ge &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; behörighet att spela in ljud?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"Aktivitetsigenkänning"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"känn igen aktivitet"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"Vill du tillåta att &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; känner igen din fysiska aktivitet?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Kamera"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"ta bilder och spela in video"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"Vill du ge &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; behörighet att ta bilder och spela in video?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Appen kan få information om din plats från källor i nätverket, som mobilmaster och Wi-Fi-nätverk. De platstjänsterna måste ha aktiverats och finnas på surfplattan om appen ska kunna använda dem."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Appen kan få information om din plats från källor i nätverket, som mobilmaster och Wi-Fi-nätverk. De platstjänsterna måste ha aktiverats och fungera på TV:n om appen ska kunna använda dem."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Appen kan få information om din plats från källor i nätverket, som mobilmaster och Wi-Fi-nätverk. De platstjänsterna måste ha aktiverats och finnas på mobilen om appen ska kunna använda dem."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"åtkomst till exakt plats i bakgrunden"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"Den här appen kan när som helst få information om din exakta plats när den körs i bakgrunden. Platstjänsterna måste ha aktiverats och finnas på mobilen om appen ska kunna använda dem. Detta kan leda till ökad batteriförbrukning."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"få åtkomst till platsinformation i bakgrunden"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Om denna behörighet ges utöver ungefärlig eller exakt platsåtkomst får appen åtkomst till platsinformation när den körs i bakgrunden."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"ändra dina ljudinställningar"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Tillåter att appen ändrar globala ljudinställningar som volym och vilken högtalarutgång som används."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"spela in ljud"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"Appen kan spela in ljud med mikrofonen när som helst."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"skicka kommandon till SIM-kortet"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Tillåter att appen skickar kommandon till SIM-kortet. Detta är mycket farligt."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"känn igen fysisk aktivitet"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"Den här appen kan känna igen fysisk aktivitet."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"ta bilder och spela in videoklipp"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"Appen kan ta kort och spela in video med kameran när som helst."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"styra vibration"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Tillåter att appen gör ändringar i din fotosamling."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"läsa av platser i din mediesamling"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Tillåter att appen läser av platser i din mediesamling."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"Appen <xliff:g id="APP">%s</xliff:g> vill autentisera"</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Biometrisk maskinvara är inte tillgänglig"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Ofullständigt fingeravtryck. Försök igen."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Det gick inte att bearbeta fingeravtrycket. Försök igen."</string>
@@ -1897,14 +1903,14 @@
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> förslag från autofyll</item>
       <item quantity="one">Ett förslag från autofyll</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"Vill du spara innehållet i &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Vill du spara <xliff:g id="TYPE">%1$s</xliff:g> i &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Vill du spara <xliff:g id="TYPE_0">%1$s</xliff:g> och <xliff:g id="TYPE_1">%2$s</xliff:g> i &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Vill du spara <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> och <xliff:g id="TYPE_2">%3$s</xliff:g> i &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"Vill du uppdatera till &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Vill du uppdatera <xliff:g id="TYPE">%1$s</xliff:g> till &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Vill du uppdatera <xliff:g id="TYPE_0">%1$s</xliff:g> och <xliff:g id="TYPE_1">%2$s</xliff:g> till &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Vill du uppdatera <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> och <xliff:g id="TYPE_2">%3$s</xliff:g> till &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"Vill du spara i "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"Vill du spara <xliff:g id="TYPE">%1$s</xliff:g> i "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"Vill du spara <xliff:g id="TYPE_0">%1$s</xliff:g> och <xliff:g id="TYPE_1">%2$s</xliff:g> i "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"Vill du spara <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> och <xliff:g id="TYPE_2">%3$s</xliff:g> i "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"Vill du uppdatera detta i "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"Vill du uppdatera <xliff:g id="TYPE">%1$s</xliff:g> i "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"Vill du uppdatera <xliff:g id="TYPE_0">%1$s</xliff:g> och <xliff:g id="TYPE_1">%2$s</xliff:g> i "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"Vill du uppdatera dessa objekt i "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> och <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Spara"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Nej tack"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"Uppdatera"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index b0858dc..dcfa08d 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Kipokea sauti"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"irekodi sauti"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"Ungependa kuiruhusu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; irekodi sauti?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"Kutambua shughuli"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"itambue shughuli"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"Ungependa kuruhusu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; itambue shughuli unazofanya?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Kamera"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"ipige picha na kurekodi video"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"Ungependa kuiruhusu &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ipige picha na kurekodi video?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Programu hii inaweza kupata eneo lako kulingana na vyanzo vya mtandao kama vile minara ya simu na mitandao ya Wi-Fi. Huduma hizi za mahali lazima ziwashwe na zipatikane kwenye kompyuta yako kibao ili programu iweze kuzitumia."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Programu hii inaweza kupata eneo lako kulingana na vyanzo vya mtandao kama vile minara ya simu na mitandao ya Wi-Fi. Huduma hizi za mahali lazima ziwashwe na zipatikane kwenye runinga yako ili programu iweze kuzitumia."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Programu hii inaweza kupata eneo lako kulingana na vyanzo vya mtandao kama vile minara ya simu na mitandao ya Wi-Fi. Huduma hizi za mahali lazima ziwashwe na zipatikane kwenye simu yako ili programu iweze kuzitumia."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"kufikia mahali halisi ikiwa inatumika chinichini"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"Programu hii inaweza kupata mahali halisi ulipo wakati wowote ikiwa inatumika chinichini. Ni lazima uwashe huduma hizi za mahali na zipatikane kwenye simu yako ili programu iweze kuzitumia. Hatua hii inaweza kuongeza utumiaji wa betri."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"ifikie mahali inapotumika chinichini"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Kama ruhusa hii itatolewa, mbali na idhini ya kufikia mahali panapokadiriwa au mahali mahususi, programu inaweza kufikia mahali wakati inatumika chinichini."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"badilisha mipangilio yako ya sauti"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Inaruhusu programu kurekebisha mipangilio ya sauti kila mahali kama vile sauti na ni kipaza sauti kipi ambacho kinatumika kwa kutoa."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"kurekodi sauti"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"Programu hii inaweza kurekodi sauti kwa kutumia maikrofoni wakati wowote."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"tuma amri kwenye SIM"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Huruhusu programu kutuma amri kwa SIM. Hii ni hatari sana."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"itambue shughuli unazofanya"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"Programu hii inaweza kutambua shughuli unazofanya."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"Kupiga picha na kurekodi video"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"Programu hii inaweza kupiga picha na kurekodi video kwa kutumia kamera wakati wowote."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"Kudhibiti mtetemo"</string>
@@ -465,7 +470,7 @@
     <string name="permdesc_getAccounts" product="tv" msgid="4190633395633907543">"Huruhusu programu kupata orodha ya akaunti zinazojulikana na runinga. Hii inaweza kujumuisha akaunti zozote zilizofunguliwa na programu ambazo umesakinisha."</string>
     <string name="permdesc_getAccounts" product="default" msgid="3448316822451807382">"Inaruhusu programu kupata orodha ya akaunti zinazojulikana kwa simu. Hii inaweza kujumuisha akaunti zozote zilizoundwa na programu ambazo umesakinisha."</string>
     <string name="permlab_accessNetworkState" msgid="4951027964348974773">"kuona mitandao"</string>
-    <string name="permdesc_accessNetworkState" msgid="8318964424675960975">"Inaruhusu programu kuona taarifa kuhusu miunganisho ya mtandao kama vile mitandao ipi iliyopo na imeunganishwa."</string>
+    <string name="permdesc_accessNetworkState" msgid="8318964424675960975">"Huruhusu programu kuona taarifa kuhusu miunganisho ya mtandao kama vile mitandao iliyopo na iliyounganishwa."</string>
     <string name="permlab_createNetworkSockets" msgid="7934516631384168107">"pata ufikiaji kamili wa mtandao"</string>
     <string name="permdesc_createNetworkSockets" msgid="3403062187779724185">"Inaruhusu programu kuunda soketi za mtandao na kutumia itifaki za mtandao maalum. Kivinajri na programu nyingine zilizotolewa zinamaanisha kutuma data kwenye mtandao, kwa hivyo kibali hiki hakihitajiki kutuma data kwenye mtandao."</string>
     <string name="permlab_changeNetworkState" msgid="958884291454327309">"kubadilisha muunganisho wa mtandao"</string>
@@ -473,7 +478,7 @@
     <string name="permlab_changeTetherState" msgid="5952584964373017960">"Badilisha muunganisho uliofunganishwa"</string>
     <string name="permdesc_changeTetherState" msgid="1524441344412319780">"Inaruhusu programu kubadilisha hali ya muunganisho wa mtandao uliofungwa."</string>
     <string name="permlab_accessWifiState" msgid="5202012949247040011">"Kuona miunganisho ya Wi-Fi"</string>
-    <string name="permdesc_accessWifiState" msgid="5002798077387803726">"Inaruhusu programu kuona taarifa kuhusu mtandao wa Wi-Fi, kama vile ikiwa Wi-Fi imewezeshwa mna jina la vifaa vya Wi-Fi vilivyounganishwa."</string>
+    <string name="permdesc_accessWifiState" msgid="5002798077387803726">"Huruhusu programu kuona taarifa kuhusu mtandao wa Wi-Fi, kama vile ikiwa Wi-Fi imewashwa na majina ya vifaa vya Wi-Fi vilivyounganishwa."</string>
     <string name="permlab_changeWifiState" msgid="6550641188749128035">"unganisha na utenganishe kutoka kwa Wi-Fi"</string>
     <string name="permdesc_changeWifiState" msgid="7137950297386127533">"Inaruhusu programu kuunganisha kwenye au kukata kutoka pointi za ufikivu wa Wi-Fi na kufanya mabadiliko kwenye usanidi wa kifaa cha mitandao ya Wi-Fi."</string>
     <string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"ruhusu upokeaji wa Wi-Fi Multicast"</string>
@@ -491,9 +496,9 @@
     <string name="permdesc_changeWimaxState" product="tv" msgid="6022307083934827718">"Huruhusu programu kuunganisha runinga kwenye na kuondoa runinga kutoka mitandao ya WiMAX."</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Inaruhusu programu kuunganisha simu kwenye, na kukata simu kutoka mitandao ya WiMAX."</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"oanisha na vifaa vya Bluetooth"</string>
-    <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Inaruhusu programu kuona usanidi wa Bluetooth kwenye kompyuta kibao, na kuunda na kukubali miunganisho kwa vifaa vilivyooanishwa."</string>
+    <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Huruhusu programu kuona usanidi wa Bluetooth kwenye kompyuta kibao, na kutuma na kukubali miunganisho kwa vifaa vilivyooanishwa."</string>
     <string name="permdesc_bluetooth" product="tv" msgid="3974124940101104206">"Huruhusu programu kuona usanidi wa Bluetooth kwenye runinga, na kuomba na kukubali miunganisho kwa vifaa vilivyooanishwa."</string>
-    <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Inaruhusu programu kuona usanidi wa Bluetooth kwenye simu, na kuunda na kukubali miunganisho kwa vifaa vilivyooanishwa."</string>
+    <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Huruhusu programu kuona usanidi wa Bluetooth kwenye simu, na kutuma na kukubali miunganisho kwa vifaa vilivyooanishwa."</string>
     <string name="permlab_nfc" msgid="4423351274757876953">"kudhibiti Mawasiliano ya Vifaa Vilivyokaribu (NFC)"</string>
     <string name="permdesc_nfc" msgid="7120611819401789907">"Inaruhusu programu kuwasiliana na lebo, kadi na wasomaji wa Near Field Communication (NFC)."</string>
     <string name="permlab_disableKeyguard" msgid="3598496301486439258">"zima kufuli la skrini yako"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Inaruhusu programu kubadilisha mkusanyiko wa picha zako."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"kusoma maeneo kwenye mkusanyiko wa vipengee vyako"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Inaruhusu programu kusoma maeneo kwenye mkusanyiko wa vipengee vyako."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"Programu ya <xliff:g id="APP">%s</xliff:g> inataka kuthibitishwa."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Maunzi ya bayometriki hayapatikani"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Kitambuzi kimegundua sehemu ya kitambulisho. Tafadhali jaribu tena."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Haikuweza kuchakata kitambulisho. Tafadhali jaribu tena."</string>
@@ -1581,7 +1587,7 @@
     </plurals>
     <string name="kg_pattern_instructions" msgid="398978611683075868">"Chora ruwaza yako"</string>
     <string name="kg_sim_pin_instructions" msgid="2319508550934557331">"Ingiza PIN ya SIM"</string>
-    <string name="kg_pin_instructions" msgid="2377242233495111557">"Ingiza PIN"</string>
+    <string name="kg_pin_instructions" msgid="2377242233495111557">"Weka PIN"</string>
     <string name="kg_password_instructions" msgid="5753646556186936819">"Weka Nenosiri"</string>
     <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"SIM sasa imelemazwa. Ingiza msimbo wa PUK ili kuendelea. Wasiliana na mtoa huduma kwa maelezo."</string>
     <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"Weka nambari yako ya PIN"</string>
@@ -1725,7 +1731,7 @@
     <string name="print_service_installed_title" msgid="2246317169444081628">"Huduma ya <xliff:g id="NAME">%s</xliff:g> imesakinisha"</string>
     <string name="print_service_installed_message" msgid="5897362931070459152">"Gusa ili uwashe"</string>
     <string name="restr_pin_enter_admin_pin" msgid="8641662909467236832">"Weka PIN ya msimamizi"</string>
-    <string name="restr_pin_enter_pin" msgid="3395953421368476103">"Ingiza PIN"</string>
+    <string name="restr_pin_enter_pin" msgid="3395953421368476103">"Weka PIN"</string>
     <string name="restr_pin_incorrect" msgid="8571512003955077924">"Sio sahihi"</string>
     <string name="restr_pin_enter_old_pin" msgid="1462206225512910757">"PIN ya sasa"</string>
     <string name="restr_pin_enter_new_pin" msgid="5959606691619959184">"PIN mpya"</string>
@@ -1897,14 +1903,14 @@
       <item quantity="other">Mapendekezo <xliff:g id="COUNT">%1$s</xliff:g> ya kujaza kiotomatiki</item>
       <item quantity="one">Pendekezo moja la kujaza kiotomatiki</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"Ungependa kuhifadhi kwenye &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Ungependa kuhifadhi <xliff:g id="TYPE">%1$s</xliff:g> kwenye &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Ungependa kuhifadhi <xliff:g id="TYPE_0">%1$s</xliff:g> na <xliff:g id="TYPE_1">%2$s</xliff:g> kwenye &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Ungependa kuhifadhi <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, na <xliff:g id="TYPE_2">%3$s</xliff:g> kwenye &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"Ungependa kusasisha kuwa &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Ungependa kusasisha <xliff:g id="TYPE">%1$s</xliff:g> kuwa &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Ungependa kusasisha <xliff:g id="TYPE_0">%1$s</xliff:g> na <xliff:g id="TYPE_1">%2$s</xliff:g> kuwa &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Ungependa kusasisha <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> na <xliff:g id="TYPE_2">%3$s</xliff:g> kuwa &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"Ungependa kuhifadhi kwenye "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"Ungependa kuhifadhi <xliff:g id="TYPE">%1$s</xliff:g> kwenye "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"Ungependa kuhifadhi <xliff:g id="TYPE_0">%1$s</xliff:g> na <xliff:g id="TYPE_1">%2$s</xliff:g> kwenye "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"Ungependa kuhifadhi <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> na <xliff:g id="TYPE_2">%3$s</xliff:g> kwenye "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"Ungependa kusasisha katika "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"Ungependa kusasisha <xliff:g id="TYPE">%1$s</xliff:g> katika "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"Ungependa kusasisha <xliff:g id="TYPE_0">%1$s</xliff:g> na <xliff:g id="TYPE_1">%2$s</xliff:g> katika "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"Ungependa kusasisha vipengee hivi katika "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> na <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Hifadhi"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Hapana, asante"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"Sasisha"</string>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index 3bf8b78..8ed9b7d 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"மைக்ரோஃபோன்"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"ஒலிப் பதிவு செய்யலாம்"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"ஆடியோவைப் பதிவு செய்ய &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; பயன்பாட்டை அனுமதிக்கவா?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"செயல்பாட்டைக் கண்டறிதல்"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"செயல்பாட்டைக் கண்டறியும்"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"உங்கள் உடல் செயல்பாட்டைக் கண்டறிய &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ஆப்ஸை அனுமதிக்கவா?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"கேமரா"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"படங்கள் மற்றும் வீடியோக்கள் எடுக்கலாம்"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"படங்கள் எடுக்கவும், வீடியோ பதிவு செய்யவும் &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; பயன்பாட்டை அனுமதிக்கவா?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"இந்தப் பயன்பாடு நெட்வொர்க் மூலங்களின் (செல் கோபுரங்கள், வைஃபை நெட்வொர்க்குகள் போன்றவை) அடிப்படையில் உங்கள் இருப்பிடத்தைப் பெறலாம். பயன்பாடு பயன்படுத்தும் வகையில், உங்கள் டேப்லெட்டில் இந்த இருப்பிடச் சேவைகள் இயக்கப்பட்டு, கிடைக்கும்படி இருக்க வேண்டும்."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"இந்தப் பயன்பாடு நெட்வொர்க் மூலங்களின் (செல் கோபுரங்கள், வைஃபை நெட்வொர்க்குகள் போன்றவை) அடிப்படையில் உங்கள் இருப்பிடத்தைப் பெறலாம். பயன்பாடு பயன்படுத்தும் வகையில், உங்கள் டிவியில் இந்த இருப்பிடச் சேவைகள் இயக்கப்பட்டு, கிடைக்கும்படி இருக்க வேண்டும்."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"இந்தப் பயன்பாடு நெட்வொர்க் மூலங்களின் (செல் கோபுரங்கள், வைஃபை நெட்வொர்க்குகள் போன்றவை) அடிப்படையில் உங்கள் இருப்பிடத்தைப் பெறலாம். பயன்பாடு பயன்படுத்தும் வகையில், உங்கள் மொபைலில் இந்த இருப்பிடச் சேவைகள் இயக்கப்பட்டு, கிடைக்கும்படி இருக்க வேண்டும்."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"பின்புலத்தில் இயங்கும்போது துல்லியமான இடத்தைக் கண்டறிதல்"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"இந்த ஆப்ஸ் பின்புலத்தில் இயங்கும்போது நீங்கள் இருக்கும் இடத்தைத் துல்லியமாகக் கண்டறியும். உங்கள் மொபைலில், இருப்பிடச் சேவைகளை ஆப்ஸ் பயன்படுத்துவதற்கு வசதியாக, அவை ஆன் செய்யப்பட்டிருக்க வேண்டும். இதனால் பேட்டரி அதிகம் பயன்படுத்தப்படலாம்."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"பின்புலத்தில் இருப்பிடத்தை அணுகுதல்"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"தோராயமான அல்லது துல்லியமான \'இருப்பிட அணுகலுடன்\' சேர்ந்து இதற்கும் அனுமதி வழங்கப்பட்டால், ஆப்ஸ் பின்புலத்தில் இயங்கினாலும் இருப்பிடத்தை அணுக இயலும்."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"எனது ஆடியோ அமைப்புகளை மாற்றுதல்"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"ஒலியளவு மற்றும் வெளியீட்டிற்கு ஸ்பீக்கர்கள் பயன்படுத்தப்படுவது போன்ற ஒட்டுமொத்த ஆடியோ அமைப்புகளைக் கட்டுப்படுத்தப் பயன்பாட்டை அனுமதிக்கிறது."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"ஆடியோவைப் பதிவுசெய்தல்"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"இந்தப் பயன்பாடு எப்போது வேண்டுமானாலும் மைக்ரோஃபோனைப் பயன்படுத்தி ஆடியோவை ரெக்கார்டு செய்யலாம்."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"கட்டளைகளை சிம்மிற்கு அனுப்புதல்"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"சிம் க்குக் கட்டளைகளை அனுப்ப பயன்பாட்டை அனுமதிக்கிறது. இது மிகவும் ஆபத்தானதாகும்."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"உடல் செயல்பாட்டைக் கண்டறிதல்"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"உங்கள் உடல் செயல்பாட்டை இந்த ஆப்ஸால் கண்டறிய முடியும்."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"படங்கள் மற்றும் வீடியோக்களை எடுத்தல்"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"இந்தப் பயன்பாடு எப்போது வேண்டுமானாலும் கேமராவைப் பயன்படுத்தி படங்களை எடுக்கலாம், வீடியோக்களை ரெக்கார்டு செய்யலாம்."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"அதிர்வைக் கட்டுப்படுத்துதல்"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"உங்களின் படத் தொகுப்பை மாற்ற ஆப்ஸை அனுமதிக்கும்."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"மீடியா தொகுப்பிலிருந்து இடங்களை அறிதல்"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"உங்களின் மீடியா தொகுப்பிலிருந்து இடங்களை அறிந்துகொள்ள ஆப்ஸை அனுமதிக்கும்."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"<xliff:g id="APP">%s</xliff:g>ஐப் பயன்படுத்த அங்கீகாரத்தை உறுதிசெய்க."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"பயோமெட்ரிக் வன்பொருள் இல்லை"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"கைரேகையை ஓரளவுதான் கண்டறிய முடிந்தது. மீண்டும் முயலவும்."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"கைரேகையைச் செயலாக்க முடியவில்லை. மீண்டும் முயலவும்."</string>
@@ -1898,14 +1904,14 @@
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> தன்னிரப்பிப் பரிந்துரைகள்</item>
       <item quantity="one">ஒரு தன்னிரப்பிப் பரிந்துரை</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; இல் சேமிக்கவா?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"<xliff:g id="TYPE">%1$s</xliff:g>ஐ &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; இல் சேமிக்கவா?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"<xliff:g id="TYPE_0">%1$s</xliff:g> மற்றும் <xliff:g id="TYPE_1">%2$s</xliff:g>ஐ &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; இல் சேமிக்கவா?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, <xliff:g id="TYPE_2">%3$s</xliff:g> ஆகியவற்றை &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; இல் சேமிக்கவா?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; என்பதற்குப் புதுப்பிக்கவா?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"<xliff:g id="TYPE">%1$s</xliff:g>ஐ &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; என்பதற்குப் புதுப்பிக்கவா?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"<xliff:g id="TYPE_0">%1$s</xliff:g> மற்றும் <xliff:g id="TYPE_1">%2$s</xliff:g>ஐ &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; என்பதற்குப் புதுப்பிக்கவா?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> மற்றும் <xliff:g id="TYPE_2">%3$s</xliff:g>ஐ &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; என்பதற்குப் புதுப்பிக்கவா?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" இல் சேமிக்கவா?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"<xliff:g id="TYPE">%1$s</xliff:g>ஐ "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" இல் சேமிக்கவா?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"<xliff:g id="TYPE_0">%1$s</xliff:g> மற்றும் <xliff:g id="TYPE_1">%2$s</xliff:g>ஐ "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" இல் சேமிக்கவா?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> மற்றும் <xliff:g id="TYPE_2">%3$s</xliff:g>ஐ "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" இல் சேமிக்கவா?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" இல் மாற்றவா?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233"><b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" இல் <xliff:g id="TYPE">%1$s</xliff:g>ஐ மாற்றவா?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484"><b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" இல் <xliff:g id="TYPE_0">%1$s</xliff:g> மற்றும் <xliff:g id="TYPE_1">%2$s</xliff:g>ஐ மாற்றவா?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922"><b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" இல் <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> மற்றும் <xliff:g id="TYPE_2">%3$s</xliff:g>ஐ மாற்றவா?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"சேமி"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"வேண்டாம்"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"புதுப்பி"</string>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index a5430b6..cce816d 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"మైక్రోఫోన్"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"ఆడియోను రికార్డ్ చేయడానికి"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"ఆడియోని రికార్డ్ చేయడానికి &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ని అనుమతించాలా?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"కార్యకలాప గుర్తింపు"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"కార్యాకలాపాన్ని గుర్తించండి"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"భౌతిక కార్యాకలాపాన్ని గుర్తించడానికి &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ని అనుమతించాలా?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"కెమెరా"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"చిత్రాలను తీయడానికి మరియు వీడియోను రికార్డ్ చేయడానికి"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"చిత్రాలు తీయడానికి మరియు వీడియో రికార్డ్ చేయడానికి &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;ని అనుమతించాలా?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"ఈ యాప్‌ సెల్ టవర్‌లు మరియు Wi-Fi నెట్‌వర్క్‌ల వంటి నెట్‌వర్క్ మూలాధారాల ఆధారంగా మీ స్థానాన్ని తెలుసుకోగలదు. యాప్‌ ఉపయోగించడానికి మీ టాబ్లెట్‌లో ఈ స్థాన సేవలను తప్పనిసరిగా ఆన్ చేయాలి మరియు అందుబాటులో ఉండాలి."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"ఈ యాప్‌ సెల్ టవర్‌లు మరియు Wi-Fi నెట్‌వర్క్‌ల వంటి నెట్‌వర్క్ మూలాధారాల ఆధారంగా మీ స్థానాన్ని తెలుసుకోగలదు. యాప్‌ ఉపయోగించడానికి మీ టీవీలో ఈ స్థాన సేవలను తప్పనిసరిగా ఆన్ చేయాలి మరియు అందుబాటులో ఉండాలి."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"ఈ యాప్‌ సెల్ టవర్‌లు మరియు Wi-Fi నెట్‌వర్క్‌ల వంటి నెట్‌వర్క్ మూలాధారాల ఆధారంగా మీ స్థానాన్ని తెలుసుకోగలదు. యాప్‌ ఉపయోగించడానికి మీ ఫోన్‌లో ఈ స్థాన సేవలను తప్పనిసరిగా ఆన్ చేయాలి మరియు అందుబాటులో ఉండాలి."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"నేపథ్యంలో ఖచ్చితమైన స్థానాన్ని యాక్సెస్ చేయి"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"ఈ యాప్ నేపథ్యంలో ఉన్నప్పుడు ఎప్పుడైనా అది మీ ఖచ్చితమైన స్థానాన్ని తెలుసుకోగలదు. యాప్‌ ఉపయోగించడానికి మీ ఫోన్‌లో ఈ స్థాన సేవలను తప్పనిసరిగా ఆన్ చేయాలి మరియు అందుబాటులో ఉండాలి. ఇది బ్యాటరీ వినియోగాన్ని పెంచవచ్చు."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"నేపథ్యంలో స్థానాన్ని యాక్సెస్ చేయి"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"సుమారుగా లేదా ఖచ్చితమైన స్థాన యాక్సెస్‌తో పాటు అదనందా ఇది మంజూరు చేయబడితే, యాప్ నేపథ్యంలో నడుస్తున్నప్పుడు స్థానాన్ని యాక్సెస్ చేయగలదు."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"మీ ఆడియో సెట్టింగ్‌లను మార్చడం"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"వాల్యూమ్ మరియు అవుట్‌పుట్ కోసం ఉపయోగించాల్సిన స్పీకర్ వంటి సార్వజనీన ఆడియో సెట్టింగ్‌లను సవరించడానికి యాప్‌ను అనుమతిస్తుంది."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"ఆడియోను రికార్డ్ చేయడం"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"ఈ యాప్ మైక్రోఫోన్‌ని ఉపయోగించి ఎప్పుడైనా ఆడియోను రికార్డ్ చేయగలదు."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"SIMకి ఆదేశాలను పంపడం"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"సిమ్‌కు ఆదేశాలను పంపడానికి అనువర్తనాన్ని అనుమతిస్తుంది. ఇది చాలా ప్రమాదకరం."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"భౌతిక కార్యాకలాపాన్ని గుర్తించండి"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"ఈ యాప్ మీ భౌతిక కార్యాకలాపాన్ని గుర్తించగలదు."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"చిత్రాలు మరియు వీడియోలు తీయడం"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"ఈ యాప్‌ కెమెరాను ఉపయోగించి ఎప్పుడైనా చిత్రాలను తీయగలదు మరియు వీడియోలను రికార్డ్ చేయగలదు."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"వైబ్రేషన్‌ను నియంత్రించడం"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"మీ ఫోటో సేకరణను సవరించడానికి యాప్‌ను అనుమతిస్తుంది."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"మీ మీడియా సేకరణ నుండి స్థానాలను చదవండి"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"మీ మీడియా సేకరణ నుండి స్థానాలను చదవడానికి యాప్‌ను అనుమతిస్తుంది."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"అప్లికేషన్ <xliff:g id="APP">%s</xliff:g>కు ప్రమాణీకరణ అవసరం."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"బయోమెట్రిక్ హార్డ్‌వేర్‌ అందుబాటులో లేదు"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"పాక్షిక వేలిముద్ర గుర్తించబడింది. దయచేసి మళ్లీ ప్రయత్నించండి."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"వేలిముద్రను ప్రాసెస్ చేయడం సాధ్యపడలేదు. దయచేసి మళ్లీ ప్రయత్నించండి."</string>
@@ -1898,14 +1904,14 @@
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> స్వీయ పూరింపు సూచనలు</item>
       <item quantity="one">ఒక స్వీయ పూరింపు సూచన</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;కు సేవ్ చేయాలా?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"<xliff:g id="TYPE">%1$s</xliff:g>ని &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;కు సేవ్ చేయాలా?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"<xliff:g id="TYPE_0">%1$s</xliff:g> మరియు <xliff:g id="TYPE_1">%2$s</xliff:g>లను &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;కు సేవ్ చేయాలా?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> మరియు <xliff:g id="TYPE_2">%3$s</xliff:g>లను &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;కు సేవ్ చేయాలా?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;కు అప్‌డేట్ చేయాలా?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"<xliff:g id="TYPE">%1$s</xliff:g>ని &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;కు అప్‌డేట్ చేయాలా?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"<xliff:g id="TYPE_0">%1$s</xliff:g> మరియు <xliff:g id="TYPE_1">%2$s</xliff:g>లను &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;కు అప్‌డేట్ చేయాలా?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> మరియు <xliff:g id="TYPE_2">%3$s</xliff:g>లను &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;కు అప్‌డేట్ చేయాలా?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"లో సేవ్ చేయాలా?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"<xliff:g id="TYPE">%1$s</xliff:g>ని "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"లో సేవ్ చేయాలా?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"<xliff:g id="TYPE_0">%1$s</xliff:g> మరియు <xliff:g id="TYPE_1">%2$s</xliff:g>ని "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"లో సేవ్ చేయాలా?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>,మరియు<xliff:g id="TYPE_2">%3$s</xliff:g>ని "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"లో సేవ్ చేయాలా?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"లో అప్‌డేట్ చేయాలా?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"<xliff:g id="TYPE">%1$s</xliff:g>ని "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"లో అప్‌డేట్ చేయాలా?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"<xliff:g id="TYPE_0">%1$s</xliff:g> మరియు <xliff:g id="TYPE_1">%2$s</xliff:g>ని "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"లో అప్‌డేట్ చేయాలా?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"ఈ అంశాలను "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"లో అప్‌డేట్ చేయాలా: <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> మరియు <xliff:g id="TYPE_2">%3$s</xliff:g> ?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"సేవ్ చేయి"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"వద్దు, ధన్యవాదాలు"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"అప్‌డేట్ చేయి"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 0b7e031..ebbf155 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"ไมโครโฟน"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"บันทึกเสียง"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"อนุญาตให้ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; บันทึกเสียงไหม"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"การจดจำกิจกรรม"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"จดจำกิจกรรม"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"อนุญาตให้ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; จดจำกิจกรรมการเคลื่อนไหวร่างกายของคุณไหม"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"กล้องถ่ายรูป"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"ถ่ายภาพและบันทึกวิดีโอ"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"อนุญาตให้ &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ถ่ายรูปและบันทึกวิดีโอไหม"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"แอปนี้สามารถรับตำแหน่งของคุณโดยอิงจากแหล่งข้อมูลเครือข่าย เช่น เสาสัญญาณมือถือและเครือข่าย Wi-Fi แอปจะใช้บริการตำแหน่งเหล่านี้ได้ต่อเมื่อคุณเปิดบริการและบริการพร้อมใช้งานในแท็บเล็ตของคุณ"</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"แอปนี้สามารถรับตำแหน่งของคุณโดยอิงจากแหล่งข้อมูลเครือข่าย เช่น เสาสัญญาณมือถือและเครือข่าย Wi-Fi แอปจะใช้บริการตำแหน่งเหล่านี้ได้ต่อเมื่อคุณเปิดบริการและบริการพร้อมใช้งานในทีวีของคุณ"</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"แอปนี้สามารถรับตำแหน่งของคุณโดยอิงจากแหล่งข้อมูลเครือข่าย เช่น เสาสัญญาณมือถือและเครือข่าย Wi-Fi แอปจะใช้บริการตำแหน่งเหล่านี้ได้ต่อเมื่อคุณเปิดบริการและบริการพร้อมใช้งานในโทรศัพท์ของคุณ"</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"เข้าถึงตำแหน่งที่แม่นยำเมื่ออยู่เบื้องหลัง"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"แอปนี้รับตำแหน่งที่แม่นยำของคุณได้ทุกเมื่อที่ทำงานอยู่เบื้องหลัง แอปจะใช้บริการตำแหน่งเหล่านี้ได้ต่อเมื่อคุณเปิดบริการและบริการพร้อมใช้งานในโทรศัพท์ของคุณ ซึ่งอาจทำให้มีการใช้แบตเตอรี่มากขึ้น"</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"เข้าถึงตำแหน่งในเบื้องหลัง"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"หากได้รับสิทธิ์นี้เพิ่มจากการเข้าถึงตำแหน่งโดยประมาณหรือตำแหน่งที่แม่นยำ แอปจะมีสิทธิ์เข้าถึงตำแหน่งระหว่างที่ทำงานในเบื้องหลังได้"</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"เปลี่ยนการตั้งค่าเสียงของคุณ"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"อนุญาตให้แอปพลิเคชันปรับเปลี่ยนการตั้งค่าเสียงทั้งหมดได้ เช่น ระดับเสียงและลำโพงที่จะใช้งาน"</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"บันทึกเสียง"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"แอปนี้สามารถบันทึกเสียงด้วยไมโครโฟนได้ทุกเมื่อ"</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"ส่งคำสั่งไปยังซิม"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"อนุญาตให้แอปส่งคำสั่งไปยัง SIM ซึ่งอันตรายมาก"</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"จดจำกิจกรรมการเคลื่อนไหวร่างกาย"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"แอปนี้จดจำกิจกรรมการเคลื่อนไหวร่างกายของคุณได้"</string>
     <string name="permlab_camera" msgid="3616391919559751192">"ถ่ายภาพและวิดีโอ"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"แอปนี้สามารถถ่ายภาพและวิดีโอด้วยกล้องได้ทุกเมื่อ"</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"ควบคุมการสั่นเตือน"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"อนุญาตให้แอปแก้ไขคอลเล็กชันรูปภาพของคุณ"</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"อ่านตำแหน่งจากคอลเล็กชันสื่อของคุณ"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"อนุญาตให้แอปอ่านตำแหน่งจากคอลเล็กชันสื่อของคุณ"</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"แอปพลิเคชัน <xliff:g id="APP">%s</xliff:g> ต้องการตรวจสอบสิทธิ์"</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"ฮาร์ดแวร์ไบโอเมตริกไม่พร้อมใช้งาน"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"ตรวจพบลายนิ้วมือเพียงบางส่วน โปรดลองอีกครั้ง"</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"ไม่สามารถประมวลผลลายนิ้วมือได้ โปรดลองอีกครั้ง"</string>
@@ -1897,14 +1903,14 @@
       <item quantity="other">คำแนะนำสำหรับการป้อนอัตโนมัติ <xliff:g id="COUNT">%1$s</xliff:g> รายการ</item>
       <item quantity="one">คำแนะนำสำหรับการป้อนอัตโนมัติ 1 รายการ</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"บันทึกไปยัง &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; ใช่ไหม"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"บันทึก <xliff:g id="TYPE">%1$s</xliff:g> ไปยัง &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; ใช่ไหม"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"บันทึก <xliff:g id="TYPE_0">%1$s</xliff:g> และ <xliff:g id="TYPE_1">%2$s</xliff:g> ไปยัง &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; ใช่ไหม"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"บันทึก <xliff:g id="TYPE_0">%1$s</xliff:g> <xliff:g id="TYPE_1">%2$s</xliff:g> และ <xliff:g id="TYPE_2">%3$s</xliff:g> ไปยัง &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; ใช่ไหม"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"อัปเดตเป็น &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; ไหม"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"อัปเดต<xliff:g id="TYPE">%1$s</xliff:g>เป็น &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; ไหม"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"อัปเดต<xliff:g id="TYPE_0">%1$s</xliff:g>และ<xliff:g id="TYPE_1">%2$s</xliff:g>เป็น &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; ไหม"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"อัปเดต<xliff:g id="TYPE_0">%1$s</xliff:g> <xliff:g id="TYPE_1">%2$s</xliff:g> และ<xliff:g id="TYPE_2">%3$s</xliff:g>เป็น &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; ไหม"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"บันทึกลงใน "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" ไหม"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"บันทึก<xliff:g id="TYPE">%1$s</xliff:g>ลงใน "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" ไหม"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"บันทึก<xliff:g id="TYPE_0">%1$s</xliff:g>และ<xliff:g id="TYPE_1">%2$s</xliff:g>ลงใน "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" ไหม"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"บันทึก<xliff:g id="TYPE_0">%1$s</xliff:g> <xliff:g id="TYPE_1">%2$s</xliff:g> และ<xliff:g id="TYPE_2">%3$s</xliff:g>ลงใน "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" ไหม"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"อัปเดตใน "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" ไหม"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"อัปเดต<xliff:g id="TYPE">%1$s</xliff:g>ใน "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" ไหม"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"อัปเดต<xliff:g id="TYPE_0">%1$s</xliff:g>และ<xliff:g id="TYPE_1">%2$s</xliff:g>ใน "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" ไหม"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"อัปเดตข้อมูล<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> และ<xliff:g id="TYPE_2">%3$s</xliff:g> ใน "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" ไหม"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"บันทึก"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"ไม่เป็นไร"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"อัปเดต"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index e21f59c..e5bde1d 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Mikropono"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"mag-record ng audio"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"Payagan ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na mag-record ng audio?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"Pagtukoy ng aktibidad"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"tukuyin ang aktibidad"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"Payagan ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na tukuyin ang iyong pisikal na aktibidad?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Camera"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"kumuha ng mga larawan at mag-record ng video"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"Payagan ang &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; na kumuha ng mga larawan at mag-record ng video?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Makukuha ng app na ito ang iyong lokasyon batay sa mga pinagmulan ng network gaya ng mga cell tower at Wi-Fi network. Ang mga serbisyo ng lokasyon na ito ay dapat naka-on at available sa iyong tablet para sa app upang magamit ang mga ito."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Makukuha ng app na ito ang iyong lokasyon batay sa mga pinagmulan ng network gaya ng mga cell tower at Wi-Fi network. Ang mga serbisyo ng lokasyon na ito ay dapat naka-on at available sa iyong TV para sa app upang magamit ang mga ito."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Makukuha ng app na ito ang iyong lokasyon batay sa mga pinagmulan ng network gaya ng mga cell tower at Wi-Fi network. Ang mga serbisyo ng lokasyon na ito ay dapat naka-on at available sa iyong telepono para sa app upang magamit ang mga ito."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"i-access ang tumpak na lokasyon sa background"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"Makukuha ng app na ito ang iyong eksaktong lokasyon anumang oras na nasa background ito. Ang mga serbisyo ng lokasyon na ito ay dapat naka-on at available sa iyong telepono para magamit ng app ang mga ito. Maaaring lumakas ang pagkonsumo ng baterya dahil dito."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"i-access ang lokasyon sa background"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Kung papahintulutan ito bukod pa sa pag-access sa tinataya o tumpak na lokasyon, maaaring i-access ng app ang lokasyon habang tumatakbo sa background."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"baguhin ang mga setting ng iyong audio"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Pinapayagan ang app na baguhin ang mga pandaigdigang setting ng audio gaya ng volume at kung aling speaker ang ginagamit para sa output."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"mag-record ng audio"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"Makakapag-record ng audio ang app na ito gamit ang mikropono anumang oras."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"magpadala ng mga command sa SIM"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Pinapahintulutang magpadala ang app ng mga command sa SIM. Napakapanganib nito."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"tukuyin ang pisikal na aktibidad"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"Matutukoy ng app na ito ang iyong pisikal na aktibidad."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"kumuha ng mga larawan at video"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"Makakakuha ng mga larawan at makakapag-record ng mga video ang app na ito gamit ang camera anumang oras."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"kontrolin ang pag-vibrate"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Pinapayagan ang app na baguhin ang iyong koleksyon ng larawan."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"basahin ang mga lokasyon mula sa iyong koleksyon ng media"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Pinapayagan ang app na basahin ang mga lokasyon mula sa iyong koleksyon ng media."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"Gustong mag-authenticate ng app na <xliff:g id="APP">%s</xliff:g>."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Walang biometric hardware"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Hindi buo ang natukoy na fingerprint. Pakisubukang muli."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Hindi maproseso ang fingerprint. Pakisubukang muli."</string>
@@ -1897,14 +1903,14 @@
       <item quantity="one"><xliff:g id="COUNT">%1$s</xliff:g> suhestyon sa autofill</item>
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> na suhestyon sa autofill</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"I-save sa &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"I-save ang <xliff:g id="TYPE">%1$s</xliff:g> sa &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"I-save ang <xliff:g id="TYPE_0">%1$s</xliff:g> at <xliff:g id="TYPE_1">%2$s</xliff:g> sa &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"I-save ang <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, at <xliff:g id="TYPE_2">%3$s</xliff:g> sa &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"I-update sa &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"I-update ang <xliff:g id="TYPE">%1$s</xliff:g> sa &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"I-update ang <xliff:g id="TYPE_0">%1$s</xliff:g> at <xliff:g id="TYPE_1">%2$s</xliff:g> sa &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"I-update ang <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, at <xliff:g id="TYPE_2">%3$s</xliff:g> sa &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"I-save sa "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"I-save ang <xliff:g id="TYPE">%1$s</xliff:g> sa "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"I-save ang <xliff:g id="TYPE_0">%1$s</xliff:g> at <xliff:g id="TYPE_1">%2$s</xliff:g> sa "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"I-save ang <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, at <xliff:g id="TYPE_2">%3$s</xliff:g> sa "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"I-update sa "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"I-update ang <xliff:g id="TYPE">%1$s</xliff:g> sa "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"I-update ang <xliff:g id="TYPE_0">%1$s</xliff:g> at <xliff:g id="TYPE_1">%2$s</xliff:g> sa "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"I-update ang mga item na ito sa "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, at <xliff:g id="TYPE_2">%3$s</xliff:g> ?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"I-save"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Hindi, salamat na lang"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"I-update"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 912db20..18e1911 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Mikrofon"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"ses kaydetme"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uygulamasının ses kaydetmesine izin verilsin mi?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"Aktivite algılama"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"aktiviteyi algıla"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uygulamasına fiziksel aktivitenizi algılama izni verilsin mi?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Kamera"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"fotoğraf çekme ve video kaydetme"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uygulamasının resim çekmesine ve video kaydı yapmasına izin verilsin mi?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Bu uygulama baz istasyonu ve kablosuz ağ gibi ağ kaynaklarını kullanarak konumunuzu belirleyebilir. Uygulamanın bu hizmetleri kullanabilmesi için tabletinizde bu konum hizmetleri açık ve kullanılabilir olmalıdır."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Bu uygulama baz istasyonu ve kablosuz ağ gibi ağ kaynaklarını kullanarak konumunuzu belirleyebilir. Uygulamanın bu hizmetleri kullanabilmesi için TV\'nizde bu konum hizmetleri açık ve kullanılabilir olmalıdır."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Bu uygulama baz istasyonu ve kablosuz ağ gibi ağ kaynaklarını kullanarak konumunuzu belirleyebilir. Uygulamanın bu hizmetleri kullanabilmesi için telefonunuzda bu konum hizmetleri açık ve kullanılabilir olmalıdır."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"arka planda kesin konuma erişme"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"Bu uygulama arka plandayken istediği zaman kesin konumunuzu alabilir. Uygulamanın bu hizmetleri kullanabilmesi için telefonunuzda bu konum hizmetleri açık ve kullanılabilir olmalıdır. Bu, pil tüketimini artırabilir."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"konum bilgisine arka planda eriş"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Bu izin, yaklaşık veya tam konum erişimine ek olarak verilirse uygulama, konum bilgisine arka planda çalışırken erişebilir."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"ses ayarlarınızı değiştirin"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Uygulamaya ses düzeyi ve ses çıkışı için kullanılan hoparlör gibi genel ses ayarlarını değiştirme izni verir."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"ses kaydet"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"Bu uygulama, istediği zaman mikrofonu kullanarak ses kaydedebilir."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"SIM karta komut gönderme"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Uygulamanın SIM karta komut göndermesine izin verir. Bu izin çok tehlikelidir."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"fiziksel aktiviteyi algıla"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"Bu uygulama fiziksel aktivitenizi algılayabilir."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"resim çekme ve görüntü kaydetme"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"Bu uygulama, herhangi bir zamanda kamerayı kullanarak fotoğraf ve video çekebilir."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"titreşimi denetleme"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Uygulamanın fotoğraf koleksiyonunuzu değiştirmesine izin verir."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"medya koleksiyonunuzdaki konumları okuma"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Uygulamanın medya koleksiyonunuzdaki konumları okumasına izin verir."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"<xliff:g id="APP">%s</xliff:g> uygulaması kimlik doğrulamak istiyor."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Biyometrik donanım kullanılamıyor"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Parmak izinin tümü algılanamadı. Lütfen tekrar deneyin."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Parmak izi işlenemedi. Lütfen tekrar deneyin."</string>
@@ -1897,14 +1903,14 @@
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> otomatik doldurma önerisi</item>
       <item quantity="one">Bir otomatik doldurma önerisi</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; hizmetine kaydedilsin mi?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"<xliff:g id="TYPE">%1$s</xliff:g>, &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; hizmetine kaydedilsin mi?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"<xliff:g id="TYPE_0">%1$s</xliff:g> ve <xliff:g id="TYPE_1">%2$s</xliff:g>, &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; hizmetine kaydedilsin mi?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ve <xliff:g id="TYPE_2">%3$s</xliff:g>, &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; hizmetine kaydedilsin mi?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; hizmetine güncellensin mi?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"<xliff:g id="TYPE">%1$s</xliff:g>, &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; hizmetine güncellensin mi?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"<xliff:g id="TYPE_0">%1$s</xliff:g>  ve <xliff:g id="TYPE_1">%2$s</xliff:g>, &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; hizmetine güncellensin mi?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ve <xliff:g id="TYPE_2">%3$s</xliff:g>, &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;hizmetine güncellensin mi?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" hizmetine kaydedilsin mi?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"<xliff:g id="TYPE">%1$s</xliff:g> "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" hizmetine kaydedilsin mi?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"<xliff:g id="TYPE_0">%1$s</xliff:g> ve <xliff:g id="TYPE_1">%2$s</xliff:g> "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" hizmetine kaydedilsin mi?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ve <xliff:g id="TYPE_2">%3$s</xliff:g> "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" hizmetine kaydedilsin mi?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" hizmetinde güncellensin mi?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"<xliff:g id="TYPE">%1$s</xliff:g> "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" hizmetinde güncellensin mi?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"<xliff:g id="TYPE_0">%1$s</xliff:g> ve <xliff:g id="TYPE_1">%2$s</xliff:g> "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" hizmetinde güncellensin mi?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"Şu öğeler "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" hizmetinde güncellensin mi: <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> ve <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Kaydet"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Hayır, teşekkürler"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"Güncelle"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index f84e3e2..e9f44bf 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -298,6 +298,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Мікрофон"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"записувати аудіо"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"Дозволити додатку &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; записувати аудіо?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"Розпізнавання активності"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"розпізнавати активність"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"Дозволити додатку &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; розпізнавати вашу фізичну активність?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Камера"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"фотографувати та записувати відео"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"Дозволити додатку &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; робити знімки та записувати відео?"</string>
@@ -424,14 +427,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Цей додаток може отримувати дані про ваше місцезнаходження на основі джерел мережі, як-от антен мобільного зв’язку та мереж Wi-Fi. Щоб додаток міг користуватися цими службами локації, вони мають бути доступними й увімкненими на вашому планшеті."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Цей додаток може отримувати дані про ваше місцезнаходження на основі джерел мережі, як-от антен мобільного зв’язку та мереж Wi-Fi. Щоб додаток міг користуватися цими службами локації, вони мають бути доступними й увімкненими на вашому телевізорі."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Цей додаток може отримувати дані про ваше місцезнаходження на основі джерел мережі, як-от антен мобільного зв’язку та мереж Wi-Fi. Щоб додаток міг користуватися цими службами локації, вони мають бути доступними й увімкненими на вашому телефоні."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"отримувати доступ до даних про точне місцезнаходження у фоновому режимі"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"Цей додаток може будь-коли отримувати дані про ваше точне місцезнаходження у фоновому режимі. Щоб додаток користувався службами локації, вони мають бути наявні й увімкнені на вашому телефоні. Через це може швидше розряджатись акумулятор."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"доступ до геоданих у фоновому режимі"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Якщо ви надасте цей дозвіл і доступ до приблизного або точного місцезнаходження, додаток зможе отримувати геодані у фоновому режимі."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"змінювати налаштув-ня звуку"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Дозволяє програмі змінювати загальні налаштування звуку, як-от гучність і динамік, який використовується для виводу сигналу."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"запис-ти аудіо"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"Цей додаток може будь-коли записувати звук за допомогою мікрофона."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"надсилати команди на SIM-карту"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Дозволяє програмі надсилати команди на SIM-карту. Це дуже небезпечно."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"розпізнавати фізичну активність"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"Цей додаток може розпізнавати фізичну активність."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"фотограф. та знімати відео"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"Цей додаток може будь-коли робити фотографії та записувати відео за допомогою камери."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"контролювати вібросигнал"</string>
@@ -524,6 +529,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Додаток зможе змінювати вашу колекцію фотографій."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"розпізнавати геодані з колекції медіа-вмісту"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Додаток зможе розпізнавати геодані з вашої колекції медіа-вмісту."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"Для додатка <xliff:g id="APP">%s</xliff:g> потрібна автентифікація."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Біометричне апаратне забезпечення недоступне"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Відбиток розпізнано частково. Повторіть спробу."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Не вдалось обробити відбиток. Повторіть спробу."</string>
@@ -1967,14 +1973,14 @@
       <item quantity="many"><xliff:g id="COUNT">%1$s</xliff:g> пропозицій автозаповнення</item>
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> пропозиції автозаповнення</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"Зберегти дані в службі &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Зберегти дані (<xliff:g id="TYPE">%1$s</xliff:g>) у службі &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Зберегти дані (<xliff:g id="TYPE_0">%1$s</xliff:g> і <xliff:g id="TYPE_1">%2$s</xliff:g>) у службі &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Зберегти дані (<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> і <xliff:g id="TYPE_2">%3$s</xliff:g>) у службі &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"Оновити дані в сервісі &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Оновити дані (<xliff:g id="TYPE">%1$s</xliff:g>) у сервісі &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Оновити дані (<xliff:g id="TYPE_0">%1$s</xliff:g> і <xliff:g id="TYPE_1">%2$s</xliff:g>) у сервісі &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Оновити дані (<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> і <xliff:g id="TYPE_2">%3$s</xliff:g>) у сервісі &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"Зберегти в сервісі "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"Зберегти дані (<xliff:g id="TYPE">%1$s</xliff:g>) у сервісі "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"Зберегти дані (<xliff:g id="TYPE_0">%1$s</xliff:g> і <xliff:g id="TYPE_1">%2$s</xliff:g>) у сервісі "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"Зберегти дані (<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> і <xliff:g id="TYPE_2">%3$s</xliff:g>) у сервісі "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"Оновити в сервісі "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"Оновити дані (<xliff:g id="TYPE">%1$s</xliff:g>) у сервісі "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"Оновити дані (<xliff:g id="TYPE_0">%1$s</xliff:g> і <xliff:g id="TYPE_1">%2$s</xliff:g>) у сервісі "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"Оновити в сервісі "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" такі дані: <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> і <xliff:g id="TYPE_2">%3$s</xliff:g>?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Зберегти"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Ні, дякую"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"Оновити"</string>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index dc801cd..96bd9a3 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"مائکروفون"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"آڈیو ریکارڈ کریں"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"‏&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; کو آڈیو ریکارڈ کرنے کی اجازت دیں؟"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"سرگرمی کی شناخت"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"سرگرمی کی شناخت کریں"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"‏&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; کو آپ کی جسمانی سرگرمی کی شناخت کرنے کی اجازت دیں؟"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"کیمرا"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"تصاویر لیں اور ویڈیو ریکارڈ کریں"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"‏&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; کو تصاویر لینے اور ویڈیو ریکارڈ کرنے کی اجازت دیں؟"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"‏نیٹ ورک مآخذات جیسے کہ سیل ٹاورز اور Wi-Fi نیٹ ورکس کی بنیاد پر یہ ایپ آپ کا مقام حاصل کر سکتی ہے۔ ایپ کو ان مقام کی سروسز کو استعمال کرنے کیلئے ان کا آن ہونا اور آپ کے ٹیبلیٹ پر دستیاب ہونا ضروری ہے۔"</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"‏نیٹ ورک مآخذات جیسے کہ سیل ٹاورز اور Wi-Fi نیٹ ورکس کی بنیاد پر یہ ایپ آپ کا مقام حاصل کر سکتی ہے۔ ایپ کو ان مقام کی سروسز کو استعمال کرنے کیلئے ان کا آن ہونا اور آپ کے TV پر دستیاب ہونا ضروری ہے۔"</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"‏نیٹ ورک مآخذات جیسے کہ سیل ٹاورز اور Wi-Fi نیٹ ورکس کی بنیاد پر یہ ایپ آپ کا مقام حاصل کر سکتی ہے۔ ایپ کو ان مقام کی سروسز کو استعمال کرنے کیلئے ان کا آن ہونا اور آپ کے فون پر دستیاب ہونا ضروری ہے۔"</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"پس منظر میں درست مقام تک رسائی حاصل کریں"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"یہ ایپ جب بھی پس منظر میں ہو آپ کا صحیح مقام حاصل کر سکتی ہے۔ ایپ کو ان مقام کی سروسز کو استعمال کر سکنے کیلئے ان کا آن ہونا اور آپ کے فون پر دستیاب ہونا ضروری ہے۔"</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"پس منظر میں مقام کی رسائی حاصل کریں"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"اگر اضافی طور پر اسے تخمینی یا درست مقام تک رسائی کی منظوری دی جاتی ہے تو پس منظر میں چلنے کے دوران ایپ اس مقام تک رسائی حاصل کر سکتی ہے۔"</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"اپنے آڈیو کی ترتیبات کو تبدیل کریں"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"ایپ کو مجموعی آڈیو ترتیبات جیسے والیوم اور آؤٹ پٹ کیلئے جو اسپیکر استعمال ہوتا ہے اس میں ترمیم کرنے کی اجازت دیتا ہے۔"</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"آڈیو ریکارڈ کریں"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"یہ ایپ کسی بھی وقت مائیکروفون استعمال کرتے ہوئے آڈیو ریکارڈ کر سکتی ہے۔"</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"‏SIM کو ہدایات بھیجیں"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"‏ایپ کو SIM کو کمانڈز بھیجنے کی اجازت دیتا ہے۔ یہ بہت خطرناک ہے۔"</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"جسمانی سرگرمی کی شناخت کریں"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"یہ ایپ آپ کی جسمانی سرگرمی کی شناخت کر سکتی ہے۔"</string>
     <string name="permlab_camera" msgid="3616391919559751192">"تصاویر لیں اور ویڈیوز بنائیں"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"یہ ایپ کسی بھی وقت کیمرا استعمال کرتے ہوئے تصاویر لے سکتی ہے اور ویڈیوز ریکارڈ کر سکتی ہے۔"</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"ارتعاش کو کنٹرول کریں"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"ایپ کو آپ کی تصویر کے مجموعے میں ترمیم کی اجازت دیتا ہے۔"</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"اپنی میڈيا کے مجموعے سے مقامات پڑھیں"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"ایپ کو آپ کی میڈيا کے مجموعے سے مقامات پڑھنے کی اجازت دیتا ہے۔"</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"ایپلیکیشن <xliff:g id="APP">%s</xliff:g> تصدیق کرنا چاہتی ہے۔"</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"بایومیٹرک ہارڈ ویئر دستیاب نہیں ہے"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"جزوی فنگر پرنٹ کی شناخت ہوئی۔ براہ کرم دوبارہ کوشش کریں۔"</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"فنگر پرنٹ پر کارروائی نہیں کی جا سکی۔ براہ کرم دوبارہ کوشش کریں۔"</string>
@@ -1898,14 +1904,14 @@
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> آٹو فل تجاویز</item>
       <item quantity="one">ایک آٹو فل تجویز</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"‏&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; میں محفوظ کریں؟"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"‏<xliff:g id="TYPE">%1$s</xliff:g> کو &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; میں محفوظ کریں؟"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"‏<xliff:g id="TYPE_0">%1$s</xliff:g> اور <xliff:g id="TYPE_1">%2$s</xliff:g> کو &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; میں محفوظ کریں؟"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"‏<xliff:g id="TYPE_0">%1$s</xliff:g>،<xliff:g id="TYPE_1">%2$s</xliff:g>، اور <xliff:g id="TYPE_2">%3$s</xliff:g> کو &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; میں محفوظ کریں؟"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"‏&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; میں اپ ڈیٹ کریں؟"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"‏<xliff:g id="TYPE">%1$s</xliff:g> کو &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; میں اپ ڈیٹ کریں؟"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"‏<xliff:g id="TYPE_0">%1$s</xliff:g> اور <xliff:g id="TYPE_1">%2$s</xliff:g> کو &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; میں اپ ڈیٹ کریں؟"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"‏<xliff:g id="TYPE_0">%1$s</xliff:g>،<xliff:g id="TYPE_1">%2$s</xliff:g>، اور <xliff:g id="TYPE_2">%3$s</xliff:g> کو &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; میں اپ ڈیٹ کریں؟"</string>
+    <string name="autofill_save_title" msgid="327541108460384555"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" میں محفوظ کریں؟"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"<xliff:g id="TYPE">%1$s</xliff:g> کو "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" میں محفوظ کریں؟"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"<xliff:g id="TYPE_0">%1$s</xliff:g> اور <xliff:g id="TYPE_1">%2$s</xliff:g> کو "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" میں محفوظ کریں؟"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"<xliff:g id="TYPE_0">%1$s</xliff:g>، <xliff:g id="TYPE_1">%2$s</xliff:g> اور <xliff:g id="TYPE_2">%3$s</xliff:g> کو "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" میں محفوظ کریں؟"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" میں اپ ڈیٹ کریں؟"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233"><b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" میں <xliff:g id="TYPE">%1$s</xliff:g> اپ ڈیٹ کریں؟"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"<xliff:g id="TYPE_0">%1$s</xliff:g> اور <xliff:g id="TYPE_1">%2$s</xliff:g> کو "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" میں اپ ڈیٹ کریں؟"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"ان آئٹمز کو "<b>"<xliff:g id="LABEL">%4$s</xliff:g> "</b>" میں اپ ڈیٹ کریں: <xliff:g id="TYPE_0">%1$s</xliff:g>، <xliff:g id="TYPE_1">%2$s</xliff:g> اور <xliff:g id="TYPE_2">%3$s</xliff:g> ؟"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"محفوظ کریں"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"نہیں، شکریہ"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"اپ ڈیٹ کریں"</string>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index e51b810..ccb9e15 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -100,7 +100,7 @@
     <string name="peerTtyModeVco" msgid="1742404978686538049">"Teng huquqli ishtirokchi teletayp rejimini VCO (gapiradi, eshitolmaydi) qilib o‘zgartirdi"</string>
     <string name="peerTtyModeOff" msgid="3280819717850602205">"Teng huquqli ishtirokchi teletayp rejimini OFF (o‘chirilgan) qilib o‘zgartirdi"</string>
     <string name="serviceClassVoice" msgid="1258393812335258019">"Ovozli aloqa"</string>
-    <string name="serviceClassData" msgid="872456782077937893">"Ma’lumot"</string>
+    <string name="serviceClassData" msgid="872456782077937893">"Internet"</string>
     <string name="serviceClassFAX" msgid="5566624998840486475">"FAKS"</string>
     <string name="serviceClassSMS" msgid="2015460373701527489">"SMS"</string>
     <string name="serviceClassDataAsync" msgid="4523454783498551468">"Asinx"</string>
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Mikrofon"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"ovoz yozib olish"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uchun audio yozib olishga ruxsat berilsinmi?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"Harakatni aniqlash"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"harakatni aniqlash"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uchun jismoniy harakatlaringizni aniqlashga ruxsat berilsinmi?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Kamera"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"suratga olish va video yozib olish"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; uchun surat va videoga olishga ruxsat berilsinmi?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Bu ilova Wi-Fi va uyali tarmoq antennalari kabi tarmoq manbalari asosida joylashuvingiz axborotini olishi mumkin. Ilova ushbu joylashuv xizmatlaridan foydalana olishi uchun ular planshetda yoniq bo‘lishi va ishlashi kerak."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Bu ilova Wi-Fi va uyali tarmoq antennalari kabi tarmoq manbalari asosida joylashuvingiz axborotini olishi mumkin. Ilova ushbu joylashuv xizmatlaridan foydalana olishi uchun ular televizorda yoniq bo‘lishi va ishlashi kerak."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Bu ilova Wi-Fi va uyali tarmoq antennalari kabi tarmoq manbalari asosida joylashuvingiz axborotini olishi mumkin. Ilova ushbu joylashuv xizmatlaridan foydalana olishi uchun ular telefoningizda yoniq bo‘lishi va ishlashi kerak."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"fonda joylashuv axborotini olishga ruxsat"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"Bu ilova fon rejimida aniq joylashuv axborotingizdan foydalanishi mumkin. Ilova ushbu joylashuv xizmatlaridan foydalana olishi uchun ular telefoningizda yoniq turishi va ishlashi kerak. Bunda batareya sarfi oshishi mumkin."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"fonda joylashuv axborotidan foydalanish"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Agar taxminiy yoki aniq joylashuv axborotiga qo‘shimcha tarzda ruxsat berilgan bo‘lsa, ilova ishlayotganda joylashuv axborotidan fonda foydala oladi."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"audio sozlamalaringizni o‘zgartirish"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Ilovalarga tovush va ovoz chiqarish uchun foydalaniladigan karnay kabi global audio sozlamalarini o‘zgartirish uchun ruxsat beradi."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"ovoz yozib olish"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"Bu ilova xohlagan vaqtda mikrofon yordami audio yozib olishi mumkin."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"SIM kartaga buyruqlar yuborish"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Dasturga SIM kartaga buyruqlar jo‘natishga ruxsat beradi. Bu juda ham xavfli."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"jismoniy harakatni aniqlash"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"Bu ilova jismoniy harakatlaringizni aniqlay oladi."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"rasm va videoga olish"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"Bu ilova xohlagan vaqtda kamera orqali suratga olishi va video yozib olishi mumkin."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"tebranishni boshqarish"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Ilovaga suratlar to‘plamingizni o‘zgartirishga ruxsat beradi."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"multimedia to‘plamidan joylashuv axborotini o‘qish"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Ilovaga multimedia to‘plamingizdan joylashuv axborotini o‘qishga ruxsat beradi."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"<xliff:g id="APP">%s</xliff:g> ilovasi qurilma qulfini ochmoqchi."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Biometrik sensor ishlamayapti"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Barmoq izi qisman aniqlandi. Qayta urinib ko‘ring."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Barmoq izi aniqlanmadi. Qayta urinib ko‘ring."</string>
@@ -1898,14 +1904,14 @@
       <item quantity="other">Avtomatik to‘ldirishga oid <xliff:g id="COUNT">%1$s</xliff:g> ta taklif</item>
       <item quantity="one">Avtomatik to‘ldirishga oid bitta taklif</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; xizmatiga saqlansinmi?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"<xliff:g id="TYPE">%1$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; xizmatiga saqlansinmi?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"<xliff:g id="TYPE_0">%1$s</xliff:g> va <xliff:g id="TYPE_1">%2$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; xizmatiga saqlansinmi?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> va <xliff:g id="TYPE_2">%3$s</xliff:g> &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; xizmatiga saqlansinmi?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; xizmatidagi ma’lumot yangilansinmi?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"&lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; xizmatida <xliff:g id="TYPE">%1$s</xliff:g> ma’lumotlari yangilansinmi?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"&lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; xizmatidagi <xliff:g id="TYPE_0">%1$s</xliff:g> va <xliff:g id="TYPE_1">%2$s</xliff:g> ma’lumotlari yangilansinmi?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"&lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; xizmatidagi <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> va <xliff:g id="TYPE_2">%3$s</xliff:g> ma’lumotlari yangilansinmi?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" xizmatiga saqlansinmi?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"<xliff:g id="TYPE">%1$s</xliff:g> "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" xizmatiga saqlansinmi?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"<xliff:g id="TYPE_0">%1$s</xliff:g> va <xliff:g id="TYPE_1">%2$s</xliff:g> "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" xizmatiga saqlansinmi?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> va <xliff:g id="TYPE_2">%3$s</xliff:g> "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" xizmatiga saqlansinmi?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279"><b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" xizmatida yangilansinmi?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"<xliff:g id="TYPE">%1$s</xliff:g> "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" xizmatida yangilansinmi?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"<xliff:g id="TYPE_0">%1$s</xliff:g> va <xliff:g id="TYPE_1">%2$s</xliff:g> "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" xizmatida yangilansinmi?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922"><b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" xizmatidagi <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> va <xliff:g id="TYPE_2">%3$s</xliff:g> yangilansinmi?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Saqlash"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Kerak emas"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"Yangilash"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 4d8a20b..02b9ed9 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Micrô"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"ghi âm"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"Cho phép &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ghi âm?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"Nhận dạng hoạt động"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"nhận dạng hoạt động"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"Bạn có muốn cho phép &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; nhận dạng hoạt động thể chất của mình không?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Máy ảnh"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"chụp ảnh và quay video"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"Cho phép &lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; chụp ảnh và quay video?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Ứng dụng này có thể nhận thông tin vị trí của bạn dựa trên các nguồn mạng như tháp phát sóng di động và mạng Wi-Fi. Các dịch vụ vị trí này phải được bật và khả dụng trên máy tính bảng của bạn để ứng dụng có thể sử dụng chúng."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Ứng dụng này có thể nhận thông tin vị trí của bạn dựa trên các nguồn mạng như tháp phát sóng di động và mạng Wi-Fi. Các dịch vụ vị trí này phải được bật và khả dụng trên TV của bạn để ứng dụng có thể sử dụng chúng."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Ứng dụng này có thể nhận thông tin vị trí của bạn dựa trên các nguồn mạng như tháp phát sóng di động và mạng Wi-Fi. Các dịch vụ vị trí này phải được bật và khả dụng trên điện thoại của bạn để ứng dụng có thể sử dụng chúng."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"truy cập vị trí chính xác trong nền"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"Bất cứ khi nào chạy trong nền, ứng dụng này có thể nhận thông tin vị trí chính xác của bạn. Để ứng dụng có thể sử dụng các dịch vụ vị trí, điện thoại của bạn phải có các dịch vụ này và dịch vụ ở trạng thái bật. Hoạt động này có thể tăng mức tiêu thụ pin."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"truy cập vào vị trí trong nền"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Nếu bạn cấp cho ứng dụng quyền truy cập bổ sung vào vị trị gần đúng hoặc chính xác, thì ứng dụng có thể truy cập vào vị trí đó khi chạy trong nền."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"thay đổi cài đặt âm thanh của bạn"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Cho phép ứng dụng sửa đổi cài đặt âm thanh chung chẳng hạn như âm lượng và loa nào được sử dụng cho thiết bị ra."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"ghi âm"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"Ứng dụng này có thể ghi âm bằng micrô bất kỳ lúc nào."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"gửi lệnh đến SIM"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Cho phép ứng dụng gửi lệnh đến SIM. Việc này rất nguy hiểm."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"nhận dạng hoạt động thể chất"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"Ứng dụng này có thể nhận dạng hoạt động thể chất của bạn."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"chụp ảnh và quay video"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"Ứng dụng này có thể chụp ảnh và quay video bằng máy ảnh bất cứ lúc nào."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"kiểm soát rung"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Cho phép ứng dụng này sửa đổi bộ sưu tập ảnh của bạn."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"đọc vị trí từ bộ sưu tập phương tiện"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Cho phép ứng dụng này đọc vị trí từ bộ sưu tập phương tiện của bạn."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"Ứng dụng <xliff:g id="APP">%s</xliff:g> muốn xác thực."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"Không có phần cứng sinh trắc học"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Đã phát hiện được một phần vân tay. Vui lòng thử lại."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Không thể xử lý vân tay. Vui lòng thử lại."</string>
@@ -1897,14 +1903,14 @@
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> đề xuất tự động điền</item>
       <item quantity="one">Một đề xuất tự động điền</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"Lưu vào &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Lưu <xliff:g id="TYPE">%1$s</xliff:g> vào &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Lưu <xliff:g id="TYPE_0">%1$s</xliff:g> và <xliff:g id="TYPE_1">%2$s</xliff:g> vào &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Lưu <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> và <xliff:g id="TYPE_2">%3$s</xliff:g> vào &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"Bạn có muốn cập nhật cho &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; không?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Bạn có muốn cập nhật <xliff:g id="TYPE">%1$s</xliff:g> cho &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; không?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Bạn có muốn cập nhật <xliff:g id="TYPE_0">%1$s</xliff:g> và <xliff:g id="TYPE_1">%2$s</xliff:g> cho &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; không?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Bạn có muốn cập nhật <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> và <xliff:g id="TYPE_2">%3$s</xliff:g> cho &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; không?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"Lưu vào "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"Lưu <xliff:g id="TYPE">%1$s</xliff:g> vào "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"Lưu <xliff:g id="TYPE_0">%1$s</xliff:g> và <xliff:g id="TYPE_1">%2$s</xliff:g> vào "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"Lưu <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> và <xliff:g id="TYPE_2">%3$s</xliff:g> vào "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"Cập nhật trong "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"Cập nhật <xliff:g id="TYPE">%1$s</xliff:g> trong "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"Cập nhật <xliff:g id="TYPE_0">%1$s</xliff:g> và <xliff:g id="TYPE_1">%2$s</xliff:g> trong "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"Cập nhật các mục này: <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g> và <xliff:g id="TYPE_2">%3$s</xliff:g> trong "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Lưu"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Không, cảm ơn"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"Cập nhật"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 609f9bcf..076d6f9 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"麦克风"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"录制音频"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"允许&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;录音吗?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"运动识别"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"识别运动"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"允许&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;识别您的健身运动吗?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"相机"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"拍摄照片和录制视频"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"允许&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt;拍摄照片和录制视频吗?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"此应用可根据网络来源(例如基站和 WLAN 网络)获取您的位置信息。您的平板电脑必须支持并开启这些位置信息服务,此应用才能使用这些服务。"</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"此应用可根据网络来源(例如基站和 WLAN 网络)获取您的位置信息。您的电视必须支持并开启这些位置信息服务,此应用才能使用这些服务。"</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"此应用可根据网络来源(例如基站和 WLAN 网络)获取您的位置信息。您的手机必须支持并开启这些位置信息服务,此应用才能使用这些服务。"</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"在后台获取精确的位置信息"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"此应用在后台运行时可随时获取您的精确位置信息。您的手机必须支持并开启这些位置信息服务,此应用才能使用这些服务。这可能会增加耗电量。"</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"在后台使用位置信息"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"如果另外授予大致位置信息或精确位置信息访问权限,该应用便可在后台运行时使用位置信息。"</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"更改您的音频设置"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"允许该应用修改全局音频设置,例如音量和用于输出的扬声器。"</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"录音"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"此应用可随时使用麦克风进行录音。"</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"向 SIM 卡发送命令"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"允许应用向SIM卡发送命令(此权限具有很高的危险性)。"</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"识别健身运动"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"此应用可以识别您的健身运动。"</string>
     <string name="permlab_camera" msgid="3616391919559751192">"拍摄照片和视频"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"此应用可随时使用相机拍摄照片和录制视频。"</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"控制振动"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"允许该应用修改您的照片收藏。"</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"从您的媒体收藏中读取位置信息"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"允许该应用从您的媒体收藏中读取位置信息。"</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"<xliff:g id="APP">%s</xliff:g>应用需要进行身份验证。"</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"生物识别硬件无法使用"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"仅检测到部分指纹,请重试。"</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"无法处理指纹,请重试。"</string>
@@ -1897,14 +1903,14 @@
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> 条自动填充建议</item>
       <item quantity="one">1 条自动填充建议</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"要保存到&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;吗?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"要将<xliff:g id="TYPE">%1$s</xliff:g>保存到&lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;吗?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"要将<xliff:g id="TYPE_0">%1$s</xliff:g>和<xliff:g id="TYPE_1">%2$s</xliff:g>保存到&lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;吗?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"要将<xliff:g id="TYPE_0">%1$s</xliff:g>、<xliff:g id="TYPE_1">%2$s</xliff:g>和<xliff:g id="TYPE_2">%3$s</xliff:g>保存到&lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;吗?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"要更新到&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;吗?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"要将<xliff:g id="TYPE">%1$s</xliff:g>更新到&lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;吗?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"要将<xliff:g id="TYPE_0">%1$s</xliff:g>和<xliff:g id="TYPE_1">%2$s</xliff:g>更新到&lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;吗?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"要将<xliff:g id="TYPE_0">%1$s</xliff:g>、<xliff:g id="TYPE_1">%2$s</xliff:g>和<xliff:g id="TYPE_2">%3$s</xliff:g>更新到&lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;吗?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"要保存到"<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"吗?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"要将<xliff:g id="TYPE">%1$s</xliff:g>保存到"<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"吗?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"要将<xliff:g id="TYPE_0">%1$s</xliff:g>和<xliff:g id="TYPE_1">%2$s</xliff:g>保存到"<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"吗?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"要将<xliff:g id="TYPE_0">%1$s</xliff:g>、<xliff:g id="TYPE_1">%2$s</xliff:g>和<xliff:g id="TYPE_2">%3$s</xliff:g>保存到"<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"吗?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"要在"<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"中更新吗?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"要在"<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"中更新<xliff:g id="TYPE">%1$s</xliff:g>吗?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"要在"<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"中更新<xliff:g id="TYPE_0">%1$s</xliff:g>和<xliff:g id="TYPE_1">%2$s</xliff:g>吗?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"要在"<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"中更新<xliff:g id="TYPE_0">%1$s</xliff:g>、<xliff:g id="TYPE_1">%2$s</xliff:g>和<xliff:g id="TYPE_2">%3$s</xliff:g>这些内容吗?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"保存"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"不用了"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"更新"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 2e3c7d7..1484006 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"麥克風"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"錄音"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;錄音嗎?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"活動識別"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"識別活動"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;識別您的運動嗎?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"相機"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"拍照和錄製影片"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;拍照和錄製影片嗎?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"此應用程式可以根據您的網絡來源 (例如手機訊號塔和 Wi-Fi 網絡) 取得您的位置。您的平板電腦必須支援並啟用這些位置資訊服務,應用程式方可使用這項功能。"</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"此應用程式可以根據您的網絡來源 (例如手機訊號塔和 Wi-Fi 網絡) 取得您的位置。您的電視必須支援並啟用這些位置資訊服務,應用程式方可使用這項功能。"</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"此應用程式可以根據您的網絡來源 (例如手機訊號塔和 Wi-Fi 網絡) 取得您的位置。您的手機必須支援並啟用這些位置資訊服務,應用程式方可使用這項功能。"</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"在背景中存取精確位置"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"此應用程式可在背景運行時隨時獲取您的確實位置資訊。您的手機必須支援並啟用這些位置資訊服務,應用程式方可使用這項功能,但這樣做可能會增加耗電量。"</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"在背景存取位置資訊"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"如果您另外授予概略位置或精確位置的存取權,這個應用程式在背景運行時將可存取位置資訊。"</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"更改音效設定"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"允許應用程式修改全域音頻設定,例如音量和用於輸出的喇叭。"</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"錄製音效"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"此應用程式可以隨時使用麥克風錄音。"</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"發送指令至 SIM 卡"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"允許應用程式傳送指令到 SIM 卡。這項操作具有高危險性。"</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"識別運動"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"此應用程式可識別您的運動。"</string>
     <string name="permlab_camera" msgid="3616391919559751192">"拍照和拍攝影片"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"此應用程式可以隨時使用相機拍照和攝錄。"</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"控制震動"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"允許應用程式修改您的相片集。"</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"讀取媒體集的位置"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"允許應用程式讀取媒體集的位置。"</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"「<xliff:g id="APP">%s</xliff:g>」應用程式需要驗證。"</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"無法使用生物識別硬件"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"只偵測到部分指紋。請再試一次。"</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"無法處理指紋。請再試一次。"</string>
@@ -1897,14 +1903,14 @@
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> 個自動填入建議</item>
       <item quantity="one">一個自動填入建議</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"要儲存至「&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;」嗎?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"要將<xliff:g id="TYPE">%1$s</xliff:g>儲存至「&lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;」嗎?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"要將<xliff:g id="TYPE_0">%1$s</xliff:g>和<xliff:g id="TYPE_1">%2$s</xliff:g>儲存至「&lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;」嗎?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"要將<xliff:g id="TYPE_0">%1$s</xliff:g>、<xliff:g id="TYPE_1">%2$s</xliff:g>和<xliff:g id="TYPE_2">%3$s</xliff:g>儲存至「&lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;」嗎?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"要更新至 &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt; 嗎?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"要將<xliff:g id="TYPE">%1$s</xliff:g>更新至 &lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt; 嗎?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"要將<xliff:g id="TYPE_0">%1$s</xliff:g>和<xliff:g id="TYPE_1">%2$s</xliff:g>更新至 &lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt; 嗎?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"要將<xliff:g id="TYPE_0">%1$s</xliff:g>、<xliff:g id="TYPE_1">%2$s</xliff:g>和<xliff:g id="TYPE_2">%3$s</xliff:g>更新至 &lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt; 嗎?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"要儲存至 "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" 嗎?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"要將<xliff:g id="TYPE">%1$s</xliff:g>儲存至 "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" 嗎?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"要將<xliff:g id="TYPE_0">%1$s</xliff:g>和<xliff:g id="TYPE_1">%2$s</xliff:g>儲存至 "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" 嗎?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"要將<xliff:g id="TYPE_0">%1$s</xliff:g>、<xliff:g id="TYPE_1">%2$s</xliff:g>和<xliff:g id="TYPE_2">%3$s</xliff:g>儲存至 "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" 嗎?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"要在 "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" 中更新嗎?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"要在 "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" 中更新<xliff:g id="TYPE">%1$s</xliff:g>嗎?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"要在 "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" 中更新<xliff:g id="TYPE_0">%1$s</xliff:g>和<xliff:g id="TYPE_1">%2$s</xliff:g>嗎?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"要在 "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" 中更新<xliff:g id="TYPE_0">%1$s</xliff:g>、<xliff:g id="TYPE_1">%2$s</xliff:g>和<xliff:g id="TYPE_2">%3$s</xliff:g>嗎?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"儲存"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"不用了,謝謝"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"更新"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 9149f47..608a758 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"麥克風"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"錄音"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」錄音嗎?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"活動識別"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"辨識活動"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」&lt;b&gt;&lt;/b&gt;辨識你從事的體能活動嗎?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"相機"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"拍照及錄製影片"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"要允許「<xliff:g id="APP_NAME">%1$s</xliff:g>」拍攝相片及錄製影片嗎?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"這個應用程式可根據網路來源 (例如基地台和 Wi-Fi 網路) 取得你的位置資訊。你必須在平板電腦上開啟這類定位服務,才能讓這個應用程式取得位置資訊。"</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"這個應用程式可根據網路來源 (例如基地台和 Wi-Fi 網路) 取得你的位置資訊。你必須在電視上開啟這類定位服務,才能讓這個應用程式取得位置資訊。"</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"這個應用程式可根據網路來源 (例如基地台和 Wi-Fi 網路) 取得你的位置資訊。你必須在手機上開啟這類定位服務,才能讓這個應用程式取得位置資訊。"</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"在背景中取得精確位置"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"這個應用程式可在背景中隨時取得你的確切位置。你必須在手機上開啟這些定位服務,才能讓這個應用程式取得確切位置。請注意,這麼做可能會增加耗電量。"</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"在背景存取位置資訊"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"除了概略位置或精確位置的存取權外,若您另外授予這項存取權,這個應用程式就能在背景執行時存取位置資訊。"</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"變更音訊設定"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"允許應用程式修改全域音訊設定,例如音量和用來輸出的喇叭。"</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"錄製音訊"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"這個應用程式隨時可使用麥克風錄音。"</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"傳送指令到 SIM 卡"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"允許應用程式傳送指令到 SIM 卡。這麼做非常危險。"</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"辨識體能活動"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"這個應用程式可以辨識你從事的體能活動。"</string>
     <string name="permlab_camera" msgid="3616391919559751192">"拍攝相片和影片"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"這個應用程式隨時可使用相機拍照及錄影。"</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"控制震動"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"允許應用程式修改你的相片收藏。"</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"讀取你的媒體收藏的位置資訊"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"允許應用程式讀取你的媒體收藏的位置資訊。"</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"「<xliff:g id="APP">%s</xliff:g>」應用程式需要驗證使用者身分。"</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"無法使用生物特徵辨識硬體"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"僅偵測到部分指紋,請再試一次。"</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"無法處理指紋,請再試一次。"</string>
@@ -1897,14 +1903,14 @@
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> 項自動填入建議</item>
       <item quantity="one">1 項自動填入建議</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"要儲存到「<xliff:g id="LABEL">%1$s</xliff:g>」嗎?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"要將<xliff:g id="TYPE">%1$s</xliff:g>儲存到「<xliff:g id="LABEL">%2$s</xliff:g>」嗎?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"要將<xliff:g id="TYPE_0">%1$s</xliff:g>和<xliff:g id="TYPE_1">%2$s</xliff:g>儲存到「<xliff:g id="LABEL">%3$s</xliff:g>」嗎?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"要將<xliff:g id="TYPE_0">%1$s</xliff:g>、<xliff:g id="TYPE_1">%2$s</xliff:g>和<xliff:g id="TYPE_2">%3$s</xliff:g>儲存到「<xliff:g id="LABEL">%4$s</xliff:g>」嗎?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"要更新「<xliff:g id="LABEL">%1$s</xliff:g>」中的資料嗎?&lt;b&gt;&lt;/b&gt;"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"要更新「<xliff:g id="LABEL">%2$s</xliff:g>」中的<xliff:g id="TYPE">%1$s</xliff:g>嗎?&lt;b&gt;&lt;/b&gt;"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"要更新「<xliff:g id="LABEL">%3$s</xliff:g>」中的<xliff:g id="TYPE_0">%1$s</xliff:g>和<xliff:g id="TYPE_1">%2$s</xliff:g>嗎?&lt;b&gt;&lt;/b&gt;"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"要更新「<xliff:g id="LABEL">%4$s</xliff:g>」中的<xliff:g id="TYPE_0">%1$s</xliff:g>、<xliff:g id="TYPE_1">%2$s</xliff:g>和<xliff:g id="TYPE_2">%3$s</xliff:g>嗎?&lt;b&gt;&lt;/b&gt;"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"要儲存到 "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" 嗎?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"要將<xliff:g id="TYPE">%1$s</xliff:g>儲存到 "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" 嗎?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"要將<xliff:g id="TYPE_0">%1$s</xliff:g>和<xliff:g id="TYPE_1">%2$s</xliff:g>儲存到 "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" 嗎?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"要將<xliff:g id="TYPE_0">%1$s</xliff:g>、<xliff:g id="TYPE_1">%2$s</xliff:g>和<xliff:g id="TYPE_2">%3$s</xliff:g>儲存到 "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" 嗎?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"要更新 "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" 中的內容嗎?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"要更新 "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" 中的<xliff:g id="TYPE">%1$s</xliff:g>嗎?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"要更新 "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" 中的<xliff:g id="TYPE_0">%1$s</xliff:g>和<xliff:g id="TYPE_1">%2$s</xliff:g>嗎?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"要更新 "<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>" 中的<xliff:g id="TYPE_0">%1$s</xliff:g>、<xliff:g id="TYPE_1">%2$s</xliff:g>和<xliff:g id="TYPE_2">%3$s</xliff:g>嗎?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"儲存"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"不用了,謝謝"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"更新"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 75709ca..42a1ad0 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -292,6 +292,9 @@
     <string name="permgrouplab_microphone" msgid="171539900250043464">"I-Microphone"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"rekhoda ividiyo"</string>
     <string name="permgrouprequest_microphone" msgid="9167492350681916038">"Vumela i-&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ukuthi irekhode umsindo?"</string>
+    <string name="permgrouplab_activityRecognition" msgid="2838596644535616493">"Ukubonwa komsebenzi"</string>
+    <string name="permgroupdesc_activityRecognition" msgid="7672248027571522602">"bona umsebenzi"</string>
+    <string name="permgrouprequest_activityRecognition" msgid="8121253142311250055">"Vumela i-&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ukubona umsebenzi wakho?"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Ikhamela"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"thatha izithombe uphinde urekhode ividiyo"</string>
     <string name="permgrouprequest_camera" msgid="1299833592069671756">"Vumela i-&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; ukuthatha izithombe iphinde irekhode ividiyo?"</string>
@@ -418,14 +421,16 @@
     <string name="permdesc_accessCoarseLocation" product="tablet" msgid="3373266766487862426">"Lolu hlelo lokusebenza lungathola indawo yakho ngokususelwe kumithombo yenethiwekhi njengamathawa eseli namanethiwekhi e-Wi-Fi. Lawa masevisi endawo kufanele avulwe futhi atholakale kuthebhulethi yakho ukuze uhlelo lokusebenza lukwazi ukuwasebenzisa."</string>
     <string name="permdesc_accessCoarseLocation" product="tv" msgid="1884022719818788511">"Lolu hlelo lokusebenza lingathola indawo yakho ngokususelwe kumithombo yenethiwekhi njengamathawa eseli namanethiwekhi e-Wi-Fi. Lawa masevisi endawo kufanele avulwe futhi atholakale ku-TV yakho ukuze uhlelo lokusebenza lukwazi ukuwasebenzisa."</string>
     <string name="permdesc_accessCoarseLocation" product="default" msgid="7788009094906196995">"Lolu hlelo lokusebenza lungathola indawo yakho ngokususelwe kumithombo yenethiwekhi njengamathawa eseli kanye namanethiwekhi e-Wi-Fi. Lawa masevisi endawo kufanele avulwe futhi atholakale efonini yakho ukuze uhlelo lokusebenza likwazi ukuwasebenzisa."</string>
-    <string name="permlab_accessBackgroundLocation" msgid="5742466381902568536">"finyelela indawo eqondile emuva"</string>
-    <string name="permdesc_accessBackgroundLocation" msgid="6371533283380774135">"Lolu hlelo lokusebenza lungakutholela indawo eqondile noma kunini lusemuva. Lawa masevisi endawo kufanele avulwe futhi atholakale efonini yakho ukuze uhlelo lokusebenza lukwazi ukuwasebenzisa. Lokhu kungakhulisa ukusebenza kwebhethri."</string>
+    <string name="permlab_accessBackgroundLocation" msgid="3965397804300661062">"finyelela kundawo ngemuva"</string>
+    <string name="permdesc_accessBackgroundLocation" msgid="1096394429579210251">"Uma lokhu kunikezwa ngokungeziwe ekufinyeleleni okulinganiselwe noma okunembile kwendawo uhlelo lokusebenza lungafinyelela kundawo ngenkathi lusebenza ngemuva."</string>
     <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"shintsha izilungiselelo zakho zomsindo"</string>
     <string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Ivumela uhlelo lokusebenza ukushintsha izilungiselelo zomsindo we-global njengevolomu nokuthi isiphi isipika esisetshenziselwa okukhiphayo."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"qopha umsindo"</string>
     <string name="permdesc_recordAudio" msgid="4245930455135321433">"Lolu hlelo lokusebenza lungafunda umsindo lisebenzisa imakrofoni noma kunini."</string>
     <string name="permlab_sim_communication" msgid="2935852302216852065">"thumela imilayezo ku-SIM"</string>
     <string name="permdesc_sim_communication" msgid="5725159654279639498">"Ivumela uhlelo lokusebenza ukuthumela imiyalo ku-SIM. Lokhu kuyingozi kakhulu."</string>
+    <string name="permlab_activityRecognition" msgid="3634590230567608356">"bona umsebenzi"</string>
+    <string name="permdesc_activityRecognition" msgid="3143453925156552894">"Lolu hlelo lokusebenza lingabona umsebenzi wakho."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"thatha izithombe namavidiyo"</string>
     <string name="permdesc_camera" msgid="5392231870049240670">"Lolu hlelo lokusebenza lungathatha izithombe futhi lirekhode amavidiyo lusebenzisa ikhamera noma kunini."</string>
     <string name="permlab_vibrate" msgid="7696427026057705834">"lawula ukudlidliza"</string>
@@ -518,6 +523,7 @@
     <string name="permdesc_imagesWrite" msgid="7073662756617474375">"Ivumela uhlelo lwakho lokusebenza ukuthi lilungise iqoqo lakho lesithombe."</string>
     <string name="permlab_mediaLocation" msgid="8675148183726247864">"funda izindawo kusukela kuqoqo lakho lemidiya"</string>
     <string name="permdesc_mediaLocation" msgid="2237023389178865130">"Ivumela uhlelo lokusebenza ukuthi lifunde izindawo kusukela kuqoqo lakho lemidiya."</string>
+    <string name="biometric_dialog_default_title" msgid="4229778503907743328">"Uhlelo lokusebenza lwe-<xliff:g id="APP">%s</xliff:g> lifuna ukufakazela ubuqiniso."</string>
     <string name="biometric_error_hw_unavailable" msgid="645781226537551036">"I-Biometric hardware ayitholakali"</string>
     <string name="fingerprint_acquired_partial" msgid="735082772341716043">"Izigxivizo zeminwe ezincane zitholiwe. Sicela uzame futhi."</string>
     <string name="fingerprint_acquired_insufficient" msgid="4596546021310923214">"Ayikwazanga ukucubungula izigxivizo zeminwe. Sicela uzame futhi."</string>
@@ -1897,14 +1903,14 @@
       <item quantity="one"><xliff:g id="COUNT">%1$s</xliff:g> iziphakamiso zokugcwalisa ngokuzenzakalelayo</item>
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> iziphakamiso zokugcwalisa ngokuzenzakalelayo</item>
     </plurals>
-    <string name="autofill_save_title" msgid="3345527308992082601">"Londoloza ku-&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_type" msgid="8637809388029313305">"Londoloza i-<xliff:g id="TYPE">%1$s</xliff:g> ku-&lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_2types" msgid="5214035651838265325">"Londoloza i-<xliff:g id="TYPE_0">%1$s</xliff:g> ne-<xliff:g id="TYPE_1">%2$s</xliff:g> ku-&lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_save_title_with_3types" msgid="6943161834231458441">"Londoloza i-<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, ne-<xliff:g id="TYPE_2">%3$s</xliff:g> ku-&lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title" msgid="4879673117448810818">"Buyekezela ku-&lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_type" msgid="339733442087186755">"Buyekeza i-<xliff:g id="TYPE">%1$s</xliff:g> ukuya ku-&lt;b&gt;<xliff:g id="LABEL">%2$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_2types" msgid="6321714204167424745">"Buyekeza i-<xliff:g id="TYPE_0">%1$s</xliff:g> ne-<xliff:g id="TYPE_1">%2$s</xliff:g> ukuya ku-&lt;b&gt;<xliff:g id="LABEL">%3$s</xliff:g>&lt;/b&gt;?"</string>
-    <string name="autofill_update_title_with_3types" msgid="5866735124066629287">"Buyekeza i-<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, ne-<xliff:g id="TYPE_2">%3$s</xliff:g> ukuya ku-&lt;b&gt;<xliff:g id="LABEL">%4$s</xliff:g>&lt;/b&gt;?"</string>
+    <string name="autofill_save_title" msgid="327541108460384555">"Londoloza ku-"<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_type" msgid="2339135393607143594">"Londoloza i-<xliff:g id="TYPE">%1$s</xliff:g> ku-"<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_2types" msgid="87616102361154432">"Londoloza i-<xliff:g id="TYPE_0">%1$s</xliff:g> ne-<xliff:g id="TYPE_1">%2$s</xliff:g> ku-"<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_save_title_with_3types" msgid="4108978552969604555">"Londoloza i-<xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, ne-<xliff:g id="TYPE_2">%3$s</xliff:g> ku-"<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title" msgid="5305781141104585279">"Buyekeza ku-"<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_type" msgid="4624181147422762233">"Buyekeza i-<xliff:g id="TYPE">%1$s</xliff:g> ku-"<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_2types" msgid="2300113827053626484">"Buyekeza i-<xliff:g id="TYPE_0">%1$s</xliff:g> ne-<xliff:g id="TYPE_1">%2$s</xliff:g> ku-"<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string>
+    <string name="autofill_update_title_with_3types" msgid="9089824354296211922">"Buyekeza lezi zinto ku-"<b>"<xliff:g id="LABEL">%4$s</xliff:g>"</b>": <xliff:g id="TYPE_0">%1$s</xliff:g>, <xliff:g id="TYPE_1">%2$s</xliff:g>, ne-<xliff:g id="TYPE_2">%3$s</xliff:g> ?"</string>
     <string name="autofill_save_yes" msgid="6398026094049005921">"Londoloza"</string>
     <string name="autofill_save_no" msgid="2625132258725581787">"Cha ngiyabonga"</string>
     <string name="autofill_update_yes" msgid="310358413273276958">"Buyekeza"</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 32cf2e8..a25c998 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -1141,6 +1141,15 @@
 
         <!-- Alpha value of the spot shadow projected by elevated views, between 0 and 1. -->
         <attr name="spotShadowAlpha" format="float" />
+
+        <!-- <p>Whether or not the force dark feature is allowed to be applied to this theme.
+             <p>Setting this to false will disable the auto-dark feature on everything this
+             theme is applied to along with anything drawn by any children of views using
+             this theme.
+             <p>Setting this to true will allow this view to be automatically made dark, however
+             a value of 'true' will not override any 'false' value in its parent chain nor will
+             it prevent any 'false' in any of its children. -->
+        <attr name="forceDarkAllowed" format="boolean" />
     </declare-styleable>
 
     <!-- **************************************************************** -->
@@ -3116,8 +3125,13 @@
              {@link android.R.attr#ambientShadowAlpha} theme attribute. -->
         <attr name="outlineAmbientShadowColor" format="color" />
 
-        <!-- Whether to allow the rendering system to force this View to render as light-on-dark. -->
-        <attr name="allowForceDark" format="boolean" />
+        <!-- <p>Whether or not the force dark feature is allowed to be applied to this View.
+             <p>Setting this to false will disable the auto-dark feature on this View draws
+             including any descendants.
+             <p>Setting this to true will allow this view to be automatically made dark, however
+             a value of 'true' will not override any 'false' value in its parent chain nor will
+             it prevent any 'false' in any of its children. -->
+        <attr name="forceDarkAllowed" format="boolean" />
     </declare-styleable>
 
     <!-- Attributes that can be assigned to a tag for a particular View. -->
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 097ce44..ba483fb 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -47,6 +47,20 @@
     <dimen name="navigation_bar_height_landscape">48dp</dimen>
     <!-- Width of the navigation bar when it is placed vertically on the screen -->
     <dimen name="navigation_bar_width">48dp</dimen>
+
+    <!-- EXPERIMENT BEGIN -->
+    <!-- Height of the bottom navigation bar frame; this is different than navigation_bar_height
+         where that is the height reported to all the other windows to resize themselves around the
+         navigation bar window but navigation_bar_frame_height is reported to SystemUI navigation
+         bar view's window -->
+    <dimen name="navigation_bar_frame_height">@dimen/navigation_bar_height</dimen>
+    <!-- Width of the left/right navigation bar frame; this is different than navigation_bar_width
+         where that is the width reported to all the other windows to resize themselves around the
+         navigation bar window but navigation_bar_frame_width is reported to SystemUI navigation
+         bar view's window -->
+    <dimen name="navigation_bar_frame_width">@dimen/navigation_bar_width</dimen>
+    <!-- EXPERIMENT END-->
+
     <!-- Height of the bottom navigation / system bar in car mode. -->
     <dimen name="navigation_bar_height_car_mode">96dp</dimen>
     <!-- Height of the bottom navigation bar in portrait; often the same as
diff --git a/core/res/res/values/ids.xml b/core/res/res/values/ids.xml
index 8bca211..3183169 100644
--- a/core/res/res/values/ids.xml
+++ b/core/res/res/values/ids.xml
@@ -175,4 +175,7 @@
 
   <!-- Accessibility action to notify a window there is an outside touch. -->
   <item type="id" name="accessibilityActionOutsideTouch" />
+
+  <!-- A tag used to save the view added to a transition overlay -->
+  <item type="id" name="transition_overlay_view_tag" />
 </resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index fd688a7..b790829 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2908,7 +2908,7 @@
         <public name="opticalInsetTop" />
         <public name="opticalInsetRight" />
         <public name="opticalInsetBottom" />
-        <public name="allowForceDark" />
+        <public name="forceDarkAllowed" />
         <public name="supportsAmbientMode" />
         <!-- @hide For use by platform and tools only. Developers should not specify this value. -->
         <public name="usesNonSdkApi" />
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 81a1bf8..abd653b 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1681,6 +1681,8 @@
   <java-symbol type="dimen" name="navigation_bar_height" />
   <java-symbol type="dimen" name="navigation_bar_height_landscape" />
   <java-symbol type="dimen" name="navigation_bar_width" />
+  <java-symbol type="dimen" name="navigation_bar_frame_height" />
+  <java-symbol type="dimen" name="navigation_bar_frame_width" />
   <java-symbol type="dimen" name="navigation_bar_height_car_mode" />
   <java-symbol type="dimen" name="navigation_bar_height_landscape_car_mode" />
   <java-symbol type="dimen" name="navigation_bar_width_car_mode" />
@@ -3483,4 +3485,6 @@
   <java-symbol type="bool" name="config_useSmsAppService" />
 
   <java-symbol type="string" name="config_defaultAssistantComponentName" />
+
+  <java-symbol type="id" name="transition_overlay_view_tag" />
 </resources>
diff --git a/core/tests/coretests/src/android/content/ContentResolverTest.java b/core/tests/coretests/src/android/content/ContentResolverTest.java
index 0036186..9940bf7 100644
--- a/core/tests/coretests/src/android/content/ContentResolverTest.java
+++ b/core/tests/coretests/src/android/content/ContentResolverTest.java
@@ -158,4 +158,19 @@
 
         assertImageAspectAndContents(res);
     }
+
+    @Test
+    public void testTranslateDeprecatedDataPath() throws Exception {
+        assertTranslate(Uri.parse("content://com.example/path/?foo=bar&baz=meow"));
+        assertTranslate(Uri.parse("content://com.example/path/subpath/12/"));
+        assertTranslate(Uri.parse("content://com.example/path/subpath/12"));
+        assertTranslate(Uri.parse("content://com.example/path/12"));
+        assertTranslate(Uri.parse("content://com.example/"));
+        assertTranslate(Uri.parse("content://com.example"));
+    }
+
+    private static void assertTranslate(Uri uri) {
+        assertEquals(uri, ContentResolver
+                .translateDeprecatedDataPath(ContentResolver.translateDeprecatedDataPath(uri)));
+    }
 }
diff --git a/core/tests/coretests/src/android/content/pm/AndroidHidlUpdaterTest.java b/core/tests/coretests/src/android/content/pm/AndroidHidlUpdaterTest.java
index 7218b3a2..2acb08d 100644
--- a/core/tests/coretests/src/android/content/pm/AndroidHidlUpdaterTest.java
+++ b/core/tests/coretests/src/android/content/pm/AndroidHidlUpdaterTest.java
@@ -36,37 +36,37 @@
     private static final String OTHER_LIBRARY = "other.library";
 
     @Test
-    public void targeted_at_O() {
+    public void targeted_at_P() {
         PackageBuilder before = builder()
-                .targetSdkVersion(Build.VERSION_CODES.O);
+                .targetSdkVersion(Build.VERSION_CODES.P);
 
         // Should add both HIDL libraries
         PackageBuilder after = builder()
-                .targetSdkVersion(Build.VERSION_CODES.O)
+                .targetSdkVersion(Build.VERSION_CODES.P)
                 .requiredLibraries(ANDROID_HIDL_MANAGER, ANDROID_HIDL_BASE);
 
         checkBackwardsCompatibility(before, after);
     }
 
     @Test
-    public void targeted_at_O_not_empty_usesLibraries() {
+    public void targeted_at_P_not_empty_usesLibraries() {
         PackageBuilder before = builder()
-                .targetSdkVersion(Build.VERSION_CODES.O)
+                .targetSdkVersion(Build.VERSION_CODES.P)
                 .requiredLibraries(OTHER_LIBRARY);
 
         // The hidl jars should be added at the start of the list because it
         // is not on the bootclasspath and the package targets pre-P.
         PackageBuilder after = builder()
-                .targetSdkVersion(Build.VERSION_CODES.O)
+                .targetSdkVersion(Build.VERSION_CODES.P)
                 .requiredLibraries(ANDROID_HIDL_MANAGER, ANDROID_HIDL_BASE, OTHER_LIBRARY);
 
         checkBackwardsCompatibility(before, after);
     }
 
     @Test
-    public void targeted_at_O_in_usesLibraries() {
+    public void targeted_at_P_in_usesLibraries() {
         PackageBuilder before = builder()
-                .targetSdkVersion(Build.VERSION_CODES.O)
+                .targetSdkVersion(Build.VERSION_CODES.P)
                 .requiredLibraries(ANDROID_HIDL_MANAGER, ANDROID_HIDL_BASE);
 
         // No change is required because although the HIDL libraries has been removed from
@@ -78,18 +78,24 @@
     public void in_usesLibraries() {
         PackageBuilder before = builder().requiredLibraries(ANDROID_HIDL_BASE);
 
+        // Dependency is removed, it is not available.
+        PackageBuilder after = builder();
+
         // No change is required because the package explicitly requests the HIDL libraries
         // and is targeted at the current version so does not need backwards compatibility.
-        checkBackwardsCompatibility(before, before);
+        checkBackwardsCompatibility(before, after);
     }
 
     @Test
     public void in_usesOptionalLibraries() {
         PackageBuilder before = builder().optionalLibraries(ANDROID_HIDL_BASE);
 
+        // Dependency is removed, it is not available.
+        PackageBuilder after = builder();
+
         // No change is required because the package explicitly requests the HIDL libraries
         // and is targeted at the current version so does not need backwards compatibility.
-        checkBackwardsCompatibility(before, before);
+        checkBackwardsCompatibility(before, after);
     }
 
     private void checkBackwardsCompatibility(PackageBuilder before, PackageBuilder after) {
diff --git a/core/tests/coretests/src/android/os/BinderProxyTest.java b/core/tests/coretests/src/android/os/BinderProxyTest.java
new file mode 100644
index 0000000..4c36b5c
--- /dev/null
+++ b/core/tests/coretests/src/android/os/BinderProxyTest.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+
+public class BinderProxyTest extends AndroidTestCase {
+    private static class CountingListener implements Binder.ProxyTransactListener {
+        int mStartedCount;
+        int mEndedCount;
+
+        public Object onTransactStarted(IBinder binder, int transactionCode) {
+            mStartedCount++;
+            return null;
+        }
+
+        public void onTransactEnded(@Nullable Object session) {
+            mEndedCount++;
+        }
+    };
+
+    private PowerManager mPowerManager;
+
+    /**
+     * Setup any common data for the upcoming tests.
+     */
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+    }
+
+    @MediumTest
+    public void testNoListener() throws Exception {
+        CountingListener listener = new CountingListener();
+        Binder.setProxyTransactListener(listener);
+        Binder.setProxyTransactListener(null);
+
+        mPowerManager.isInteractive();
+
+        assertEquals(0, listener.mStartedCount);
+        assertEquals(0, listener.mEndedCount);
+    }
+
+    @MediumTest
+    public void testListener() throws Exception {
+        CountingListener listener = new CountingListener();
+        Binder.setProxyTransactListener(listener);
+
+        mPowerManager.isInteractive();
+
+        assertEquals(1, listener.mStartedCount);
+        assertEquals(1, listener.mEndedCount);
+    }
+
+    @MediumTest
+    public void testSessionPropagated() throws Exception {
+        Binder.setProxyTransactListener(new Binder.ProxyTransactListener() {
+            public Object onTransactStarted(IBinder binder, int transactionCode) {
+                return "foo";
+            }
+
+            public void onTransactEnded(@Nullable Object session) {
+                assertEquals("foo", session);
+            }
+        });
+
+        // Check it does not throw..
+        mPowerManager.isInteractive();
+    }
+}
diff --git a/core/tests/coretests/src/android/os/FileUtilsTest.java b/core/tests/coretests/src/android/os/FileUtilsTest.java
index 6966448..55e21a7 100644
--- a/core/tests/coretests/src/android/os/FileUtilsTest.java
+++ b/core/tests/coretests/src/android/os/FileUtilsTest.java
@@ -17,6 +17,7 @@
 package android.os;
 
 import static android.os.FileUtils.roundStorageSize;
+import static android.os.FileUtils.translateModeAccessToPosix;
 import static android.os.FileUtils.translateModePfdToPosix;
 import static android.os.FileUtils.translateModePosixToPfd;
 import static android.os.FileUtils.translateModePosixToString;
@@ -27,12 +28,16 @@
 import static android.os.ParcelFileDescriptor.MODE_READ_WRITE;
 import static android.os.ParcelFileDescriptor.MODE_TRUNCATE;
 import static android.os.ParcelFileDescriptor.MODE_WRITE_ONLY;
+import static android.system.OsConstants.F_OK;
 import static android.system.OsConstants.O_APPEND;
 import static android.system.OsConstants.O_CREAT;
 import static android.system.OsConstants.O_RDONLY;
 import static android.system.OsConstants.O_RDWR;
 import static android.system.OsConstants.O_TRUNC;
 import static android.system.OsConstants.O_WRONLY;
+import static android.system.OsConstants.R_OK;
+import static android.system.OsConstants.W_OK;
+import static android.system.OsConstants.X_OK;
 import static android.text.format.DateUtils.DAY_IN_MILLIS;
 import static android.text.format.DateUtils.HOUR_IN_MILLIS;
 import static android.text.format.DateUtils.WEEK_IN_MILLIS;
@@ -525,6 +530,15 @@
         }
     }
 
+    @Test
+    public void testTranslateMode_Access() throws Exception {
+        assertEquals(O_RDONLY, translateModeAccessToPosix(F_OK));
+        assertEquals(O_RDONLY, translateModeAccessToPosix(R_OK));
+        assertEquals(O_WRONLY, translateModeAccessToPosix(W_OK));
+        assertEquals(O_RDWR, translateModeAccessToPosix(R_OK | W_OK));
+        assertEquals(O_RDWR, translateModeAccessToPosix(R_OK | W_OK | X_OK));
+    }
+
     private static void assertTranslate(String string, int posix, int pfd) {
         assertEquals(posix, translateModeStringToPosix(string));
         assertEquals(string, translateModePosixToString(posix));
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 9778acb..182f189 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -547,6 +547,7 @@
                  Settings.Secure.BACKUP_PROVISIONED,
                  Settings.Secure.BACKUP_TRANSPORT,
                  Settings.Secure.CALL_REDIRECTION_DEFAULT_APPLICATION,
+                 Settings.Secure.CALL_SCREENING_DEFAULT_COMPONENT,
                  Settings.Secure.CAMERA_LIFT_TRIGGER_ENABLED, // Candidate for backup?
                  Settings.Secure.CARRIER_APPS_HANDLED,
                  Settings.Secure.CMAS_ADDITIONAL_BROADCAST_PKG,
diff --git a/core/tests/coretests/src/android/text/format/FormatterTest.java b/core/tests/coretests/src/android/text/format/FormatterTest.java
index c02d97c..82e4bff 100644
--- a/core/tests/coretests/src/android/text/format/FormatterTest.java
+++ b/core/tests/coretests/src/android/text/format/FormatterTest.java
@@ -162,7 +162,7 @@
 
         // Make sure it works on different locales.
         setLocale(Locale.FRANCE);
-        assertEquals("2 j", Formatter.formatShortElapsedTime(mContext, 2 * DAY));
+        assertEquals("2\u202fj", Formatter.formatShortElapsedTime(mContext, 2 * DAY));
     }
 
     @Test
diff --git a/core/tests/coretests/src/android/view/textclassifier/TextClassificationTest.java b/core/tests/coretests/src/android/view/textclassifier/TextClassificationTest.java
index de863d7..91a5440 100644
--- a/core/tests/coretests/src/android/view/textclassifier/TextClassificationTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/TextClassificationTest.java
@@ -29,6 +29,7 @@
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.Icon;
+import android.os.Bundle;
 import android.os.LocaleList;
 import android.os.Parcel;
 import android.support.test.InstrumentationRegistry;
@@ -48,6 +49,13 @@
 @RunWith(AndroidJUnit4.class)
 public class TextClassificationTest {
 
+    private static final String BUNDLE_KEY = "key";
+    private static final String BUNDLE_VALUE = "value";
+    private static final Bundle BUNDLE = new Bundle();
+    static {
+        BUNDLE.putString(BUNDLE_KEY, BUNDLE_VALUE);
+    }
+
     public Icon generateTestIcon(int width, int height, int colorValue) {
         final int numPixels = width * height;
         final int[] colors = new int[numPixels];
@@ -89,6 +97,7 @@
                 .setEntityType(TextClassifier.TYPE_ADDRESS, 0.3f)
                 .setEntityType(TextClassifier.TYPE_PHONE, 0.7f)
                 .setId(id)
+                .setExtras(BUNDLE)
                 .build();
 
         // Parcel and unparcel
@@ -119,6 +128,9 @@
         assertEquals(TextClassifier.TYPE_ADDRESS, result.getEntity(1));
         assertEquals(0.7f, result.getConfidenceScore(TextClassifier.TYPE_PHONE), 1e-7f);
         assertEquals(0.3f, result.getConfidenceScore(TextClassifier.TYPE_ADDRESS), 1e-7f);
+
+        // Extras
+        assertEquals(BUNDLE_VALUE, result.getExtras().getString(BUNDLE_KEY));
     }
 
     @Test
@@ -182,6 +194,7 @@
                 new TextClassification.Request.Builder(text, 0, text.length())
                         .setDefaultLocales(new LocaleList(Locale.US, Locale.GERMANY))
                         .setReferenceTime(referenceTime)
+                        .setExtras(BUNDLE)
                         .build();
 
         // Parcel and unparcel.
@@ -197,5 +210,6 @@
         assertEquals(referenceTime, result.getReferenceTime());
         assertEquals("en-US,de-DE", result.getDefaultLocales().toLanguageTags());
         assertEquals(referenceTime, result.getReferenceTime());
+        assertEquals(BUNDLE_VALUE, result.getExtras().getString(BUNDLE_KEY));
     }
 }
diff --git a/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java b/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
index 364dcfd..30309cf 100644
--- a/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BinderCallsStatsTest.java
@@ -43,7 +43,8 @@
 @RunWith(AndroidJUnit4.class)
 @Presubmit
 public class BinderCallsStatsTest {
-    private static final int TEST_UID = 1;
+    private static final int WORKSOURCE_UID = 1;
+    private static final int CALLING_UID = 2;
     private static final int REQUEST_SIZE = 2;
     private static final int REPLY_SIZE = 3;
     private final CachedDeviceState mDeviceState = new CachedDeviceState(false, true);
@@ -61,7 +62,7 @@
 
         SparseArray<BinderCallsStats.UidEntry> uidEntries = bcs.getUidEntries();
         assertEquals(1, uidEntries.size());
-        BinderCallsStats.UidEntry uidEntry = uidEntries.get(TEST_UID);
+        BinderCallsStats.UidEntry uidEntry = uidEntries.get(WORKSOURCE_UID);
         Assert.assertNotNull(uidEntry);
         List<BinderCallsStats.CallStat> callStatsList = new ArrayList(uidEntry.getCallStatsList());
         assertEquals(1, uidEntry.callCount);
@@ -82,7 +83,7 @@
         callSession = bcs.callStarted(binder, 2);
         bcs.time += 50;
         bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
-        uidEntry = bcs.getUidEntries().get(TEST_UID);
+        uidEntry = bcs.getUidEntries().get(WORKSOURCE_UID);
         assertEquals(3, uidEntry.callCount);
         assertEquals(1, uidEntry.recordedCallCount);
         // Still sampled even for another API.
@@ -102,7 +103,7 @@
 
         SparseArray<BinderCallsStats.UidEntry> uidEntries = bcs.getUidEntries();
         assertEquals(1, uidEntries.size());
-        BinderCallsStats.UidEntry uidEntry = uidEntries.get(TEST_UID);
+        BinderCallsStats.UidEntry uidEntry = uidEntries.get(WORKSOURCE_UID);
         Assert.assertNotNull(uidEntry);
         assertEquals(1, uidEntry.callCount);
         assertEquals(10, uidEntry.cpuTimeMicros);
@@ -118,7 +119,7 @@
         bcs.time += 20;
         bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
 
-        uidEntry = bcs.getUidEntries().get(TEST_UID);
+        uidEntry = bcs.getUidEntries().get(WORKSOURCE_UID);
         assertEquals(2, uidEntry.callCount);
         assertEquals(30, uidEntry.cpuTimeMicros);
         callStatsList = new ArrayList(uidEntry.getCallStatsList());
@@ -127,7 +128,7 @@
         callSession = bcs.callStarted(binder, 2);
         bcs.time += 50;
         bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
-        uidEntry = bcs.getUidEntries().get(TEST_UID);
+        uidEntry = bcs.getUidEntries().get(WORKSOURCE_UID);
         assertEquals(3, uidEntry.callCount);
 
         // This is the first transaction of a new type, so the real CPU time will be measured
@@ -178,7 +179,7 @@
 
         SparseArray<BinderCallsStats.UidEntry> uidEntries = bcs.getUidEntries();
         assertEquals(1, uidEntries.size());
-        BinderCallsStats.UidEntry uidEntry = uidEntries.get(TEST_UID);
+        BinderCallsStats.UidEntry uidEntry = uidEntries.get(WORKSOURCE_UID);
         Assert.assertNotNull(uidEntry);
         assertEquals(3, uidEntry.callCount);
         assertEquals(60 /* 10 + 50 */, uidEntry.cpuTimeMicros);
@@ -212,7 +213,7 @@
 
         SparseArray<BinderCallsStats.UidEntry> uidEntries = bcs.getUidEntries();
         assertEquals(1, uidEntries.size());
-        BinderCallsStats.UidEntry uidEntry = uidEntries.get(TEST_UID);
+        BinderCallsStats.UidEntry uidEntry = uidEntries.get(WORKSOURCE_UID);
         assertEquals(2, uidEntry.callCount);
         assertEquals(1, uidEntry.recordedCallCount);
         assertEquals(10, uidEntry.cpuTimeMicros);
@@ -309,7 +310,7 @@
         bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
 
         List<BinderCallsStats.CallStat> callStatsList =
-                new ArrayList(bcs.getUidEntries().get(TEST_UID).getCallStatsList());
+                new ArrayList(bcs.getUidEntries().get(WORKSOURCE_UID).getCallStatsList());
 
         assertEquals(REQUEST_SIZE, callStatsList.get(0).maxRequestSizeBytes);
         assertEquals(REPLY_SIZE, callStatsList.get(0).maxReplySizeBytes);
@@ -329,7 +330,7 @@
         bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
 
         List<BinderCallsStats.CallStat> callStatsList =
-                new ArrayList(bcs.getUidEntries().get(TEST_UID).getCallStatsList());
+                new ArrayList(bcs.getUidEntries().get(WORKSOURCE_UID).getCallStatsList());
 
         assertEquals(50, callStatsList.get(0).maxCpuTimeMicros);
     }
@@ -348,7 +349,7 @@
         bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
 
         List<BinderCallsStats.CallStat> callStatsList =
-                new ArrayList(bcs.getUidEntries().get(TEST_UID).getCallStatsList());
+                new ArrayList(bcs.getUidEntries().get(WORKSOURCE_UID).getCallStatsList());
 
         assertEquals(5, callStatsList.get(0).maxLatencyMicros);
     }
@@ -424,7 +425,7 @@
 
         SparseArray<BinderCallsStats.UidEntry> uidEntries = bcs.getUidEntries();
         assertEquals(1, uidEntries.size());
-        BinderCallsStats.UidEntry uidEntry = uidEntries.get(TEST_UID);
+        BinderCallsStats.UidEntry uidEntry = uidEntries.get(WORKSOURCE_UID);
         Assert.assertNotNull(uidEntry);
         List<BinderCallsStats.CallStat> callStatsList = new ArrayList(uidEntry.getCallStatsList());
         assertEquals(false, callStatsList.get(0).screenInteractive);
@@ -441,7 +442,7 @@
 
         SparseArray<BinderCallsStats.UidEntry> uidEntries = bcs.getUidEntries();
         assertEquals(1, uidEntries.size());
-        BinderCallsStats.UidEntry uidEntry = uidEntries.get(TEST_UID);
+        BinderCallsStats.UidEntry uidEntry = uidEntries.get(WORKSOURCE_UID);
         Assert.assertNotNull(uidEntry);
         List<BinderCallsStats.CallStat> callStatsList = new ArrayList(uidEntry.getCallStatsList());
         assertEquals(true, callStatsList.get(0).screenInteractive);
@@ -510,7 +511,8 @@
 
         assertEquals(1, bcs.getExportedCallStats().size());
         BinderCallsStats.ExportedCallStat stat = bcs.getExportedCallStats().get(0);
-        assertEquals(TEST_UID, stat.uid);
+        assertEquals(WORKSOURCE_UID, stat.workSourceUid);
+        assertEquals(CALLING_UID, stat.callingUid);
         assertEquals("android.os.Binder", stat.className);
         assertEquals("1", stat.methodName);
         assertEquals(true, stat.screenInteractive);
@@ -526,6 +528,22 @@
     }
 
     @Test
+    public void testCallingUidUsedWhenWorkSourceNotSet() {
+        TestBinderCallsStats bcs = new TestBinderCallsStats();
+        bcs.setDetailedTracking(true);
+        bcs.workSourceUid = -1;
+
+        Binder binder = new Binder();
+        CallSession callSession = bcs.callStarted(binder, 1);
+        bcs.callEnded(callSession, REQUEST_SIZE, REPLY_SIZE);
+
+        assertEquals(1, bcs.getExportedCallStats().size());
+        BinderCallsStats.ExportedCallStat stat = bcs.getExportedCallStats().get(0);
+        assertEquals(CALLING_UID, stat.workSourceUid);
+        assertEquals(CALLING_UID, stat.callingUid);
+    }
+
+    @Test
     public void testGetExportedStatsWithoutCalls() {
         TestBinderCallsStats bcs = new TestBinderCallsStats();
         Binder binder = new Binder();
@@ -540,9 +558,10 @@
     }
 
     class TestBinderCallsStats extends BinderCallsStats {
-        int callingUid = TEST_UID;
-        long time = 1234;
-        long elapsedTime = 0;
+        public int callingUid = CALLING_UID;
+        public int workSourceUid = WORKSOURCE_UID;
+        public long time = 1234;
+        public long elapsedTime = 0;
 
         TestBinderCallsStats() {
             // Make random generator not random.
@@ -575,6 +594,11 @@
         protected int getCallingUid() {
             return callingUid;
         }
+
+        @Override
+        protected int getWorkSourceUid() {
+            return workSourceUid;
+        }
     }
 
 }
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderTest.java
new file mode 100644
index 0000000..b9ef434
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderTest.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.os;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import android.content.Context;
+import android.os.FileUtils;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Comparator;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class KernelCpuThreadReaderTest {
+
+    private static final String PROCESS_NAME = "test_process";
+    private static final int[] THREAD_IDS = {0, 1000, 1235, 4321};
+    private static final String[] THREAD_NAMES = {
+            "test_thread_1", "test_thread_2", "test_thread_3", "test_thread_4"
+    };
+    private static final int[] THREAD_CPU_FREQUENCIES = {
+            1000, 2000, 3000, 4000,
+    };
+    private static final int[][] THREAD_CPU_TIMES = {
+            {1, 0, 0, 1},
+            {0, 0, 0, 0},
+            {1000, 1000, 1000, 1000},
+            {0, 1, 2, 3},
+    };
+
+    private File mProcDirectory;
+
+    @Before
+    public void setUp() {
+        Context context = InstrumentationRegistry.getContext();
+        mProcDirectory = context.getDir("proc", Context.MODE_PRIVATE);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        FileUtils.deleteContents(mProcDirectory);
+    }
+
+    @Test
+    public void testSimple() throws IOException {
+        // Make /proc/self
+        final Path selfPath = mProcDirectory.toPath().resolve("self");
+        assertTrue(selfPath.toFile().mkdirs());
+
+        // Make /proc/self/task
+        final Path selfThreadsPath = selfPath.resolve("task");
+        assertTrue(selfThreadsPath.toFile().mkdirs());
+
+        // Make /proc/self/cmdline
+        Files.write(selfPath.resolve("cmdline"), PROCESS_NAME.getBytes());
+
+        // Make thread directories in reverse order, as they are read in order of creation by
+        // CpuThreadProcReader
+        for (int i = 0; i < THREAD_IDS.length; i++) {
+            // Make /proc/self/task/$TID
+            final Path threadPath = selfThreadsPath.resolve(String.valueOf(THREAD_IDS[i]));
+            assertTrue(threadPath.toFile().mkdirs());
+
+            // Make /proc/self/task/$TID/comm
+            Files.write(threadPath.resolve("comm"), THREAD_NAMES[i].getBytes());
+
+            // Make /proc/self/task/$TID/time_in_state
+            final OutputStream timeInStateStream =
+                    Files.newOutputStream(threadPath.resolve("time_in_state"));
+            for (int j = 0; j < THREAD_CPU_FREQUENCIES.length; j++) {
+                final String line = String.valueOf(THREAD_CPU_FREQUENCIES[j]) + " "
+                        + String.valueOf(THREAD_CPU_TIMES[i][j]) + "\n";
+                timeInStateStream.write(line.getBytes());
+            }
+            timeInStateStream.close();
+        }
+
+        final KernelCpuThreadReader kernelCpuThreadReader = new KernelCpuThreadReader(
+                mProcDirectory.toPath(),
+                mProcDirectory.toPath().resolve("self/task/" + THREAD_IDS[0] + "/time_in_state"));
+        final KernelCpuThreadReader.ProcessCpuUsage processCpuUsage =
+                kernelCpuThreadReader.getCurrentProcessCpuUsage();
+
+        assertNotNull(processCpuUsage);
+        assertEquals(android.os.Process.myPid(), processCpuUsage.processId);
+        assertEquals(android.os.Process.myUid(), processCpuUsage.uid);
+        assertEquals(PROCESS_NAME, processCpuUsage.processName);
+
+        // Sort the thread CPU usages to compare with test case
+        final ArrayList<KernelCpuThreadReader.ThreadCpuUsage> threadCpuUsages =
+                new ArrayList<>(processCpuUsage.threadCpuUsages);
+        threadCpuUsages.sort(Comparator.comparingInt(a -> a.threadId));
+
+        int threadCount = 0;
+        for (KernelCpuThreadReader.ThreadCpuUsage threadCpuUsage : threadCpuUsages) {
+            assertEquals(THREAD_IDS[threadCount], threadCpuUsage.threadId);
+            assertEquals(THREAD_NAMES[threadCount], threadCpuUsage.threadName);
+
+            for (int i = 0; i < threadCpuUsage.usageTimesMillis.length; i++) {
+                assertEquals(
+                        THREAD_CPU_TIMES[threadCount][i] * 10,
+                        threadCpuUsage.usageTimesMillis[i]);
+                assertEquals(
+                        THREAD_CPU_FREQUENCIES[i],
+                        kernelCpuThreadReader.getCpuFrequenciesKhz()[i]);
+            }
+            threadCount++;
+        }
+
+        assertEquals(threadCount, THREAD_IDS.length);
+    }
+}
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 28e92db..8964ee3 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -313,6 +313,7 @@
         <permission name="android.permission.INSTALL_PACKAGES"/>
         <permission name="android.permission.INTERACT_ACROSS_USERS"/>
         <permission name="android.permission.LOCAL_MAC_ADDRESS"/>
+        <permission name="android.permission.MANAGE_ACCESSIBILITY"/>
         <permission name="android.permission.MANAGE_ACTIVITY_STACKS"/>
         <permission name="android.permission.MANAGE_DEVICE_ADMINS"/>
         <permission name="android.permission.MANAGE_USB"/>
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 364fb04..790b37e 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -773,7 +773,13 @@
      * @param src       The source bitmap.
      * @param dstWidth  The new bitmap's desired width.
      * @param dstHeight The new bitmap's desired height.
-     * @param filter    true if the source should be filtered.
+     * @param filter    Whether or not bilinear filtering should be used when scaling the
+     *                  bitmap. If this is true then bilinear filtering will be used when
+     *                  scaling which has better image quality at the cost of worse performance.
+     *                  If this is false then nearest-neighbor scaling is used instead which
+     *                  will have worse image quality but is faster. Recommended default
+     *                  is to set filter to 'true' as the cost of bilinear filtering is
+     *                  typically minimal and the improved image quality is significant.
      * @return The new scaled bitmap or the source bitmap if no scaling is required.
      * @throws IllegalArgumentException if width is <= 0, or height is <= 0
      */
@@ -1294,14 +1300,14 @@
             final RenderNode node = RenderNode.create("BitmapTemporary", null);
             node.setLeftTopRightBottom(0, 0, width, height);
             node.setClipToBounds(false);
-            node.setAllowForceDark(false);
-            final RecordingCanvas canvas = node.start(width, height);
+            node.setForceDarkAllowed(false);
+            final RecordingCanvas canvas = node.startRecording(width, height);
             if (source.getWidth() != width || source.getHeight() != height) {
                 canvas.scale(width / (float) source.getWidth(),
                         height / (float) source.getHeight());
             }
             canvas.drawPicture(source);
-            node.end(canvas);
+            node.endRecording();
             Bitmap bitmap = ThreadedRenderer.createHardwareBitmap(node, width, height);
             if (config != Config.HARDWARE) {
                 bitmap = bitmap.copy(config, false);
diff --git a/graphics/java/android/graphics/RenderNode.java b/graphics/java/android/graphics/RenderNode.java
index 60641d8..320fb20 100644
--- a/graphics/java/android/graphics/RenderNode.java
+++ b/graphics/java/android/graphics/RenderNode.java
@@ -19,7 +19,6 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.annotation.UnsupportedAppUsage;
 import android.view.NativeVectorDrawableAnimator;
 import android.view.RenderNodeAnimator;
 import android.view.View;
@@ -33,89 +32,92 @@
 import java.lang.annotation.RetentionPolicy;
 
 /**
- * <p>A display list records a series of graphics related operations and can replay
- * them later. Display lists are usually built by recording operations on a
- * {@link RecordingCanvas}. Replaying the operations from a display list avoids
- * executing application code on every frame, and is thus much more efficient.</p>
+ * <p>RenderNode is used to build hardware accelerated rendering hierarchies. Each RenderNode
+ * contains both a display list as well as a set of properties that affect the rendering of the
+ * display list. RenderNodes are used internally for all Views by default and are not typically
+ * used directly.</p>
  *
- * <p>Display lists are used internally for all views by default, and are not
- * typically used directly. One reason to consider using a display is a custom
- * {@link View} implementation that needs to issue a large number of drawing commands.
- * When the view invalidates, all the drawing commands must be reissued, even if
- * large portions of the drawing command stream stay the same frame to frame, which
- * can become a performance bottleneck. To solve this issue, a custom View might split
- * its content into several display lists. A display list is updated only when its
- * content, and only its content, needs to be updated.</p>
+ * <p>RenderNodes are used to divide up the rendering content of a complex scene into smaller
+ * pieces that can then be updated individually more cheaply. Updating part of the scene only needs
+ * to update the display list or properties of a small number of RenderNode instead of redrawing
+ * everything from scratch. A RenderNode only needs its display list re-recorded when its content
+ * alone should be changed. RenderNodes can also be transformed without re-recording the display
+ * list through the transform properties.</p>
  *
- * <p>A text editor might for instance store each paragraph into its own display list.
+ * <p>A text editor might for instance store each paragraph into its own RenderNode.
  * Thus when the user inserts or removes characters, only the display list of the
  * affected paragraph needs to be recorded again.</p>
  *
  * <h3>Hardware acceleration</h3>
- * <p>Display lists can only be replayed using a {@link RecordingCanvas}. They are not
+ * <p>RenderNodes can be drawn using a {@link RecordingCanvas}. They are not
  * supported in software. Always make sure that the {@link android.graphics.Canvas}
  * you are using to render a display list is hardware accelerated using
  * {@link android.graphics.Canvas#isHardwareAccelerated()}.</p>
  *
- * <h3>Creating a display list</h3>
+ * <h3>Creating a RenderNode</h3>
  * <pre class="prettyprint">
- *     ThreadedRenderer renderer = myView.getThreadedRenderer();
- *     if (renderer != null) {
- *         DisplayList displayList = renderer.createDisplayList();
- *         RecordingCanvas canvas = displayList.start(width, height);
- *         try {
- *             // Draw onto the canvas
- *             // For instance: canvas.drawBitmap(...);
- *         } finally {
- *             displayList.end();
- *         }
+ *     RenderNode renderNode = RenderNode.create("myRenderNode");
+ *     renderNode.setLeftTopRightBottom(0, 0, 50, 50); // Set the size to 50x50
+ *     RecordingCanvas canvas = renderNode.startRecording();
+ *     try {
+ *         // Draw with the canvas
+ *         canvas.drawRect(...);
+ *     } finally {
+ *         renderNode.endRecording();
  *     }
  * </pre>
  *
- * <h3>Rendering a display list on a View</h3>
+ * <h3>Drawing a RenderNode in a View</h3>
  * <pre class="prettyprint">
  *     protected void onDraw(Canvas canvas) {
- *         if (canvas.isHardwareAccelerated()) {
- *             RecordingCanvas displayListCanvas = (RecordingCanvas) canvas;
- *             displayListCanvas.drawDisplayList(mDisplayList);
+ *         if (canvas instanceof RecordingCanvas) {
+ *             RecordingCanvas recordingCanvas = (RecordingCanvas) canvas;
+ *             // Check that the RenderNode has a display list, re-recording it if it does not.
+ *             if (!myRenderNode.hasDisplayList()) {
+ *                 updateDisplayList(myRenderNode);
+ *             }
+ *             // Draw the RenderNode into this canvas.
+ *             recordingCanvas.drawRenderNode(myRenderNode);
  *         }
  *     }
  * </pre>
  *
  * <h3>Releasing resources</h3>
  * <p>This step is not mandatory but recommended if you want to release resources
- * held by a display list as soon as possible.</p>
+ * held by a display list as soon as possible. Most significantly any bitmaps it may contain.</p>
  * <pre class="prettyprint">
- *     // Mark this display list invalid, it cannot be used for drawing anymore,
- *     // and release resources held by this display list
- *     displayList.clear();
+ *     // Discards the display list content allowing for any held resources to be released.
+ *     // After calling this
+ *     renderNode.discardDisplayList();
  * </pre>
  *
+ *
  * <h3>Properties</h3>
- * <p>In addition, a display list offers several properties, such as
+ * <p>In addition, a RenderNode offers several properties, such as
  * {@link #setScaleX(float)} or {@link #setLeft(int)}, that can be used to affect all
  * the drawing commands recorded within. For instance, these properties can be used
  * to move around a large number of images without re-issuing all the individual
- * <code>drawBitmap()</code> calls.</p>
+ * <code>canvas.drawBitmap()</code> calls.</p>
  *
  * <pre class="prettyprint">
  *     private void createDisplayList() {
- *         mDisplayList = DisplayList.create("MyDisplayList");
- *         RecordingCanvas canvas = mDisplayList.start(width, height);
+ *         mRenderNode = RenderNode.create("MyRenderNode");
+ *         mRenderNode.setLeftTopRightBottom(0, 0, width, height);
+ *         RecordingCanvas canvas = mRenderNode.startRecording();
  *         try {
  *             for (Bitmap b : mBitmaps) {
  *                 canvas.drawBitmap(b, 0.0f, 0.0f, null);
  *                 canvas.translate(0.0f, b.getHeight());
  *             }
  *         } finally {
- *             displayList.end();
+ *             mRenderNode.endRecording();
  *         }
  *     }
  *
  *     protected void onDraw(Canvas canvas) {
- *         if (canvas.isHardwareAccelerated()) {
- *             RecordingCanvas displayListCanvas = (RecordingCanvas) canvas;
- *             displayListCanvas.drawDisplayList(mDisplayList);
+ *         if (canvas instanceof RecordingCanvas) {
+ *             RecordingCanvas recordingCanvas = (RecordingCanvas) canvas;
+ *             recordingCanvas.drawRenderNode(mRenderNode);
  *         }
  *     }
  *
@@ -124,13 +126,16 @@
  *          // by x pixels to the right and redraw this view. All the commands
  *          // recorded in createDisplayList() won't be re-issued, only onDraw()
  *          // will be invoked and will execute very quickly
- *          mDisplayList.offsetLeftAndRight(x);
+ *          mRenderNode.offsetLeftAndRight(x);
  *          invalidate();
  *     }
  * </pre>
  *
  * <h3>Threading</h3>
- * <p>Display lists must be created on and manipulated from the UI thread only.</p>
+ * <p>RenderNode may be created and used on any thread but they are not thread-safe. Only
+ * a single thread may interact with a RenderNode at any given time. It is critical
+ * that the RenderNode is only used on the same thread it is drawn with. For example when using
+ * RenderNode with a custom View, then that RenderNode must only be used from the UI thread.</p>
  *
  * @hide
  */
@@ -147,6 +152,7 @@
      */
     public final long mNativeRenderNode;
     private final AnimationHost mAnimationHost;
+    private RecordingCanvas mCurrentRecordingCanvas;
 
     private RenderNode(String name, AnimationHost animationHost) {
         mNativeRenderNode = nCreate(name);
@@ -171,7 +177,6 @@
      *
      * @return A new RenderNode.
      */
-    @UnsupportedAppUsage
     public static RenderNode create(String name, @Nullable AnimationHost animationHost) {
         return new RenderNode(name, animationHost);
     }
@@ -226,64 +231,106 @@
      * operations performed on the returned canvas are recorded and
      * stored in this display list.
      *
-     * Calling this method will mark the render node invalid until
-     * {@link #end(RecordingCanvas)} is called.
-     * Only valid render nodes can be replayed.
+     * {@link #endRecording()} must be called when the recording is finished in order to apply
+     * the updated display list.
      *
-     * @param width The width of the recording viewport
-     * @param height The height of the recording viewport
+     * @param width The width of the recording viewport. This will not alter the width of the
+     *              RenderNode itself, that must be set with {@link #setLeft(int)} and
+     *              {@link #setRight(int)}
+     * @param height The height of the recording viewport. This will not alter the height of the
+     *               RenderNode itself, that must be set with {@link #setTop(int)} and
+     *               {@link #setBottom(int)}.
      *
      * @return A canvas to record drawing operations.
      *
-     * @see #end(RecordingCanvas)
-     * @see #isValid()
+     * @see #endRecording()
+     * @see #hasDisplayList()
      */
-    @UnsupportedAppUsage
-    public RecordingCanvas start(int width, int height) {
-        return RecordingCanvas.obtain(this, width, height);
+    public RecordingCanvas startRecording(int width, int height) {
+        if (mCurrentRecordingCanvas != null) {
+            throw new IllegalStateException(
+                    "Recording currently in progress - missing #endRecording() call?");
+        }
+        mCurrentRecordingCanvas = RecordingCanvas.obtain(this, width, height);
+        return mCurrentRecordingCanvas;
     }
 
     /**
-     * Same as {@link #start(int, int)} but with the RenderNode's width & height
+     * Same as {@link #startRecording(int, int)} with the width & height set
+     * to the RenderNode's own width & height. The RenderNode's width & height may be set
+     * with {@link #setLeftTopRightBottom(int, int, int, int)}.
      */
-    public RecordingCanvas start() {
+    public RecordingCanvas startRecording() {
         return RecordingCanvas.obtain(this,
                 nGetWidth(mNativeRenderNode), nGetHeight(mNativeRenderNode));
     }
 
     /**
-     * Ends the recording for this display list. A display list cannot be
-     * replayed if recording is not finished. Calling this method marks
-     * the display list valid and {@link #isValid()} will return true.
-     *
-     * @see #start(int, int)
-     * @see #isValid()
+     * @deprecated use {@link #startRecording(int, int)} instead
+     * @hide
      */
-    @UnsupportedAppUsage
-    public void end(RecordingCanvas canvas) {
+    @Deprecated
+    public RecordingCanvas start(int width, int height) {
+        return startRecording(width, height);
+    }
+
+    /**`
+     * Ends the recording for this display list. Calling this method marks
+     * the display list valid and {@link #hasDisplayList()} will return true.
+     *
+     * @see #startRecording(int, int)
+     * @see #hasDisplayList()
+     */
+    public void endRecording() {
+        if (mCurrentRecordingCanvas == null) {
+            throw new IllegalStateException(
+                    "No recording in progress, forgot to call #startRecording()?");
+        }
+        RecordingCanvas canvas = mCurrentRecordingCanvas;
+        mCurrentRecordingCanvas = null;
         long displayList = canvas.finishRecording();
         nSetDisplayList(mNativeRenderNode, displayList);
         canvas.recycle();
     }
 
     /**
+     * @deprecated use {@link #endRecording()} instead
+     * @hide
+     */
+    @Deprecated
+    public void end(RecordingCanvas canvas) {
+        if (mCurrentRecordingCanvas != canvas) {
+            throw new IllegalArgumentException(
+                    "Canvas given isn't the one that was returned from #startRecording");
+        }
+        endRecording();
+    }
+
+    /**
      * Reset native resources. This is called when cleaning up the state of display lists
      * during destruction of hardware resources, to ensure that we do not hold onto
      * obsolete resources after related resources are gone.
      */
-    @UnsupportedAppUsage
     public void discardDisplayList() {
         nSetDisplayList(mNativeRenderNode, 0);
     }
 
     /**
-     * Returns whether the RenderNode's display list content is currently usable.
-     * If this returns false, the display list should be re-recorded prior to replaying it.
+     * Returns whether the RenderNode has a display list. If this returns false, the RenderNode
+     * should be re-recorded with {@link #startRecording()} and {@link #endRecording()}.
      *
-     * @return boolean true if the display list is able to be replayed, false otherwise.
+     * A RenderNode without a display list may still be drawn, however it will have no impact
+     * on the rendering content until its display list is updated.
+     *
+     * When a RenderNode is no longer drawn by anything the system may automatically
+     * invoke {@link #discardDisplayList()}. It is therefore important to ensure that
+     * {@link #hasDisplayList()} is true on a RenderNode prior to drawing it.
+     *
+     * See {@link #discardDisplayList()}
+     *
+     * @return boolean true if this RenderNode has a display list, false otherwise.
      */
-    @UnsupportedAppUsage
-    public boolean isValid() {
+    public boolean hasDisplayList() {
         return nIsValid(mNativeRenderNode);
     }
 
@@ -358,7 +405,6 @@
      *
      * @param clipToBounds true if the display list should clip to its bounds
      */
-    @UnsupportedAppUsage
     public boolean setClipToBounds(boolean clipToBounds) {
         return nSetClipToBounds(mNativeRenderNode, clipToBounds);
     }
@@ -370,7 +416,6 @@
      * @param shouldProject true if the display list should be projected onto a
      *            containing volume.
      */
-    @UnsupportedAppUsage
     public boolean setProjectBackwards(boolean shouldProject) {
         return nSetProjectBackwards(mNativeRenderNode, shouldProject);
     }
@@ -521,7 +566,6 @@
      * @see android.view.View#hasOverlappingRendering()
      * @see #hasOverlappingRendering()
      */
-    @UnsupportedAppUsage
     public boolean setHasOverlappingRendering(boolean hasOverlappingRendering) {
         return nSetHasOverlappingRendering(mNativeRenderNode, hasOverlappingRendering);
     }
@@ -872,7 +916,6 @@
      * @see View#setRight(int)
      * @see View#setBottom(int)
      */
-    @UnsupportedAppUsage
     public boolean setLeftTopRightBottom(int left, int top, int right, int bottom) {
         return nSetLeftTopRightBottom(mNativeRenderNode, left, top, right, bottom);
     }
@@ -885,7 +928,6 @@
      *
      * @see View#offsetLeftAndRight(int)
      */
-    @UnsupportedAppUsage
     public boolean offsetLeftAndRight(int offset) {
         return nOffsetLeftAndRight(mNativeRenderNode, offset);
     }
@@ -906,7 +948,6 @@
      * Outputs the display list to the log. This method exists for use by
      * tools to output display lists for selected nodes to the log.
      */
-    @UnsupportedAppUsage
     public void output() {
         nOutput(mNativeRenderNode);
     }
@@ -931,16 +972,16 @@
      * @param allow Whether or not to allow force dark.
      * @return true If the value has changed, false otherwise.
      */
-    public boolean setAllowForceDark(boolean allow) {
+    public boolean setForceDarkAllowed(boolean allow) {
         return nSetAllowForceDark(mNativeRenderNode, allow);
     }
 
     /**
-     * See {@link #setAllowForceDark(boolean)}
+     * See {@link #setForceDarkAllowed(boolean)}
      *
      * @return true if force dark is allowed (default), false if it is disabled
      */
-    public boolean getAllowForceDark() {
+    public boolean isForceDarkAllowed() {
         return nGetAllowForceDark(mNativeRenderNode);
     }
 
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index ba47300..5c0c38e 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -1115,6 +1115,13 @@
         }
     }
 
+    private static void registerGenericFamilyNative(@NonNull String familyName,
+            @Nullable Typeface typeface) {
+        if (typeface != null) {
+            nativeRegisterGenericFamily(familyName, typeface.native_instance);
+        }
+    }
+
     static {
         final HashMap<String, Typeface> systemFontMap = new HashMap<>();
         initSystemDefaultTypefaces(systemFontMap, SystemFonts.getRawSystemFallbackMap(),
@@ -1140,6 +1147,15 @@
             create((String) null, Typeface.BOLD_ITALIC),
         };
 
+        // A list of generic families to be registered in native.
+        // https://www.w3.org/TR/css-fonts-4/#generic-font-families
+        String[] genericFamilies = {
+            "serif", "sans-serif", "cursive", "fantasy", "monospace", "system-ui"
+        };
+
+        for (String genericFamily : genericFamilies) {
+            registerGenericFamilyNative(genericFamily, systemFontMap.get(genericFamily));
+        }
     }
 
     @Override
@@ -1202,4 +1218,6 @@
 
     @CriticalNative
     private static native long nativeGetReleaseFunc();
+
+    private static native void nativeRegisterGenericFamily(String str, long nativePtr);
 }
diff --git a/graphics/java/android/graphics/fonts/Font.java b/graphics/java/android/graphics/fonts/Font.java
index f426b2d..0a8c685 100644
--- a/graphics/java/android/graphics/fonts/Font.java
+++ b/graphics/java/android/graphics/fonts/Font.java
@@ -372,7 +372,9 @@
                 }
             }
             final ByteBuffer readonlyBuffer = mBuffer.asReadOnlyBuffer();
-            final long ptr = nBuild(builderPtr, readonlyBuffer, mWeight, italic, mTtcIndex);
+            final String filePath = mFile == null ? "" : mFile.getAbsolutePath();
+            final long ptr = nBuild(builderPtr, readonlyBuffer, filePath, mWeight, italic,
+                    mTtcIndex);
             final Font font = new Font(ptr, readonlyBuffer, mFile,
                     new FontStyle(mWeight, slant), mTtcIndex, mAxes, mLocaleList);
             sFontRegistory.registerNativeAllocation(font, ptr);
@@ -395,7 +397,8 @@
         @CriticalNative
         private static native void nAddAxis(long builderPtr, int tag, float value);
         private static native long nBuild(
-                long builderPtr, ByteBuffer buffer, int weight, boolean italic, int ttcIndex);
+                long builderPtr, @NonNull ByteBuffer buffer, @NonNull String filePath, int weight,
+                boolean italic, int ttcIndex);
         @CriticalNative
         private static native long nGetReleaseNativeFont();
     }
diff --git a/graphics/java/android/graphics/text/MeasuredText.java b/graphics/java/android/graphics/text/MeasuredText.java
index 3efe655..6f78651 100644
--- a/graphics/java/android/graphics/text/MeasuredText.java
+++ b/graphics/java/android/graphics/text/MeasuredText.java
@@ -48,9 +48,6 @@
  * </p>
  */
 public class MeasuredText {
-    private static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
-            MeasuredText.class.getClassLoader(), nGetReleaseFunc(), 1024);
-
     private long mNativePtr;
     private @NonNull char[] mChars;
 
@@ -166,6 +163,9 @@
      * Note: The appendStyle and appendReplacementRun should be called to cover the text length.
      */
     public static class Builder {
+        private static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
+                MeasuredText.class.getClassLoader(), nGetReleaseFunc(), 1024);
+
         private long mNativePtr;
 
         private final @NonNull char[] mText;
diff --git a/libs/androidfw/Android.bp b/libs/androidfw/Android.bp
index 98af3eb..92efb6b 100644
--- a/libs/androidfw/Android.bp
+++ b/libs/androidfw/Android.bp
@@ -59,6 +59,8 @@
         "ZipFileRO.cpp",
         "ZipUtils.cpp",
     ],
+    // Allow implicit fallthroughs in Locale.cpp and ResourceTypes.cpp until they are fixed.
+    cflags: ["-Wno-implicit-fallthrough"],
     export_include_dirs: ["include"],
     export_shared_lib_headers: ["libz"],
     target: {
diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp
index a699e2f..3f2c616 100644
--- a/libs/hwui/Properties.cpp
+++ b/libs/hwui/Properties.cpp
@@ -61,7 +61,7 @@
 bool Properties::disableVsync = false;
 bool Properties::skpCaptureEnabled = false;
 bool Properties::forceDarkMode = false;
-bool Properties::enableForceDarkSupport = false;
+bool Properties::enableForceDarkSupport = true;
 bool Properties::enableRTAnimations = true;
 
 bool Properties::runningInEmulator = false;
@@ -150,8 +150,7 @@
 
     forceDarkMode = property_get_bool(PROPERTY_FORCE_DARK, false);
 
-    // TODO: make this on by default
-    enableForceDarkSupport = property_get_bool(PROPERTY_ENABLE_FORCE_DARK, false);
+    enableForceDarkSupport = property_get_bool(PROPERTY_ENABLE_FORCE_DARK, true);
 
     return (prevDebugLayersUpdates != debugLayersUpdates) || (prevDebugOverdraw != debugOverdraw) ||
            (prevDebugStencilClip != debugStencilClip);
diff --git a/libs/hwui/hwui/MinikinSkia.cpp b/libs/hwui/hwui/MinikinSkia.cpp
index c6e4c15..2ca40b9 100644
--- a/libs/hwui/hwui/MinikinSkia.cpp
+++ b/libs/hwui/hwui/MinikinSkia.cpp
@@ -30,13 +30,15 @@
 namespace android {
 
 MinikinFontSkia::MinikinFontSkia(sk_sp<SkTypeface> typeface, const void* fontData, size_t fontSize,
-                                 int ttcIndex, const std::vector<minikin::FontVariation>& axes)
+                                 std::string_view filePath, int ttcIndex,
+                                 const std::vector<minikin::FontVariation>& axes)
         : minikin::MinikinFont(typeface->uniqueID())
         , mTypeface(std::move(typeface))
         , mFontData(fontData)
         , mFontSize(fontSize)
         , mTtcIndex(ttcIndex)
-        , mAxes(axes) {}
+        , mAxes(axes)
+        , mFilePath(filePath) {}
 
 static void MinikinFontSkia_SetSkiaPaint(const minikin::MinikinFont* font, SkPaint* skPaint,
                                          const minikin::MinikinPaint& paint,
@@ -131,8 +133,8 @@
     sk_sp<SkFontMgr> fm(SkFontMgr::RefDefault());
     sk_sp<SkTypeface> face(fm->makeFromStream(std::move(stream), params));
 
-    return std::make_shared<MinikinFontSkia>(std::move(face), mFontData, mFontSize, ttcIndex,
-                                             variations);
+    return std::make_shared<MinikinFontSkia>(std::move(face), mFontData, mFontSize, mFilePath,
+                                             ttcIndex, variations);
 }
 
 uint32_t MinikinFontSkia::packPaintFlags(const SkPaint* paint) {
diff --git a/libs/hwui/hwui/MinikinSkia.h b/libs/hwui/hwui/MinikinSkia.h
index d156598..55576b7 100644
--- a/libs/hwui/hwui/MinikinSkia.h
+++ b/libs/hwui/hwui/MinikinSkia.h
@@ -28,8 +28,9 @@
 
 class ANDROID_API MinikinFontSkia : public minikin::MinikinFont {
 public:
-    explicit MinikinFontSkia(sk_sp<SkTypeface> typeface, const void* fontData, size_t fontSize,
-                             int ttcIndex, const std::vector<minikin::FontVariation>& axes);
+    MinikinFontSkia(sk_sp<SkTypeface> typeface, const void* fontData, size_t fontSize,
+                    std::string_view filePath, int ttcIndex,
+                    const std::vector<minikin::FontVariation>& axes);
 
     float GetHorizontalAdvance(uint32_t glyph_id, const minikin::MinikinPaint& paint,
                                const minikin::FontFakery& fakery) const override;
@@ -48,6 +49,7 @@
     const void* GetFontData() const;
     size_t GetFontSize() const;
     int GetFontIndex() const;
+    const std::string& getFilePath() const { return mFilePath; }
     const std::vector<minikin::FontVariation>& GetAxes() const;
     std::shared_ptr<minikin::MinikinFont> createFontWithVariation(
             const std::vector<minikin::FontVariation>&) const;
@@ -68,6 +70,7 @@
     size_t mFontSize;
     int mTtcIndex;
     std::vector<minikin::FontVariation> mAxes;
+    std::string mFilePath;
 };
 
 }  // namespace android
diff --git a/libs/hwui/hwui/Typeface.cpp b/libs/hwui/hwui/Typeface.cpp
index e8332a8..c4d8aa6 100644
--- a/libs/hwui/hwui/Typeface.cpp
+++ b/libs/hwui/hwui/Typeface.cpp
@@ -183,7 +183,8 @@
     LOG_ALWAYS_FATAL_IF(typeface == nullptr, "Failed to make typeface from %s", kRobotoFont);
 
     std::shared_ptr<minikin::MinikinFont> font = std::make_shared<MinikinFontSkia>(
-            std::move(typeface), data, st.st_size, 0, std::vector<minikin::FontVariation>());
+            std::move(typeface), data, st.st_size, kRobotoFont, 0,
+            std::vector<minikin::FontVariation>());
     std::vector<minikin::Font> fonts;
     fonts.push_back(minikin::Font::Builder(font).build());
 
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index 9e435a5..f96b1f8 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -16,8 +16,6 @@
 
 #include "VulkanManager.h"
 
-#include <private/gui/SyncFeatures.h>
-
 #include "Properties.h"
 #include "RenderThread.h"
 #include "renderstate/RenderState.h"
@@ -1033,69 +1031,59 @@
         return INVALID_OPERATION;
     }
 
-    if (SyncFeatures::getInstance().useWaitSync() &&
-        SyncFeatures::getInstance().useNativeFenceSync()) {
-        // Block GPU on the fence.
-        int fenceFd = fence->dup();
-        if (fenceFd == -1) {
-            ALOGE("VulkanManager::fenceWait: error dup'ing fence fd: %d", errno);
-            return -errno;
-        }
-
-        VkSemaphoreCreateInfo semaphoreInfo;
-        semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
-        semaphoreInfo.pNext = nullptr;
-        semaphoreInfo.flags = 0;
-        VkSemaphore semaphore;
-        VkResult err = mCreateSemaphore(mDevice, &semaphoreInfo, nullptr, &semaphore);
-        if (VK_SUCCESS != err) {
-            ALOGE("Failed to create import semaphore, err: %d", err);
-            return UNKNOWN_ERROR;
-        }
-        VkImportSemaphoreFdInfoKHR importInfo;
-        importInfo.sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR;
-        importInfo.pNext = nullptr;
-        importInfo.semaphore = semaphore;
-        importInfo.flags = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT;
-        importInfo.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
-        importInfo.fd = fenceFd;
-
-        err = mImportSemaphoreFdKHR(mDevice, &importInfo);
-        if (VK_SUCCESS != err) {
-            ALOGE("Failed to import semaphore, err: %d", err);
-            return UNKNOWN_ERROR;
-        }
-
-        LOG_ALWAYS_FATAL_IF(mDummyCB == VK_NULL_HANDLE);
-
-        VkPipelineStageFlags waitDstStageFlags = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
-
-        VkSubmitInfo submitInfo;
-        memset(&submitInfo, 0, sizeof(VkSubmitInfo));
-        submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
-        submitInfo.waitSemaphoreCount = 1;
-        // Wait to make sure aquire semaphore set above has signaled.
-        submitInfo.pWaitSemaphores = &semaphore;
-        submitInfo.pWaitDstStageMask = &waitDstStageFlags;
-        submitInfo.commandBufferCount = 1;
-        submitInfo.pCommandBuffers = &mDummyCB;
-        submitInfo.signalSemaphoreCount = 0;
-
-        mQueueSubmit(mGraphicsQueue, 1, &submitInfo, VK_NULL_HANDLE);
-
-        // On Android when we import a semaphore, it is imported using temporary permanence. That
-        // means as soon as we queue the semaphore for a wait it reverts to its previous permanent
-        // state before importing. This means it will now be in an idle state with no pending
-        // signal or wait operations, so it is safe to immediately delete it.
-        mDestroySemaphore(mDevice, semaphore, nullptr);
-    } else {
-        // Block CPU on the fence.
-        status_t err = fence->waitForever("VulkanManager::fenceWait");
-        if (err != NO_ERROR) {
-            ALOGE("VulkanManager::fenceWait: error waiting for fence: %d", err);
-            return err;
-        }
+    // Block GPU on the fence.
+    int fenceFd = fence->dup();
+    if (fenceFd == -1) {
+        ALOGE("VulkanManager::fenceWait: error dup'ing fence fd: %d", errno);
+        return -errno;
     }
+
+    VkSemaphoreCreateInfo semaphoreInfo;
+    semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
+    semaphoreInfo.pNext = nullptr;
+    semaphoreInfo.flags = 0;
+    VkSemaphore semaphore;
+    VkResult err = mCreateSemaphore(mDevice, &semaphoreInfo, nullptr, &semaphore);
+    if (VK_SUCCESS != err) {
+        ALOGE("Failed to create import semaphore, err: %d", err);
+        return UNKNOWN_ERROR;
+    }
+    VkImportSemaphoreFdInfoKHR importInfo;
+    importInfo.sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR;
+    importInfo.pNext = nullptr;
+    importInfo.semaphore = semaphore;
+    importInfo.flags = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT;
+    importInfo.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
+    importInfo.fd = fenceFd;
+
+    err = mImportSemaphoreFdKHR(mDevice, &importInfo);
+    if (VK_SUCCESS != err) {
+        ALOGE("Failed to import semaphore, err: %d", err);
+        return UNKNOWN_ERROR;
+    }
+
+    LOG_ALWAYS_FATAL_IF(mDummyCB == VK_NULL_HANDLE);
+
+    VkPipelineStageFlags waitDstStageFlags = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
+
+    VkSubmitInfo submitInfo;
+    memset(&submitInfo, 0, sizeof(VkSubmitInfo));
+    submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+    submitInfo.waitSemaphoreCount = 1;
+    // Wait to make sure aquire semaphore set above has signaled.
+    submitInfo.pWaitSemaphores = &semaphore;
+    submitInfo.pWaitDstStageMask = &waitDstStageFlags;
+    submitInfo.commandBufferCount = 1;
+    submitInfo.pCommandBuffers = &mDummyCB;
+    submitInfo.signalSemaphoreCount = 0;
+
+    mQueueSubmit(mGraphicsQueue, 1, &submitInfo, VK_NULL_HANDLE);
+
+    // On Android when we import a semaphore, it is imported using temporary permanence. That
+    // means as soon as we queue the semaphore for a wait it reverts to its previous permanent
+    // state before importing. This means it will now be in an idle state with no pending
+    // signal or wait operations, so it is safe to immediately delete it.
+    mDestroySemaphore(mDevice, semaphore, nullptr);
     return OK;
 }
 
@@ -1105,15 +1093,6 @@
         return INVALID_OPERATION;
     }
 
-    if (SyncFeatures::getInstance().useFenceSync()) {
-        ALOGE("VulkanManager::createReleaseFence: Vk backend doesn't support non-native fences");
-        return INVALID_OPERATION;
-    }
-
-    if (!SyncFeatures::getInstance().useNativeFenceSync()) {
-        return OK;
-    }
-
     VkExportSemaphoreCreateInfo exportInfo;
     exportInfo.sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO;
     exportInfo.pNext = nullptr;
diff --git a/libs/hwui/tests/unit/TypefaceTests.cpp b/libs/hwui/tests/unit/TypefaceTests.cpp
index e424a26..b645aeb 100644
--- a/libs/hwui/tests/unit/TypefaceTests.cpp
+++ b/libs/hwui/tests/unit/TypefaceTests.cpp
@@ -55,7 +55,8 @@
     sk_sp<SkTypeface> typeface(fm->makeFromStream(std::move(fontData)));
     LOG_ALWAYS_FATAL_IF(typeface == nullptr, "Failed to make typeface from %s", fileName);
     std::shared_ptr<minikin::MinikinFont> font = std::make_shared<MinikinFontSkia>(
-            std::move(typeface), data, st.st_size, 0, std::vector<minikin::FontVariation>());
+            std::move(typeface), data, st.st_size, fileName, 0,
+            std::vector<minikin::FontVariation>());
     std::vector<minikin::Font> fonts;
     fonts.push_back(minikin::Font::Builder(font).build());
     return std::make_shared<minikin::FontFamily>(std::move(fonts));
diff --git a/libs/incident/Android.bp b/libs/incident/Android.bp
new file mode 100644
index 0000000..0619a9c
--- /dev/null
+++ b/libs/incident/Android.bp
@@ -0,0 +1,50 @@
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+cc_library_shared {
+    name: "libincident",
+
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wno-missing-field-initializers",
+        "-Wno-unused-variable",
+        "-Wunused-parameter",
+    ],
+
+    shared_libs: [
+        "libbinder",
+        "liblog",
+        "libutils",
+    ],
+
+    aidl: {
+        include_dirs: ["frameworks/base/core/java"],
+        export_aidl_headers: true,
+    },
+
+    srcs: [
+        ":libincident_aidl",
+        "proto/android/os/header.proto",
+        "proto/android/os/metadata.proto",
+        "src/IncidentReportArgs.cpp",
+    ],
+
+    proto: {
+        type: "lite",
+        export_proto_headers: true,
+    },
+
+    export_include_dirs: ["include"],
+}
diff --git a/libs/incident/Android.mk b/libs/incident/Android.mk
deleted file mode 100644
index 08c8346..0000000
--- a/libs/incident/Android.mk
+++ /dev/null
@@ -1,43 +0,0 @@
-# Copyright (C) 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libincident
-
-LOCAL_CFLAGS := \
-        -Wall -Werror -Wno-missing-field-initializers -Wno-unused-variable -Wunused-parameter
-
-LOCAL_SHARED_LIBRARIES := \
-        libbinder \
-        liblog \
-        libutils
-
-LOCAL_AIDL_INCLUDES := $(LOCAL_PATH)/../../core/java
-LOCAL_C_INCLUDES := \
-        $(LOCAL_PATH)/include
-
-LOCAL_SRC_FILES := \
-        ../../core/java/android/os/IIncidentManager.aidl \
-        ../../core/java/android/os/IIncidentReportStatusListener.aidl \
-        proto/android/os/header.proto \
-        proto/android/os/metadata.proto \
-        src/IncidentReportArgs.cpp
-
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_PROTO_OPTIMIZE_TYPE := lite
-
-include $(BUILD_SHARED_LIBRARY)
-
diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java
index 38204a5..a02b6af 100644
--- a/media/java/android/media/AudioFormat.java
+++ b/media/java/android/media/AudioFormat.java
@@ -1068,6 +1068,7 @@
         ENCODING_E_AC3_JOC,
         ENCODING_DTS,
         ENCODING_DTS_HD,
+        ENCODING_MP3,
         ENCODING_IEC61937,
         ENCODING_AAC_HE_V1,
         ENCODING_AAC_HE_V2,
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index e8c97bc..274da11 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -1379,14 +1379,20 @@
     //====================================================================
     // Offload query
     /**
-     * @hide
      * Returns whether offloaded playback of an audio format is supported on the device.
-     * Offloaded playback is where the decoding of an audio stream is not competing with other
-     * software resources. In general, it is supported by dedicated hardware, such as audio DSPs.
+     * <p>Offloaded playback is the feature where the decoding and playback of an audio stream
+     * is not competing with other software resources. In general, it is supported by dedicated
+     * hardware, such as audio DSPs.
+     * <p>Note that this query only provides information about the support of an audio format,
+     * it does not indicate whether the resources necessary for the offloaded playback are
+     * available at that instant.
      * @param format the audio format (codec, sample rate, channels) being checked.
      * @return true if the given audio format can be offloaded.
      */
-    public boolean isOffloadedPlaybackSupported(@NonNull AudioFormat format) {
+    public static boolean isOffloadedPlaybackSupported(@NonNull AudioFormat format) {
+        if (format == null) {
+            throw new IllegalArgumentException("Illegal null AudioFormat");
+        }
         return AudioSystem.isOffloadSupported(format);
     }
 
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index f399274..3ec595d 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -23,7 +23,7 @@
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 import java.nio.NioUtils;
-import java.util.Collection;
+import java.util.LinkedList;
 import java.util.concurrent.Executor;
 
 import android.annotation.CallbackExecutor;
@@ -31,17 +31,13 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UnsupportedAppUsage;
-import android.app.ActivityThread;
-import android.content.Context;
 import android.os.Build;
+import android.os.Binder;
 import android.os.Handler;
-import android.os.IBinder;
+import android.os.HandlerThread;
 import android.os.Looper;
 import android.os.Message;
 import android.os.PersistableBundle;
-import android.os.Process;
-import android.os.RemoteException;
-import android.os.ServiceManager;
 import android.util.ArrayMap;
 import android.util.Log;
 
@@ -192,9 +188,8 @@
     private static final int NATIVE_EVENT_NEW_POS = 4;
     /**
      * Callback for more data
-     * TODO only for offload
      */
-    private static final int NATIVE_EVENT_MORE_DATA = 0;
+    private static final int NATIVE_EVENT_CAN_WRITE_MORE_DATA = 9;
     /**
      * IAudioTrack tear down for offloaded tracks
      * TODO: when received, java AudioTrack must be released
@@ -203,7 +198,6 @@
     /**
      * Event id denotes when all the buffers queued in AF and HW are played
      * back (after stop is called) for an offloaded track.
-     * TODO: not just for offload
      */
     private static final int NATIVE_EVENT_STREAM_END = 7;
 
@@ -393,6 +387,10 @@
      * Offset of the first sample of the audio in byte from start of HW_AV_SYNC track AV header.
      */
     private int mOffset = 0;
+    /**
+     * Indicates whether the track is intended to play in offload mode.
+     */
+    private boolean mOffloaded = false;
 
     //--------------------------------
     // Used exclusively by native code
@@ -615,6 +613,7 @@
             encoding = format.getEncoding();
         }
         audioParamCheck(rate, channelMask, channelIndexMask, encoding, mode);
+        mOffloaded = offload;
         mStreamType = AudioSystem.STREAM_DEFAULT;
 
         audioBuffSizeCheck(bufferSizeInBytes);
@@ -902,7 +901,6 @@
         }
 
         /**
-         * @hide
          * Sets whether this track will play through the offloaded audio path.
          * When set to true, at build time, the audio format will be checked against
          * {@link AudioManager#isOffloadedPlaybackSupported(AudioFormat)} to verify the audio format
@@ -961,8 +959,11 @@
                         .build();
             }
 
-            //TODO tie offload to PERFORMANCE_MODE_POWER_SAVING?    
             if (mOffload) {
+                if (mPerformanceMode == PERFORMANCE_MODE_LOW_LATENCY) {
+                    throw new UnsupportedOperationException(
+                            "Offload and low latency modes are incompatible");
+                }
                 if (mAttributes.getUsage() != AudioAttributes.USAGE_MEDIA) {
                     throw new UnsupportedOperationException(
                             "Cannot create AudioTrack, offload requires USAGE_MEDIA");
@@ -1224,6 +1225,9 @@
      * Releases the native AudioTrack resources.
      */
     public void release() {
+        synchronized (mStreamEventCbLock){
+            endStreamEventHandling();
+        }
         // even though native_release() stops the native AudioTrack, we need to stop
         // AudioTrack subclasses too.
         try {
@@ -2283,7 +2287,8 @@
             return ERROR_BAD_VALUE;
         }
 
-        int ret = native_write_byte(audioData, offsetInBytes, sizeInBytes, mAudioFormat,
+
+        final int ret = native_write_byte(audioData, offsetInBytes, sizeInBytes, mAudioFormat,
                 writeMode == WRITE_BLOCKING);
 
         if ((mDataLoadMode == MODE_STATIC)
@@ -2392,7 +2397,7 @@
             return ERROR_BAD_VALUE;
         }
 
-        int ret = native_write_short(audioData, offsetInShorts, sizeInShorts, mAudioFormat,
+        final int ret = native_write_short(audioData, offsetInShorts, sizeInShorts, mAudioFormat,
                 writeMode == WRITE_BLOCKING);
 
         if ((mDataLoadMode == MODE_STATIC)
@@ -2480,7 +2485,7 @@
             return ERROR_BAD_VALUE;
         }
 
-        int ret = native_write_float(audioData, offsetInFloats, sizeInFloats, mAudioFormat,
+        final int ret = native_write_float(audioData, offsetInFloats, sizeInFloats, mAudioFormat,
                 writeMode == WRITE_BLOCKING);
 
         if ((mDataLoadMode == MODE_STATIC)
@@ -2987,68 +2992,205 @@
     }
 
     /**
-     * @hide
-     * Abstract class to receive event notification about the stream playback.
-     * See {@link AudioTrack#setStreamEventCallback(Executor, StreamEventCallback)} to register
+     * Abstract class to receive event notifications about the stream playback in offloaded mode.
+     * See {@link AudioTrack#registerStreamEventCallback(Executor, StreamEventCallback)} to register
      * the callback on the given {@link AudioTrack} instance.
      */
     public abstract static class StreamEventCallback {
-        /** @hide */ // add hidden empty constructor so it doesn't show in SDK
-        public StreamEventCallback() { }
         /**
          * Called when an offloaded track is no longer valid and has been discarded by the system.
          * An example of this happening is when an offloaded track has been paused too long, and
          * gets invalidated by the system to prevent any other offload.
-         * @param track the {@link AudioTrack} on which the event happened
+         * @param track the {@link AudioTrack} on which the event happened.
          */
         public void onTearDown(AudioTrack track) { }
         /**
          * Called when all the buffers of an offloaded track that were queued in the audio system
          * (e.g. the combination of the Android audio framework and the device's audio hardware)
          * have been played after {@link AudioTrack#stop()} has been called.
-         * @param track the {@link AudioTrack} on which the event happened
+         * @param track the {@link AudioTrack} on which the event happened.
          */
-        public void onStreamPresentationEnd(AudioTrack track) { }
+        public void onPresentationEnded(AudioTrack track) { }
         /**
          * Called when more audio data can be written without blocking on an offloaded track.
-         * @param track the {@link AudioTrack} on which the event happened
+         * @param track the {@link AudioTrack} on which the event happened.
+         * @param sizeInFrames the number of frames available to write without blocking.
+         *   Note that the frame size of a compressed stream is 1 byte.
          */
-        public void onStreamDataRequest(AudioTrack track) { }
+        public void onDataRequest(AudioTrack track, int sizeInFrames) { }
     }
 
-    private Executor mStreamEventExec;
-    private StreamEventCallback mStreamEventCb;
-    private final Object mStreamEventCbLock = new Object();
-
     /**
-     * @hide
-     * Sets the callback for the notification of stream events.
-     * @param executor {@link Executor} to handle the callbacks
-     * @param eventCallback the callback to receive the stream event notifications
+     * Registers a callback for the notification of stream events.
+     * This callback can only be registered for instances operating in offloaded mode
+     * (see {@link AudioTrack.Builder#setOffloadedPlayback(boolean)} and
+     * {@link AudioManager#isOffloadedPlaybackSupported(AudioFormat)} for more details).
+     * @param executor {@link Executor} to handle the callbacks.
+     * @param eventCallback the callback to receive the stream event notifications.
      */
-    public void setStreamEventCallback(@NonNull @CallbackExecutor Executor executor,
+    public void registerStreamEventCallback(@NonNull @CallbackExecutor Executor executor,
             @NonNull StreamEventCallback eventCallback) {
         if (eventCallback == null) {
             throw new IllegalArgumentException("Illegal null StreamEventCallback");
         }
+        if (!mOffloaded) {
+            throw new IllegalStateException(
+                    "Cannot register StreamEventCallback on non-offloaded AudioTrack");
+        }
         if (executor == null) {
             throw new IllegalArgumentException("Illegal null Executor for the StreamEventCallback");
         }
         synchronized (mStreamEventCbLock) {
-            mStreamEventExec = executor;
-            mStreamEventCb = eventCallback;
+            // check if eventCallback already in list
+            for (StreamEventCbInfo seci : mStreamEventCbInfoList) {
+                if (seci.mStreamEventCb == eventCallback) {
+                    throw new IllegalArgumentException(
+                            "StreamEventCallback already registered");
+                }
+            }
+            beginStreamEventHandling();
+            mStreamEventCbInfoList.add(new StreamEventCbInfo(executor, eventCallback));
         }
     }
 
     /**
-     * @hide
-     * Unregisters the callback for notification of stream events, previously set
-     * by {@link #setStreamEventCallback(Executor, StreamEventCallback)}.
+     * Unregisters the callback for notification of stream events, previously registered
+     * with {@link #registerStreamEventCallback(Executor, StreamEventCallback)}.
+     * @param eventCallback the callback to unregister.
      */
-    public void removeStreamEventCallback() {
+    public void unregisterStreamEventCallback(@NonNull StreamEventCallback eventCallback) {
+        if (eventCallback == null) {
+            throw new IllegalArgumentException("Illegal null StreamEventCallback");
+        }
+        if (!mOffloaded) {
+            throw new IllegalStateException("No StreamEventCallback on non-offloaded AudioTrack");
+        }
         synchronized (mStreamEventCbLock) {
-            mStreamEventExec = null;
-            mStreamEventCb = null;
+            StreamEventCbInfo seciToRemove = null;
+            for (StreamEventCbInfo seci : mStreamEventCbInfoList) {
+                if (seci.mStreamEventCb == eventCallback) {
+                    // ok to remove while iterating over list as we exit iteration
+                    mStreamEventCbInfoList.remove(seci);
+                    if (mStreamEventCbInfoList.size() == 0) {
+                        endStreamEventHandling();
+                    }
+                    return;
+                }
+            }
+            throw new IllegalArgumentException("StreamEventCallback was not registered");
+        }
+    }
+
+    //---------------------------------------------------------
+    // Offload
+    //--------------------
+    private static class StreamEventCbInfo {
+        final Executor mStreamEventExec;
+        final StreamEventCallback mStreamEventCb;
+
+        StreamEventCbInfo(Executor e, StreamEventCallback cb) {
+            mStreamEventExec = e;
+            mStreamEventCb = cb;
+        }
+    }
+
+    private final Object mStreamEventCbLock = new Object();
+    @GuardedBy("mStreamEventCbLock")
+    @NonNull private LinkedList<StreamEventCbInfo> mStreamEventCbInfoList =
+            new LinkedList<StreamEventCbInfo>();
+    /**
+     * Dedicated thread for handling the StreamEvent callbacks
+     */
+    private @Nullable HandlerThread mStreamEventHandlerThread;
+    private @Nullable volatile StreamEventHandler mStreamEventHandler;
+
+    /**
+     * Called from native AudioTrack callback thread, filter messages if necessary
+     * and repost event on AudioTrack message loop to prevent blocking native thread.
+     * @param what event code received from native
+     * @param arg optional argument for event
+     */
+    void handleStreamEventFromNative(int what, int arg) {
+        if (mStreamEventHandler == null) {
+            return;
+        }
+        switch (what) {
+            case NATIVE_EVENT_CAN_WRITE_MORE_DATA:
+                // replace previous CAN_WRITE_MORE_DATA messages with the latest value
+                mStreamEventHandler.removeMessages(NATIVE_EVENT_CAN_WRITE_MORE_DATA);
+                mStreamEventHandler.sendMessage(
+                        mStreamEventHandler.obtainMessage(
+                                NATIVE_EVENT_CAN_WRITE_MORE_DATA, arg, 0/*ignored*/));
+                break;
+            case NATIVE_EVENT_NEW_IAUDIOTRACK:
+                mStreamEventHandler.sendMessage(
+                        mStreamEventHandler.obtainMessage(NATIVE_EVENT_NEW_IAUDIOTRACK));
+                break;
+            case NATIVE_EVENT_STREAM_END:
+                mStreamEventHandler.sendMessage(
+                        mStreamEventHandler.obtainMessage(NATIVE_EVENT_STREAM_END));
+                break;
+        }
+    }
+
+    private class StreamEventHandler extends Handler {
+
+        StreamEventHandler(Looper looper) {
+            super(looper);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            final LinkedList<StreamEventCbInfo> cbInfoList;
+            synchronized (mStreamEventCbLock) {
+                if (mStreamEventCbInfoList.size() == 0) {
+                    return;
+                }
+                cbInfoList = new LinkedList<StreamEventCbInfo>(mStreamEventCbInfoList);
+            }
+
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                for (StreamEventCbInfo cbi : cbInfoList) {
+                    switch (msg.what) {
+                        case NATIVE_EVENT_CAN_WRITE_MORE_DATA:
+                            cbi.mStreamEventExec.execute(() ->
+                                    cbi.mStreamEventCb.onDataRequest(AudioTrack.this, msg.arg1));
+                            break;
+                        case NATIVE_EVENT_NEW_IAUDIOTRACK:
+                            // TODO also release track as it's not longer usable
+                            cbi.mStreamEventExec.execute(() ->
+                                    cbi.mStreamEventCb.onTearDown(AudioTrack.this));
+                            break;
+                        case NATIVE_EVENT_STREAM_END:
+                            cbi.mStreamEventExec.execute(() ->
+                                    cbi.mStreamEventCb.onPresentationEnded(AudioTrack.this));
+                            break;
+                    }
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+    }
+
+    @GuardedBy("mStreamEventCbLock")
+    private void beginStreamEventHandling() {
+        if (mStreamEventHandlerThread == null) {
+            mStreamEventHandlerThread = new HandlerThread(TAG + ".StreamEvent");
+            mStreamEventHandlerThread.start();
+            final Looper looper = mStreamEventHandlerThread.getLooper();
+            if (looper != null) {
+                mStreamEventHandler = new StreamEventHandler(looper);
+            }
+        }
+    }
+
+    @GuardedBy("mStreamEventCbLock")
+    private void endStreamEventHandling() {
+        if (mStreamEventHandlerThread != null) {
+            mStreamEventHandlerThread.quit();
+            mStreamEventHandlerThread = null;
         }
     }
 
@@ -3136,7 +3278,7 @@
     private static void postEventFromNative(Object audiotrack_ref,
             int what, int arg1, int arg2, Object obj) {
         //logd("Event posted from the native side: event="+ what + " args="+ arg1+" "+arg2);
-        final AudioTrack track = (AudioTrack)((WeakReference)audiotrack_ref).get();
+        final AudioTrack track = (AudioTrack) ((WeakReference) audiotrack_ref).get();
         if (track == null) {
             return;
         }
@@ -3146,29 +3288,11 @@
             return;
         }
 
-        if (what == NATIVE_EVENT_MORE_DATA || what == NATIVE_EVENT_NEW_IAUDIOTRACK
+        if (what == NATIVE_EVENT_CAN_WRITE_MORE_DATA
+                || what == NATIVE_EVENT_NEW_IAUDIOTRACK
                 || what == NATIVE_EVENT_STREAM_END) {
-            final Executor exec;
-            final StreamEventCallback cb;
-            synchronized (track.mStreamEventCbLock) {
-                exec = track.mStreamEventExec;
-                cb = track.mStreamEventCb;
-            }
-            if ((exec == null) || (cb == null)) {
-                return;
-            }
-            switch (what) {
-                case NATIVE_EVENT_MORE_DATA:
-                    exec.execute(() -> cb.onStreamDataRequest(track));
-                    return;
-                case NATIVE_EVENT_NEW_IAUDIOTRACK:
-                    // TODO also release track as it's not longer usable
-                    exec.execute(() -> cb.onTearDown(track));
-                    return;
-                case NATIVE_EVENT_STREAM_END:
-                    exec.execute(() -> cb.onStreamPresentationEnd(track));
-                    return;
-            }
+            track.handleStreamEventFromNative(what, arg1);
+            return;
         }
 
         NativePositionEventHandlerDelegate delegate = track.mEventHandlerDelegate;
@@ -3181,7 +3305,6 @@
         }
     }
 
-
     //---------------------------------------------------------
     // Native methods called from the Java side
     //--------------------
diff --git a/media/java/android/media/DataSourceDesc.java b/media/java/android/media/DataSourceDesc.java
index a53fa11..afc99a0 100644
--- a/media/java/android/media/DataSourceDesc.java
+++ b/media/java/android/media/DataSourceDesc.java
@@ -62,6 +62,11 @@
     // intentionally less than long.MAX_VALUE
     public static final long LONG_MAX = 0x7ffffffffffffffL;
 
+    // keep consistent with native code
+    public static final long LONG_MAX_TIME_MS = LONG_MAX / 1000;
+    public static final long LONG_MAX_TIME_US = LONG_MAX_TIME_MS * 1000;
+
+
     private int mType = TYPE_NONE;
 
     private Media2DataSource mMedia2DataSource;
@@ -77,7 +82,7 @@
 
     private String mMediaId;
     private long mStartPositionMs = 0;
-    private long mEndPositionMs = LONG_MAX;
+    private long mEndPositionMs = LONG_MAX_TIME_MS;
 
     private DataSourceDesc() {
     }
@@ -225,7 +230,7 @@
 
         private String mMediaId;
         private long mStartPositionMs = 0;
-        private long mEndPositionMs = LONG_MAX;
+        private long mEndPositionMs = LONG_MAX_TIME_MS;
 
         /**
          * Constructs a new Builder with the defaults.
@@ -326,7 +331,7 @@
          */
         public Builder setEndPosition(long position) {
             if (position < 0) {
-                position = LONG_MAX;
+                position = LONG_MAX_TIME_MS;
             }
             mEndPositionMs = position;
             return this;
diff --git a/media/java/android/media/MediaMetadataRetriever.java b/media/java/android/media/MediaMetadataRetriever.java
index 57b648e..e019f42 100644
--- a/media/java/android/media/MediaMetadataRetriever.java
+++ b/media/java/android/media/MediaMetadataRetriever.java
@@ -923,5 +923,39 @@
      * @hide
      */
     public static final int METADATA_KEY_EXIF_LENGTH = 34;
+
+    /**
+     * This key retrieves the color standard, if available.
+     *
+     * @see MediaFormat#COLOR_STANDARD_BT709
+     * @see MediaFormat#COLOR_STANDARD_BT601_PAL
+     * @see MediaFormat#COLOR_STANDARD_BT601_NTSC
+     * @see MediaFormat#COLOR_STANDARD_BT2020
+     *
+     * @hide
+     */
+    public static final int METADATA_KEY_COLOR_STANDARD = 35;
+
+    /**
+     * This key retrieves the color transfer, if available.
+     *
+     * @see MediaFormat#COLOR_TRANSFER_LINEAR
+     * @see MediaFormat#COLOR_TRANSFER_SDR_VIDEO
+     * @see MediaFormat#COLOR_TRANSFER_ST2084
+     * @see MediaFormat#COLOR_TRANSFER_HLG
+     *
+     * @hide
+     */
+    public static final int METADATA_KEY_COLOR_TRANSFER = 36;
+
+    /**
+     * This key retrieves the color range, if available.
+     *
+     * @see MediaFormat#COLOR_RANGE_LIMITED
+     * @see MediaFormat#COLOR_RANGE_FULL
+     *
+     * @hide
+     */
+    public static final int METADATA_KEY_COLOR_RANGE    = 37;
     // Add more here...
 }
diff --git a/media/java/android/media/MediaPlayer2.java b/media/java/android/media/MediaPlayer2.java
index e94413c..54b5ab1 100644
--- a/media/java/android/media/MediaPlayer2.java
+++ b/media/java/android/media/MediaPlayer2.java
@@ -1361,7 +1361,7 @@
     }
 
     /**
-     * Sets the callback to be invoked when the media source is ready for playback.
+     * Registers the callback to be invoked for various events covered by {@link EventCallback}.
      *
      * @param executor the executor through which the callback should be invoked
      * @param eventCallback the callback that will be run
@@ -1378,7 +1378,6 @@
     // This is a synchronous call.
     public abstract void unregisterEventCallback(EventCallback eventCallback);
 
-
     /* Do not change these values without updating their counterparts
      * in include/media/mediaplayer2.h!
      */
@@ -1387,7 +1386,8 @@
      */
     public static final int MEDIA_ERROR_UNKNOWN = 1;
 
-    /** The video is streamed and its container is not valid for progressive
+    /**
+     * The video is streamed and its container is not valid for progressive
      * playback i.e the video's index (e.g moov atom) is not at the start of the
      * file.
      * @see EventCallback#onError
@@ -1698,19 +1698,33 @@
      * @see EventCallback#onCallCompleted
      * @hide
      */
-    public static final int CALL_COMPLETED_SET_BUFFERING_PARAMS = 1001;
+    public static final int CALL_COMPLETED_SET_BUFFERING_PARAMS = 31;
 
-    /** The player just completed a call {@code setVideoScalingMode}.
+    /** The player just completed a call {@link #setVideoScalingMode}.
      * @see EventCallback#onCallCompleted
      * @hide
      */
-    public static final int CALL_COMPLETED_SET_VIDEO_SCALING_MODE = 1002;
+    public static final int CALL_COMPLETED_SET_VIDEO_SCALING_MODE = 32;
 
-    /** The player just completed a call {@code notifyWhenCommandLabelReached}.
+    /**
+     * The start of the methods which have separate call complete callback.
+     * @hide
+     */
+    public static final int SEPARATE_CALL_COMPLETED_CALLBACK_START = 1000;
+
+    /** The player just completed a call {@link #notifyWhenCommandLabelReached}.
      * @see EventCallback#onCommandLabelReached
      * @hide
      */
-    public static final int CALL_COMPLETED_NOTIFY_WHEN_COMMAND_LABEL_REACHED = 1003;
+    public static final int CALL_COMPLETED_NOTIFY_WHEN_COMMAND_LABEL_REACHED =
+            SEPARATE_CALL_COMPLETED_CALLBACK_START;
+
+    /** The player just completed a call {@link #prepareDrm}.
+     * @see DrmEventCallback#onDrmPrepared
+     * @hide
+     */
+    public static final int CALL_COMPLETED_PREPARE_DRM =
+            SEPARATE_CALL_COMPLETED_CALLBACK_START + 1;
 
     /**
      * @hide
@@ -1740,7 +1754,8 @@
             CALL_COMPLETED_CLEAR_NEXT_DATA_SOURCES,
             CALL_COMPLETED_SET_BUFFERING_PARAMS,
             CALL_COMPLETED_SET_VIDEO_SCALING_MODE,
-            CALL_COMPLETED_NOTIFY_WHEN_COMMAND_LABEL_REACHED
+            CALL_COMPLETED_NOTIFY_WHEN_COMMAND_LABEL_REACHED,
+            CALL_COMPLETED_PREPARE_DRM,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface CallCompleted {}
@@ -1864,20 +1879,22 @@
     }
 
     /**
-     * Sets the callback to be invoked when the media source is ready for playback.
+     * Registers the callback to be invoked for various DRM events.
      *
      * @param eventCallback the callback that will be run
      * @param executor the executor through which the callback should be invoked
      */
     // This is a synchronous call.
-    public abstract void setDrmEventCallback(@NonNull @CallbackExecutor Executor executor,
+    public abstract void registerDrmEventCallback(@NonNull @CallbackExecutor Executor executor,
             @NonNull DrmEventCallback eventCallback);
 
     /**
-     * Clears the {@link DrmEventCallback}.
+     * Unregisters the {@link DrmEventCallback}.
+     *
+     * @param eventCallback the callback to be unregistered
      */
     // This is a synchronous call.
-    public abstract void clearDrmEventCallback();
+    public abstract void unregisterDrmEventCallback(DrmEventCallback eventCallback);
 
     /**
      * The status codes for {@link DrmEventCallback#onDrmPrepared} listener.
@@ -1902,6 +1919,15 @@
      */
     public static final int PREPARE_DRM_STATUS_PREPARATION_ERROR = 3;
 
+    /**
+     * The crypto scheme UUID is not supported by the device.
+     */
+    public static final int PREPARE_DRM_STATUS_UNSUPPORTED_SCHEME = 4;
+
+    /**
+     * The hardware resources are not available, due to being in use.
+     */
+    public static final int PREPARE_DRM_STATUS_RESOURCE_BUSY = 5;
 
     /** @hide */
     @IntDef(flag = false, prefix = "PREPARE_DRM_STATUS", value = {
@@ -1909,6 +1935,8 @@
         PREPARE_DRM_STATUS_PROVISIONING_NETWORK_ERROR,
         PREPARE_DRM_STATUS_PROVISIONING_SERVER_ERROR,
         PREPARE_DRM_STATUS_PREPARATION_ERROR,
+        PREPARE_DRM_STATUS_UNSUPPORTED_SCHEME,
+        PREPARE_DRM_STATUS_RESOURCE_BUSY,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface PrepareDrmStatusCode {}
@@ -1925,41 +1953,28 @@
      * <p>
      * If {@link OnDrmConfigHelper} is registered, it will be called during
      * preparation to allow configuration of the DRM properties before opening the
-     * DRM session. Note that the callback is called synchronously in the thread that called
-     * {@link #prepareDrm}. It should be used only for a series of {@code getDrmPropertyString}
-     * and {@code setDrmPropertyString} calls and refrain from any lengthy operation.
+     * DRM session. It should be used only for a series of {@link #getDrmPropertyString}
+     * and {@link #setDrmPropertyString} calls and refrain from any lengthy operation.
      * <p>
      * If the device has not been provisioned before, this call also provisions the device
      * which involves accessing the provisioning server and can take a variable time to
      * complete depending on the network connectivity.
-     * If {@code OnDrmPreparedListener} is registered, prepareDrm() runs in non-blocking
-     * mode by launching the provisioning in the background and returning. The listener
-     * will be called when provisioning and preparation has finished. If a
-     * {@code OnDrmPreparedListener} is not registered, prepareDrm() waits till provisioning
-     * and preparation has finished, i.e., runs in blocking mode.
+     * When needed, the provisioning will be launched  in the background.
+     * The listener {@link DrmEventCallback#onDrmPrepared}
+     * will be called when provisioning and preparation are finished. The application should
+     * check the status code returned with {@link DrmEventCallback#onDrmPrepared} to proceed.
      * <p>
-     * If {@code OnDrmPreparedListener} is registered, it is called to indicate the DRM
+     * The registered {@link DrmEventCallback#onDrmPrepared} is called to indicate the DRM
      * session being ready. The application should not make any assumption about its call
-     * sequence (e.g., before or after prepareDrm returns), or the thread context that will
-     * execute the listener (unless the listener is registered with a handler thread).
+     * sequence (e.g., before or after prepareDrm returns).
      * <p>
      *
      * @param uuid The UUID of the crypto scheme. If not known beforehand, it can be retrieved
-     * from the source through {@code getDrmInfo} or registering a {@code onDrmInfoListener}.
-     *
-     * @throws IllegalStateException              if called before being prepared or the DRM was
-     *                                            prepared already
-     * @throws UnsupportedSchemeException         if the crypto scheme is not supported
-     * @throws ResourceBusyException              if required DRM resources are in use
-     * @throws ProvisioningNetworkErrorException  if provisioning is required but failed due to a
-     *                                            network error
-     * @throws ProvisioningServerErrorException   if provisioning is required but failed due to
-     *                                            the request denied by the provisioning server
+     * from the source through {@code getDrmInfo} or registering a
+     * {@link DrmEventCallback#onDrmInfo}.
      */
-    // This is a synchronous call.
-    public abstract void prepareDrm(@NonNull UUID uuid)
-            throws UnsupportedSchemeException, ResourceBusyException,
-                   ProvisioningNetworkErrorException, ProvisioningServerErrorException;
+    // This is an asynchronous call.
+    public abstract void prepareDrm(@NonNull UUID uuid);
 
     /**
      * Releases the DRM session
@@ -2107,28 +2122,6 @@
           }
     }
 
-    /**
-     * Thrown when the device requires DRM provisioning but the provisioning attempt has
-     * failed due to a network error (Internet reachability, timeout, etc.).
-     * Extends MediaDrm.MediaDrmException
-     */
-    public abstract static class ProvisioningNetworkErrorException extends MediaDrmException {
-          protected ProvisioningNetworkErrorException(String detailMessage) {
-              super(detailMessage);
-          }
-    }
-
-    /**
-     * Thrown when the device requires DRM provisioning but the provisioning attempt has
-     * failed due to the provisioning server denying the request.
-     * Extends MediaDrm.MediaDrmException
-     */
-    public abstract static class ProvisioningServerErrorException extends MediaDrmException {
-          protected ProvisioningServerErrorException(String detailMessage) {
-              super(detailMessage);
-          }
-    }
-
     public static final class MetricsConstants {
         private MetricsConstants() {}
 
diff --git a/media/java/android/media/MediaPlayer2Impl.java b/media/java/android/media/MediaPlayer2Impl.java
index 9bad5f1..a5eb1fb 100644
--- a/media/java/android/media/MediaPlayer2Impl.java
+++ b/media/java/android/media/MediaPlayer2Impl.java
@@ -2409,7 +2409,7 @@
         }
     }
 
-    public static void checkArgument(boolean expression, String errorMessage) {
+    private static void checkArgument(boolean expression, String errorMessage) {
         if (!expression) {
             throw new IllegalArgumentException(errorMessage);
         }
@@ -2473,15 +2473,8 @@
     private ArrayList<Pair<Executor, DrmEventCallback> > mDrmEventCallbackRecords
         = new ArrayList<Pair<Executor, DrmEventCallback> >();
 
-    /**
-     * Register a callback to be invoked when the media source is ready
-     * for playback.
-     *
-     * @param eventCallback the callback that will be run
-     * @param executor the executor through which the callback should be invoked
-     */
     @Override
-    public void setDrmEventCallback(@NonNull @CallbackExecutor Executor executor,
+    public void registerDrmEventCallback(@NonNull @CallbackExecutor Executor executor,
             @NonNull DrmEventCallback eventCallback) {
         if (eventCallback == null) {
             throw new IllegalArgumentException("Illegal null EventCallback");
@@ -2495,17 +2488,17 @@
         }
     }
 
-    /**
-     * Clears the {@link DrmEventCallback}.
-     */
     @Override
-    public void clearDrmEventCallback() {
+    public void unregisterDrmEventCallback(DrmEventCallback eventCallback) {
         synchronized (mDrmEventCbLock) {
-            mDrmEventCallbackRecords.clear();
+            for (Pair<Executor, DrmEventCallback> cb : mDrmEventCallbackRecords) {
+                if (cb.second == eventCallback) {
+                    mDrmEventCallbackRecords.remove(cb);
+                }
+            }
         }
     }
 
-
     /**
      * Retrieves the DRM Info associated with the current source
      *
@@ -2532,54 +2525,80 @@
         return drmInfo;
     }
 
-
-    /**
-     * Prepares the DRM for the current source
-     * <p>
-     * If {@code OnDrmConfigHelper} is registered, it will be called during
-     * preparation to allow configuration of the DRM properties before opening the
-     * DRM session. Note that the callback is called synchronously in the thread that called
-     * {@code prepareDrm}. It should be used only for a series of {@code getDrmPropertyString}
-     * and {@code setDrmPropertyString} calls and refrain from any lengthy operation.
-     * <p>
-     * If the device has not been provisioned before, this call also provisions the device
-     * which involves accessing the provisioning server and can take a variable time to
-     * complete depending on the network connectivity.
-     * If {@code OnDrmPreparedListener} is registered, prepareDrm() runs in non-blocking
-     * mode by launching the provisioning in the background and returning. The listener
-     * will be called when provisioning and preparation has finished. If a
-     * {@code OnDrmPreparedListener} is not registered, prepareDrm() waits till provisioning
-     * and preparation has finished, i.e., runs in blocking mode.
-     * <p>
-     * If {@code OnDrmPreparedListener} is registered, it is called to indicate the DRM
-     * session being ready. The application should not make any assumption about its call
-     * sequence (e.g., before or after prepareDrm returns), or the thread context that will
-     * execute the listener (unless the listener is registered with a handler thread).
-     * <p>
-     *
-     * @param uuid The UUID of the crypto scheme. If not known beforehand, it can be retrieved
-     * from the source through {@code getDrmInfo} or registering a {@code onDrmInfoListener}.
-     *
-     * @throws IllegalStateException              if called before prepare(), or the DRM was
-     *                                            prepared already
-     * @throws UnsupportedSchemeException         if the crypto scheme is not supported
-     * @throws ResourceBusyException              if required DRM resources are in use
-     * @throws ProvisioningNetworkErrorException  if provisioning is required but failed due to a
-     *                                            network error
-     * @throws ProvisioningServerErrorException   if provisioning is required but failed due to
-     *                                            the request denied by the provisioning server
-     */
     @Override
-    public void prepareDrm(@NonNull UUID uuid)
+    public void prepareDrm(@NonNull UUID uuid) {
+        addTask(new Task(CALL_COMPLETED_PREPARE_DRM, true) {
+            @Override
+            void process() {
+                int status = PREPARE_DRM_STATUS_SUCCESS;
+                boolean sendEvent = true;
+
+                try {
+                    doPrepareDrm(uuid);
+                } catch (ResourceBusyException e) {
+                    status = PREPARE_DRM_STATUS_RESOURCE_BUSY;
+                } catch (UnsupportedSchemeException e) {
+                    status = PREPARE_DRM_STATUS_UNSUPPORTED_SCHEME;
+                } catch (NotProvisionedException e) {
+                    Log.w(TAG, "prepareDrm: NotProvisionedException");
+
+                    // handle provisioning internally; it'll reset mPrepareDrmInProgress
+                    status = HandleProvisioninig(uuid);
+
+                    if (status == PREPARE_DRM_STATUS_SUCCESS) {
+                        // DrmEventCallback will be fired in provisioning
+                        sendEvent = false;
+                    } else {
+                        synchronized (mDrmLock) {
+                            cleanDrmObj();
+                        }
+
+                        switch (status) {
+                        case PREPARE_DRM_STATUS_PROVISIONING_NETWORK_ERROR:
+                            Log.e(TAG, "prepareDrm: Provisioning was required but failed " +
+                                    "due to a network error.");
+                            break;
+
+                        case PREPARE_DRM_STATUS_PROVISIONING_SERVER_ERROR:
+                            Log.e(TAG, "prepareDrm: Provisioning was required but the request " +
+                                    "was denied by the server.");
+                            break;
+
+                        case PREPARE_DRM_STATUS_PREPARATION_ERROR:
+                        default:
+                            Log.e(TAG, "prepareDrm: Post-provisioning preparation failed.");
+                            break;
+                        }
+                    }
+                } catch (Exception e) {
+                    status = PREPARE_DRM_STATUS_PREPARATION_ERROR;
+                }
+
+                if (sendEvent) {
+                    final int prepareDrmStatus = status;
+                    sendDrmEvent(new DrmEventNotifier() {
+                        @Override
+                        public void notify(DrmEventCallback callback) {
+                            callback.onDrmPrepared(
+                                    MediaPlayer2Impl.this, mCurrentDSD, prepareDrmStatus);
+                        }
+                    });
+
+                    synchronized (mTaskLock) {
+                        mCurrentTask = null;
+                        processPendingTask_l();
+                    }
+                }
+            }
+        });
+    }
+
+    private void doPrepareDrm(@NonNull UUID uuid)
             throws UnsupportedSchemeException, ResourceBusyException,
-                   ProvisioningNetworkErrorException, ProvisioningServerErrorException
-    {
+                   NotProvisionedException {
         Log.v(TAG, "prepareDrm: uuid: " + uuid + " mOnDrmConfigHelper: " + mOnDrmConfigHelper);
 
-        boolean allDoneWithoutProvisioning = false;
-
         synchronized (mDrmLock) {
-
             // only allowing if tied to a protected source; might relax for releasing offline keys
             if (mDrmInfoImpl == null) {
                 final String msg = "prepareDrm(): Wrong usage: The player must be prepared and " +
@@ -2623,8 +2642,7 @@
             }
 
             mDrmConfigAllowed = true;
-        }   // synchronized
-
+        }  // synchronized
 
         // call the callback outside the lock
         if (mOnDrmConfigHelper != null)  {
@@ -2640,74 +2658,28 @@
 
                 mDrmUUID = uuid;
                 mActiveDrmScheme = true;
-
-                allDoneWithoutProvisioning = true;
+                mPrepareDrmInProgress = false;
             } catch (IllegalStateException e) {
                 final String msg = "prepareDrm(): Wrong usage: The player must be " +
                         "in the prepared state to call prepareDrm().";
                 Log.e(TAG, msg);
                 earlyExit = true;
+                mPrepareDrmInProgress = false;
                 throw new IllegalStateException(msg);
             } catch (NotProvisionedException e) {
-                Log.w(TAG, "prepareDrm: NotProvisionedException");
-
-                // handle provisioning internally; it'll reset mPrepareDrmInProgress
-                int result = HandleProvisioninig(uuid);
-
-                // if blocking mode, we're already done;
-                // if non-blocking mode, we attempted to launch background provisioning
-                if (result != PREPARE_DRM_STATUS_SUCCESS) {
-                    earlyExit = true;
-                    String msg;
-
-                    switch (result) {
-                    case PREPARE_DRM_STATUS_PROVISIONING_NETWORK_ERROR:
-                        msg = "prepareDrm: Provisioning was required but failed " +
-                                "due to a network error.";
-                        Log.e(TAG, msg);
-                        throw new ProvisioningNetworkErrorExceptionImpl(msg);
-
-                    case PREPARE_DRM_STATUS_PROVISIONING_SERVER_ERROR:
-                        msg = "prepareDrm: Provisioning was required but the request " +
-                                "was denied by the server.";
-                        Log.e(TAG, msg);
-                        throw new ProvisioningServerErrorExceptionImpl(msg);
-
-                    case PREPARE_DRM_STATUS_PREPARATION_ERROR:
-                    default: // default for safeguard
-                        msg = "prepareDrm: Post-provisioning preparation failed.";
-                        Log.e(TAG, msg);
-                        throw new IllegalStateException(msg);
-                    }
-                }
-                // nothing else to do;
-                // if blocking or non-blocking, HandleProvisioninig does the re-attempt & cleanup
+                Log.w(TAG, "prepareDrm: NotProvisionedException", e);
+                throw e;
             } catch (Exception e) {
                 Log.e(TAG, "prepareDrm: Exception " + e);
                 earlyExit = true;
+                mPrepareDrmInProgress = false;
                 throw e;
             } finally {
-                if (!mDrmProvisioningInProgress) {// if early exit other than provisioning exception
-                    mPrepareDrmInProgress = false;
-                }
-                if (earlyExit) {    // cleaning up object if didn't succeed
+                if (earlyExit) {  // clean up object if didn't succeed
                     cleanDrmObj();
                 }
-            } // finally
-        }   // synchronized
-
-
-        // if finished successfully without provisioning, call the callback outside the lock
-        if (allDoneWithoutProvisioning) {
-            sendDrmEvent(new DrmEventNotifier() {
-                @Override
-                public void notify(DrmEventCallback callback) {
-                    callback.onDrmPrepared(
-                            MediaPlayer2Impl.this, mCurrentDSD, PREPARE_DRM_STATUS_SUCCESS);
-                }
-            });
-        }
-
+            }  // finally
+        }  // synchronized
     }
 
 
@@ -3164,31 +3136,6 @@
         }
     }
 
-    /**
-     * Thrown when the device requires DRM provisioning but the provisioning attempt has
-     * failed due to a network error (Internet reachability, timeout, etc.).
-     * Extends MediaDrm.MediaDrmException
-     */
-    public static final class ProvisioningNetworkErrorExceptionImpl
-            extends ProvisioningNetworkErrorException {
-        public ProvisioningNetworkErrorExceptionImpl(String detailMessage) {
-            super(detailMessage);
-        }
-    }
-
-    /**
-     * Thrown when the device requires DRM provisioning but the provisioning attempt has
-     * failed due to the provisioning server denying the request.
-     * Extends MediaDrm.MediaDrmException
-     */
-    public static final class ProvisioningServerErrorExceptionImpl
-            extends ProvisioningServerErrorException {
-        public ProvisioningServerErrorExceptionImpl(String detailMessage) {
-            super(detailMessage);
-        }
-    }
-
-
     private native void _prepareDrm(@NonNull byte[] uuid, @NonNull byte[] drmSessionId);
 
     // Modular DRM helpers
@@ -3277,12 +3224,12 @@
         }
 
         @Override
-        public void onStreamPresentationEnd(AudioTrack track) {
+        public void onPresentationEnded(AudioTrack track) {
             native_stream_event_onStreamPresentationEnd(mNativeCallbackPtr, mUserDataPtr);
         }
 
         @Override
-        public void onStreamDataRequest(AudioTrack track) {
+        public void onDataRequest(AudioTrack track, int size) {
             native_stream_event_onStreamDataRequest(
                     mJAudioTrackPtr, mNativeCallbackPtr, mUserDataPtr);
         }
@@ -3296,7 +3243,6 @@
         private Object drmLock;
         private MediaPlayer2Impl mediaPlayer;
         private int status;
-        private boolean finished;
         public  int status() {
             return status;
         }
@@ -3362,38 +3308,7 @@
 
             boolean succeeded = false;
 
-            boolean hasCallback = false;
-            synchronized (mDrmEventCbLock) {
-                hasCallback = !mDrmEventCallbackRecords.isEmpty();
-            }
-            // non-blocking mode needs the lock
-            if (hasCallback) {
-
-                synchronized (drmLock) {
-                    // continuing with prepareDrm
-                    if (provisioningSucceeded) {
-                        succeeded = mediaPlayer.resumePrepareDrm(uuid);
-                        status = (succeeded) ?
-                                PREPARE_DRM_STATUS_SUCCESS :
-                                PREPARE_DRM_STATUS_PREPARATION_ERROR;
-                    }
-                    mediaPlayer.mDrmProvisioningInProgress = false;
-                    mediaPlayer.mPrepareDrmInProgress = false;
-                    if (!succeeded) {
-                        cleanDrmObj();  // cleaning up if it hasn't gone through while in the lock
-                    }
-                } // synchronized
-
-                // calling the callback outside the lock
-                sendDrmEvent(new DrmEventNotifier() {
-                    @Override
-                    public void notify(DrmEventCallback callback) {
-                        callback.onDrmPrepared(
-                                mediaPlayer, mCurrentDSD, status);
-                    }
-                });
-            } else {   // blocking mode already has the lock
-
+            synchronized (drmLock) {
                 // continuing with prepareDrm
                 if (provisioningSucceeded) {
                     succeeded = mediaPlayer.resumePrepareDrm(uuid);
@@ -3404,12 +3319,28 @@
                 mediaPlayer.mDrmProvisioningInProgress = false;
                 mediaPlayer.mPrepareDrmInProgress = false;
                 if (!succeeded) {
-                    cleanDrmObj();  // cleaning up if it hasn't gone through
+                    cleanDrmObj();  // cleaning up if it hasn't gone through while in the lock
+                }
+            }  // synchronized
+
+            // calling the callback outside the lock
+            sendDrmEvent(new DrmEventNotifier() {
+                @Override
+                public void notify(DrmEventCallback callback) {
+                    callback.onDrmPrepared(
+                            mediaPlayer, mCurrentDSD, status);
+                }
+            });
+
+            synchronized (mTaskLock) {
+                if (mCurrentTask != null
+                        && mCurrentTask.mMediaCallType == CALL_COMPLETED_PREPARE_DRM
+                        && mCurrentTask.mNeedToWaitForEventToComplete) {
+                    mCurrentTask = null;
+                    processPendingTask_l();
                 }
             }
-
-            finished = true;
-        }   // run()
+        }
 
         /**
          * Returns a byte[] containing the remainder of 'in', closing it when done.
@@ -3437,50 +3368,29 @@
     }   // ProvisioningThread
 
     private int HandleProvisioninig(UUID uuid) {
-        // the lock is already held by the caller
-
-        if (mDrmProvisioningInProgress) {
-            Log.e(TAG, "HandleProvisioninig: Unexpected mDrmProvisioningInProgress");
-            return PREPARE_DRM_STATUS_PREPARATION_ERROR;
-        }
-
-        MediaDrm.ProvisionRequest provReq = mDrmObj.getProvisionRequest();
-        if (provReq == null) {
-            Log.e(TAG, "HandleProvisioninig: getProvisionRequest returned null.");
-            return PREPARE_DRM_STATUS_PREPARATION_ERROR;
-        }
-
-        Log.v(TAG, "HandleProvisioninig provReq " +
-                " data: " + provReq.getData() + " url: " + provReq.getDefaultUrl());
-
-        // networking in a background thread
-        mDrmProvisioningInProgress = true;
-
-        mDrmProvisioningThread = new ProvisioningThread().initialize(provReq, uuid, this);
-        mDrmProvisioningThread.start();
-
-        int result;
-
-        // non-blocking: this is not the final result
-        boolean hasCallback = false;
-        synchronized (mDrmEventCbLock) {
-            hasCallback = !mDrmEventCallbackRecords.isEmpty();
-        }
-        if (hasCallback) {
-            result = PREPARE_DRM_STATUS_SUCCESS;
-        } else {
-            // if blocking mode, wait till provisioning is done
-            try {
-                mDrmProvisioningThread.join();
-            } catch (Exception e) {
-                Log.w(TAG, "HandleProvisioninig: Thread.join Exception " + e);
+        synchronized (mDrmLock) {
+            if (mDrmProvisioningInProgress) {
+                Log.e(TAG, "HandleProvisioninig: Unexpected mDrmProvisioningInProgress");
+                return PREPARE_DRM_STATUS_PREPARATION_ERROR;
             }
-            result = mDrmProvisioningThread.status();
-            // no longer need the thread
-            mDrmProvisioningThread = null;
-        }
 
-        return result;
+            MediaDrm.ProvisionRequest provReq = mDrmObj.getProvisionRequest();
+            if (provReq == null) {
+                Log.e(TAG, "HandleProvisioninig: getProvisionRequest returned null.");
+                return PREPARE_DRM_STATUS_PREPARATION_ERROR;
+            }
+
+            Log.v(TAG, "HandleProvisioninig provReq " +
+                    " data: " + provReq.getData() + " url: " + provReq.getDefaultUrl());
+
+            // networking in a background thread
+            mDrmProvisioningInProgress = true;
+
+            mDrmProvisioningThread = new ProvisioningThread().initialize(provReq, uuid, this);
+            mDrmProvisioningThread.start();
+
+            return PREPARE_DRM_STATUS_SUCCESS;
+        }
     }
 
     private boolean resumePrepareDrm(UUID uuid) {
@@ -3691,7 +3601,9 @@
         private void sendCompleteNotification(int status) {
             // In {@link #notifyWhenCommandLabelReached} case, a separate callback
             // {@link #onCommandLabelReached} is already called in {@code process()}.
-            if (mMediaCallType == CALL_COMPLETED_NOTIFY_WHEN_COMMAND_LABEL_REACHED) {
+            // CALL_COMPLETED_PREPARE_DRM is sent via DrmEventCallback
+            if (mMediaCallType == CALL_COMPLETED_NOTIFY_WHEN_COMMAND_LABEL_REACHED
+                    || mMediaCallType == CALL_COMPLETED_PREPARE_DRM) {
                 return;
             }
             sendEvent(new EventNotifier() {
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index c537945..0cde01e 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -524,6 +524,9 @@
         private boolean mScanSuccess;
         private int mWidth;
         private int mHeight;
+        private int mColorStandard;
+        private int mColorTransfer;
+        private int mColorRange;
 
         public MyMediaScannerClient() {
             mDateFormatter = new SimpleDateFormat("yyyyMMdd'T'HHmmss");
@@ -592,6 +595,9 @@
             mCompilation = 0;
             mWidth = 0;
             mHeight = 0;
+            mColorStandard = -1;
+            mColorTransfer = -1;
+            mColorRange = -1;
 
             return entry;
         }
@@ -760,6 +766,12 @@
                 mWidth = parseSubstring(value, 0, 0);
             } else if (name.equalsIgnoreCase("height")) {
                 mHeight = parseSubstring(value, 0, 0);
+            } else if (name.equalsIgnoreCase("colorstandard")) {
+                mColorStandard = parseSubstring(value, 0, -1);
+            } else if (name.equalsIgnoreCase("colortransfer")) {
+                mColorTransfer = parseSubstring(value, 0, -1);
+            } else if (name.equalsIgnoreCase("colorrange")) {
+                mColorRange = parseSubstring(value, 0, -1);
             } else {
                 //Log.v(TAG, "unknown tag: " + name + " (" + mProcessGenres + ")");
             }
@@ -905,6 +917,15 @@
                     if (resolution != null) {
                         map.put(Video.Media.RESOLUTION, resolution);
                     }
+                    if (mColorStandard >= 0) {
+                        map.put(Video.Media.COLOR_STANDARD, mColorStandard);
+                    }
+                    if (mColorTransfer >= 0) {
+                        map.put(Video.Media.COLOR_TRANSFER, mColorTransfer);
+                    }
+                    if (mColorRange >= 0) {
+                        map.put(Video.Media.COLOR_RANGE, mColorRange);
+                    }
                     if (mDate > 0) {
                         map.put(Video.Media.DATE_TAKEN, mDate);
                     }
@@ -986,7 +1007,7 @@
                 ExifInterface exif = null;
                 try {
                     exif = new ExifInterface(entry.mPath);
-                } catch (IOException ex) {
+                } catch (Exception ex) {
                     // exif is null
                 }
                 if (exif != null) {
diff --git a/media/java/android/media/Ringtone.java b/media/java/android/media/Ringtone.java
index 32aba7f..84dfcb1 100644
--- a/media/java/android/media/Ringtone.java
+++ b/media/java/android/media/Ringtone.java
@@ -23,13 +23,12 @@
 import android.content.res.AssetFileDescriptor;
 import android.content.res.Resources.NotFoundException;
 import android.database.Cursor;
-import android.media.MediaPlayer.OnCompletionListener;
 import android.net.Uri;
 import android.os.Binder;
 import android.os.RemoteException;
 import android.provider.MediaStore;
-import android.provider.Settings;
 import android.provider.MediaStore.MediaColumns;
+import android.provider.Settings;
 import android.util.Log;
 
 import java.io.IOException;
@@ -50,7 +49,6 @@
 
     private static final String[] MEDIA_COLUMNS = new String[] {
         MediaStore.Audio.Media._ID,
-        MediaStore.Audio.Media.DATA,
         MediaStore.Audio.Media.TITLE
     };
     /** Selection that limits query results to just audio files */
@@ -254,7 +252,7 @@
                         cursor = res.query(uri, MEDIA_COLUMNS, mediaSelection, null, null);
                         if (cursor != null && cursor.getCount() == 1) {
                             cursor.moveToFirst();
-                            return cursor.getString(2);
+                            return cursor.getString(1);
                         }
                         // missing cursor is handled below
                     }
diff --git a/media/java/android/media/RingtoneManager.java b/media/java/android/media/RingtoneManager.java
index 8664aa1..436897f 100644
--- a/media/java/android/media/RingtoneManager.java
+++ b/media/java/android/media/RingtoneManager.java
@@ -497,34 +497,6 @@
         return getUriFromCursor(mCursor);
     }
 
-    /**
-     * Queries the database for the Uri to a ringtone in a specific path (the ringtone has to have
-     * been scanned before)
-     *
-     * @param context Context used to query the database
-     * @param path Path to the ringtone file
-     * @return Uri of the ringtone, null if something fails in the query or the ringtone doesn't
-     *            exist
-     *
-     * @hide
-     */
-    private static Uri getExistingRingtoneUriFromPath(Context context, String path) {
-        final String[] proj = {MediaStore.Audio.Media._ID};
-        final String[] selectionArgs = {path};
-        try (final Cursor cursor = context.getContentResolver().query(
-                MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, proj,
-                MediaStore.Audio.Media.DATA + "=? ", selectionArgs, /* sortOrder */ null)) {
-            if (cursor == null || !cursor.moveToFirst()) {
-                return null;
-            }
-            final int id = cursor.getInt(cursor.getColumnIndex(MediaStore.MediaColumns._ID));
-            if (id == -1) {
-                return null;
-            }
-            return Uri.withAppendedPath(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, "" + id);
-        }
-    }
-
     private static Uri getUriFromCursor(Cursor cursor) {
         return ContentUris.withAppendedId(Uri.parse(cursor.getString(URI_COLUMN_INDEX)), cursor
                 .getLong(ID_COLUMN_INDEX));
@@ -750,28 +722,6 @@
     }
 
     /**
-     * Look up the path for a given {@link Uri} referring to a ringtone sound (TYPE_RINGTONE,
-     * TYPE_NOTIFICATION, or TYPE_ALARM). This is saved in {@link MediaStore.Audio.Media#DATA}.
-     *
-     * @return a {@link File} pointing at the location of the {@param uri} on disk, or {@code null}
-     * if there is no such file.
-     */
-    private File getRingtonePathFromUri(Uri uri) {
-        // Query cursor to get ringtone path
-        final String[] projection = {MediaStore.Audio.Media.DATA};
-        setFilterColumnsList(TYPE_RINGTONE | TYPE_NOTIFICATION | TYPE_ALARM);
-
-        String path = null;
-        try (Cursor cursor = query(uri, projection, constructBooleanTrueWhereClause(mFilterColumns),
-                null, null)) {
-            if (cursor != null && cursor.moveToFirst()) {
-                path = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DATA));
-            }
-        }
-        return path != null ? new File(path) : null;
-    }
-
-    /**
      * Disables Settings.System.SYNC_PARENT_SOUNDS.
      *
      * @hide
@@ -879,32 +829,6 @@
                 : uriWithoutUserId.toString().startsWith(storage.toString());
     }
 
-    /** @hide */
-    public boolean isCustomRingtone(Uri uri) {
-        if(!isExternalRingtoneUri(uri)) {
-            // A custom ringtone would be in the external storage
-            return false;
-        }
-
-        final File ringtoneFile = (uri == null ? null : getRingtonePathFromUri(uri));
-        final File parent = (ringtoneFile == null ? null : ringtoneFile.getParentFile());
-        if (parent == null) {
-            return false;
-        }
-
-        final String[] directories = {
-            Environment.DIRECTORY_RINGTONES,
-            Environment.DIRECTORY_NOTIFICATIONS,
-            Environment.DIRECTORY_ALARMS
-        };
-        for (final String directory : directories) {
-            if (parent.equals(Environment.getExternalStoragePublicDirectory(directory))) {
-                return true;
-            }
-        }
-        return false;
-    }
-
     /**
      * Adds an audio file to the list of ringtones.
      *
@@ -989,39 +913,6 @@
     }
 
     /**
-     * Deletes the actual file in the Uri and its ringtone database entry if the Uri's actual path
-     * is in one of the following directories: {@link android.is.Environment#DIRECTORY_RINGTONES},
-     * {@link android.is.Environment#DIRECTORY_NOTIFICATIONS} or
-     * {@link android.is.Environment#DIRECTORY_ALARMS}.
-     *
-     * The given Uri must be a ringtone Content Uri.
-     *
-     * Keep in mind that if the ringtone deleted is a default ringtone, it will still live in the
-     * ringtone cache file so it will be playable from there. However, if an app uses the ringtone
-     * as its own ringtone, it won't be played, which is the same behavior observed for 3rd party
-     * custom ringtones.
-     *
-     * @hide
-     */
-    public boolean deleteExternalRingtone(Uri uri) {
-        if(!isCustomRingtone(uri)) {
-            // We can only delete custom ringtones in the default ringtone storages
-            return false;
-        }
-
-        // Save the path of the ringtone before deleting from our content resolver.
-        final File ringtoneFile = getRingtonePathFromUri(uri);
-        try {
-            if (ringtoneFile != null && mContext.getContentResolver().delete(uri, null, null) > 0) {
-                return ringtoneFile.delete();
-            }
-        } catch (SecurityException e) {
-            Log.d(TAG, "Unable to delete custom ringtone", e);
-        }
-        return false;
-    }
-
-    /**
      * Try opening the given ringtone locally first, but failover to
      * {@link IRingtonePlayer} if we can't access it directly. Typically happens
      * when process doesn't hold
diff --git a/media/jni/Android.bp b/media/jni/Android.bp
index fa9ab1f..e841567 100644
--- a/media/jni/Android.bp
+++ b/media/jni/Android.bp
@@ -81,6 +81,9 @@
         "-Wno-error=deprecated-declarations",
         "-Wunused",
         "-Wunreachable-code",
+        // Allow implicit fallthroughs in android_media_MediaScanner.cpp and
+        // android_mtp_MtpDatabase.cpp until they are fixed.
+        "-Wno-error=implicit-fallthrough",
     ],
 }
 
diff --git a/opengl/java/android/opengl/EGL15.java b/opengl/java/android/opengl/EGL15.java
index f855fe2..bd845e7 100644
--- a/opengl/java/android/opengl/EGL15.java
+++ b/opengl/java/android/opengl/EGL15.java
@@ -20,7 +20,9 @@
  * EGL 1.5
  *
  */
-public class EGL15 {
+public final class EGL15 {
+
+    private EGL15() {};
 
     public static final int EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT            = 0x00000001;
     public static final int EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT   = 0x00000002;
diff --git a/packages/ExtServices/src/android/ext/services/notification/ChannelImpressions.java b/packages/ExtServices/src/android/ext/services/notification/ChannelImpressions.java
index 29ee920..ca3daad 100644
--- a/packages/ExtServices/src/android/ext/services/notification/ChannelImpressions.java
+++ b/packages/ExtServices/src/android/ext/services/notification/ChannelImpressions.java
@@ -37,6 +37,8 @@
     static final String ATT_DISMISSALS = "dismisses";
     static final String ATT_VIEWS = "views";
     static final String ATT_STREAK = "streak";
+    static final String ATT_SENT = "sent";
+    static final String ATT_INTERRUPTIVE = "interruptive";
 
     private int mDismissals = 0;
     private int mViews = 0;
diff --git a/packages/ExternalStorageProvider/AndroidManifest.xml b/packages/ExternalStorageProvider/AndroidManifest.xml
index 1072f95..484dbcc 100644
--- a/packages/ExternalStorageProvider/AndroidManifest.xml
+++ b/packages/ExternalStorageProvider/AndroidManifest.xml
@@ -17,6 +17,10 @@
             <intent-filter>
                 <action android:name="android.content.action.DOCUMENTS_PROVIDER" />
             </intent-filter>
+            <!-- Stub that allows MediaProvider to make incoming calls -->
+            <path-permission
+                android:path="/media_internal"
+                android:permission="android.permission.WRITE_MEDIA_STORAGE" />
         </provider>
 
         <receiver android:name=".MountReceiver">
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index 62207c5..4e52ff6d 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -37,6 +37,7 @@
 import android.provider.DocumentsContract.Document;
 import android.provider.DocumentsContract.Path;
 import android.provider.DocumentsContract.Root;
+import android.provider.MediaStore;
 import android.provider.Settings;
 import android.system.ErrnoException;
 import android.system.Os;
@@ -606,11 +607,16 @@
                     }
                     break;
                 }
-                case "getDocumentId": {
-                    final String path = arg;
-                    final List<UriPermission> accessUriPermissions =
-                            extras.getParcelableArrayList(AUTHORITY + ".extra.uriPermissions");
+                case MediaStore.GET_DOCUMENT_URI_CALL: {
+                    // All callers must go through MediaProvider
+                    getContext().enforceCallingPermission(
+                            android.Manifest.permission.WRITE_MEDIA_STORAGE, TAG);
 
+                    final Uri fileUri = extras.getParcelable(DocumentsContract.EXTRA_URI);
+                    final List<UriPermission> accessUriPermissions = extras
+                            .getParcelableArrayList(DocumentsContract.EXTRA_URI_PERMISSIONS);
+
+                    final String path = fileUri.getPath();
                     try {
                         final Bundle out = new Bundle();
                         final Uri uri = getDocumentUri(path, accessUriPermissions);
@@ -619,7 +625,22 @@
                     } catch (FileNotFoundException e) {
                         throw new IllegalStateException("File in " + path + " is not found.", e);
                     }
+                }
+                case MediaStore.GET_MEDIA_URI_CALL: {
+                    // All callers must go through MediaProvider
+                    getContext().enforceCallingPermission(
+                            android.Manifest.permission.WRITE_MEDIA_STORAGE, TAG);
 
+                    final Uri documentUri = extras.getParcelable(DocumentsContract.EXTRA_URI);
+                    final String docId = DocumentsContract.getDocumentId(documentUri);
+                    try {
+                        final Bundle out = new Bundle();
+                        final Uri uri = Uri.fromFile(getFileForDocId(docId));
+                        out.putParcelable(DocumentsContract.EXTRA_URI, uri);
+                        return out;
+                    } catch (FileNotFoundException e) {
+                        throw new IllegalStateException(e);
+                    }
                 }
                 default:
                     Log.w(TAG, "unknown method passed to call(): " + method);
diff --git a/packages/PackageInstaller/res/drawable/app_icon_foreground.xml b/packages/PackageInstaller/res/drawable/app_icon_foreground.xml
index b1f40c1..2dcd49c 100644
--- a/packages/PackageInstaller/res/drawable/app_icon_foreground.xml
+++ b/packages/PackageInstaller/res/drawable/app_icon_foreground.xml
@@ -16,10 +16,10 @@
   -->
 <inset
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:insetTop="12dp"
-    android:insetRight="12dp"
-    android:insetBottom="12dp"
-    android:insetLeft="12dp">
+    android:insetTop="25%"
+    android:insetRight="25%"
+    android:insetBottom="25%"
+    android:insetLeft="25%">
 
     <vector
         android:width="24dp"
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothCallback.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothCallback.java
index a842229..3152e65 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothCallback.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothCallback.java
@@ -127,4 +127,17 @@
     default void onProfileConnectionStateChanged(CachedBluetoothDevice cachedDevice,
             int state, int bluetoothProfile) {
     }
+
+    /**
+     * Called when ACL connection state is changed. It listens to
+     * {@link android.bluetooth.BluetoothDevice#ACTION_ACL_CONNECTED} and {@link
+     * android.bluetooth.BluetoothDevice#ACTION_ACL_DISCONNECTED}
+     *
+     * @param cachedDevice Bluetooth device that changed
+     * @param state        the Bluetooth device connection state, the possible values are:
+     *                     {@link android.bluetooth.BluetoothAdapter#STATE_DISCONNECTED},
+     *                     {@link android.bluetooth.BluetoothAdapter#STATE_CONNECTED}
+     */
+    default void onAclConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) {
+    }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
index 7124096..2b7babd 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
@@ -26,9 +26,13 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.os.UserHandle;
 import android.telephony.TelephonyManager;
 import android.util.Log;
 
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+
 import com.android.settingslib.R;
 
 import java.util.ArrayList;
@@ -54,21 +58,32 @@
     private final BroadcastReceiver mProfileBroadcastReceiver = new BluetoothBroadcastReceiver();
     private final Collection<BluetoothCallback> mCallbacks = new ArrayList<>();
     private final android.os.Handler mReceiverHandler;
+    private final UserHandle mUserHandle;
     private final Context mContext;
 
     interface Handler {
         void onReceive(Context context, Intent intent, BluetoothDevice device);
     }
 
+    /**
+     * Creates BluetoothEventManager with the ability to pass in {@link UserHandle} that tells it to
+     * listen for bluetooth events for that particular userHandle.
+     *
+     * <p> If passing in userHandle that's different from the user running the process,
+     * {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} permission is required. If
+     * userHandle passed in is {@code null}, we register event receiver for the
+     * {@code context.getUser()} handle.
+     */
     BluetoothEventManager(LocalBluetoothAdapter adapter,
             CachedBluetoothDeviceManager deviceManager, Context context,
-            android.os.Handler handler) {
+            android.os.Handler handler, @Nullable UserHandle userHandle) {
         mLocalAdapter = adapter;
         mDeviceManager = deviceManager;
         mAdapterIntentFilter = new IntentFilter();
         mProfileIntentFilter = new IntentFilter();
         mHandlerMap = new HashMap<>();
         mContext = context;
+        mUserHandle = userHandle;
         mReceiverHandler = handler;
 
         // Bluetooth on/off broadcasts
@@ -104,7 +119,11 @@
         addHandler(TelephonyManager.ACTION_PHONE_STATE_CHANGED,
                 new AudioModeChangedHandler());
 
-        mContext.registerReceiver(mBroadcastReceiver, mAdapterIntentFilter, null, mReceiverHandler);
+        // ACL connection changed broadcasts
+        addHandler(BluetoothDevice.ACTION_ACL_CONNECTED, new AclStateChangedHandler());
+        addHandler(BluetoothDevice.ACTION_ACL_DISCONNECTED, new AclStateChangedHandler());
+
+        registerAdapterIntentReceiver();
     }
 
     /** Register to start receiving callbacks for Bluetooth events. */
@@ -121,10 +140,31 @@
         }
     }
 
+    @VisibleForTesting
     void registerProfileIntentReceiver() {
-        mContext.registerReceiver(mProfileBroadcastReceiver, mProfileIntentFilter, null, mReceiverHandler);
+        registerIntentReceiver(mProfileBroadcastReceiver, mProfileIntentFilter);
     }
 
+    @VisibleForTesting
+    void registerAdapterIntentReceiver() {
+        registerIntentReceiver(mBroadcastReceiver, mAdapterIntentFilter);
+    }
+
+    /**
+     * Registers the provided receiver to receive the broadcasts that correspond to the
+     * passed intent filter, in the context of the provided handler.
+     */
+    private void registerIntentReceiver(BroadcastReceiver receiver, IntentFilter filter) {
+        if (mUserHandle == null) {
+            // If userHandle has not been provided, simply call registerReceiver.
+            mContext.registerReceiver(receiver, filter, null, mReceiverHandler);
+        } else {
+            // userHandle was explicitly specified, so need to call multi-user aware API.
+            mContext.registerReceiverAsUser(receiver, mUserHandle, filter, null, mReceiverHandler);
+        }
+    }
+
+    @VisibleForTesting
     void addProfileHandler(String action, Handler handler) {
         mHandlerMap.put(action, handler);
         mProfileIntentFilter.addAction(action);
@@ -171,7 +211,6 @@
                 callback.onProfileConnectionStateChanged(device, state, bluetoothProfile);
             }
         }
-        mDeviceManager.onProfileConnectionStateChanged(device, state, bluetoothProfile);
     }
 
     private void dispatchConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) {
@@ -201,7 +240,17 @@
         }
     }
 
-    private void addHandler(String action, Handler handler) {
+    private void dispatchAclStateChanged(CachedBluetoothDevice activeDevice,
+            int state) {
+        synchronized (mCallbacks) {
+            for (BluetoothCallback callback : mCallbacks) {
+                callback.onAclConnectionStateChanged(activeDevice, state);
+            }
+        }
+    }
+
+    @VisibleForTesting
+    void addHandler(String action, Handler handler) {
         mHandlerMap.put(action, handler);
         mAdapterIntentFilter.addAction(action);
     }
@@ -411,6 +460,32 @@
         }
     }
 
+    private class AclStateChangedHandler implements Handler {
+        @Override
+        public void onReceive(Context context, Intent intent, BluetoothDevice device) {
+            final String action = intent.getAction();
+            if (action == null) {
+                Log.w(TAG, "AclStateChangedHandler: action is null");
+                return;
+            }
+            final CachedBluetoothDevice activeDevice = mDeviceManager.findDevice(device);
+            final int state;
+            switch (action) {
+                case BluetoothDevice.ACTION_ACL_CONNECTED:
+                    state = BluetoothAdapter.STATE_CONNECTED;
+                    break;
+                case BluetoothDevice.ACTION_ACL_DISCONNECTED:
+                    state = BluetoothAdapter.STATE_DISCONNECTED;
+                    break;
+                default:
+                    Log.w(TAG, "ActiveDeviceChangedHandler: unknown action " + action);
+                    return;
+
+            }
+            dispatchAclStateChanged(activeDevice, state);
+        }
+    }
+
     private class AudioModeChangedHandler implements Handler {
 
         @Override
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index a2e30df..b4e82e9 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -29,6 +29,8 @@
 import android.text.TextUtils;
 import android.util.Log;
 
+import androidx.annotation.VisibleForTesting;
+
 import com.android.settingslib.R;
 
 import java.util.ArrayList;
@@ -36,8 +38,6 @@
 import java.util.Collections;
 import java.util.List;
 
-import androidx.annotation.VisibleForTesting;
-
 /**
  * CachedBluetoothDevice represents a remote Bluetooth device. It contains
  * attributes of the device (such as the address, name, RSSI, etc.) and
@@ -54,11 +54,12 @@
     private final Context mContext;
     private final BluetoothAdapter mLocalAdapter;
     private final LocalBluetoothProfileManager mProfileManager;
-    private final BluetoothDevice mDevice;
+    BluetoothDevice mDevice;
     private long mHiSyncId;
     // Need this since there is no method for getting RSSI
-    private short mRssi;
-
+    short mRssi;
+    // mProfiles and mRemovedProfiles does not do swap() between main and sub device. It is
+    // because current sub device is only for HearingAid and its profile is the same.
     private final List<LocalBluetoothProfile> mProfiles =
             Collections.synchronizedList(new ArrayList<>());
 
@@ -69,7 +70,7 @@
     // Device supports PANU but not NAP: remove PanProfile after device disconnects from NAP
     private boolean mLocalNapRoleConnected;
 
-    private boolean mJustDiscovered;
+    boolean mJustDiscovered;
 
     private int mMessageRejectionCount;
 
@@ -92,6 +93,8 @@
     private boolean mIsActiveDeviceA2dp = false;
     private boolean mIsActiveDeviceHeadset = false;
     private boolean mIsActiveDeviceHearingAid = false;
+    // Group second device for Hearing Aid
+    private CachedBluetoothDevice mSubDevice;
 
     CachedBluetoothDevice(Context context, LocalBluetoothProfileManager profileManager,
             BluetoothDevice device) {
@@ -1064,4 +1067,28 @@
         return hearingAidProfile != null && hearingAidProfile.getConnectionStatus(mDevice) ==
                 BluetoothProfile.STATE_CONNECTED;
     }
+
+    public CachedBluetoothDevice getSubDevice() {
+        return mSubDevice;
+    }
+
+    public void setSubDevice(CachedBluetoothDevice subDevice) {
+        mSubDevice = subDevice;
+    }
+
+    public void switchSubDeviceContent() {
+        // Backup from main device
+        BluetoothDevice tmpDevice = mDevice;
+        short tmpRssi = mRssi;
+        boolean tmpJustDiscovered = mJustDiscovered;
+        // Set main device from sub device
+        mDevice = mSubDevice.mDevice;
+        mRssi = mSubDevice.mRssi;
+        mJustDiscovered = mSubDevice.mJustDiscovered;
+        // Set sub device from backup
+        mSubDevice.mDevice = tmpDevice;
+        mSubDevice.mRssi = tmpRssi;
+        mSubDevice.mJustDiscovered = tmpJustDiscovered;
+        fetchActiveDevices();
+    }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
index 21cf0c2..f7f6589 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
@@ -18,8 +18,6 @@
 
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothHearingAid;
-import android.bluetooth.BluetoothProfile;
 import android.content.Context;
 import android.util.Log;
 
@@ -27,12 +25,8 @@
 
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
 import java.util.List;
-import java.util.Map;
 import java.util.Objects;
-import java.util.Set;
 
 /**
  * CachedBluetoothDeviceManager manages the set of remote Bluetooth devices.
@@ -45,20 +39,14 @@
     private final LocalBluetoothManager mBtManager;
 
     @VisibleForTesting
-    final List<CachedBluetoothDevice> mCachedDevices =
-        new ArrayList<CachedBluetoothDevice>();
-    // Contains the list of hearing aid devices that should not be shown in the UI.
+    final List<CachedBluetoothDevice> mCachedDevices = new ArrayList<CachedBluetoothDevice>();
     @VisibleForTesting
-    final List<CachedBluetoothDevice> mHearingAidDevicesNotAddedInCache
-        = new ArrayList<CachedBluetoothDevice>();
-    // Maintains a list of devices which are added in mCachedDevices and have hiSyncIds.
-    @VisibleForTesting
-    final Map<Long, CachedBluetoothDevice> mCachedDevicesMapForHearingAids
-        = new HashMap<Long, CachedBluetoothDevice>();
+    HearingAidDeviceManager mHearingAidDeviceManager;
 
     CachedBluetoothDeviceManager(Context context, LocalBluetoothManager localBtManager) {
         mContext = context;
         mBtManager = localBtManager;
+        mHearingAidDeviceManager = new HearingAidDeviceManager(localBtManager, mCachedDevices);
     }
 
     public synchronized Collection<CachedBluetoothDevice> getCachedDevicesCopy() {
@@ -92,12 +80,13 @@
             if (cachedDevice.getDevice().equals(device)) {
                 return cachedDevice;
             }
-        }
-        for (CachedBluetoothDevice notCachedDevice : mHearingAidDevicesNotAddedInCache) {
-            if (notCachedDevice.getDevice().equals(device)) {
-                return notCachedDevice;
+            // Check sub devices if it exists
+            CachedBluetoothDevice subDevice = cachedDevice.getSubDevice();
+            if (subDevice != null && subDevice.getDevice().equals(device)) {
+                return subDevice;
             }
         }
+
         return null;
     }
 
@@ -111,24 +100,10 @@
         LocalBluetoothProfileManager profileManager = mBtManager.getProfileManager();
         CachedBluetoothDevice newDevice = new CachedBluetoothDevice(mContext, profileManager,
                 device);
-        if (profileManager.getHearingAidProfile() != null
-            && profileManager.getHearingAidProfile().getHiSyncId(newDevice.getDevice())
-                != BluetoothHearingAid.HI_SYNC_ID_INVALID) {
-            newDevice.setHiSyncId(profileManager.getHearingAidProfile()
-                .getHiSyncId(newDevice.getDevice()));
-        }
-        // Just add one of the hearing aids from a pair in the list that is shown in the UI.
-        if (isPairAddedInCache(newDevice.getHiSyncId())) {
-            synchronized (this) {
-                mHearingAidDevicesNotAddedInCache.add(newDevice);
-            }
-        } else {
-            synchronized (this) {
+        mHearingAidDeviceManager.initHearingAidDeviceIfNeeded(newDevice);
+        synchronized (this) {
+            if (!mHearingAidDeviceManager.setSubDeviceIfNeeded(newDevice)) {
                 mCachedDevices.add(newDevice);
-                if (newDevice.getHiSyncId() != BluetoothHearingAid.HI_SYNC_ID_INVALID
-                    && !mCachedDevicesMapForHearingAids.containsKey(newDevice.getHiSyncId())) {
-                    mCachedDevicesMapForHearingAids.put(newDevice.getHiSyncId(), newDevice);
-                }
                 mBtManager.getEventManager().dispatchDeviceAdded(newDevice);
             }
         }
@@ -137,49 +112,18 @@
     }
 
     /**
-     * Returns true if the one of the two hearing aid devices is already cached for UI.
-     *
-     * @param long hiSyncId
-     * @return {@code True} if one of the two hearing aid devices is is already cached for UI.
-     */
-    private synchronized boolean isPairAddedInCache(long hiSyncId) {
-        if (hiSyncId == BluetoothHearingAid.HI_SYNC_ID_INVALID) {
-            return false;
-        }
-        if(mCachedDevicesMapForHearingAids.containsKey(hiSyncId)) {
-            return true;
-        }
-        return false;
-    }
-
-    /**
      * Returns device summary of the pair of the hearing aid passed as the parameter.
      *
      * @param CachedBluetoothDevice device
-     * @return Device summary, or if the pair does not exist or if its not a hearing aid,
+     * @return Device summary, or if the pair does not exist or if it is not a hearing aid,
      * then {@code null}.
      */
-    public synchronized String getHearingAidPairDeviceSummary(CachedBluetoothDevice device) {
-        String pairDeviceSummary = null;
-        if (device.getHiSyncId() != BluetoothHearingAid.HI_SYNC_ID_INVALID) {
-            for (CachedBluetoothDevice hearingAidDevice : mHearingAidDevicesNotAddedInCache) {
-                if (hearingAidDevice.getHiSyncId() != BluetoothHearingAid.HI_SYNC_ID_INVALID
-                    && hearingAidDevice.getHiSyncId() == device.getHiSyncId()) {
-                    pairDeviceSummary = hearingAidDevice.getConnectionSummary();
-                }
-            }
+    public synchronized String getSubDeviceSummary(CachedBluetoothDevice device) {
+        CachedBluetoothDevice subDevice = device.getSubDevice();
+        if (subDevice != null && subDevice.isConnected()) {
+            return subDevice.getConnectionSummary();
         }
-        return pairDeviceSummary;
-    }
-
-    /**
-     * Adds the 2nd hearing aid in a pair in a list that maintains the hearing aids that are
-     * not dispalyed in the UI.
-     *
-     * @param CachedBluetoothDevice device
-     */
-    public synchronized void addDeviceNotaddedInMap(CachedBluetoothDevice device) {
-        mHearingAidDevicesNotAddedInCache.add(device);
+        return null;
     }
 
     /**
@@ -187,28 +131,8 @@
      * Hearing Aid Service is connected and the HiSyncId's are now available.
      * @param LocalBluetoothProfileManager profileManager
      */
-    public synchronized void updateHearingAidsDevices(LocalBluetoothProfileManager profileManager) {
-        HearingAidProfile profileProxy = profileManager.getHearingAidProfile();
-        if (profileProxy == null) {
-            log("updateHearingAidsDevices: getHearingAidProfile() is null");
-            return;
-        }
-        final Set<Long> syncIdChangedSet = new HashSet<Long>();
-        for (CachedBluetoothDevice cachedDevice : mCachedDevices) {
-            if (cachedDevice.getHiSyncId() != BluetoothHearingAid.HI_SYNC_ID_INVALID) {
-                continue;
-            }
-
-            long newHiSyncId = profileProxy.getHiSyncId(cachedDevice.getDevice());
-
-            if (newHiSyncId != BluetoothHearingAid.HI_SYNC_ID_INVALID) {
-                cachedDevice.setHiSyncId(newHiSyncId);
-                syncIdChangedSet.add(newHiSyncId);
-            }
-        }
-        for (Long syncId : syncIdChangedSet) {
-            onHiSyncIdChanged(syncId);
-        }
+    public synchronized void updateHearingAidsDevices() {
+        mHearingAidDeviceManager.updateHearingAidsDevices();
     }
 
     /**
@@ -232,15 +156,21 @@
     }
 
     public synchronized void clearNonBondedDevices() {
-
-        mCachedDevicesMapForHearingAids.entrySet().removeIf(entries
-            -> entries.getValue().getBondState() == BluetoothDevice.BOND_NONE);
-
+        clearNonBondedSubDevices();
         mCachedDevices.removeIf(cachedDevice
             -> cachedDevice.getBondState() == BluetoothDevice.BOND_NONE);
+    }
 
-        mHearingAidDevicesNotAddedInCache.removeIf(hearingAidDevice
-            -> hearingAidDevice.getBondState() == BluetoothDevice.BOND_NONE);
+    private void clearNonBondedSubDevices() {
+        for (int i = mCachedDevices.size() - 1; i >= 0; i--) {
+            CachedBluetoothDevice cachedDevice = mCachedDevices.get(i);
+            CachedBluetoothDevice subDevice = cachedDevice.getSubDevice();
+            if (subDevice != null
+                    && subDevice.getDevice().getBondState() == BluetoothDevice.BOND_NONE) {
+                // Sub device exists and it is not bonded
+                cachedDevice.setSubDevice(null);
+            }
+        }
     }
 
     public synchronized void onScanningStateChanged(boolean started) {
@@ -250,10 +180,10 @@
         for (int i = mCachedDevices.size() - 1; i >= 0; i--) {
             CachedBluetoothDevice cachedDevice = mCachedDevices.get(i);
             cachedDevice.setJustDiscovered(false);
-        }
-        for (int i = mHearingAidDevicesNotAddedInCache.size() - 1; i >= 0; i--) {
-            CachedBluetoothDevice notCachedDevice = mHearingAidDevicesNotAddedInCache.get(i);
-            notCachedDevice.setJustDiscovered(false);
+            final CachedBluetoothDevice subDevice = cachedDevice.getSubDevice();
+            if (subDevice != null) {
+                subDevice.setJustDiscovered(false);
+            }
         }
     }
 
@@ -277,162 +207,45 @@
         if (bluetoothState == BluetoothAdapter.STATE_TURNING_OFF) {
             for (int i = mCachedDevices.size() - 1; i >= 0; i--) {
                 CachedBluetoothDevice cachedDevice = mCachedDevices.get(i);
+                CachedBluetoothDevice subDevice = cachedDevice.getSubDevice();
+                if (subDevice != null) {
+                    if (subDevice.getBondState() != BluetoothDevice.BOND_BONDED) {
+                        cachedDevice.setSubDevice(null);
+                    }
+                }
                 if (cachedDevice.getBondState() != BluetoothDevice.BOND_BONDED) {
                     cachedDevice.setJustDiscovered(false);
                     mCachedDevices.remove(i);
-                    if (cachedDevice.getHiSyncId() != BluetoothHearingAid.HI_SYNC_ID_INVALID
-                        && mCachedDevicesMapForHearingAids.containsKey(cachedDevice.getHiSyncId()))
-                    {
-                        mCachedDevicesMapForHearingAids.remove(cachedDevice.getHiSyncId());
-                    }
-                }
-            }
-            for (int i = mHearingAidDevicesNotAddedInCache.size() - 1; i >= 0; i--) {
-                CachedBluetoothDevice notCachedDevice = mHearingAidDevicesNotAddedInCache.get(i);
-                if (notCachedDevice.getBondState() != BluetoothDevice.BOND_BONDED) {
-                    notCachedDevice.setJustDiscovered(false);
-                    mHearingAidDevicesNotAddedInCache.remove(i);
                 }
             }
         }
     }
 
     public synchronized void onActiveDeviceChanged(CachedBluetoothDevice activeDevice,
-                                                   int bluetoothProfile) {
+            int bluetoothProfile) {
         for (CachedBluetoothDevice cachedDevice : mCachedDevices) {
             boolean isActive = Objects.equals(cachedDevice, activeDevice);
             cachedDevice.onActiveDeviceChanged(isActive, bluetoothProfile);
         }
     }
 
-    public synchronized void onHiSyncIdChanged(long hiSyncId) {
-        int firstMatchedIndex = -1;
-
-        for (int i = mCachedDevices.size() - 1; i >= 0; i--) {
-            CachedBluetoothDevice cachedDevice = mCachedDevices.get(i);
-            if (cachedDevice.getHiSyncId() == hiSyncId) {
-                if (firstMatchedIndex != -1) {
-                    /* Found the second one */
-                    int indexToRemoveFromUi;
-                    CachedBluetoothDevice deviceToRemoveFromUi;
-
-                    // Since the hiSyncIds have been updated for a connected pair of hearing aids,
-                    // we remove the entry of one the hearing aids from the UI. Unless the
-                    // hiSyncId get updated, the system does not know it is a hearing aid, so we add
-                    // both the hearing aids as separate entries in the UI first, then remove one
-                    // of them after the hiSyncId is populated. We will choose the device that
-                    // is not connected to be removed.
-                    if (cachedDevice.isConnected()) {
-                        indexToRemoveFromUi = firstMatchedIndex;
-                        deviceToRemoveFromUi = mCachedDevices.get(firstMatchedIndex);
-                        mCachedDevicesMapForHearingAids.put(hiSyncId, cachedDevice);
-                    } else {
-                        indexToRemoveFromUi = i;
-                        deviceToRemoveFromUi = cachedDevice;
-                        mCachedDevicesMapForHearingAids.put(hiSyncId,
-                                                            mCachedDevices.get(firstMatchedIndex));
-                    }
-
-                    mCachedDevices.remove(indexToRemoveFromUi);
-                    mHearingAidDevicesNotAddedInCache.add(deviceToRemoveFromUi);
-                    log("onHiSyncIdChanged: removed from UI device=" + deviceToRemoveFromUi
-                        + ", with hiSyncId=" + hiSyncId);
-                    mBtManager.getEventManager().dispatchDeviceRemoved(deviceToRemoveFromUi);
-                    break;
-                } else {
-                    mCachedDevicesMapForHearingAids.put(hiSyncId, cachedDevice);
-                    firstMatchedIndex = i;
-                }
-            }
-        }
-    }
-
-    private CachedBluetoothDevice getHearingAidOtherDevice(CachedBluetoothDevice thisDevice,
-                                                           long hiSyncId) {
-        if (hiSyncId == BluetoothHearingAid.HI_SYNC_ID_INVALID) {
-            return null;
-        }
-
-        // Searched the lists for the other side device with the matching hiSyncId.
-        for (CachedBluetoothDevice notCachedDevice : mHearingAidDevicesNotAddedInCache) {
-            if ((hiSyncId == notCachedDevice.getHiSyncId()) &&
-                (!Objects.equals(notCachedDevice, thisDevice))) {
-                return notCachedDevice;
-            }
-        }
-
-        CachedBluetoothDevice cachedDevice = mCachedDevicesMapForHearingAids.get(hiSyncId);
-        if (!Objects.equals(cachedDevice, thisDevice)) {
-            return cachedDevice;
-        }
-        return null;
-    }
-
-    private void hearingAidSwitchDisplayDevice(CachedBluetoothDevice toDisplayDevice,
-                                           CachedBluetoothDevice toHideDevice, long hiSyncId)
-    {
-        log("hearingAidSwitchDisplayDevice: toDisplayDevice=" + toDisplayDevice
-            + ", toHideDevice=" + toHideDevice);
-
-        // Remove the "toHideDevice" device from the UI.
-        mHearingAidDevicesNotAddedInCache.add(toHideDevice);
-        mCachedDevices.remove(toHideDevice);
-        mBtManager.getEventManager().dispatchDeviceRemoved(toHideDevice);
-
-        // Add the "toDisplayDevice" device to the UI.
-        mHearingAidDevicesNotAddedInCache.remove(toDisplayDevice);
-        mCachedDevices.add(toDisplayDevice);
-        mCachedDevicesMapForHearingAids.put(hiSyncId, toDisplayDevice);
-        mBtManager.getEventManager().dispatchDeviceAdded(toDisplayDevice);
-    }
-
-    public synchronized void onProfileConnectionStateChanged(CachedBluetoothDevice cachedDevice,
-                                                             int state, int bluetoothProfile) {
-        if (bluetoothProfile == BluetoothProfile.HEARING_AID
-            && cachedDevice.getHiSyncId() != BluetoothHearingAid.HI_SYNC_ID_INVALID
-            && cachedDevice.getBondState() == BluetoothDevice.BOND_BONDED) {
-
-            long hiSyncId = cachedDevice.getHiSyncId();
-
-            CachedBluetoothDevice otherDevice = getHearingAidOtherDevice(cachedDevice, hiSyncId);
-            if (otherDevice == null) {
-                // no other side device. Nothing to do.
-                return;
-            }
-
-            if (state == BluetoothProfile.STATE_CONNECTED &&
-                mHearingAidDevicesNotAddedInCache.contains(cachedDevice)) {
-                hearingAidSwitchDisplayDevice(cachedDevice, otherDevice, hiSyncId);
-            } else if (state == BluetoothProfile.STATE_DISCONNECTED
-                       && otherDevice.isConnected()) {
-                CachedBluetoothDevice mapDevice = mCachedDevicesMapForHearingAids.get(hiSyncId);
-                if ((mapDevice != null) && (Objects.equals(cachedDevice, mapDevice))) {
-                    hearingAidSwitchDisplayDevice(otherDevice, cachedDevice, hiSyncId);
-                }
-            }
-        }
+    public synchronized boolean onProfileConnectionStateChangedIfProcessed(CachedBluetoothDevice
+            cachedDevice, int state) {
+        return mHearingAidDeviceManager.onProfileConnectionStateChangedIfProcessed(cachedDevice,
+                state);
     }
 
     public synchronized void onDeviceUnpaired(CachedBluetoothDevice device) {
-        final long hiSyncId = device.getHiSyncId();
-
-        if (hiSyncId == BluetoothHearingAid.HI_SYNC_ID_INVALID) return;
-
-        for (int i = mHearingAidDevicesNotAddedInCache.size() - 1; i >= 0; i--) {
-            CachedBluetoothDevice cachedDevice = mHearingAidDevicesNotAddedInCache.get(i);
-            if (cachedDevice.getHiSyncId() == hiSyncId) {
-                // TODO: Look for more cleanups on unpairing the device.
-                mHearingAidDevicesNotAddedInCache.remove(i);
-                if (device == cachedDevice) continue;
-                log("onDeviceUnpaired: Unpair device=" + cachedDevice);
-                cachedDevice.unpair();
-            }
-        }
-
-        CachedBluetoothDevice mappedDevice = mCachedDevicesMapForHearingAids.get(hiSyncId);
-        if ((mappedDevice != null) && (!Objects.equals(device, mappedDevice))) {
-            log("onDeviceUnpaired: Unpair mapped device=" + mappedDevice);
-            mappedDevice.unpair();
+        CachedBluetoothDevice mainDevice = mHearingAidDeviceManager.findMainDevice(device);
+        CachedBluetoothDevice subDevice = device.getSubDevice();
+        if (subDevice != null) {
+            // Main device is unpaired, to unpair sub device
+            subDevice.unpair();
+            device.setSubDevice(null);
+        } else if (mainDevice != null) {
+            // Sub device unpaired, to unpair main device
+            mainDevice.unpair();
+            mainDevice.setSubDevice(null);
         }
     }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidDeviceManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidDeviceManager.java
new file mode 100644
index 0000000..20ece69
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidDeviceManager.java
@@ -0,0 +1,223 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settingslib.bluetooth;
+
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHearingAid;
+import android.bluetooth.BluetoothProfile;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * HearingAidDeviceManager manages the set of remote HearingAid Bluetooth devices.
+ */
+public class HearingAidDeviceManager {
+    private static final String TAG = "HearingAidDeviceManager";
+    private static final boolean DEBUG = BluetoothUtils.D;
+
+    private final LocalBluetoothManager mBtManager;
+    private final List<CachedBluetoothDevice> mCachedDevices;
+    HearingAidDeviceManager(LocalBluetoothManager localBtManager,
+            List<CachedBluetoothDevice> CachedDevices) {
+        mBtManager = localBtManager;
+        mCachedDevices = CachedDevices;
+    }
+
+    void initHearingAidDeviceIfNeeded(CachedBluetoothDevice newDevice) {
+        long hiSyncId = getHiSyncId(newDevice.getDevice());
+        if (isValidHiSyncId(hiSyncId)) {
+            // Once hiSyncId is valid, assign hiSyncId
+            newDevice.setHiSyncId(hiSyncId);
+        }
+    }
+
+    private long getHiSyncId(BluetoothDevice device) {
+        LocalBluetoothProfileManager profileManager = mBtManager.getProfileManager();
+        HearingAidProfile profileProxy = profileManager.getHearingAidProfile();
+        if (profileProxy != null) {
+            return profileProxy.getHiSyncId(device);
+        }
+        return BluetoothHearingAid.HI_SYNC_ID_INVALID;
+    }
+
+    boolean setSubDeviceIfNeeded(CachedBluetoothDevice newDevice) {
+        final long hiSyncId = newDevice.getHiSyncId();
+        if (isValidHiSyncId(hiSyncId)) {
+            final CachedBluetoothDevice hearingAidDevice = getCachedDevice(hiSyncId);
+            // Just add one of the hearing aids from a pair in the list that is shown in the UI.
+            // Once there is another device with the same hiSyncId, to add new device as sub
+            // device.
+            if (hearingAidDevice != null) {
+                hearingAidDevice.setSubDevice(newDevice);
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private boolean isValidHiSyncId(long hiSyncId) {
+        return hiSyncId != BluetoothHearingAid.HI_SYNC_ID_INVALID;
+    }
+
+    private CachedBluetoothDevice getCachedDevice(long hiSyncId) {
+        for (int i = mCachedDevices.size() - 1; i >= 0; i--) {
+            CachedBluetoothDevice cachedDevice = mCachedDevices.get(i);
+            if (cachedDevice.getHiSyncId() == hiSyncId) {
+                return cachedDevice;
+            }
+        }
+        return null;
+    }
+
+    // To collect all HearingAid devices and call #onHiSyncIdChanged to group device by HiSyncId
+    void updateHearingAidsDevices() {
+        final Set<Long> newSyncIdSet = new HashSet<Long>();
+        for (CachedBluetoothDevice cachedDevice : mCachedDevices) {
+            // Do nothing if HiSyncId has been assigned
+            if (!isValidHiSyncId(cachedDevice.getHiSyncId())) {
+                final long newHiSyncId = getHiSyncId(cachedDevice.getDevice());
+                // Do nothing if there is no HiSyncId on Bluetooth device
+                if (isValidHiSyncId(newHiSyncId)) {
+                    cachedDevice.setHiSyncId(newHiSyncId);
+                    newSyncIdSet.add(newHiSyncId);
+                }
+            }
+        }
+        for (Long syncId : newSyncIdSet) {
+            onHiSyncIdChanged(syncId);
+        }
+    }
+
+    // Group devices by hiSyncId
+    @VisibleForTesting
+    void onHiSyncIdChanged(long hiSyncId) {
+        int firstMatchedIndex = -1;
+
+        for (int i = mCachedDevices.size() - 1; i >= 0; i--) {
+            CachedBluetoothDevice cachedDevice = mCachedDevices.get(i);
+            if (cachedDevice.getHiSyncId() != hiSyncId) {
+                continue;
+            }
+            if (firstMatchedIndex == -1) {
+                // Found the first one
+                firstMatchedIndex = i;
+                continue;
+            }
+            // Found the second one
+            int indexToRemoveFromUi;
+            CachedBluetoothDevice subDevice;
+            CachedBluetoothDevice mainDevice;
+            // Since the hiSyncIds have been updated for a connected pair of hearing aids,
+            // we remove the entry of one the hearing aids from the UI. Unless the
+            // hiSyncId get updated, the system does not know it is a hearing aid, so we add
+            // both the hearing aids as separate entries in the UI first, then remove one
+            // of them after the hiSyncId is populated. We will choose the device that
+            // is not connected to be removed.
+            if (cachedDevice.isConnected()) {
+                mainDevice = cachedDevice;
+                indexToRemoveFromUi = firstMatchedIndex;
+                subDevice = mCachedDevices.get(firstMatchedIndex);
+            } else {
+                mainDevice = mCachedDevices.get(firstMatchedIndex);
+                indexToRemoveFromUi = i;
+                subDevice = cachedDevice;
+            }
+
+            mainDevice.setSubDevice(subDevice);
+            mCachedDevices.remove(indexToRemoveFromUi);
+            log("onHiSyncIdChanged: removed from UI device =" + subDevice
+                    + ", with hiSyncId=" + hiSyncId);
+            mBtManager.getEventManager().dispatchDeviceRemoved(subDevice);
+            break;
+        }
+    }
+
+    // @return {@code true}, the event is processed inside the method. It is for updating
+    // hearing aid device on main-sub relationship when receiving connected or disconnected.
+    // @return {@code false}, it is not hearing aid device or to process it same as other profiles
+    boolean onProfileConnectionStateChangedIfProcessed(CachedBluetoothDevice cachedDevice,
+            int state) {
+        switch (state) {
+            case BluetoothProfile.STATE_CONNECTED:
+                onHiSyncIdChanged(cachedDevice.getHiSyncId());
+                CachedBluetoothDevice mainDevice = findMainDevice(cachedDevice);
+                if (mainDevice != null){
+                    if (mainDevice.isConnected()) {
+                        // When main device exists and in connected state, receiving sub device
+                        // connection. To refresh main device UI
+                        mainDevice.refresh();
+                        return true;
+                    } else {
+                        // When both Hearing Aid devices are disconnected, receiving sub device
+                        // connection. To switch content and dispatch to notify UI change
+                        mBtManager.getEventManager().dispatchDeviceRemoved(mainDevice);
+                        mainDevice.switchSubDeviceContent();
+                        mainDevice.refresh();
+                        // It is necessary to do remove and add for updating the mapping on
+                        // preference and device
+                        mBtManager.getEventManager().dispatchDeviceAdded(mainDevice);
+                        return true;
+                    }
+                }
+                break;
+            case BluetoothProfile.STATE_DISCONNECTED:
+                mainDevice = findMainDevice(cachedDevice);
+                if (mainDevice != null) {
+                    // When main device exists, receiving sub device disconnection
+                    // To update main device UI
+                    mainDevice.refresh();
+                    return true;
+                }
+                CachedBluetoothDevice subDevice = cachedDevice.getSubDevice();
+                if (subDevice != null && subDevice.isConnected()) {
+                    // Main device is disconnected and sub device is connected
+                    // To copy data from sub device to main device
+                    mBtManager.getEventManager().dispatchDeviceRemoved(cachedDevice);
+                    cachedDevice.switchSubDeviceContent();
+                    cachedDevice.refresh();
+                    // It is necessary to do remove and add for updating the mapping on
+                    // preference and device
+                    mBtManager.getEventManager().dispatchDeviceAdded(cachedDevice);
+                    return true;
+                }
+                break;
+        }
+        return false;
+    }
+
+    CachedBluetoothDevice findMainDevice(CachedBluetoothDevice device) {
+        for (CachedBluetoothDevice cachedDevice : mCachedDevices) {
+            if (isValidHiSyncId(cachedDevice.getHiSyncId())) {
+                CachedBluetoothDevice subDevice = cachedDevice.getSubDevice();
+                if (subDevice != null && subDevice.equals(device)) {
+                    return cachedDevice;
+                }
+            }
+        }
+        return null;
+    }
+
+    private void log(String msg) {
+        if (DEBUG) {
+            Log.d(TAG, msg);
+        }
+    }
+}
\ No newline at end of file
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java
index 8bc0acf..adb5ab3 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java
@@ -71,7 +71,7 @@
             }
 
             // Check current list of CachedDevices to see if any are Hearing Aid devices.
-            mDeviceManager.updateHearingAidsDevices(mProfileManager);
+            mDeviceManager.updateHearingAidsDevices();
 
             mIsProfileReady=true;
         }
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothManager.java
index 7fe6205..53c6075 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothManager.java
@@ -18,10 +18,14 @@
 
 import android.content.Context;
 import android.os.Handler;
+import android.os.UserHandle;
 import android.util.Log;
 
 import java.lang.ref.WeakReference;
 
+import androidx.annotation.Nullable;
+import androidx.annotation.RequiresPermission;
+
 /**
  * LocalBluetoothManager provides a simplified interface on top of a subset of
  * the Bluetooth API. Note that {@link #getInstance} will return null
@@ -49,6 +53,7 @@
     /** The broadcast receiver event manager. */
     private final BluetoothEventManager mEventManager;
 
+    @Nullable
     public static synchronized LocalBluetoothManager getInstance(Context context,
             BluetoothManagerCallback onInitCallback) {
         if (sInstance == null) {
@@ -57,10 +62,11 @@
                 return null;
             }
             // This will be around as long as this process is
-            Context appContext = context.getApplicationContext();
-            sInstance = new LocalBluetoothManager(adapter, appContext, null);
+            sInstance = new LocalBluetoothManager(adapter, context, /* handler= */ null,
+                    /* userHandle= */ null);
             if (onInitCallback != null) {
-                onInitCallback.onBluetoothManagerInitialized(appContext, sInstance);
+                onInitCallback.onBluetoothManagerInitialized(context.getApplicationContext(),
+                        sInstance);
             }
         }
 
@@ -71,22 +77,43 @@
      * Returns a new instance of {@link LocalBluetoothManager} or null if Bluetooth is not
      * supported for this hardware. This instance should be globally cached by the caller.
      */
+    @Nullable
     public static LocalBluetoothManager create(Context context, Handler handler) {
         LocalBluetoothAdapter adapter = LocalBluetoothAdapter.getInstance();
         if (adapter == null) {
             return null;
         }
-        return new LocalBluetoothManager(adapter, context.getApplicationContext(), handler);
+        return new LocalBluetoothManager(adapter, context, handler, /* userHandle= */ null);
     }
 
-    private LocalBluetoothManager(
-            LocalBluetoothAdapter adapter, Context context, Handler handler) {
-        mContext = context;
+    /**
+     * Returns a new instance of {@link LocalBluetoothManager} or null if Bluetooth is not
+     * supported for this hardware. This instance should be globally cached by the caller.
+     *
+     * <p> Allows to specify a {@link UserHandle} for which to receive bluetooth events.
+     *
+     * <p> Requires {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} permission.
+     */
+    @Nullable
+    @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
+    public static LocalBluetoothManager create(Context context, Handler handler,
+            UserHandle userHandle) {
+        LocalBluetoothAdapter adapter = LocalBluetoothAdapter.getInstance();
+        if (adapter == null) {
+            return null;
+        }
+        return new LocalBluetoothManager(adapter, context, handler,
+                userHandle);
+    }
+
+    private LocalBluetoothManager(LocalBluetoothAdapter adapter, Context context, Handler handler,
+            UserHandle userHandle) {
+        mContext = context.getApplicationContext();
         mLocalAdapter = adapter;
-        mCachedDeviceManager = new CachedBluetoothDeviceManager(context, this);
-        mEventManager = new BluetoothEventManager(mLocalAdapter,
-                mCachedDeviceManager, context, handler);
-        mProfileManager = new LocalBluetoothProfileManager(context,
+        mCachedDeviceManager = new CachedBluetoothDeviceManager(mContext, this);
+        mEventManager = new BluetoothEventManager(mLocalAdapter, mCachedDeviceManager, mContext,
+                handler, userHandle);
+        mProfileManager = new LocalBluetoothProfileManager(mContext,
                 mLocalAdapter, mCachedDeviceManager, mEventManager);
 
         mProfileManager.updateLocalProfiles();
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
index 9653972..29c6d71 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
@@ -40,7 +40,6 @@
 
 import androidx.annotation.VisibleForTesting;
 
-import com.android.internal.R;
 import com.android.internal.util.CollectionUtils;
 
 import java.util.ArrayList;
@@ -289,21 +288,21 @@
                 (newState == BluetoothProfile.STATE_CONNECTED)) {
                 // Check if the HiSyncID has being initialized
                 if (cachedDevice.getHiSyncId() == BluetoothHearingAid.HI_SYNC_ID_INVALID) {
-
                     long newHiSyncId = getHearingAidProfile().getHiSyncId(cachedDevice.getDevice());
-
                     if (newHiSyncId != BluetoothHearingAid.HI_SYNC_ID_INVALID) {
                         cachedDevice.setHiSyncId(newHiSyncId);
-                        mDeviceManager.onHiSyncIdChanged(newHiSyncId);
                     }
                 }
             }
-
             cachedDevice.onProfileStateChanged(mProfile, newState);
-            cachedDevice.refresh();
             // Dispatch profile changed after device update
-            mEventManager.dispatchProfileConnectionStateChanged(cachedDevice, newState,
-                    mProfile.getProfileId());
+            if (!(cachedDevice.getHiSyncId() != BluetoothHearingAid.HI_SYNC_ID_INVALID
+                    && mDeviceManager.onProfileConnectionStateChangedIfProcessed(cachedDevice,
+                    newState))) {
+                cachedDevice.refresh();
+                mEventManager.dispatchProfileConnectionStateChanged(cachedDevice, newState,
+                        mProfile.getProfileId());
+            }
         }
     }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/LogWriter.java b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/LogWriter.java
index 379a820..a16838c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/LogWriter.java
+++ b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/LogWriter.java
@@ -55,6 +55,7 @@
 
     /**
      * Logs an user action.
+     *
      * @deprecated use {@link #action(int, int, Pair[])}
      */
     @Deprecated
@@ -62,6 +63,7 @@
 
     /**
      * Logs an user action.
+     *
      * @deprecated use {@link #action(int, boolean, Pair[])}
      */
     @Deprecated
@@ -76,4 +78,10 @@
      * Logs a count.
      */
     void count(Context context, String name, int value);
+
+    /**
+     * Generically log action into statsd.
+     */
+    default void action(int attribution, int action, int pageId, String key, int value) {
+    }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/MetricsFeatureProvider.java b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/MetricsFeatureProvider.java
index 662fa10..e1f9111 100644
--- a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/MetricsFeatureProvider.java
+++ b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/MetricsFeatureProvider.java
@@ -30,7 +30,7 @@
  * FeatureProvider for metrics.
  */
 public class MetricsFeatureProvider {
-    private List<LogWriter> mLoggerWriters;
+    protected List<LogWriter> mLoggerWriters;
 
     public MetricsFeatureProvider() {
         mLoggerWriters = new ArrayList<>();
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/bluetooth/BluetoothEventManagerIntegTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/bluetooth/BluetoothEventManagerIntegTest.java
new file mode 100644
index 0000000..d0ab46a
--- /dev/null
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/bluetooth/BluetoothEventManagerIntegTest.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.bluetooth;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
+
+import static java.util.concurrent.TimeUnit.SECONDS;
+
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.UserInfo;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.LargeTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.CountDownLatch;
+
+/**
+ * Test that verifies that BluetoothEventManager can receive broadcasts for non-current
+ * users for all bluetooth events.
+ *
+ * <p>Creation and deletion of users takes a long time, so marking this as a LargeTest.
+ */
+@LargeTest
+@RunWith(AndroidJUnit4.class)
+public class BluetoothEventManagerIntegTest {
+    private static final int LATCH_TIMEOUT = 4;
+
+    private Context mContext;
+    private UserManager mUserManager;
+    private BluetoothEventManager mBluetoothEventManager;
+
+    private UserInfo mOtherUser;
+    private final Intent mTestIntent = new Intent("Test intent");
+
+    @Before
+    public void setUp() {
+        mContext = InstrumentationRegistry.getTargetContext();
+        mUserManager = UserManager.get(mContext);
+
+        mBluetoothEventManager = new BluetoothEventManager(
+                mock(LocalBluetoothAdapter.class), mock(CachedBluetoothDeviceManager.class),
+                mContext, /* handler= */ null, UserHandle.ALL);
+
+        // Create and start another user in the background.
+        mOtherUser = mUserManager.createUser("TestUser", /* flags= */ 0);
+        try {
+            ActivityManager.getService().startUserInBackground(mOtherUser.id);
+        } catch (RemoteException e) {
+            fail("Count't create an additional user.");
+        }
+    }
+
+    @After
+    public void tearDown() {
+        if (mOtherUser != null) {
+            mUserManager.removeUser(mOtherUser.id);
+        }
+    }
+
+    /**
+     * Verify that MultiUserAwareBluetoothEventManager's adapter receiver handles events coming from
+     * users other than current user.
+     */
+    @Test
+    public void registerAdapterReceiver_ifIntentFromAnotherUser_broadcastIsReceived()
+            throws Exception {
+        // Create a latch to listen for the intent.
+        final CountDownLatch broadcastLatch = new CountDownLatch(1);
+
+        // Register adapter receiver.
+        mBluetoothEventManager.addHandler(mTestIntent.getAction(),
+                (context, intent, device) -> broadcastLatch.countDown());
+        mBluetoothEventManager.registerAdapterIntentReceiver();
+
+        // Send broadcast from another user.
+        mContext.sendBroadcastAsUser(mTestIntent, mOtherUser.getUserHandle());
+
+        // Wait to receive it.
+        assertTrue(broadcastLatch.await(LATCH_TIMEOUT, SECONDS));
+    }
+
+    /**
+     * Verify that MultiUserAwareBluetoothEventManager's profile receiver handles events coming from
+     * users other than current user.
+     */
+    @Test
+    public void registerProfileReceiver_ifIntentFromAnotherUser_broadcastIsReceived()
+            throws Exception {
+        // Create a latch to listen for the intent.
+        final CountDownLatch broadcastLatch = new CountDownLatch(1);
+
+        // Register profile receiver.
+        mBluetoothEventManager.addProfileHandler(mTestIntent.getAction(),
+                (context, intent, device) -> broadcastLatch.countDown());
+        mBluetoothEventManager.registerProfileIntentReceiver();
+
+        // Send broadcast from another user.
+        mContext.sendBroadcastAsUser(mTestIntent, mOtherUser.getUserHandle());
+
+        // Wait to receive it.
+        assertTrue(broadcastLatch.await(LATCH_TIMEOUT, SECONDS));
+    }
+}
\ No newline at end of file
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothEventManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothEventManagerTest.java
index 14bfb27..c147d5e 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothEventManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothEventManagerTest.java
@@ -15,12 +15,22 @@
  */
 package com.android.settingslib.bluetooth;
 
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothHeadset;
 import android.bluetooth.BluetoothProfile;
+import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Handler;
+import android.os.UserHandle;
 import android.telephony.TelephonyManager;
 
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
@@ -43,6 +53,8 @@
     private BluetoothCallback mBluetoothCallback;
     @Mock
     private CachedBluetoothDevice mCachedBluetoothDevice;
+    @Mock
+    private BluetoothDevice mBluetoothDevice;
 
     private Context mContext;
     private Intent mIntent;
@@ -54,7 +66,30 @@
         mContext = RuntimeEnvironment.application;
 
         mBluetoothEventManager = new BluetoothEventManager(mLocalAdapter,
-                mCachedDeviceManager, mContext, null);
+                mCachedDeviceManager, mContext, /* handler= */ null, /* userHandle= */ null);
+        when(mCachedDeviceManager.findDevice(mBluetoothDevice)).thenReturn(mCachedBluetoothDevice);
+    }
+
+    @Test
+    public void ifUserHandleIsNull_registerReceiverIsCalled() {
+        Context mockContext = mock(Context.class);
+        BluetoothEventManager eventManager =
+                new BluetoothEventManager(mLocalAdapter, mCachedDeviceManager, mockContext,
+                        /* handler= */ null, /* userHandle= */ null);
+
+        verify(mockContext).registerReceiver(any(BroadcastReceiver.class), any(IntentFilter.class),
+                eq(null), eq(null));
+    }
+
+    @Test
+    public void ifUserHandleSpecified_registerReceiverAsUserIsCalled() {
+        Context mockContext = mock(Context.class);
+        BluetoothEventManager eventManager =
+                new BluetoothEventManager(mLocalAdapter, mCachedDeviceManager, mockContext,
+                        /* handler= */ null, UserHandle.ALL);
+
+        verify(mockContext).registerReceiverAsUser(any(BroadcastReceiver.class), eq(UserHandle.ALL),
+                any(IntentFilter.class), eq(null), eq(null));
     }
 
     /**
@@ -96,8 +131,29 @@
 
         verify(mBluetoothCallback).onProfileConnectionStateChanged(mCachedBluetoothDevice,
                 BluetoothProfile.STATE_CONNECTED, BluetoothProfile.A2DP);
+    }
 
-        verify(mCachedDeviceManager).onProfileConnectionStateChanged(mCachedBluetoothDevice,
-                BluetoothProfile.STATE_CONNECTED, BluetoothProfile.A2DP);
+    @Test
+    public void dispatchAclConnectionStateChanged_aclDisconnected_shouldDispatchCallback() {
+        mBluetoothEventManager.registerCallback(mBluetoothCallback);
+        mIntent = new Intent(BluetoothDevice.ACTION_ACL_DISCONNECTED);
+        mIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, mBluetoothDevice);
+
+        mContext.sendBroadcast(mIntent);
+
+        verify(mBluetoothCallback).onAclConnectionStateChanged(mCachedBluetoothDevice,
+                BluetoothAdapter.STATE_DISCONNECTED);
+    }
+
+    @Test
+    public void dispatchAclConnectionStateChanged_aclConnected_shouldDispatchCallback() {
+        mBluetoothEventManager.registerCallback(mBluetoothCallback);
+        mIntent = new Intent(BluetoothDevice.ACTION_ACL_CONNECTED);
+        mIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, mBluetoothDevice);
+
+        mContext.sendBroadcast(mIntent);
+
+        verify(mBluetoothCallback).onAclConnectionStateChanged(mCachedBluetoothDevice,
+                BluetoothAdapter.STATE_CONNECTED);
     }
 }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
index 62b5688..9c75491 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
@@ -18,7 +18,9 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.bluetooth.BluetoothClass;
@@ -80,6 +82,7 @@
     private CachedBluetoothDevice mCachedDevice2;
     private CachedBluetoothDevice mCachedDevice3;
     private CachedBluetoothDeviceManager mCachedDeviceManager;
+    private HearingAidDeviceManager mHearingAidDeviceManager;
     private Context mContext;
 
     @Before
@@ -105,13 +108,12 @@
         when(mA2dpProfile.isProfileReady()).thenReturn(true);
         when(mPanProfile.isProfileReady()).thenReturn(true);
         when(mHearingAidProfile.isProfileReady()).thenReturn(true);
+        doAnswer((invocation) -> mHearingAidProfile).
+                when(mLocalProfileManager).getHearingAidProfile();
         mCachedDeviceManager = new CachedBluetoothDeviceManager(mContext, mLocalBluetoothManager);
-        mCachedDevice1 = spy(
-            new CachedBluetoothDevice(mContext, mLocalProfileManager, mDevice1));
-        mCachedDevice2 = spy(
-            new CachedBluetoothDevice(mContext, mLocalProfileManager, mDevice2));
-        mCachedDevice3 = spy(
-            new CachedBluetoothDevice(mContext, mLocalProfileManager, mDevice3));
+        mCachedDevice1 = spy(new CachedBluetoothDevice(mContext, mLocalProfileManager, mDevice1));
+        mCachedDevice2 = spy(new CachedBluetoothDevice(mContext, mLocalProfileManager, mDevice2));
+        mCachedDevice3 = spy(new CachedBluetoothDevice(mContext, mLocalProfileManager, mDevice3));
     }
 
     /**
@@ -133,6 +135,76 @@
     }
 
     /**
+     * Test to verify getSubDevice(), new device has the same HiSyncId.
+     */
+    @Test
+    public void addDevice_sameHiSyncId_validSubDevice() {
+        doAnswer((invocation) -> HISYNCID1).when(mHearingAidProfile).getHiSyncId(mDevice1);
+        doAnswer((invocation) -> HISYNCID1).when(mHearingAidProfile).getHiSyncId(mDevice2);
+        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
+        CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2);
+
+        assertThat(cachedDevice1.getSubDevice()).isEqualTo(cachedDevice2);
+    }
+
+    /**
+     * Test to verify getSubDevice(), new device has the different HiSyncId.
+     */
+    @Test
+    public void addDevice_differentHiSyncId_validSubDevice() {
+        doAnswer((invocation) -> HISYNCID1).when(mHearingAidProfile).getHiSyncId(mDevice1);
+        doAnswer((invocation) -> HISYNCID2).when(mHearingAidProfile).getHiSyncId(mDevice2);
+        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
+        CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2);
+
+        assertThat(cachedDevice1.getSubDevice()).isNull();
+    }
+
+    /**
+     * Test to verify addDevice(), new device has the same HiSyncId.
+     */
+    @Test
+    public void addDevice_sameHiSyncId_validCachedDevices_mainDevicesAdded_subDevicesNotAdded() {
+        doAnswer((invocation) -> HISYNCID1).when(mHearingAidProfile).getHiSyncId(mDevice1);
+        doAnswer((invocation) -> HISYNCID1).when(mHearingAidProfile).getHiSyncId(mDevice2);
+        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
+        CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2);
+
+        Collection<CachedBluetoothDevice> devices = mCachedDeviceManager.getCachedDevicesCopy();
+        assertThat(devices).contains(cachedDevice1);
+        assertThat(devices).doesNotContain(cachedDevice2);
+    }
+
+    /**
+     * Test to verify addDevice(), new device has the different HiSyncId.
+     */
+    @Test
+    public void addDevice_differentHiSyncId_validCachedDevices_bothAdded() {
+        doAnswer((invocation) -> HISYNCID1).when(mHearingAidProfile).getHiSyncId(mDevice1);
+        doAnswer((invocation) -> HISYNCID2).when(mHearingAidProfile).getHiSyncId(mDevice2);
+        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
+        CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2);
+
+        Collection<CachedBluetoothDevice> devices = mCachedDeviceManager.getCachedDevicesCopy();
+        assertThat(devices).contains(cachedDevice1);
+        assertThat(devices).contains(cachedDevice2);
+    }
+
+    /**
+     * Test to verify findDevice(), new device has the same HiSyncId.
+     */
+    @Test
+    public void findDevice_sameHiSyncId_foundBothDevice() {
+        doAnswer((invocation) -> HISYNCID1).when(mHearingAidProfile).getHiSyncId(mDevice1);
+        doAnswer((invocation) -> HISYNCID1).when(mHearingAidProfile).getHiSyncId(mDevice2);
+        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
+        CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2);
+
+        assertThat(mCachedDeviceManager.findDevice(mDevice1)).isEqualTo(cachedDevice1);
+        assertThat(mCachedDeviceManager.findDevice(mDevice2)).isEqualTo(cachedDevice2);
+    }
+
+    /**
      * Test to verify getName().
      */
     @Test
@@ -190,453 +262,89 @@
     }
 
     /**
-     * Test to verify clearNonBondedDevices() for hearing aids.
+     * Test to verify clearNonBondedDevices() for hearing aids sub device.
      */
     @Test
-    public void clearNonBondedDevices_HearingAids_nonBondedHAsClearedFromCachedDevicesMap() {
+    public void clearNonBondedDevices_nonBondedSubDevice() {
         when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
         when(mDevice2.getBondState()).thenReturn(BluetoothDevice.BOND_NONE);
+        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
+        CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2);
+        cachedDevice1.setSubDevice(cachedDevice2);
 
-        mCachedDevice1.setHiSyncId(HISYNCID1);
-        mCachedDevice2.setHiSyncId(HISYNCID2);
-        mCachedDeviceManager.mCachedDevicesMapForHearingAids.put(HISYNCID1, mCachedDevice1);
-        mCachedDeviceManager.mCachedDevicesMapForHearingAids.put(HISYNCID2, mCachedDevice2);
-
+        assertThat(cachedDevice1.getSubDevice()).isEqualTo(cachedDevice2);
         mCachedDeviceManager.clearNonBondedDevices();
 
-        assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids.values())
-            .doesNotContain(mCachedDevice2);
-        assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids.values())
-            .contains(mCachedDevice1);
+        assertThat(cachedDevice1.getSubDevice()).isNull();
     }
 
     /**
-     * Test to verify onHiSyncIdChanged() for hearing aid devices with same HiSyncId.
+     * Test to verify OnDeviceUnpaired() for main hearing Aid device unpair.
      */
     @Test
-    public void onHiSyncIdChanged_sameHiSyncId_populateInDifferentLists() {
-        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
-        assertThat(cachedDevice1).isNotNull();
-        CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2);
-        assertThat(cachedDevice2).isNotNull();
-
-        // Since both devices do not have hiSyncId, they should be added in mCachedDevices.
-        assertThat(mCachedDeviceManager.getCachedDevicesCopy()).hasSize(2);
-        assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache).isEmpty();
-        assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids).isEmpty();
-
-        cachedDevice1.setHiSyncId(HISYNCID1);
-        cachedDevice2.setHiSyncId(HISYNCID1);
-        mCachedDeviceManager.onHiSyncIdChanged(HISYNCID1);
-
-        // Since both devices have the same hiSyncId, one should remain in mCachedDevices
-        // and the other should be removed from mCachedDevices and get added in
-        // mHearingAidDevicesNotAddedInCache. The one that is in mCachedDevices should also be
-        // added in mCachedDevicesMapForHearingAids.
-        assertThat(mCachedDeviceManager.getCachedDevicesCopy()).hasSize(1);
-        assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache).hasSize(1);
-        assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids).hasSize(1);
-        Collection<CachedBluetoothDevice> devices = mCachedDeviceManager.getCachedDevicesCopy();
-        assertThat(devices).contains(cachedDevice2);
-        assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids)
-            .containsKey(HISYNCID1);
-    }
-
-    /**
-     * Test to verify onHiSyncIdChanged() for 2 hearing aid devices with same HiSyncId but one
-     * device is connected and other is disconnected. The connected device should be chosen.
-     */
-    @Test
-    public void onHiSyncIdChanged_sameHiSyncIdAndOneConnected_chooseConnectedDevice() {
-        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
-        assertThat(cachedDevice1).isNotNull();
-        CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2);
-        assertThat(cachedDevice2).isNotNull();
-        cachedDevice1.onProfileStateChanged(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
-        cachedDevice2.onProfileStateChanged(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
-
-        /* Device 1 is connected and Device 2 is disconnected */
-        when(mHearingAidProfile.getConnectionStatus(mDevice1)).
-            thenReturn(BluetoothProfile.STATE_CONNECTED);
-        when(mHearingAidProfile.getConnectionStatus(mDevice2)).
-            thenReturn(BluetoothProfile.STATE_DISCONNECTED);
-
-        // Since both devices do not have hiSyncId, they should be added in mCachedDevices.
-        assertThat(mCachedDeviceManager.getCachedDevicesCopy()).hasSize(2);
-        assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache).isEmpty();
-        assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids).isEmpty();
-
-        cachedDevice1.setHiSyncId(HISYNCID1);
-        cachedDevice2.setHiSyncId(HISYNCID1);
-        mCachedDeviceManager.onHiSyncIdChanged(HISYNCID1);
-
-        // Only the connected device, device 1, should be visible to UI.
-        assertThat(mCachedDeviceManager.getCachedDevicesCopy()).containsExactly(cachedDevice1);
-        assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids).
-            containsExactly(HISYNCID1, cachedDevice1);
-        assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache).
-            containsExactly(cachedDevice2);
-    }
-
-    /**
-     * Test to verify onHiSyncIdChanged() for hearing aid devices with different HiSyncId.
-     */
-    @Test
-    public void onHiSyncIdChanged_differentHiSyncId_populateInSameList() {
-        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
-        assertThat(cachedDevice1).isNotNull();
-        CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2);
-        assertThat(cachedDevice2).isNotNull();
-
-        // Since both devices do not have hiSyncId, they should be added in mCachedDevices.
-        assertThat(mCachedDeviceManager.getCachedDevicesCopy()).hasSize(2);
-        assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache).isEmpty();
-        assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids).isEmpty();
-
-        cachedDevice1.setHiSyncId(HISYNCID1);
-        cachedDevice2.setHiSyncId(HISYNCID2);
-        mCachedDeviceManager.onHiSyncIdChanged(HISYNCID1);
-        mCachedDeviceManager.onHiSyncIdChanged(HISYNCID2);
-
-        // Since both devices do not have same hiSyncId, they should remain in mCachedDevices and
-        // also be added in mCachedDevicesMapForHearingAids.
-        assertThat(mCachedDeviceManager.getCachedDevicesCopy()).hasSize(2);
-        assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache).isEmpty();
-        assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids).hasSize(2);
-        Collection<CachedBluetoothDevice> devices = mCachedDeviceManager.getCachedDevicesCopy();
-        assertThat(devices).contains(cachedDevice2);
-        assertThat(devices).contains(cachedDevice1);
-        assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids.values())
-            .contains(cachedDevice1);
-        assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids.values())
-            .contains(cachedDevice2);
-    }
-
-    /**
-     * Test to verify onProfileConnectionStateChanged() for single hearing aid device connection.
-     */
-    @Test
-    public void onProfileConnectionStateChanged_singleDeviceConnected_visible() {
-        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
-        assertThat(cachedDevice1).isNotNull();
-        cachedDevice1.onProfileStateChanged(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
-
-        // Since both devices do not have hiSyncId, they should be added in mCachedDevices.
-        assertThat(mCachedDeviceManager.getCachedDevicesCopy()).containsExactly(cachedDevice1);
-        assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache).isEmpty();
-        assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids).isEmpty();
-
-        cachedDevice1.setHiSyncId(HISYNCID1);
-        mCachedDeviceManager.onHiSyncIdChanged(HISYNCID1);
-
-        // Connect the Device 1
-        mCachedDeviceManager.onProfileConnectionStateChanged(cachedDevice1,
-            BluetoothProfile.STATE_CONNECTED, BluetoothProfile.HEARING_AID);
-
-        assertThat(mCachedDeviceManager.getCachedDevicesCopy()).containsExactly(cachedDevice1);
-        assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids).
-            containsExactly(HISYNCID1, cachedDevice1);
-        assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache).isEmpty();
-
-        // Disconnect the Device 1
-        mCachedDeviceManager.onProfileConnectionStateChanged(cachedDevice1,
-            BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.HEARING_AID);
-
-        assertThat(mCachedDeviceManager.getCachedDevicesCopy()).containsExactly(cachedDevice1);
-        assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids).
-            containsExactly(HISYNCID1, cachedDevice1);
-        assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache).isEmpty();
-    }
-
-    /**
-     * Test to verify onProfileConnectionStateChanged() for two hearing aid devices where both
-     * devices are disconnected and they get connected.
-     */
-    @Test
-    public void onProfileConnectionStateChanged_twoDevicesConnected_oneDeviceVisible() {
-        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
-        assertThat(cachedDevice1).isNotNull();
-        CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2);
-        assertThat(cachedDevice2).isNotNull();
-        cachedDevice1.onProfileStateChanged(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
-        cachedDevice2.onProfileStateChanged(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
+    public void onDeviceUnpaired_unpairMainDevice() {
         when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
-        when(mDevice2.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
-
-        // Since both devices do not have hiSyncId, they should be added in mCachedDevices.
-        assertThat(mCachedDeviceManager.getCachedDevicesCopy()).hasSize(2);
-        assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache).isEmpty();
-        assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids).isEmpty();
-
-        cachedDevice1.setHiSyncId(HISYNCID1);
-        cachedDevice2.setHiSyncId(HISYNCID1);
-        mCachedDeviceManager.onHiSyncIdChanged(HISYNCID1);
-
-        // There should be one cached device but can be either one.
-        assertThat(mCachedDeviceManager.getCachedDevicesCopy()).hasSize(1);
-
-        // Connect the Device 1
-        mCachedDeviceManager.onProfileConnectionStateChanged(cachedDevice1,
-            BluetoothProfile.STATE_CONNECTED, BluetoothProfile.HEARING_AID);
-
-        assertThat(mCachedDeviceManager.getCachedDevicesCopy()).containsExactly(cachedDevice1);
-        assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids).
-            containsExactly(HISYNCID1, cachedDevice1);
-        assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache).contains(cachedDevice2);
-        assertThat(mCachedDeviceManager.mCachedDevices).contains(cachedDevice1);
-
-        when(mHearingAidProfile.getConnectionStatus(mDevice1)).
-            thenReturn(BluetoothProfile.STATE_CONNECTED);
-        when(mHearingAidProfile.getConnectionStatus(mDevice2)).
-            thenReturn(BluetoothProfile.STATE_DISCONNECTED);
-
-        // Connect the Device 2
-        mCachedDeviceManager.onProfileConnectionStateChanged(cachedDevice2,
-            BluetoothProfile.STATE_CONNECTED, BluetoothProfile.HEARING_AID);
-
-        assertThat(mCachedDeviceManager.getCachedDevicesCopy()).hasSize(1);
-        assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache).hasSize(1);
-        assertThat(mCachedDeviceManager.mCachedDevices).hasSize(1);
-        assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids).hasSize(1);
-    }
-
-    /**
-     * Test to verify onProfileConnectionStateChanged() for two hearing aid devices where both
-     * devices are connected and they get disconnected.
-     */
-    @Test
-    public void onProfileConnectionStateChanged_twoDevicesDisconnected_oneDeviceVisible() {
         CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
-        assertThat(cachedDevice1).isNotNull();
         CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2);
-        assertThat(cachedDevice2).isNotNull();
-        cachedDevice1.onProfileStateChanged(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
-        cachedDevice2.onProfileStateChanged(mHearingAidProfile, BluetoothProfile.STATE_CONNECTED);
-
-        when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
-        when(mDevice2.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
-        when(mHearingAidProfile.getConnectionStatus(mDevice1)).
-            thenReturn(BluetoothProfile.STATE_CONNECTED);
-        when(mHearingAidProfile.getConnectionStatus(mDevice2)).
-            thenReturn(BluetoothProfile.STATE_CONNECTED);
-
-        // Since both devices do not have hiSyncId, they should be added in mCachedDevices.
-        assertThat(mCachedDeviceManager.getCachedDevicesCopy()).hasSize(2);
-        assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache).isEmpty();
-        assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids).isEmpty();
-
         cachedDevice1.setHiSyncId(HISYNCID1);
         cachedDevice2.setHiSyncId(HISYNCID1);
-        mCachedDeviceManager.onHiSyncIdChanged(HISYNCID1);
-
-        /* Disconnect the Device 1 */
-        mCachedDeviceManager.onProfileConnectionStateChanged(cachedDevice1,
-            BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.HEARING_AID);
-
-        assertThat(mCachedDeviceManager.getCachedDevicesCopy()).containsExactly(cachedDevice2);
-        assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache).contains(cachedDevice1);
-        assertThat(mCachedDeviceManager.mCachedDevices).contains(cachedDevice2);
-        assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids)
-            .containsExactly(HISYNCID1, cachedDevice2);
-
-        when(mHearingAidProfile.getConnectionStatus(mDevice1)).
-            thenReturn(BluetoothProfile.STATE_DISCONNECTED);
-        when(mHearingAidProfile.getConnectionStatus(mDevice2)).
-            thenReturn(BluetoothProfile.STATE_CONNECTED);
-
-        /* Disconnect the Device 2 */
-        mCachedDeviceManager.onProfileConnectionStateChanged(cachedDevice2,
-            BluetoothProfile.STATE_DISCONNECTED, BluetoothProfile.HEARING_AID);
-
-        assertThat(mCachedDeviceManager.getCachedDevicesCopy()).hasSize(1);
-        assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache).hasSize(1);
-        assertThat(mCachedDeviceManager.mCachedDevices).hasSize(1);
-        assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids).hasSize(1);
-    }
-
-    /**
-     * Test to verify OnDeviceUnpaired() for a paired hearing Aid device pair.
-     */
-    @Test
-    public void onDeviceUnpaired_bothHearingAidsPaired_removesItsPairFromList() {
-        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
-        assertThat(cachedDevice1).isNotNull();
-        CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2);
-        assertThat(cachedDevice2).isNotNull();
-
-        cachedDevice1.setHiSyncId(HISYNCID1);
-        cachedDevice2.setHiSyncId(HISYNCID1);
-        mCachedDeviceManager.onHiSyncIdChanged(HISYNCID1);
-
-        // Check if one device is in mCachedDevices and one in mHearingAidDevicesNotAddedInCache.
-        Collection<CachedBluetoothDevice> devices = mCachedDeviceManager.getCachedDevicesCopy();
-        assertThat(devices).contains(cachedDevice2);
-        assertThat(devices).doesNotContain(cachedDevice1);
-        assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache).contains(cachedDevice1);
-        assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache)
-            .doesNotContain(cachedDevice2);
+        cachedDevice1.setSubDevice(cachedDevice2);
 
         // Call onDeviceUnpaired for the one in mCachedDevices.
         mCachedDeviceManager.onDeviceUnpaired(cachedDevice2);
-
-        // Check if its pair is removed from mHearingAidDevicesNotAddedInCache.
-        assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache)
-            .doesNotContain(cachedDevice1);
+        verify(mDevice1).removeBond();
     }
 
     /**
-     * Test to verify OnDeviceUnpaired() for paired hearing Aid devices which are not a pair.
+     * Test to verify OnDeviceUnpaired() for sub hearing Aid device unpair.
      */
     @Test
-    public void onDeviceUnpaired_bothHearingAidsNotPaired_doesNotRemoveAnyDeviceFromList() {
+    public void onDeviceUnpaired_unpairSubDevice() {
+        when(mDevice2.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
         CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
-        assertThat(cachedDevice1).isNotNull();
         CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2);
-        assertThat(cachedDevice2).isNotNull();
-        CachedBluetoothDevice cachedDevice3 = mCachedDeviceManager.addDevice(mDevice3);
-        assertThat(cachedDevice2).isNotNull();
+        cachedDevice1.setSubDevice(cachedDevice2);
 
-        cachedDevice1.setHiSyncId(HISYNCID1);
-        cachedDevice2.setHiSyncId(HISYNCID1);
-        cachedDevice3.setHiSyncId(HISYNCID2);
-        mCachedDeviceManager.onHiSyncIdChanged(HISYNCID1);
-        mCachedDeviceManager.onHiSyncIdChanged(HISYNCID2);
-
-        // Check if one device is in mCachedDevices and one in mHearingAidDevicesNotAddedInCache.
-        Collection<CachedBluetoothDevice> devices = mCachedDeviceManager.getCachedDevicesCopy();
-        assertThat(devices).contains(cachedDevice2);
-        assertThat(devices).contains(cachedDevice3);
-        assertThat(devices).doesNotContain(cachedDevice1);
-        assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache).contains(cachedDevice1);
-        assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache)
-            .doesNotContain(cachedDevice2);
-        assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache)
-            .doesNotContain(cachedDevice3);
-
-        // Call onDeviceUnpaired for the one in mCachedDevices with no pair.
-        mCachedDeviceManager.onDeviceUnpaired(cachedDevice3);
-
-        // Check if no list is changed.
-        devices = mCachedDeviceManager.getCachedDevicesCopy();
-        assertThat(devices).contains(cachedDevice2);
-        assertThat(devices).contains(cachedDevice3);
-        assertThat(devices).doesNotContain(cachedDevice1);
-        assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache).contains(cachedDevice1);
-        assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache)
-            .doesNotContain(cachedDevice2);
-        assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache)
-            .doesNotContain(cachedDevice3);
+        // Call onDeviceUnpaired for the one in mCachedDevices.
+        mCachedDeviceManager.onDeviceUnpaired(cachedDevice1);
+        verify(mDevice2).removeBond();
     }
 
     /**
-     * Test to verify addDevice() for hearing aid devices with same HiSyncId.
+     * Test to verify getSubDeviceSummary() for disconnected sub device
      */
     @Test
-    public void addDevice_hearingAidDevicesWithSameHiSyncId_populateInDifferentLists() {
-        doAnswer((invocation) -> mHearingAidProfile).when(mLocalProfileManager)
-            .getHearingAidProfile();
-        doAnswer((invocation) -> HISYNCID1).when(mHearingAidProfile).getHiSyncId(mDevice1);
-        doAnswer((invocation) -> HISYNCID1).when(mHearingAidProfile).getHiSyncId(mDevice2);
+    public void getSubDeviceSummary_SubDeviceDisconnected() {
+        when(mCachedDevice2.isConnected()).thenReturn(false);
+        mCachedDevice1.setSubDevice(mCachedDevice2);
+        mCachedDeviceManager.getSubDeviceSummary(mCachedDevice1);
 
-        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
-        assertThat(cachedDevice1).isNotNull();
-        // The first hearing aid device should be populated in mCachedDevice and
-        // mCachedDevicesMapForHearingAids.
-        assertThat(mCachedDeviceManager.getCachedDevicesCopy()).hasSize(1);
-        assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache).isEmpty();
-        assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids).hasSize(1);
-        assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids.values())
-            .contains(cachedDevice1);
-
-        CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2);
-        assertThat(cachedDevice2).isNotNull();
-        // The second hearing aid device should be populated in mHearingAidDevicesNotAddedInCache.
-        assertThat(mCachedDeviceManager.getCachedDevicesCopy()).hasSize(1);
-        assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache).hasSize(1);
-        assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids).hasSize(1);
+        verify(mCachedDevice2, never()).getConnectionSummary();
     }
 
     /**
-     * Test to verify addDevice() for hearing aid devices with different HiSyncId.
+     * Test to verify getSubDeviceSummary() for connected sub device
      */
     @Test
-    public void addDevice_hearingAidDevicesWithDifferentHiSyncId_populateInSameList() {
-        doAnswer((invocation) -> mHearingAidProfile).when(mLocalProfileManager)
-            .getHearingAidProfile();
-        doAnswer((invocation) -> HISYNCID1).when(mHearingAidProfile).getHiSyncId(mDevice1);
-        doAnswer((invocation) -> HISYNCID2).when(mHearingAidProfile).getHiSyncId(mDevice2);
-        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
-        assertThat(cachedDevice1).isNotNull();
-        // The first hearing aid device should be populated in mCachedDevice and
-        // mCachedDevicesMapForHearingAids.
-        assertThat(mCachedDeviceManager.getCachedDevicesCopy()).hasSize(1);
-        assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache).isEmpty();
-        assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids).hasSize(1);
-        assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids.values())
-            .contains(cachedDevice1);
+    public void getSubDeviceSummary_SubDeviceConnected() {
+        when(mCachedDevice2.isConnected()).thenReturn(true);
+        mCachedDevice1.setSubDevice(mCachedDevice2);
+        mCachedDeviceManager.getSubDeviceSummary(mCachedDevice1);
 
-        CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2);
-        assertThat(cachedDevice2).isNotNull();
-        // The second hearing aid device should also be populated in mCachedDevice
-        // and mCachedDevicesMapForHearingAids as its not a pair of the first one.
-        assertThat(mCachedDeviceManager.getCachedDevicesCopy()).hasSize(2);
-        assertThat(mCachedDeviceManager.mHearingAidDevicesNotAddedInCache).isEmpty();
-        assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids).hasSize(2);
-        assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids.values())
-            .contains(cachedDevice1);
-        assertThat(mCachedDeviceManager.mCachedDevicesMapForHearingAids.values())
-            .contains(cachedDevice2);
-    }
-
-    /**
-     * Test to verify getHearingAidPairDeviceSummary() for hearing aid devices with same HiSyncId.
-     */
-    @Test
-    public void getHearingAidPairDeviceSummary_bothHearingAidsPaired_returnsSummaryOfPair() {
-        mCachedDevice1.setHiSyncId(HISYNCID1);
-        mCachedDevice2.setHiSyncId(HISYNCID1);
-        mCachedDeviceManager.mCachedDevices.add(mCachedDevice1);
-        mCachedDeviceManager.mHearingAidDevicesNotAddedInCache.add(mCachedDevice2);
-        doAnswer((invocation) -> DEVICE_SUMMARY_1).when(mCachedDevice1).getConnectionSummary();
-        doAnswer((invocation) -> DEVICE_SUMMARY_2).when(mCachedDevice2).getConnectionSummary();
-
-        assertThat(mCachedDeviceManager.getHearingAidPairDeviceSummary(mCachedDevice1))
-            .isEqualTo(DEVICE_SUMMARY_2);
-    }
-
-    /**
-     * Test to verify getHearingAidPairDeviceSummary() for hearing aid devices with different
-     * HiSyncId.
-     */
-    @Test
-    public void getHearingAidPairDeviceSummary_bothHearingAidsNotPaired_returnsNull() {
-        mCachedDevice1.setHiSyncId(HISYNCID1);
-        mCachedDevice2.setHiSyncId(HISYNCID2);
-        mCachedDeviceManager.mCachedDevices.add(mCachedDevice1);
-        mCachedDeviceManager.mHearingAidDevicesNotAddedInCache.add(mCachedDevice2);
-        doAnswer((invocation) -> DEVICE_SUMMARY_1).when(mCachedDevice1).getConnectionSummary();
-        doAnswer((invocation) -> DEVICE_SUMMARY_2).when(mCachedDevice2).getConnectionSummary();
-
-        assertThat(mCachedDeviceManager.getHearingAidPairDeviceSummary(mCachedDevice1))
-            .isEqualTo(null);
+        verify(mCachedDevice2).getConnectionSummary();
     }
 
     /**
      * Test to verify updateHearingAidsDevices().
      */
     @Test
-    public void updateHearingAidDevices_hiSyncIdAvailable_setsHiSyncId() {
-        doAnswer((invocation) -> mHearingAidProfile).when(mLocalProfileManager)
-            .getHearingAidProfile();
-        doAnswer((invocation) -> HISYNCID1).when(mHearingAidProfile).getHiSyncId(mDevice1);
-        doAnswer((invocation) -> HISYNCID1).when(mHearingAidProfile).getHiSyncId(mDevice2);
-        mCachedDeviceManager.mCachedDevices.add(mCachedDevice1);
-        mCachedDeviceManager.mCachedDevices.add(mCachedDevice2);
-        mCachedDeviceManager.updateHearingAidsDevices(mLocalProfileManager);
+    public void updateHearingAidDevices_directToHearingAidDeviceManager() {
+        mHearingAidDeviceManager = spy(new HearingAidDeviceManager(mLocalBluetoothManager,
+                mCachedDeviceManager.mCachedDevices));
+        mCachedDeviceManager.mHearingAidDeviceManager = mHearingAidDeviceManager;
+        mCachedDeviceManager.updateHearingAidsDevices();
 
-        // Assert that the mCachedDevice1 and mCachedDevice2 have an updated HiSyncId.
-        assertThat(mCachedDevice1.getHiSyncId()).isEqualTo(HISYNCID1);
-        assertThat(mCachedDevice2.getHiSyncId()).isEqualTo(HISYNCID1);
+        verify(mHearingAidDeviceManager).updateHearingAidsDevices();
     }
 
     /**
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
index f6201dd..7f9a5af 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
@@ -48,6 +48,10 @@
     private final static String DEVICE_ALIAS = "TestAlias";
     private final static String DEVICE_ADDRESS = "AA:BB:CC:DD:EE:FF";
     private final static String DEVICE_ALIAS_NEW = "TestAliasNew";
+    private final static short RSSI_1 = 10;
+    private final static short RSSI_2 = 11;
+    private final static boolean JUSTDISCOVERED_1 = true;
+    private final static boolean JUSTDISCOVERED_2 = false;
     @Mock
     private LocalBluetoothProfileManager mProfileManager;
     @Mock
@@ -60,6 +64,8 @@
     private HearingAidProfile mHearingAidProfile;
     @Mock
     private BluetoothDevice mDevice;
+    @Mock
+    private BluetoothDevice mSubDevice;
     private CachedBluetoothDevice mCachedDevice;
     private ShadowAudioManager mShadowAudioManager;
     private Context mContext;
@@ -657,4 +663,39 @@
         doReturn(status).when(profile).getConnectionStatus(mDevice);
         mCachedDevice.onProfileStateChanged(profile, status);
     }
+
+    @Test
+    public void getSubDevice_setSubDevice() {
+        CachedBluetoothDevice subCachedDevice = new CachedBluetoothDevice(mContext, mProfileManager,
+                mSubDevice);
+        mCachedDevice.setSubDevice(subCachedDevice);
+
+        assertThat(mCachedDevice.getSubDevice()).isEqualTo(subCachedDevice);
+    }
+
+    @Test
+    public void switchSubDeviceContent() {
+        CachedBluetoothDevice subCachedDevice = new CachedBluetoothDevice(mContext, mProfileManager,
+                mSubDevice);
+        mCachedDevice.mRssi = RSSI_1;
+        mCachedDevice.mJustDiscovered = JUSTDISCOVERED_1;
+        subCachedDevice.mRssi = RSSI_2;
+        subCachedDevice.mJustDiscovered = JUSTDISCOVERED_2;
+        mCachedDevice.setSubDevice(subCachedDevice);
+
+        assertThat(mCachedDevice.mRssi).isEqualTo(RSSI_1);
+        assertThat(mCachedDevice.mJustDiscovered).isEqualTo(JUSTDISCOVERED_1);
+        assertThat(mCachedDevice.mDevice).isEqualTo(mDevice);
+        assertThat(subCachedDevice.mRssi).isEqualTo(RSSI_2);
+        assertThat(subCachedDevice.mJustDiscovered).isEqualTo(JUSTDISCOVERED_2);
+        assertThat(subCachedDevice.mDevice).isEqualTo(mSubDevice);
+        mCachedDevice.switchSubDeviceContent();
+
+        assertThat(mCachedDevice.mRssi).isEqualTo(RSSI_2);
+        assertThat(mCachedDevice.mJustDiscovered).isEqualTo(JUSTDISCOVERED_2);
+        assertThat(mCachedDevice.mDevice).isEqualTo(mSubDevice);
+        assertThat(subCachedDevice.mRssi).isEqualTo(RSSI_1);
+        assertThat(subCachedDevice.mJustDiscovered).isEqualTo(JUSTDISCOVERED_1);
+        assertThat(subCachedDevice.mDevice).isEqualTo(mDevice);
+    }
 }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidDeviceManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidDeviceManagerTest.java
new file mode 100644
index 0000000..cb1b12d
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidDeviceManagerTest.java
@@ -0,0 +1,410 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settingslib.bluetooth;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.bluetooth.BluetoothClass;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHearingAid;
+import android.bluetooth.BluetoothProfile;
+import android.content.Context;
+
+import com.android.settingslib.SettingsLibRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(SettingsLibRobolectricTestRunner.class)
+public class HearingAidDeviceManagerTest {
+    private final static long HISYNCID1 = 10;
+    private final static long HISYNCID2 = 11;
+    private final static String DEVICE_NAME_1 = "TestName_1";
+    private final static String DEVICE_NAME_2 = "TestName_2";
+    private final static String DEVICE_ALIAS_1 = "TestAlias_1";
+    private final static String DEVICE_ALIAS_2 = "TestAlias_2";
+    private final static String DEVICE_ADDRESS_1 = "AA:BB:CC:DD:EE:11";
+    private final static String DEVICE_ADDRESS_2 = "AA:BB:CC:DD:EE:22";
+    private final BluetoothClass DEVICE_CLASS =
+            new BluetoothClass(BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE);
+    @Mock
+    private LocalBluetoothProfileManager mLocalProfileManager;
+    @Mock
+    private LocalBluetoothManager mLocalBluetoothManager;
+    @Mock
+    private BluetoothEventManager mBluetoothEventManager;
+    @Mock
+    private HearingAidProfile mHearingAidProfile;
+    @Mock
+    private BluetoothDevice mDevice1;
+    @Mock
+    private BluetoothDevice mDevice2;
+    private CachedBluetoothDevice mCachedDevice1;
+    private CachedBluetoothDevice mCachedDevice2;
+    private CachedBluetoothDeviceManager mCachedDeviceManager;
+    private HearingAidDeviceManager mHearingAidDeviceManager;
+    private Context mContext;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext = RuntimeEnvironment.application;
+        when(mDevice1.getAddress()).thenReturn(DEVICE_ADDRESS_1);
+        when(mDevice2.getAddress()).thenReturn(DEVICE_ADDRESS_2);
+        when(mDevice1.getName()).thenReturn(DEVICE_NAME_1);
+        when(mDevice2.getName()).thenReturn(DEVICE_NAME_2);
+        when(mDevice1.getAliasName()).thenReturn(DEVICE_ALIAS_1);
+        when(mDevice2.getAliasName()).thenReturn(DEVICE_ALIAS_2);
+        when(mDevice1.getBluetoothClass()).thenReturn(DEVICE_CLASS);
+        when(mDevice2.getBluetoothClass()).thenReturn(DEVICE_CLASS);
+        when(mLocalBluetoothManager.getEventManager()).thenReturn(mBluetoothEventManager);
+        when(mLocalBluetoothManager.getProfileManager()).thenReturn(mLocalProfileManager);
+        when(mLocalProfileManager.getHearingAidProfile()).thenReturn(mHearingAidProfile);
+
+        mCachedDeviceManager = new CachedBluetoothDeviceManager(mContext, mLocalBluetoothManager);
+        mHearingAidDeviceManager = spy(new HearingAidDeviceManager(mLocalBluetoothManager,
+                mCachedDeviceManager.mCachedDevices));
+        mCachedDevice1 = spy(new CachedBluetoothDevice(mContext, mLocalProfileManager, mDevice1));
+        mCachedDevice2 = spy(new CachedBluetoothDevice(mContext, mLocalProfileManager, mDevice2));
+    }
+
+    /**
+     * Test initHearingAidDeviceIfNeeded, a valid HiSyncId will be assigned
+     */
+    @Test
+    public void initHearingAidDeviceIfNeeded_validHiSyncId_verifyHiSyncId() {
+        when(mHearingAidProfile.getHiSyncId(mDevice1)).thenReturn(HISYNCID1);
+
+        assertThat(mCachedDevice1.getHiSyncId()).isNotEqualTo(HISYNCID1);
+        mHearingAidDeviceManager.initHearingAidDeviceIfNeeded(mCachedDevice1);
+
+        assertThat(mCachedDevice1.getHiSyncId()).isEqualTo(HISYNCID1);
+    }
+
+    /**
+     * Test initHearingAidDeviceIfNeeded, an invalid HiSyncId will not be assigned
+     */
+    @Test
+    public void initHearingAidDeviceIfNeeded_invalidHiSyncId_notToSetHiSyncId() {
+        when(mHearingAidProfile.getHiSyncId(mDevice1)).thenReturn(
+                BluetoothHearingAid.HI_SYNC_ID_INVALID);
+        mHearingAidDeviceManager.initHearingAidDeviceIfNeeded(mCachedDevice1);
+
+        verify(mCachedDevice1, never()).setHiSyncId(anyLong());
+    }
+
+    /**
+     * Test setSubDeviceIfNeeded, a device with same HiSyncId will be set as sub device
+     */
+    @Test
+    public void setSubDeviceIfNeeded_sameHiSyncId_setSubDevice() {
+        mCachedDevice1.setHiSyncId(HISYNCID1);
+        mCachedDevice2.setHiSyncId(HISYNCID1);
+        mCachedDeviceManager.mCachedDevices.add(mCachedDevice1);
+        mHearingAidDeviceManager.setSubDeviceIfNeeded(mCachedDevice2);
+
+        assertThat(mCachedDevice1.getSubDevice()).isEqualTo(mCachedDevice2);
+    }
+
+    /**
+     * Test setSubDeviceIfNeeded, a device with different HiSyncId will not be set as sub device
+     */
+    @Test
+    public void setSubDeviceIfNeeded_differentHiSyncId_notSetSubDevice() {
+        mCachedDevice1.setHiSyncId(HISYNCID1);
+        mCachedDevice2.setHiSyncId(HISYNCID2);
+        mCachedDeviceManager.mCachedDevices.add(mCachedDevice1);
+        mHearingAidDeviceManager.setSubDeviceIfNeeded(mCachedDevice2);
+
+        assertThat(mCachedDevice1.getSubDevice()).isNull();
+    }
+
+    /**
+     * Test updateHearingAidsDevices, to link two devices with the same HiSyncId.
+     * When first paired devices is connected and second paired device is disconnected, first
+     * paired device would be set as main device and second device will be removed from
+     * CachedDevices list.
+     */
+    @Test
+    public void updateHearingAidsDevices_firstPairedDevicesConnected_verifySubDevice() {
+        when(mHearingAidProfile.getHiSyncId(mDevice1)).thenReturn(HISYNCID1);
+        when(mHearingAidProfile.getHiSyncId(mDevice2)).thenReturn(HISYNCID1);
+        when(mCachedDevice1.isConnected()).thenReturn(true);
+        when(mCachedDevice2.isConnected()).thenReturn(false);
+        mCachedDeviceManager.mCachedDevices.add(mCachedDevice1);
+        mCachedDeviceManager.mCachedDevices.add(mCachedDevice2);
+
+        assertThat(mCachedDeviceManager.mCachedDevices.contains(mCachedDevice2)).isTrue();
+        assertThat(mCachedDevice1.getSubDevice()).isNull();
+        mHearingAidDeviceManager.updateHearingAidsDevices();
+
+        assertThat(mCachedDeviceManager.mCachedDevices.contains(mCachedDevice2)).isFalse();
+        assertThat(mCachedDevice1.getSubDevice()).isEqualTo(mCachedDevice2);
+    }
+
+    /**
+     * Test updateHearingAidsDevices, to link two devices with the same HiSyncId.
+     * When second paired devices is connected and first paired device is disconnected, second
+     * paired device would be set as main device and first device will be removed from
+     * CachedDevices list.
+     */
+    @Test
+    public void updateHearingAidsDevices_secondPairedDeviceConnected_verifySubDevice() {
+        when(mHearingAidProfile.getHiSyncId(mDevice1)).thenReturn(HISYNCID1);
+        when(mHearingAidProfile.getHiSyncId(mDevice2)).thenReturn(HISYNCID1);
+        when(mCachedDevice1.isConnected()).thenReturn(false);
+        when(mCachedDevice2.isConnected()).thenReturn(true);
+        mCachedDeviceManager.mCachedDevices.add(mCachedDevice1);
+        mCachedDeviceManager.mCachedDevices.add(mCachedDevice2);
+
+        assertThat(mCachedDeviceManager.mCachedDevices.contains(mCachedDevice1)).isTrue();
+        assertThat(mCachedDevice2.getSubDevice()).isNull();
+        mHearingAidDeviceManager.updateHearingAidsDevices();
+
+        assertThat(mCachedDeviceManager.mCachedDevices.contains(mCachedDevice1)).isFalse();
+        assertThat(mCachedDevice2.getSubDevice()).isEqualTo(mCachedDevice1);
+    }
+
+    /**
+     * Test updateHearingAidsDevices, to link two devices with the same HiSyncId.
+     * When both devices are connected, to build up main and sub relationship and to remove sub
+     * device from CachedDevices list.
+     */
+    @Test
+    public void updateHearingAidsDevices_BothConnected_verifySubDevice() {
+        when(mHearingAidProfile.getHiSyncId(mDevice1)).thenReturn(HISYNCID1);
+        when(mHearingAidProfile.getHiSyncId(mDevice2)).thenReturn(HISYNCID1);
+        when(mCachedDevice1.isConnected()).thenReturn(true);
+        when(mCachedDevice2.isConnected()).thenReturn(true);
+        mCachedDeviceManager.mCachedDevices.add(mCachedDevice1);
+        mCachedDeviceManager.mCachedDevices.add(mCachedDevice2);
+
+        assertThat(mCachedDeviceManager.mCachedDevices.contains(mCachedDevice2)).isTrue();
+        assertThat(mCachedDevice1.getSubDevice()).isNull();
+        mHearingAidDeviceManager.updateHearingAidsDevices();
+
+        assertThat(mCachedDeviceManager.mCachedDevices.contains(mCachedDevice2)).isFalse();
+        assertThat(mCachedDevice1.getSubDevice()).isEqualTo(mCachedDevice2);
+    }
+
+    /**
+     * Test updateHearingAidsDevices, dispatch callback
+     */
+    @Test
+    public void updateHearingAidsDevices_dispatchDeviceRemovedCallback() {
+        when(mHearingAidProfile.getHiSyncId(mDevice1)).thenReturn(HISYNCID1);
+        when(mHearingAidProfile.getHiSyncId(mDevice2)).thenReturn(HISYNCID1);
+        mCachedDeviceManager.mCachedDevices.add(mCachedDevice1);
+        mCachedDeviceManager.mCachedDevices.add(mCachedDevice2);
+        mHearingAidDeviceManager.updateHearingAidsDevices();
+
+        verify(mBluetoothEventManager).dispatchDeviceRemoved(mCachedDevice1);
+    }
+
+    /**
+     * Test updateHearingAidsDevices, do nothing when HiSyncId is invalid
+     */
+    @Test
+    public void updateHearingAidsDevices_invalidHiSyncId_doNothing() {
+        when(mHearingAidProfile.getHiSyncId(mDevice1)).
+                thenReturn(BluetoothHearingAid.HI_SYNC_ID_INVALID);
+        when(mHearingAidProfile.getHiSyncId(mDevice2)).
+                thenReturn(BluetoothHearingAid.HI_SYNC_ID_INVALID);
+        mCachedDeviceManager.mCachedDevices.add(mCachedDevice1);
+        mCachedDeviceManager.mCachedDevices.add(mCachedDevice2);
+        mHearingAidDeviceManager.updateHearingAidsDevices();
+
+        verify(mHearingAidDeviceManager, never()).onHiSyncIdChanged(anyLong());
+    }
+
+    /**
+     * Test onProfileConnectionStateChangedIfProcessed.
+     * When first hearing aid device is connected, to process it same as other generic devices.
+     * No need to process it.
+     */
+    @Test
+    public void onProfileConnectionStateChanged_connected_singleDevice_returnFalse() {
+        when(mHearingAidProfile.getHiSyncId(mDevice1)).thenReturn(HISYNCID1);
+
+        assertThat(mHearingAidDeviceManager.onProfileConnectionStateChangedIfProcessed(
+                mCachedDevice1, BluetoothProfile.STATE_CONNECTED)).isFalse();
+    }
+
+    /**
+     * Test onProfileConnectionStateChangedIfProcessed.
+     * When a new hearing aid device is connected, to set it as sub device by onHiSyncIdChanged().
+     * And, to verify new device is not in CachedDevices list.
+     */
+    @Test
+    public void onProfileConnectionStateChanged_connected_newDevice_verifySubDevice() {
+        when(mCachedDevice1.getHiSyncId()).thenReturn(HISYNCID1);
+        when(mCachedDevice2.getHiSyncId()).thenReturn(HISYNCID1);
+        when(mCachedDevice1.isConnected()).thenReturn(true);
+        when(mCachedDevice2.isConnected()).thenReturn(true);
+        mCachedDeviceManager.mCachedDevices.add(mCachedDevice1);
+        mCachedDeviceManager.mCachedDevices.add(mCachedDevice2);
+
+        assertThat(mCachedDeviceManager.mCachedDevices.contains(mCachedDevice2)).isTrue();
+        assertThat(mCachedDevice1.getSubDevice()).isNull();
+        mHearingAidDeviceManager.onProfileConnectionStateChangedIfProcessed(mCachedDevice1,
+                BluetoothProfile.STATE_CONNECTED);
+
+        assertThat(mCachedDeviceManager.mCachedDevices.contains(mCachedDevice2)).isFalse();
+        assertThat(mCachedDevice1.getSubDevice()).isEqualTo(mCachedDevice2);
+        verify(mHearingAidDeviceManager).onHiSyncIdChanged(anyLong());
+    }
+
+    /**
+     * Test onProfileConnectionStateChangedIfProcessed.
+     * When sub device is disconnected, do nothing and return False for main device connected event
+     */
+    @Test
+    public void
+    onProfileConnectionStateChanged_connected_mainDevice_subDeviceDisconnected_returnFalse() {
+        when(mCachedDevice1.getHiSyncId()).thenReturn(HISYNCID1);
+        when(mCachedDevice2.getHiSyncId()).thenReturn(HISYNCID1);
+        when(mCachedDevice2.isConnected()).thenReturn(false);
+        mCachedDeviceManager.mCachedDevices.add(mCachedDevice1);
+        mCachedDevice1.setSubDevice(mCachedDevice2);
+
+        assertThat(mHearingAidDeviceManager.onProfileConnectionStateChangedIfProcessed(
+                mCachedDevice1, BluetoothProfile.STATE_CONNECTED)).isFalse();
+        verify(mHearingAidDeviceManager).onHiSyncIdChanged(anyLong());
+    }
+
+    /**
+     * Test onProfileConnectionStateChangedIfProcessed.
+     * When main device is connected, do main device refresh() for sub device connected event
+     */
+    @Test
+    public void
+    onProfileConnectionStateChanged_connected_subDevice_mainDeviceConnected_verifyRefresh() {
+        when(mCachedDevice1.getHiSyncId()).thenReturn(HISYNCID1);
+        when(mCachedDevice2.getHiSyncId()).thenReturn(HISYNCID1);
+        when(mCachedDevice1.isConnected()).thenReturn(true);
+        mCachedDeviceManager.mCachedDevices.add(mCachedDevice1);
+        mCachedDevice1.setSubDevice(mCachedDevice2);
+
+        assertThat(mHearingAidDeviceManager.onProfileConnectionStateChangedIfProcessed(
+                mCachedDevice2, BluetoothProfile.STATE_CONNECTED)).isTrue();
+        verify(mHearingAidDeviceManager).onHiSyncIdChanged(anyLong());
+        verify(mCachedDevice1).refresh();
+    }
+
+    /**
+     * Test onProfileConnectionStateChangedIfProcessed.
+     * When main device is disconnected, to verify switch() result for sub device connected
+     * event
+     */
+    @Test
+    public void onProfileConnectionStateChanged_connected_subDevice_mainDeviceDisconnected_switch()
+    {
+        when(mCachedDevice1.getHiSyncId()).thenReturn(HISYNCID1);
+        when(mCachedDevice2.getHiSyncId()).thenReturn(HISYNCID1);
+        when(mCachedDevice1.isConnected()).thenReturn(false);
+        mCachedDeviceManager.mCachedDevices.add(mCachedDevice1);
+        mCachedDevice1.setSubDevice(mCachedDevice2);
+
+        assertThat(mCachedDevice1.mDevice).isEqualTo(mDevice1);
+        assertThat(mCachedDevice2.mDevice).isEqualTo(mDevice2);
+        assertThat(mHearingAidDeviceManager.onProfileConnectionStateChangedIfProcessed(
+                mCachedDevice2, BluetoothProfile.STATE_CONNECTED)).isTrue();
+
+        assertThat(mCachedDevice1.mDevice).isEqualTo(mDevice2);
+        assertThat(mCachedDevice2.mDevice).isEqualTo(mDevice1);
+        verify(mHearingAidDeviceManager).onHiSyncIdChanged(anyLong());
+        verify(mCachedDevice1).refresh();
+    }
+
+    /**
+     * Test onProfileConnectionStateChangedIfProcessed.
+     * When sub device is connected, to verify switch() result for main device disconnected
+     * event
+     */
+    @Test
+    public void onProfileConnectionStateChanged_disconnected_mainDevice_subDeviceConnected_switch()
+    {
+        when(mCachedDevice1.getHiSyncId()).thenReturn(HISYNCID1);
+        when(mCachedDevice2.getHiSyncId()).thenReturn(HISYNCID1);
+        when(mCachedDevice2.isConnected()).thenReturn(true);
+        mCachedDeviceManager.mCachedDevices.add(mCachedDevice1);
+        mCachedDevice1.setSubDevice(mCachedDevice2);
+
+        assertThat(mCachedDevice1.mDevice).isEqualTo(mDevice1);
+        assertThat(mCachedDevice2.mDevice).isEqualTo(mDevice2);
+        assertThat(mHearingAidDeviceManager.onProfileConnectionStateChangedIfProcessed(
+                mCachedDevice1, BluetoothProfile.STATE_DISCONNECTED)).isTrue();
+
+        assertThat(mCachedDevice1.mDevice).isEqualTo(mDevice2);
+        assertThat(mCachedDevice2.mDevice).isEqualTo(mDevice1);
+        verify(mCachedDevice1).refresh();
+    }
+
+    /**
+     * Test onProfileConnectionStateChangedIfProcessed.
+     * When sub device is disconnected, do nothing and return False for main device disconnected
+     * event
+     */
+    @Test
+    public void
+    onProfileConnectionStateChanged_disconnected_mainDevice_subDeviceDisconnected_returnFalse() {
+        when(mCachedDevice1.getHiSyncId()).thenReturn(HISYNCID1);
+        when(mCachedDevice2.getHiSyncId()).thenReturn(HISYNCID1);
+        when(mCachedDevice2.isConnected()).thenReturn(false);
+        mCachedDeviceManager.mCachedDevices.add(mCachedDevice1);
+        mCachedDevice1.setSubDevice(mCachedDevice2);
+
+        assertThat(mHearingAidDeviceManager.onProfileConnectionStateChangedIfProcessed(
+                mCachedDevice1, BluetoothProfile.STATE_DISCONNECTED)).isFalse();
+    }
+
+    /**
+     * Test onProfileConnectionStateChangedIfProcessed.
+     * Refresh main device UI for sub device disconnected event
+     */
+    @Test
+    public void onProfileConnectionStateChanged_disconnected_subDevice_verifyRefresh() {
+        when(mCachedDevice1.getHiSyncId()).thenReturn(HISYNCID1);
+        when(mCachedDevice2.getHiSyncId()).thenReturn(HISYNCID1);
+        mCachedDeviceManager.mCachedDevices.add(mCachedDevice1);
+        mCachedDevice1.setSubDevice(mCachedDevice2);
+
+        assertThat(mHearingAidDeviceManager.onProfileConnectionStateChangedIfProcessed(
+                mCachedDevice2, BluetoothProfile.STATE_DISCONNECTED)).isTrue();
+        verify(mCachedDevice1).refresh();
+    }
+
+    @Test
+    public void findMainDevice() {
+        when(mCachedDevice1.getHiSyncId()).thenReturn(HISYNCID1);
+        when(mCachedDevice2.getHiSyncId()).thenReturn(HISYNCID1);
+        mCachedDeviceManager.mCachedDevices.add(mCachedDevice1);
+        mCachedDevice1.setSubDevice(mCachedDevice2);
+
+        assertThat(mHearingAidDeviceManager.findMainDevice(mCachedDevice2)).
+                isEqualTo(mCachedDevice1);
+    }
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java
index 6f4c292..a3c3a54 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManagerTest.java
@@ -55,6 +55,8 @@
 @RunWith(SettingsLibRobolectricTestRunner.class)
 @Config(shadows = {ShadowBluetoothAdapter.class})
 public class LocalBluetoothProfileManagerTest {
+    private final static long HISYNCID = 10;
+
     @Mock
     private CachedBluetoothDeviceManager mDeviceManager;
     @Mock
@@ -76,9 +78,10 @@
         mContext = spy(RuntimeEnvironment.application);
         mLocalBluetoothAdapter = LocalBluetoothAdapter.getInstance();
         mEventManager = spy(new BluetoothEventManager(mLocalBluetoothAdapter, mDeviceManager,
-                mContext, null));
+                mContext, /* handler= */ null, /* userHandle= */ null));
         mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter());
         when(mDeviceManager.findDevice(mDevice)).thenReturn(mCachedBluetoothDevice);
+        when(mCachedBluetoothDevice.getDevice()).thenReturn(mDevice);
         mProfileManager = new LocalBluetoothProfileManager(mContext, mLocalBluetoothAdapter,
                 mDeviceManager, mEventManager);
     }
@@ -186,13 +189,14 @@
 
     /**
      * Verify BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED with uuid intent will dispatch to
-     * profile connection state changed callback
+     * CachedBluetoothDeviceManager method
      */
     @Test
-    public void stateChangedHandler_receiveHAPConnectionStateChanged_shouldDispatchCallback() {
+    public void stateChangedHandler_receiveHAPConnectionStateChanged_shouldDispatchDeviceManager() {
         mShadowBluetoothAdapter.setSupportedProfiles(generateList(
                 new int[] {BluetoothProfile.HEARING_AID}));
         mProfileManager.updateLocalProfiles();
+        when(mCachedBluetoothDevice.getHiSyncId()).thenReturn(HISYNCID);
 
         mIntent = new Intent(BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED);
         mIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice);
@@ -201,8 +205,8 @@
 
         mContext.sendBroadcast(mIntent);
 
-        verify(mEventManager).dispatchProfileConnectionStateChanged(mCachedBluetoothDevice,
-                BluetoothProfile.STATE_CONNECTED, BluetoothProfile.HEARING_AID);
+        verify(mDeviceManager).onProfileConnectionStateChangedIfProcessed(mCachedBluetoothDevice,
+                BluetoothProfile.STATE_CONNECTED);
     }
 
     /**
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index 9c33116..b770d5c 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -156,3 +156,43 @@
     ],
 
 }
+
+// Only used for products that are shipping legacy Recents
+android_app {
+    name: "SystemUIWithLegacyRecents",
+    overrides: [
+        "SystemUI",
+    ],
+
+    platform_apis: true,
+    certificate: "platform",
+    privileged: true,
+
+    dxflags: ["--multi-dex"],
+    aaptflags: [
+        "--extra-packages",
+        "com.android.keyguard",
+    ],
+    optimize: {
+        proguard_flags_files: ["proguard.flags", "legacy/recents/proguard.flags"],
+    },
+
+    static_libs: [
+        "SystemUI-core",
+    ],
+    libs: [
+        "telephony-common",
+        "android.car",
+        "android.car.user",
+    ],
+
+    srcs: [
+        "legacy/recents/src/**/*.java",
+        "legacy/recents/src/**/I*.aidl",
+    ],
+    resource_dirs: [
+        "legacy/recents/res",
+    ],
+
+    manifest: "legacy/recents/AndroidManifest.xml",
+}
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 3725940..44bc3f2 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -128,9 +128,6 @@
     <!-- Needed for WallpaperManager.clear in ImageWallpaper.updateWallpaperLocked -->
     <uses-permission android:name="android.permission.SET_WALLPAPER"/>
 
-    <!-- Recents -->
-    <uses-permission android:name="android.permission.BIND_APPWIDGET" />
-
     <!-- Wifi Display -->
     <uses-permission android:name="android.permission.CONFIGURE_WIFI_DISPLAY" />
 
@@ -209,6 +206,9 @@
     <!-- to read and change hvac values in a car -->
     <uses-permission android:name="android.car.permission.CONTROL_CAR_CLIMATE" />
 
+    <!-- to be able to detect the driving state in a car-->
+    <uses-permission android:name="android.car.permission.CAR_DRIVING_STATE" />
+
     <!-- Permission necessary to change car audio volume through CarAudioManager -->
     <uses-permission android:name="android.car.permission.CAR_CONTROL_AUDIO_VOLUME" />
 
@@ -244,14 +244,14 @@
             android:exported="true"
         />
 
-        <!-- Recents depends on every user having their own SystemUI process, so on user switch,
-             ensure that the process is created by starting this service.
+        <!-- On user switch, this service is started to ensure that the associated SystemUI
+             process for the current user is started. See the resource
+             "config_systemUIServiceComponentsPerUser".
              -->
         <service android:name="SystemUISecondaryUserService"
-            android:exported="true"
+            android:exported="false"
             android:permission="com.android.systemui.permission.SELF" />
 
-
         <!-- started from PhoneWindowManager
              TODO: Should have an android:permission attribute -->
         <service android:name=".screenshot.TakeScreenshotService"
@@ -310,27 +310,6 @@
             </intent-filter>
         </activity-alias>
 
-        <!-- Service used by secondary users to register themselves with the system user. -->
-        <service android:name=".recents.RecentsSystemUserService"
-            android:exported="false"
-            android:permission="com.android.systemui.permission.SELF" />
-
-        <!-- Alternate Recents -->
-        <activity android:name=".recents.RecentsActivity"
-                  android:label="@string/accessibility_desc_recent_apps"
-                  android:exported="false"
-                  android:launchMode="singleInstance"
-                  android:excludeFromRecents="true"
-                  android:stateNotNeeded="true"
-                  android:resumeWhilePausing="true"
-                  android:resizeableActivity="true"
-                  android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|keyboard|keyboardHidden"
-                  android:theme="@style/RecentsTheme.Wallpaper">
-            <intent-filter>
-                <action android:name="com.android.systemui.recents.TOGGLE_RECENTS" />
-            </intent-filter>
-        </activity>
-
         <activity
             android:name=".stackdivider.ForcedResizableInfoActivity"
             android:theme="@style/ForcedResizableTheme"
diff --git a/packages/SystemUI/legacy/recents/AndroidManifest.xml b/packages/SystemUI/legacy/recents/AndroidManifest.xml
new file mode 100644
index 0000000..0d8b3cd
--- /dev/null
+++ b/packages/SystemUI/legacy/recents/AndroidManifest.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (c) 2018 Google Inc.
+ *
+ * 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"
+          xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+          xmlns:tools="http://schemas.android.com/tools"
+          package="com.android.systemui"
+          android:sharedUserId="android.uid.systemui"
+          coreApp="true">
+
+    <application
+        android:name="com.android.systemui.SystemUIApplication">
+
+        <!-- Service used by secondary users to register themselves with the system user. -->
+        <service android:name=".recents.RecentsSystemUserService"
+            android:exported="false"
+            android:permission="com.android.systemui.permission.SELF" />
+
+        <!-- Alternate Recents -->
+        <activity android:name=".recents.RecentsActivity"
+                  android:label="@string/accessibility_desc_recent_apps"
+                  android:exported="false"
+                  android:launchMode="singleInstance"
+                  android:excludeFromRecents="true"
+                  android:stateNotNeeded="true"
+                  android:resumeWhilePausing="true"
+                  android:resizeableActivity="true"
+                  android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|keyboard|keyboardHidden"
+                  android:theme="@style/RecentsTheme.Wallpaper">
+            <intent-filter>
+                <action android:name="com.android.systemui.recents.TOGGLE_RECENTS" />
+            </intent-filter>
+        </activity>
+
+    </application>
+</manifest>
diff --git a/packages/SystemUI/legacy/recents/proguard.flags b/packages/SystemUI/legacy/recents/proguard.flags
new file mode 100644
index 0000000..c358949
--- /dev/null
+++ b/packages/SystemUI/legacy/recents/proguard.flags
@@ -0,0 +1,14 @@
+-keepclassmembers class ** {
+    public void onBusEvent(**);
+    public void onInterprocessBusEvent(**);
+}
+-keepclassmembers class ** extends **.EventBus$InterprocessEvent {
+    public <init>(android.os.Bundle);
+}
+
+-keep class com.android.systemui.recents.views.TaskView {
+    public int getDim();
+    public void setDim(int);
+    public float getTaskProgress();
+    public void setTaskProgress(float);
+}
\ No newline at end of file
diff --git a/packages/SystemUI/res/anim/recents_fast_toggle_app_home_exit.xml b/packages/SystemUI/legacy/recents/res/anim/recents_fast_toggle_app_home_exit.xml
similarity index 100%
rename from packages/SystemUI/res/anim/recents_fast_toggle_app_home_exit.xml
rename to packages/SystemUI/legacy/recents/res/anim/recents_fast_toggle_app_home_exit.xml
diff --git a/packages/SystemUI/res/anim/recents_from_launcher_enter.xml b/packages/SystemUI/legacy/recents/res/anim/recents_from_launcher_enter.xml
similarity index 100%
rename from packages/SystemUI/res/anim/recents_from_launcher_enter.xml
rename to packages/SystemUI/legacy/recents/res/anim/recents_from_launcher_enter.xml
diff --git a/packages/SystemUI/res/anim/recents_from_launcher_exit.xml b/packages/SystemUI/legacy/recents/res/anim/recents_from_launcher_exit.xml
similarity index 100%
rename from packages/SystemUI/res/anim/recents_from_launcher_exit.xml
rename to packages/SystemUI/legacy/recents/res/anim/recents_from_launcher_exit.xml
diff --git a/packages/SystemUI/res/anim/recents_from_unknown_enter.xml b/packages/SystemUI/legacy/recents/res/anim/recents_from_unknown_enter.xml
similarity index 100%
rename from packages/SystemUI/res/anim/recents_from_unknown_enter.xml
rename to packages/SystemUI/legacy/recents/res/anim/recents_from_unknown_enter.xml
diff --git a/packages/SystemUI/res/anim/recents_from_unknown_exit.xml b/packages/SystemUI/legacy/recents/res/anim/recents_from_unknown_exit.xml
similarity index 100%
rename from packages/SystemUI/res/anim/recents_from_unknown_exit.xml
rename to packages/SystemUI/legacy/recents/res/anim/recents_from_unknown_exit.xml
diff --git a/packages/SystemUI/res/anim/recents_launch_next_affiliated_task_bounce.xml b/packages/SystemUI/legacy/recents/res/anim/recents_launch_next_affiliated_task_bounce.xml
similarity index 100%
rename from packages/SystemUI/res/anim/recents_launch_next_affiliated_task_bounce.xml
rename to packages/SystemUI/legacy/recents/res/anim/recents_launch_next_affiliated_task_bounce.xml
diff --git a/packages/SystemUI/res/anim/recents_launch_next_affiliated_task_source.xml b/packages/SystemUI/legacy/recents/res/anim/recents_launch_next_affiliated_task_source.xml
similarity index 100%
rename from packages/SystemUI/res/anim/recents_launch_next_affiliated_task_source.xml
rename to packages/SystemUI/legacy/recents/res/anim/recents_launch_next_affiliated_task_source.xml
diff --git a/packages/SystemUI/res/anim/recents_launch_next_affiliated_task_target.xml b/packages/SystemUI/legacy/recents/res/anim/recents_launch_next_affiliated_task_target.xml
similarity index 100%
rename from packages/SystemUI/res/anim/recents_launch_next_affiliated_task_target.xml
rename to packages/SystemUI/legacy/recents/res/anim/recents_launch_next_affiliated_task_target.xml
diff --git a/packages/SystemUI/res/anim/recents_launch_prev_affiliated_task_bounce.xml b/packages/SystemUI/legacy/recents/res/anim/recents_launch_prev_affiliated_task_bounce.xml
similarity index 100%
rename from packages/SystemUI/res/anim/recents_launch_prev_affiliated_task_bounce.xml
rename to packages/SystemUI/legacy/recents/res/anim/recents_launch_prev_affiliated_task_bounce.xml
diff --git a/packages/SystemUI/res/anim/recents_launch_prev_affiliated_task_source.xml b/packages/SystemUI/legacy/recents/res/anim/recents_launch_prev_affiliated_task_source.xml
similarity index 100%
rename from packages/SystemUI/res/anim/recents_launch_prev_affiliated_task_source.xml
rename to packages/SystemUI/legacy/recents/res/anim/recents_launch_prev_affiliated_task_source.xml
diff --git a/packages/SystemUI/res/anim/recents_launch_prev_affiliated_task_target.xml b/packages/SystemUI/legacy/recents/res/anim/recents_launch_prev_affiliated_task_target.xml
similarity index 100%
rename from packages/SystemUI/res/anim/recents_launch_prev_affiliated_task_target.xml
rename to packages/SystemUI/legacy/recents/res/anim/recents_launch_prev_affiliated_task_target.xml
diff --git a/packages/SystemUI/res/anim/recents_to_launcher_enter.xml b/packages/SystemUI/legacy/recents/res/anim/recents_to_launcher_enter.xml
similarity index 100%
rename from packages/SystemUI/res/anim/recents_to_launcher_enter.xml
rename to packages/SystemUI/legacy/recents/res/anim/recents_to_launcher_enter.xml
diff --git a/packages/SystemUI/res/anim/recents_to_launcher_exit.xml b/packages/SystemUI/legacy/recents/res/anim/recents_to_launcher_exit.xml
similarity index 100%
rename from packages/SystemUI/res/anim/recents_to_launcher_exit.xml
rename to packages/SystemUI/legacy/recents/res/anim/recents_to_launcher_exit.xml
diff --git a/packages/SystemUI/res/drawable-hdpi/recents_lower_gradient.9.png b/packages/SystemUI/legacy/recents/res/drawable-hdpi/recents_lower_gradient.9.png
similarity index 100%
rename from packages/SystemUI/res/drawable-hdpi/recents_lower_gradient.9.png
rename to packages/SystemUI/legacy/recents/res/drawable-hdpi/recents_lower_gradient.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/recents_status_gradient.9.png b/packages/SystemUI/legacy/recents/res/drawable-hdpi/recents_status_gradient.9.png
similarity index 100%
rename from packages/SystemUI/res/drawable-hdpi/recents_status_gradient.9.png
rename to packages/SystemUI/legacy/recents/res/drawable-hdpi/recents_status_gradient.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/recents_lower_gradient.9.png b/packages/SystemUI/legacy/recents/res/drawable-mdpi/recents_lower_gradient.9.png
similarity index 100%
rename from packages/SystemUI/res/drawable-mdpi/recents_lower_gradient.9.png
rename to packages/SystemUI/legacy/recents/res/drawable-mdpi/recents_lower_gradient.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/recents_status_gradient.9.png b/packages/SystemUI/legacy/recents/res/drawable-mdpi/recents_status_gradient.9.png
similarity index 100%
rename from packages/SystemUI/res/drawable-mdpi/recents_status_gradient.9.png
rename to packages/SystemUI/legacy/recents/res/drawable-mdpi/recents_status_gradient.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/recents_lower_gradient.9.png b/packages/SystemUI/legacy/recents/res/drawable-xhdpi/recents_lower_gradient.9.png
similarity index 100%
rename from packages/SystemUI/res/drawable-xhdpi/recents_lower_gradient.9.png
rename to packages/SystemUI/legacy/recents/res/drawable-xhdpi/recents_lower_gradient.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/recents_status_gradient.9.png b/packages/SystemUI/legacy/recents/res/drawable-xhdpi/recents_status_gradient.9.png
similarity index 100%
rename from packages/SystemUI/res/drawable-xhdpi/recents_status_gradient.9.png
rename to packages/SystemUI/legacy/recents/res/drawable-xhdpi/recents_status_gradient.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/recents_lower_gradient.9.png b/packages/SystemUI/legacy/recents/res/drawable-xxhdpi/recents_lower_gradient.9.png
similarity index 100%
rename from packages/SystemUI/res/drawable-xxhdpi/recents_lower_gradient.9.png
rename to packages/SystemUI/legacy/recents/res/drawable-xxhdpi/recents_lower_gradient.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/recents_status_gradient.9.png b/packages/SystemUI/legacy/recents/res/drawable-xxhdpi/recents_status_gradient.9.png
similarity index 100%
rename from packages/SystemUI/res/drawable-xxhdpi/recents_status_gradient.9.png
rename to packages/SystemUI/legacy/recents/res/drawable-xxhdpi/recents_status_gradient.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/recents_task_shadow.9.png b/packages/SystemUI/legacy/recents/res/drawable-xxhdpi/recents_task_shadow.9.png
similarity index 100%
rename from packages/SystemUI/res/drawable-xxhdpi/recents_task_shadow.9.png
rename to packages/SystemUI/legacy/recents/res/drawable-xxhdpi/recents_task_shadow.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable/ic_lock_to_app_24dp.xml b/packages/SystemUI/legacy/recents/res/drawable/ic_lock_to_app_24dp.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_lock_to_app_24dp.xml
rename to packages/SystemUI/legacy/recents/res/drawable/ic_lock_to_app_24dp.xml
diff --git a/packages/SystemUI/res/drawable/recents_dismiss_dark.xml b/packages/SystemUI/legacy/recents/res/drawable/recents_dismiss_dark.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/recents_dismiss_dark.xml
rename to packages/SystemUI/legacy/recents/res/drawable/recents_dismiss_dark.xml
diff --git a/packages/SystemUI/res/drawable/recents_dismiss_light.xml b/packages/SystemUI/legacy/recents/res/drawable/recents_dismiss_light.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/recents_dismiss_light.xml
rename to packages/SystemUI/legacy/recents/res/drawable/recents_dismiss_light.xml
diff --git a/packages/SystemUI/res/drawable/recents_empty.xml b/packages/SystemUI/legacy/recents/res/drawable/recents_empty.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/recents_empty.xml
rename to packages/SystemUI/legacy/recents/res/drawable/recents_empty.xml
diff --git a/packages/SystemUI/res/drawable/recents_freeform_workspace_bg.xml b/packages/SystemUI/legacy/recents/res/drawable/recents_freeform_workspace_bg.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/recents_freeform_workspace_bg.xml
rename to packages/SystemUI/legacy/recents/res/drawable/recents_freeform_workspace_bg.xml
diff --git a/packages/SystemUI/res/drawable/recents_grid_task_view_focus_frame_background.xml b/packages/SystemUI/legacy/recents/res/drawable/recents_grid_task_view_focus_frame_background.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/recents_grid_task_view_focus_frame_background.xml
rename to packages/SystemUI/legacy/recents/res/drawable/recents_grid_task_view_focus_frame_background.xml
diff --git a/packages/SystemUI/res/drawable/recents_info_dark.xml b/packages/SystemUI/legacy/recents/res/drawable/recents_info_dark.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/recents_info_dark.xml
rename to packages/SystemUI/legacy/recents/res/drawable/recents_info_dark.xml
diff --git a/packages/SystemUI/res/drawable/recents_info_light.xml b/packages/SystemUI/legacy/recents/res/drawable/recents_info_light.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/recents_info_light.xml
rename to packages/SystemUI/legacy/recents/res/drawable/recents_info_light.xml
diff --git a/packages/SystemUI/res/drawable/recents_lock_to_app_pin.xml b/packages/SystemUI/legacy/recents/res/drawable/recents_lock_to_app_pin.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/recents_lock_to_app_pin.xml
rename to packages/SystemUI/legacy/recents/res/drawable/recents_lock_to_app_pin.xml
diff --git a/packages/SystemUI/res/drawable/recents_lock_to_task_button_bg.xml b/packages/SystemUI/legacy/recents/res/drawable/recents_lock_to_task_button_bg.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/recents_lock_to_task_button_bg.xml
rename to packages/SystemUI/legacy/recents/res/drawable/recents_lock_to_task_button_bg.xml
diff --git a/packages/SystemUI/res/drawable/recents_low_ram_stack_button_background.xml b/packages/SystemUI/legacy/recents/res/drawable/recents_low_ram_stack_button_background.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/recents_low_ram_stack_button_background.xml
rename to packages/SystemUI/legacy/recents/res/drawable/recents_low_ram_stack_button_background.xml
diff --git a/packages/SystemUI/res/drawable/recents_move_task_freeform_dark.xml b/packages/SystemUI/legacy/recents/res/drawable/recents_move_task_freeform_dark.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/recents_move_task_freeform_dark.xml
rename to packages/SystemUI/legacy/recents/res/drawable/recents_move_task_freeform_dark.xml
diff --git a/packages/SystemUI/res/drawable/recents_move_task_freeform_light.xml b/packages/SystemUI/legacy/recents/res/drawable/recents_move_task_freeform_light.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/recents_move_task_freeform_light.xml
rename to packages/SystemUI/legacy/recents/res/drawable/recents_move_task_freeform_light.xml
diff --git a/packages/SystemUI/res/drawable/recents_move_task_fullscreen_dark.xml b/packages/SystemUI/legacy/recents/res/drawable/recents_move_task_fullscreen_dark.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/recents_move_task_fullscreen_dark.xml
rename to packages/SystemUI/legacy/recents/res/drawable/recents_move_task_fullscreen_dark.xml
diff --git a/packages/SystemUI/res/drawable/recents_move_task_fullscreen_light.xml b/packages/SystemUI/legacy/recents/res/drawable/recents_move_task_fullscreen_light.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/recents_move_task_fullscreen_light.xml
rename to packages/SystemUI/legacy/recents/res/drawable/recents_move_task_fullscreen_light.xml
diff --git a/packages/SystemUI/res/drawable/recents_stack_action_background.xml b/packages/SystemUI/legacy/recents/res/drawable/recents_stack_action_background.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/recents_stack_action_background.xml
rename to packages/SystemUI/legacy/recents/res/drawable/recents_stack_action_background.xml
diff --git a/packages/SystemUI/res/interpolator/recents_from_launcher_exit_interpolator.xml b/packages/SystemUI/legacy/recents/res/interpolator/recents_from_launcher_exit_interpolator.xml
similarity index 100%
rename from packages/SystemUI/res/interpolator/recents_from_launcher_exit_interpolator.xml
rename to packages/SystemUI/legacy/recents/res/interpolator/recents_from_launcher_exit_interpolator.xml
diff --git a/packages/SystemUI/res/interpolator/recents_launch_next_affiliated_task_bounce_scale.xml b/packages/SystemUI/legacy/recents/res/interpolator/recents_launch_next_affiliated_task_bounce_scale.xml
similarity index 100%
rename from packages/SystemUI/res/interpolator/recents_launch_next_affiliated_task_bounce_scale.xml
rename to packages/SystemUI/legacy/recents/res/interpolator/recents_launch_next_affiliated_task_bounce_scale.xml
diff --git a/packages/SystemUI/res/interpolator/recents_launch_prev_affiliated_task_bounce_ydelta.xml b/packages/SystemUI/legacy/recents/res/interpolator/recents_launch_prev_affiliated_task_bounce_ydelta.xml
similarity index 100%
rename from packages/SystemUI/res/interpolator/recents_launch_prev_affiliated_task_bounce_ydelta.xml
rename to packages/SystemUI/legacy/recents/res/interpolator/recents_launch_prev_affiliated_task_bounce_ydelta.xml
diff --git a/packages/SystemUI/res/interpolator/recents_to_launcher_enter_interpolator.xml b/packages/SystemUI/legacy/recents/res/interpolator/recents_to_launcher_enter_interpolator.xml
similarity index 100%
rename from packages/SystemUI/res/interpolator/recents_to_launcher_enter_interpolator.xml
rename to packages/SystemUI/legacy/recents/res/interpolator/recents_to_launcher_enter_interpolator.xml
diff --git a/packages/SystemUI/res/layout/recents.xml b/packages/SystemUI/legacy/recents/res/layout/recents.xml
similarity index 100%
rename from packages/SystemUI/res/layout/recents.xml
rename to packages/SystemUI/legacy/recents/res/layout/recents.xml
diff --git a/packages/SystemUI/res/layout/recents_empty.xml b/packages/SystemUI/legacy/recents/res/layout/recents_empty.xml
similarity index 100%
rename from packages/SystemUI/res/layout/recents_empty.xml
rename to packages/SystemUI/legacy/recents/res/layout/recents_empty.xml
diff --git a/packages/SystemUI/res/layout/recents_grid_task_view.xml b/packages/SystemUI/legacy/recents/res/layout/recents_grid_task_view.xml
similarity index 100%
rename from packages/SystemUI/res/layout/recents_grid_task_view.xml
rename to packages/SystemUI/legacy/recents/res/layout/recents_grid_task_view.xml
diff --git a/packages/SystemUI/res/layout/recents_incompatible_app_overlay.xml b/packages/SystemUI/legacy/recents/res/layout/recents_incompatible_app_overlay.xml
similarity index 100%
rename from packages/SystemUI/res/layout/recents_incompatible_app_overlay.xml
rename to packages/SystemUI/legacy/recents/res/layout/recents_incompatible_app_overlay.xml
diff --git a/packages/SystemUI/res/layout/recents_low_ram_stack_action_button.xml b/packages/SystemUI/legacy/recents/res/layout/recents_low_ram_stack_action_button.xml
similarity index 100%
rename from packages/SystemUI/res/layout/recents_low_ram_stack_action_button.xml
rename to packages/SystemUI/legacy/recents/res/layout/recents_low_ram_stack_action_button.xml
diff --git a/packages/SystemUI/res/layout/recents_search_bar.xml b/packages/SystemUI/legacy/recents/res/layout/recents_search_bar.xml
similarity index 100%
rename from packages/SystemUI/res/layout/recents_search_bar.xml
rename to packages/SystemUI/legacy/recents/res/layout/recents_search_bar.xml
diff --git a/packages/SystemUI/res/layout/recents_stack_action_button.xml b/packages/SystemUI/legacy/recents/res/layout/recents_stack_action_button.xml
similarity index 100%
rename from packages/SystemUI/res/layout/recents_stack_action_button.xml
rename to packages/SystemUI/legacy/recents/res/layout/recents_stack_action_button.xml
diff --git a/packages/SystemUI/res/layout/recents_task_view.xml b/packages/SystemUI/legacy/recents/res/layout/recents_task_view.xml
similarity index 100%
rename from packages/SystemUI/res/layout/recents_task_view.xml
rename to packages/SystemUI/legacy/recents/res/layout/recents_task_view.xml
diff --git a/packages/SystemUI/res/layout/recents_task_view_header.xml b/packages/SystemUI/legacy/recents/res/layout/recents_task_view_header.xml
similarity index 100%
rename from packages/SystemUI/res/layout/recents_task_view_header.xml
rename to packages/SystemUI/legacy/recents/res/layout/recents_task_view_header.xml
diff --git a/packages/SystemUI/res/layout/recents_task_view_header_overlay.xml b/packages/SystemUI/legacy/recents/res/layout/recents_task_view_header_overlay.xml
similarity index 100%
rename from packages/SystemUI/res/layout/recents_task_view_header_overlay.xml
rename to packages/SystemUI/legacy/recents/res/layout/recents_task_view_header_overlay.xml
diff --git a/packages/SystemUI/res/layout/recents_task_view_header_progress_bar.xml b/packages/SystemUI/legacy/recents/res/layout/recents_task_view_header_progress_bar.xml
similarity index 100%
rename from packages/SystemUI/res/layout/recents_task_view_header_progress_bar.xml
rename to packages/SystemUI/legacy/recents/res/layout/recents_task_view_header_progress_bar.xml
diff --git a/packages/SystemUI/res/layout/recents_task_view_incompatible_app_toast.xml b/packages/SystemUI/legacy/recents/res/layout/recents_task_view_incompatible_app_toast.xml
similarity index 100%
rename from packages/SystemUI/res/layout/recents_task_view_incompatible_app_toast.xml
rename to packages/SystemUI/legacy/recents/res/layout/recents_task_view_incompatible_app_toast.xml
diff --git a/packages/SystemUI/res/layout/recents_task_view_lock_to_app.xml b/packages/SystemUI/legacy/recents/res/layout/recents_task_view_lock_to_app.xml
similarity index 100%
rename from packages/SystemUI/res/layout/recents_task_view_lock_to_app.xml
rename to packages/SystemUI/legacy/recents/res/layout/recents_task_view_lock_to_app.xml
diff --git a/packages/SystemUI/legacy/recents/res/values-sw600dp/dimens.xml b/packages/SystemUI/legacy/recents/res/values-sw600dp/dimens.xml
new file mode 100644
index 0000000..20d6670
--- /dev/null
+++ b/packages/SystemUI/legacy/recents/res/values-sw600dp/dimens.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (c) 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+-->
+<resources>
+    <!-- The offsets the tasks animate from when recents is launched while docking -->
+    <dimen name="recents_task_stack_animation_launched_while_docking_offset">192dp</dimen>
+</resources>
diff --git a/packages/SystemUI/legacy/recents/res/values/attrs.xml b/packages/SystemUI/legacy/recents/res/values/attrs.xml
new file mode 100644
index 0000000..ef4cd5b
--- /dev/null
+++ b/packages/SystemUI/legacy/recents/res/values/attrs.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+
+    <declare-styleable name="RecentsPanelView">
+        <attr name="recentItemLayout" format="reference" />
+        <!-- Style for the "Clear all" button. -->
+        <attr name="clearAllStyle" format="reference" />
+        <attr name="clearAllBackgroundColor" format="reference" />
+    </declare-styleable>
+
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/legacy/recents/res/values/colors.xml b/packages/SystemUI/legacy/recents/res/values/colors.xml
new file mode 100644
index 0000000..88b9b70
--- /dev/null
+++ b/packages/SystemUI/legacy/recents/res/values/colors.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources>
+	<!-- The disabled recents task bar background color. -->
+    <color name="recents_task_bar_disabled_background_color">#ff676767</color>
+    <!-- The default recents task bar background color. -->
+    <color name="recents_task_bar_default_background_color">#ffe6e6e6</color>
+    <!-- The default recents task view background color. -->
+    <color name="recents_task_view_default_background_color">#fff3f3f3</color>
+    <!-- The recents task bar light text color to be drawn on top of dark backgrounds. -->
+    <color name="recents_task_bar_light_text_color">#ffeeeeee</color>
+    <!-- The recents task bar dark text color to be drawn on top of light backgrounds. -->
+    <color name="recents_task_bar_dark_text_color">#cc000000</color>
+    <!-- The recents task bar light dismiss icon color to be drawn on top of dark backgrounds. -->
+    <color name="recents_task_bar_light_icon_color">#ccffffff</color>
+    <!-- The recents task bar dark dismiss icon color to be drawn on top of light backgrounds. -->
+    <color name="recents_task_bar_dark_icon_color">#99000000</color>
+    <!-- The lock to task button background color. -->
+    <color name="recents_task_view_lock_to_app_button_background_color">#ffe6e6e6</color>
+    <!-- The lock to task button foreground color. -->
+    <color name="recents_task_view_lock_to_app_button_color">#ff666666</color>
+    <!-- The background color for the freeform workspace. -->
+    <color name="recents_freeform_workspace_bg_color">#33FFFFFF</color>
+
+    <!-- The background color for clear all button on light backgrounds if not transparent. -->
+    <color name="recents_clear_all_button_bg_light_color">#CCFFFFFF</color>
+    <!-- The background color for clear all button on dark backgrounds if not transparent. -->
+    <color name="recents_clear_all_button_bg_dark_color">#CC000000</color>
+
+    <!-- Shadow color for the first pixels around the fake shadow for recents. -->
+    <color name="fake_shadow_start_color">#44000000</color>
+
+    <!-- Shadow color for the furthest pixels around the fake shadow for recents. -->
+    <color name="fake_shadow_end_color">#03000000</color>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/legacy/recents/res/values/config.xml b/packages/SystemUI/legacy/recents/res/values/config.xml
new file mode 100644
index 0000000..2ff9abf
--- /dev/null
+++ b/packages/SystemUI/legacy/recents/res/values/config.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2009, 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+     for different hardware and product builds. -->
+<resources>
+
+    <!-- Component to be used as the recents implementation.  Must implement the
+     RecentsImplementation interface.  This name is in the ComponentName flattened format
+     (package/class)  -->
+    <string name="config_recentsComponent" translatable="false">com.android.systemui.recents.LegacyRecentsImpl</string>
+
+    <!-- Whether recents should use hardware layers for its taskviews. This flag can be enabled
+    for devices where the java drawing of round rects may be slow -->
+    <bool name="config_recents_use_hardware_layers">false</bool>
+
+    <!-- The number of app thumbnails we keep in memory -->
+    <integer name="config_recents_max_thumbnail_count">10</integer>
+
+    <!-- The number of app icons we keep in memory -->
+    <integer name="config_recents_max_icon_count">20</integer>
+
+    <!-- Whether to use cheap, less good looking shadows for recents -->
+    <bool name="config_recents_fake_shadows">false</bool>
+
+    <!-- The duration in seconds to wait before the dismiss buttons are shown. -->
+    <integer name="recents_task_bar_dismiss_delay_seconds">1000</integer>
+
+    <!-- The duration for animating the task decorations in after transitioning from an app. -->
+    <integer name="recents_task_enter_from_app_duration">200</integer>
+
+    <!-- The duration for animating the task decorations in after transitioning from an app. -->
+    <integer name="recents_task_enter_from_affiliated_app_duration">125</integer>
+
+    <!-- The duration for animating the task decorations out before transitioning to an app. -->
+    <integer name="recents_task_exit_to_app_duration">125</integer>
+
+    <!-- The min animation duration for animating the nav bar scrim in. -->
+    <integer name="recents_nav_bar_scrim_enter_duration">400</integer>
+
+    <!-- The animation duration for scrolling the stack to a particular item. -->
+    <integer name="recents_animate_task_stack_scroll_duration">200</integer>
+
+    <!-- The delay to enforce between each alt-tab key press. -->
+    <integer name="recents_alt_tab_key_delay">200</integer>
+
+    <!-- Svelte specific logic, see RecentsConfiguration.SVELTE_* constants. -->
+    <integer name="recents_svelte_level">0</integer>
+
+    <!-- Recents: The relative range of visible tasks from the current scroll position
+         while the stack is focused. -->
+    <item name="recents_layout_focused_range_min" format="float" type="integer">-3</item>
+    <item name="recents_layout_focused_range_max" format="float" type="integer">2</item>
+
+    <!-- Recents: The relative range of visible tasks from the current scroll position
+         while the stack is not focused. -->
+    <item name="recents_layout_unfocused_range_min" format="float" type="integer">-2</item>
+    <item name="recents_layout_unfocused_range_max" format="float" type="integer">2.5</item>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/legacy/recents/res/values/dimens.xml b/packages/SystemUI/legacy/recents/res/values/dimens.xml
new file mode 100644
index 0000000..528610e4
--- /dev/null
+++ b/packages/SystemUI/legacy/recents/res/values/dimens.xml
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (c) 2006, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+-->
+<resources>
+<!-- Recents Layout -->
+
+    <!-- The amount to inset the stack, specifically at the top and the other sides.  We also
+         don't want this to change across configurations that Recents can be opened in, so we
+         define them statically for all display sizes. -->
+    <dimen name="recents_layout_min_margin">16dp</dimen>
+    <dimen name="recents_layout_top_margin_phone">16dp</dimen>
+    <dimen name="recents_layout_top_margin_tablet">32dp</dimen>
+    <dimen name="recents_layout_top_margin_tablet_xlarge">40dp</dimen>
+    <dimen name="recents_layout_bottom_margin">16dp</dimen>
+    <dimen name="recents_layout_side_margin_phone">16dp</dimen>
+    <dimen name="recents_layout_side_margin_tablet">48dp</dimen>
+    <dimen name="recents_layout_side_margin_tablet_docked">16dp</dimen>
+    <dimen name="recents_layout_side_margin_tablet_xlarge">64dp</dimen>
+    <dimen name="recents_layout_side_margin_tablet_xlarge_docked">16dp</dimen>
+
+    <!-- The height between the top margin and the top of the focused task. -->
+    <dimen name="recents_layout_top_peek_size">48dp</dimen>
+    <!-- The height between the bottom margin and the top of task in front of the focused task. -->
+    <dimen name="recents_layout_bottom_peek_size">56dp</dimen>
+
+    <!-- The offset from the top and bottom of the stack of the focused task.  The bottom offset
+         will be additionally offset by the bottom system insets since it goes under the nav bar
+         in certain orientations. -->
+    <dimen name="recents_layout_initial_top_offset_phone_port">128dp</dimen>
+    <dimen name="recents_layout_initial_bottom_offset_phone_port">80dp</dimen>
+    <dimen name="recents_layout_initial_top_offset_phone_land">72dp</dimen>
+    <dimen name="recents_layout_initial_bottom_offset_phone_land">72dp</dimen>
+    <dimen name="recents_layout_initial_top_offset_tablet">160dp</dimen>
+    <dimen name="recents_layout_initial_bottom_offset_tablet">112dp</dimen>
+
+    <!-- The min/max translationZ for the tasks in the stack. -->
+    <dimen name="recents_layout_z_min">3dp</dimen>
+    <dimen name="recents_layout_z_max">24dp</dimen>
+
+    <!-- The margin between the freeform and stack.  We also don't want this to change across
+         configurations that Recents can be opened in, so we define them statically for all
+         display sizes. -->
+    <dimen name="recents_freeform_layout_bottom_margin">16dp</dimen>
+
+    <!-- The padding between each freeform task. -->
+    <dimen name="recents_freeform_layout_task_padding">8dp</dimen>
+
+<!-- Recents Views -->
+
+    <!-- The height of a task view bar.  This has to be large enough to cover the action bar
+         height in either orientation at this smallest width. -->
+    <dimen name="recents_task_view_header_height">56dp</dimen>
+    <dimen name="recents_task_view_header_height_tablet_land">64dp</dimen>
+
+    <!-- The padding of a button in the recents task view header. -->
+    <dimen name="recents_task_view_header_button_padding">16dp</dimen>
+    <dimen name="recents_task_view_header_button_padding_tablet_land">20dp</dimen>
+
+    <!-- The radius of the rounded corners on a task view and its shadow (which can be larger
+         to create a softer corner effect. -->
+    <dimen name="recents_task_view_rounded_corners_radius">2dp</dimen>
+    <dimen name="recents_task_view_shadow_rounded_corners_radius">6dp</dimen>
+
+    <!-- The amount of highlight to make on each task view. -->
+    <dimen name="recents_task_view_highlight">1dp</dimen>
+
+    <!-- The size of the lock-to-app button and its icon. -->
+    <dimen name="recents_lock_to_app_size">56dp</dimen>
+    <dimen name="recents_lock_to_app_icon_size">28dp</dimen>
+
+    <!-- The amount of overscroll allowed when flinging to the end of the stack. -->
+    <dimen name="recents_fling_overscroll_distance">24dp</dimen>
+
+    <!-- The size of the drag hint text. -->
+    <dimen name="recents_drag_hint_text_size">14sp</dimen>
+
+    <!-- The min alpha to apply to a task affiliation group color. -->
+    <item name="recents_task_affiliation_color_min_alpha_percentage" format="float" type="dimen">0.6</item>
+
+    <!-- The amount to offset when animating into an affiliate group. -->
+    <dimen name="recents_task_stack_animation_affiliate_enter_offset">32dp</dimen>
+
+    <!-- The offsets the tasks animate from when recents is launched while docking -->
+    <dimen name="recents_task_stack_animation_launched_while_docking_offset">144dp</dimen>
+
+    <!-- The amount to translate when animating the removal of a task. -->
+    <dimen name="recents_task_view_remove_anim_translation_x">100dp</dimen>
+
+    <!-- The alpha to apply to the recents row when it doesn't have focus -->
+    <item name="recents_recents_row_dim_alpha" format="float" type="dimen">0.5</item>
+
+    <!-- The speed in dp/s at which the user needs to be scrolling in recents such that we start
+         loading full resolution screenshots. -->
+    <dimen name="recents_fast_fling_velocity">600dp</dimen>
+
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/res/values/dimens_grid.xml b/packages/SystemUI/legacy/recents/res/values/dimens_grid.xml
similarity index 100%
rename from packages/SystemUI/res/values/dimens_grid.xml
rename to packages/SystemUI/legacy/recents/res/values/dimens_grid.xml
diff --git a/packages/SystemUI/legacy/recents/res/values/strings.xml b/packages/SystemUI/legacy/recents/res/values/strings.xml
new file mode 100644
index 0000000..4b44ba9
--- /dev/null
+++ b/packages/SystemUI/legacy/recents/res/values/strings.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2009, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+	
+    <!-- Content description for the recent apps panel (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_desc_recent_apps">Overview.</string>
+
+    <!-- Content description to tell the user that this button will remove an application from recents -->
+    <string name="accessibility_recents_item_will_be_dismissed">Dismiss <xliff:g id="app" example="Calendar">%s</xliff:g>.</string>
+    <!-- Content description to tell the user an application has been removed from recents -->
+    <string name="accessibility_recents_item_dismissed"><xliff:g id="app" example="Calendar">%s</xliff:g> dismissed.</string>
+    <!-- Content description to tell the user all applications has been removed from recents -->
+    <string name="accessibility_recents_all_items_dismissed">All recent applications dismissed.</string>
+    <!-- Content description to tell the user that this button will open application info for an application in recents -->
+    <string name="accessibility_recents_item_open_app_info">Open <xliff:g id="app" example="Calendar">%s</xliff:g> application info.</string>
+    <!-- Content description to tell the user an application has been launched from recents -->
+    <string name="accessibility_recents_item_launched">Starting <xliff:g id="app" example="Calendar">%s</xliff:g>.</string>
+
+    <!-- Recents: The empty recents string. [CHAR LIMIT=NONE] -->
+    <string name="recents_empty_message">No recent items</string>
+    <!-- Recents: The empty recents string after dismissing all tasks. [CHAR LIMIT=NONE] -->
+    <string name="recents_empty_message_dismissed_all">You\'ve cleared everything</string>
+    <!-- Recents: The info panel app info button string. [CHAR LIMIT=NONE] -->
+    <string name="recents_app_info_button_label">Application Info</string>
+    <!-- Recents: The screen pinning button. [CHAR LIMIT=NONE] -->
+    <string name="recents_lock_to_app_button_label">screen pinning</string>
+    <!-- Recents: Temporary string for the button in the recents search bar. [CHAR LIMIT=NONE] -->
+    <string name="recents_search_bar_label">search</string>
+    <!-- Recents: Launch error string. [CHAR LIMIT=NONE] -->
+    <string name="recents_launch_error_message">Could not start <xliff:g id="app" example="Calendar">%s</xliff:g>.</string>
+    <!-- Recents: Launch disabled string. [CHAR LIMIT=NONE] -->
+    <string name="recents_launch_disabled_message"><xliff:g id="app" example="Calendar">%s</xliff:g> is disabled in safe-mode.</string>
+    <!-- Recents: Stack action button string. [CHAR LIMIT=NONE] -->
+    <string name="recents_stack_action_button_label">Clear all</string>
+    <!-- Recents: Hint text that shows on the drop targets to start multiwindow. [CHAR LIMIT=NONE] -->
+    <string name="recents_drag_hint_message">Drag here to use split screen</string>
+
+    <!-- Recents: MultiStack add stack split horizontal radio button. [CHAR LIMIT=NONE] -->
+    <string name="recents_multistack_add_stack_dialog_split_horizontal">Split Horizontal</string>
+    <!-- Recents: MultiStack add stack split vertical radio button. [CHAR LIMIT=NONE] -->
+    <string name="recents_multistack_add_stack_dialog_split_vertical">Split Vertical</string>
+    <!-- Recents: MultiStack add stack split custom radio button. [CHAR LIMIT=NONE] -->
+    <string name="recents_multistack_add_stack_dialog_split_custom">Split Custom</string>
+    <!-- Recents: Accessibility split to the top -->
+    <string name="recents_accessibility_split_screen_top">Split screen to the top</string>
+    <!-- Recents: Accessibility split to the left -->
+    <string name="recents_accessibility_split_screen_left">Split screen to the left</string>
+    <!-- Recents: Accessibility split to the right -->
+    <string name="recents_accessibility_split_screen_right">Split screen to the right</string>
+
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/legacy/recents/res/values/styles.xml b/packages/SystemUI/legacy/recents/res/values/styles.xml
new file mode 100644
index 0000000..eb16be7
--- /dev/null
+++ b/packages/SystemUI/legacy/recents/res/values/styles.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2006 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <style name="RecentsTheme" parent="@android:style/Theme.Material">
+        <!-- NoTitle -->
+        <item name="android:windowNoTitle">true</item>
+        <!-- Misc -->
+        <item name="android:statusBarColor">@android:color/transparent</item>
+        <item name="android:navigationBarColor">@android:color/transparent</item>
+        <item name="android:windowDrawsSystemBarBackgrounds">true</item>
+        <item name="android:windowAnimationStyle">@null</item>
+        <item name="android:ambientShadowAlpha">0.35</item>
+    </style>
+
+    <!-- Recents theme -->
+    <style name="RecentsTheme.Wallpaper">
+        <item name="android:windowBackground">@*android:color/transparent</item>
+        <item name="android:colorBackgroundCacheHint">@null</item>
+        <item name="android:windowShowWallpaper">true</item>
+        <item name="android:windowDisablePreview">true</item>
+        <item name="clearAllStyle">@style/ClearAllButtonDefaultMargins</item>
+        <item name="clearAllBackgroundColor">@color/recents_clear_all_button_bg_dark_color</item>
+        <item name="wallpaperTextColor">@*android:color/primary_text_material_dark</item>
+        <item name="wallpaperTextColorSecondary">@*android:color/secondary_text_material_dark</item>
+    </style>
+
+    <style name="RecentsTheme.Wallpaper.Light">
+        <item name="clearAllBackgroundColor">@color/recents_clear_all_button_bg_light_color</item>
+        <item name="wallpaperTextColor">@*android:color/primary_text_material_light</item>
+        <item name="wallpaperTextColorSecondary">@*android:color/secondary_text_material_light</item>
+    </style>
+
+    <!-- Performance optimized Recents theme (no wallpaper) -->
+    <style name="RecentsTheme.NoWallpaper">
+        <item name="android:windowBackground">@android:color/black</item>
+        <item name="wallpaperTextColor">@android:color/white</item>
+        <item name="wallpaperTextColorSecondary">@android:color/white</item>
+    </style>
+
+  </resources>
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Constants.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/Constants.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/Constants.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/Constants.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/IRecentsNonSystemUserCallbacks.aidl b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/IRecentsNonSystemUserCallbacks.aidl
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/IRecentsNonSystemUserCallbacks.aidl
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/IRecentsNonSystemUserCallbacks.aidl
diff --git a/packages/SystemUI/src/com/android/systemui/recents/IRecentsSystemUserCallbacks.aidl b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/IRecentsSystemUserCallbacks.aidl
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/IRecentsSystemUserCallbacks.aidl
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/IRecentsSystemUserCallbacks.aidl
diff --git a/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/LegacyRecentsImpl.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/LegacyRecentsImpl.java
new file mode 100644
index 0000000..b7bb751
--- /dev/null
+++ b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/LegacyRecentsImpl.java
@@ -0,0 +1,744 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.recents;
+
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
+import static com.android.systemui.statusbar.phone.StatusBar.SYSTEM_DIALOG_REASON_RECENT_APPS;
+
+import android.app.ActivityManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.content.pm.ActivityInfo;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.hardware.display.DisplayManager;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.util.EventLog;
+import android.util.Log;
+import android.view.Display;
+import android.widget.Toast;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.systemui.EventLogConstants;
+import com.android.systemui.EventLogTags;
+import com.android.systemui.R;
+import com.android.systemui.SysUiServiceProvider;
+import com.android.systemui.pip.PipUI;
+import com.android.systemui.recents.events.EventBus;
+import com.android.systemui.recents.events.activity.ConfigurationChangedEvent;
+import com.android.systemui.recents.events.activity.DockedFirstAnimationFrameEvent;
+import com.android.systemui.recents.events.activity.DockedTopTaskEvent;
+import com.android.systemui.recents.events.activity.LaunchTaskFailedEvent;
+import com.android.systemui.recents.events.activity.RecentsActivityStartingEvent;
+import com.android.systemui.recents.events.component.ExpandPipEvent;
+import com.android.systemui.recents.events.component.HidePipMenuEvent;
+import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
+import com.android.systemui.recents.events.component.ScreenPinningRequestEvent;
+import com.android.systemui.recents.events.component.SetWaitingForTransitionStartEvent;
+import com.android.systemui.recents.events.component.ShowUserToastEvent;
+import com.android.systemui.recents.events.ui.RecentsDrawnEvent;
+import com.android.systemui.recents.events.ui.RecentsGrowingEvent;
+import com.android.systemui.recents.misc.SystemServicesProxy;
+import com.android.systemui.recents.model.RecentsTaskLoader;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
+import com.android.systemui.stackdivider.Divider;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * An implementation of the SystemUI recents component, which supports both system and secondary
+ * users.
+ */
+public class LegacyRecentsImpl implements RecentsImplementation {
+
+    private final static String TAG = "Recents";
+
+    public final static int EVENT_BUS_PRIORITY = 1;
+    public final static int BIND_TO_SYSTEM_USER_RETRY_DELAY = 5000;
+
+    public final static Set<String> RECENTS_ACTIVITIES = new HashSet<>();
+    static {
+        RECENTS_ACTIVITIES.add(RecentsImpl.RECENTS_ACTIVITY);
+    }
+
+    private static final String COUNTER_WINDOW_SUPPORTED = "window_enter_supported";
+    private static final String COUNTER_WINDOW_UNSUPPORTED = "window_enter_unsupported";
+    private static final String COUNTER_WINDOW_INCOMPATIBLE = "window_enter_incompatible";
+
+    private static SystemServicesProxy sSystemServicesProxy;
+    private static RecentsDebugFlags sDebugFlags;
+    private static RecentsTaskLoader sTaskLoader;
+    private static RecentsConfiguration sConfiguration;
+
+    private Context mContext;
+    private SysUiServiceProvider mSysUiServiceProvider;
+    private Handler mHandler;
+    private RecentsImpl mImpl;
+
+    // Only For system user, this is the callbacks instance we return to each secondary user
+    private RecentsSystemUser mSystemToUserCallbacks;
+
+    // Only for secondary users, this is the callbacks instance provided by the system user to make
+    // calls back
+    private IRecentsSystemUserCallbacks mUserToSystemCallbacks;
+
+    // The set of runnables to run after binding to the system user's service.
+    private final ArrayList<Runnable> mOnConnectRunnables = new ArrayList<>();
+
+    // Only for secondary users, this is the death handler for the binder from the system user
+    private final IBinder.DeathRecipient mUserToSystemCallbacksDeathRcpt = new IBinder.DeathRecipient() {
+        @Override
+        public void binderDied() {
+            mUserToSystemCallbacks = null;
+            EventLog.writeEvent(EventLogTags.SYSUI_RECENTS_CONNECTION,
+                    EventLogConstants.SYSUI_RECENTS_CONNECTION_USER_SYSTEM_UNBOUND,
+                    sSystemServicesProxy.getProcessUser());
+
+            // Retry after a fixed duration
+            mHandler.postDelayed(new Runnable() {
+                @Override
+                public void run() {
+                    registerWithSystemUser();
+                }
+            }, BIND_TO_SYSTEM_USER_RETRY_DELAY);
+        }
+    };
+
+    // Only for secondary users, this is the service connection we use to connect to the system user
+    private final ServiceConnection mUserToSystemServiceConnection = new ServiceConnection() {
+        @Override
+        public void onServiceConnected(ComponentName name, IBinder service) {
+            if (service != null) {
+                mUserToSystemCallbacks = IRecentsSystemUserCallbacks.Stub.asInterface(
+                        service);
+                EventLog.writeEvent(EventLogTags.SYSUI_RECENTS_CONNECTION,
+                        EventLogConstants.SYSUI_RECENTS_CONNECTION_USER_SYSTEM_BOUND,
+                        sSystemServicesProxy.getProcessUser());
+
+                // Listen for system user's death, so that we can reconnect later
+                try {
+                    service.linkToDeath(mUserToSystemCallbacksDeathRcpt, 0);
+                } catch (RemoteException e) {
+                    Log.e(TAG, "Lost connection to (System) SystemUI", e);
+                }
+
+                // Run each of the queued runnables
+                runAndFlushOnConnectRunnables();
+            }
+
+            // Unbind ourselves now that we've registered our callbacks.  The
+            // binder to the system user are still valid at this point.
+            mContext.unbindService(this);
+        }
+
+        @Override
+        public void onServiceDisconnected(ComponentName name) {
+            // Do nothing
+        }
+    };
+
+    /**
+     * Returns the callbacks interface that non-system users can call.
+     */
+    public IBinder getSystemUserCallbacks() {
+        return mSystemToUserCallbacks;
+    }
+
+    public static RecentsTaskLoader getTaskLoader() {
+        return sTaskLoader;
+    }
+
+
+    public static SystemServicesProxy getSystemServices() {
+        return sSystemServicesProxy;
+    }
+
+    public static RecentsConfiguration getConfiguration() {
+        return sConfiguration;
+    }
+
+    public static RecentsDebugFlags getDebugFlags() {
+        return sDebugFlags;
+    }
+
+    @Override
+    public void onStart(Context context, SysUiServiceProvider sysUiServiceProvider) {
+        mContext = context;
+        mSysUiServiceProvider = sysUiServiceProvider;
+        final Resources res = mContext.getResources();
+        final int defaultTaskBarBackgroundColor =
+                mContext.getColor(R.color.recents_task_bar_default_background_color);
+        final int defaultTaskViewBackgroundColor =
+                mContext.getColor(R.color.recents_task_view_default_background_color);
+        sDebugFlags = new RecentsDebugFlags();
+        sSystemServicesProxy = SystemServicesProxy.getInstance(mContext);
+        sConfiguration = new RecentsConfiguration(mContext);
+        sTaskLoader = new RecentsTaskLoader(mContext,
+                // TODO: Once we start building the AAR, move these into the loader
+                res.getInteger(R.integer.config_recents_max_thumbnail_count),
+                res.getInteger(R.integer.config_recents_max_icon_count),
+                res.getInteger(R.integer.recents_svelte_level));
+        sTaskLoader.setDefaultColors(defaultTaskBarBackgroundColor, defaultTaskViewBackgroundColor);
+        mHandler = new Handler();
+        mImpl = new RecentsImpl(mContext);
+
+        // Register with the event bus
+        EventBus.getDefault().register(this, EVENT_BUS_PRIORITY);
+        EventBus.getDefault().register(sSystemServicesProxy, EVENT_BUS_PRIORITY);
+        EventBus.getDefault().register(sTaskLoader, EVENT_BUS_PRIORITY);
+
+        // Due to the fact that RecentsActivity is per-user, we need to establish and interface for
+        // the system user's Recents component to pass events (like show/hide/toggleRecents) to the
+        // secondary user, and vice versa (like visibility change, screen pinning).
+        final int processUser = sSystemServicesProxy.getProcessUser();
+        if (sSystemServicesProxy.isSystemUser(processUser)) {
+            // For the system user, initialize an instance of the interface that we can pass to the
+            // secondary user
+            mSystemToUserCallbacks = new RecentsSystemUser(mContext, mImpl);
+        } else {
+            // For the secondary user, bind to the primary user's service to get a persistent
+            // interface to register its implementation and to later update its state
+            registerWithSystemUser();
+        }
+    }
+
+    @Override
+    public void onBootCompleted() {
+        mImpl.onBootCompleted();
+    }
+
+
+    @Override
+    public void growRecents() {
+        EventBus.getDefault().send(new RecentsGrowingEvent());
+    }
+
+    /**
+     * Shows the Recents.
+     */
+    @Override
+    public void showRecentApps(boolean triggeredFromAltTab) {
+        ActivityManagerWrapper.getInstance().closeSystemWindows(SYSTEM_DIALOG_REASON_RECENT_APPS);
+        int recentsGrowTarget = getComponent(Divider.class).getView().growsRecents();
+        int currentUser = sSystemServicesProxy.getCurrentUser();
+        if (sSystemServicesProxy.isSystemUser(currentUser)) {
+            mImpl.showRecents(triggeredFromAltTab, false /* draggingInRecents */,
+                    true /* animate */, recentsGrowTarget);
+        } else {
+            if (mSystemToUserCallbacks != null) {
+                IRecentsNonSystemUserCallbacks callbacks =
+                        mSystemToUserCallbacks.getNonSystemUserRecentsForUser(currentUser);
+                if (callbacks != null) {
+                    try {
+                        callbacks.showRecents(triggeredFromAltTab, false /* draggingInRecents */,
+                                true /* animate */, recentsGrowTarget);
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "Callback failed", e);
+                    }
+                } else {
+                    Log.e(TAG, "No SystemUI callbacks found for user: " + currentUser);
+                }
+            }
+        }
+    }
+
+    /**
+     * Hides the Recents.
+     */
+    @Override
+    public void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) {
+        int currentUser = sSystemServicesProxy.getCurrentUser();
+        if (sSystemServicesProxy.isSystemUser(currentUser)) {
+            mImpl.hideRecents(triggeredFromAltTab, triggeredFromHomeKey);
+        } else {
+            if (mSystemToUserCallbacks != null) {
+                IRecentsNonSystemUserCallbacks callbacks =
+                        mSystemToUserCallbacks.getNonSystemUserRecentsForUser(currentUser);
+                if (callbacks != null) {
+                    try {
+                        callbacks.hideRecents(triggeredFromAltTab, triggeredFromHomeKey);
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "Callback failed", e);
+                    }
+                } else {
+                    Log.e(TAG, "No SystemUI callbacks found for user: " + currentUser);
+                }
+            }
+        }
+    }
+
+    /**
+     * Toggles the Recents activity.
+     */
+    @Override
+    public void toggleRecentApps() {
+        int growTarget = getComponent(Divider.class).getView().growsRecents();
+        int currentUser = sSystemServicesProxy.getCurrentUser();
+        if (sSystemServicesProxy.isSystemUser(currentUser)) {
+            mImpl.toggleRecents(growTarget);
+        } else {
+            if (mSystemToUserCallbacks != null) {
+                IRecentsNonSystemUserCallbacks callbacks =
+                        mSystemToUserCallbacks.getNonSystemUserRecentsForUser(currentUser);
+                if (callbacks != null) {
+                    try {
+                        callbacks.toggleRecents(growTarget);
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "Callback failed", e);
+                    }
+                } else {
+                    Log.e(TAG, "No SystemUI callbacks found for user: " + currentUser);
+                }
+            }
+        }
+    }
+
+    /**
+     * Preloads info for the Recents activity.
+     */
+    @Override
+    public void preloadRecentApps() {
+        int currentUser = sSystemServicesProxy.getCurrentUser();
+        if (sSystemServicesProxy.isSystemUser(currentUser)) {
+            mImpl.preloadRecents();
+        } else {
+            if (mSystemToUserCallbacks != null) {
+                IRecentsNonSystemUserCallbacks callbacks =
+                        mSystemToUserCallbacks.getNonSystemUserRecentsForUser(currentUser);
+                if (callbacks != null) {
+                    try {
+                        callbacks.preloadRecents();
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "Callback failed", e);
+                    }
+                } else {
+                    Log.e(TAG, "No SystemUI callbacks found for user: " + currentUser);
+                }
+            }
+        }
+    }
+
+    @Override
+    public void cancelPreloadRecentApps() {
+        int currentUser = sSystemServicesProxy.getCurrentUser();
+        if (sSystemServicesProxy.isSystemUser(currentUser)) {
+            mImpl.cancelPreloadingRecents();
+        } else {
+            if (mSystemToUserCallbacks != null) {
+                IRecentsNonSystemUserCallbacks callbacks =
+                        mSystemToUserCallbacks.getNonSystemUserRecentsForUser(currentUser);
+                if (callbacks != null) {
+                    try {
+                        callbacks.cancelPreloadingRecents();
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "Callback failed", e);
+                    }
+                } else {
+                    Log.e(TAG, "No SystemUI callbacks found for user: " + currentUser);
+                }
+            }
+        }
+    }
+
+    @Override
+    public boolean splitPrimaryTask(int stackCreateMode, Rect initialBounds, int metricsDockAction) {
+        Point realSize = new Point();
+        if (initialBounds == null) {
+            mContext.getSystemService(DisplayManager.class).getDisplay(Display.DEFAULT_DISPLAY)
+                    .getRealSize(realSize);
+            initialBounds = new Rect(0, 0, realSize.x, realSize.y);
+        }
+
+        int currentUser = sSystemServicesProxy.getCurrentUser();
+        ActivityManager.RunningTaskInfo runningTask =
+                ActivityManagerWrapper.getInstance().getRunningTask();
+        final int activityType = runningTask != null
+                ? runningTask.configuration.windowConfiguration.getActivityType()
+                : ACTIVITY_TYPE_UNDEFINED;
+        boolean screenPinningActive = ActivityManagerWrapper.getInstance().isScreenPinningActive();
+        boolean isRunningTaskInHomeOrRecentsStack =
+                activityType == ACTIVITY_TYPE_HOME || activityType == ACTIVITY_TYPE_RECENTS;
+        if (runningTask != null && !isRunningTaskInHomeOrRecentsStack && !screenPinningActive) {
+            logDockAttempt(mContext, runningTask.topActivity, runningTask.resizeMode);
+            if (runningTask.supportsSplitScreenMultiWindow) {
+                if (metricsDockAction != -1) {
+                    MetricsLogger.action(mContext, metricsDockAction,
+                            runningTask.topActivity.flattenToShortString());
+                }
+                if (sSystemServicesProxy.isSystemUser(currentUser)) {
+                    mImpl.splitPrimaryTask(runningTask.id, stackCreateMode, initialBounds);
+                } else {
+                    if (mSystemToUserCallbacks != null) {
+                        IRecentsNonSystemUserCallbacks callbacks =
+                                mSystemToUserCallbacks.getNonSystemUserRecentsForUser(currentUser);
+                        if (callbacks != null) {
+                            try {
+                                callbacks.splitPrimaryTask(runningTask.id, stackCreateMode,
+                                        initialBounds);
+                            } catch (RemoteException e) {
+                                Log.e(TAG, "Callback failed", e);
+                            }
+                        } else {
+                            Log.e(TAG, "No SystemUI callbacks found for user: " + currentUser);
+                        }
+                    }
+                }
+
+                return true;
+            } else {
+                EventBus.getDefault().send(new ShowUserToastEvent(
+                        R.string.dock_non_resizeble_failed_to_dock_text, Toast.LENGTH_SHORT));
+                return false;
+            }
+        } else {
+            return false;
+        }
+    }
+
+    public static void logDockAttempt(Context ctx, ComponentName activity, int resizeMode) {
+        if (resizeMode == ActivityInfo.RESIZE_MODE_UNRESIZEABLE) {
+            MetricsLogger.action(ctx, MetricsEvent.ACTION_WINDOW_DOCK_UNRESIZABLE,
+                    activity.flattenToShortString());
+        }
+        MetricsLogger.count(ctx, getMetricsCounterForResizeMode(resizeMode), 1);
+    }
+
+    private static String getMetricsCounterForResizeMode(int resizeMode) {
+        switch (resizeMode) {
+            case ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE:
+                return COUNTER_WINDOW_UNSUPPORTED;
+            case ActivityInfo.RESIZE_MODE_RESIZEABLE:
+            case ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION:
+                return COUNTER_WINDOW_SUPPORTED;
+            default:
+                return COUNTER_WINDOW_INCOMPATIBLE;
+        }
+    }
+
+    @Override
+    public void onAppTransitionFinished() {
+        if (!LegacyRecentsImpl.getConfiguration().isLowRamDevice) {
+            // Fallback, reset the flag once an app transition ends
+            EventBus.getDefault().send(new SetWaitingForTransitionStartEvent(
+                    false /* waitingForTransitionStart */));
+        }
+    }
+
+    /**
+     * Updates on configuration change.
+     */
+    public void onConfigurationChanged(Configuration newConfig) {
+        int currentUser = sSystemServicesProxy.getCurrentUser();
+        if (sSystemServicesProxy.isSystemUser(currentUser)) {
+            mImpl.onConfigurationChanged();
+        } else {
+            if (mSystemToUserCallbacks != null) {
+                IRecentsNonSystemUserCallbacks callbacks =
+                        mSystemToUserCallbacks.getNonSystemUserRecentsForUser(currentUser);
+                if (callbacks != null) {
+                    try {
+                        callbacks.onConfigurationChanged();
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "Callback failed", e);
+                    }
+                } else {
+                    Log.e(TAG, "No SystemUI callbacks found for user: " + currentUser);
+                }
+            }
+        }
+    }
+
+    /**
+     * Handle Recents activity visibility changed.
+     */
+    public final void onBusEvent(final RecentsVisibilityChangedEvent event) {
+        SystemServicesProxy ssp = LegacyRecentsImpl.getSystemServices();
+        int processUser = ssp.getProcessUser();
+        if (ssp.isSystemUser(processUser)) {
+            mImpl.onVisibilityChanged(event.applicationContext, event.visible);
+        } else {
+            postToSystemUser(new Runnable() {
+                @Override
+                public void run() {
+                    try {
+                        mUserToSystemCallbacks.updateRecentsVisibility(event.visible);
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "Callback failed", e);
+                    }
+                }
+            });
+        }
+
+        // This will catch the cases when a user launches from recents to another app
+        // (and vice versa) that is not in the recents stack (such as home or bugreport) and it
+        // would not reset the wait for transition flag. This will catch it and make sure that the
+        // flag is reset.
+        if (!event.visible) {
+            mImpl.setWaitingForTransitionStart(false);
+        }
+    }
+
+    public final void onBusEvent(DockedFirstAnimationFrameEvent event) {
+        SystemServicesProxy ssp = LegacyRecentsImpl.getSystemServices();
+        int processUser = ssp.getProcessUser();
+        if (ssp.isSystemUser(processUser)) {
+            final Divider divider = getComponent(Divider.class);
+            if (divider != null) {
+                divider.onDockedFirstAnimationFrame();
+            }
+        } else {
+            postToSystemUser(new Runnable() {
+                @Override
+                public void run() {
+                    try {
+                        mUserToSystemCallbacks.sendDockedFirstAnimationFrameEvent();
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "Callback failed", e);
+                    }
+                }
+            });
+        }
+    }
+
+    /**
+     * Handle screen pinning request.
+     */
+    public final void onBusEvent(final ScreenPinningRequestEvent event) {
+        int processUser = sSystemServicesProxy.getProcessUser();
+        if (sSystemServicesProxy.isSystemUser(processUser)) {
+            mImpl.onStartScreenPinning(event.applicationContext, event.taskId);
+        } else {
+            postToSystemUser(new Runnable() {
+                @Override
+                public void run() {
+                    try {
+                        mUserToSystemCallbacks.startScreenPinning(event.taskId);
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "Callback failed", e);
+                    }
+                }
+            });
+        }
+    }
+
+    public final void onBusEvent(final RecentsDrawnEvent event) {
+        int processUser = sSystemServicesProxy.getProcessUser();
+        if (sSystemServicesProxy.isSystemUser(processUser)) {
+            final Divider divider = getComponent(Divider.class);
+            if (divider != null) {
+                divider.onRecentsDrawn();
+            }
+        } else {
+            postToSystemUser(new Runnable() {
+                @Override
+                public void run() {
+                    try {
+                        mUserToSystemCallbacks.sendRecentsDrawnEvent();
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "Callback failed", e);
+                    }
+                }
+            });
+        }
+    }
+
+    public final void onBusEvent(final DockedTopTaskEvent event) {
+        int processUser = sSystemServicesProxy.getProcessUser();
+        if (sSystemServicesProxy.isSystemUser(processUser)) {
+            final Divider divider = getComponent(Divider.class);
+            if (divider != null) {
+                divider.onDockedTopTask();
+            }
+        } else {
+            postToSystemUser(new Runnable() {
+                @Override
+                public void run() {
+                    try {
+                        mUserToSystemCallbacks.sendDockingTopTaskEvent(event.initialRect);
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "Callback failed", e);
+                    }
+                }
+            });
+        }
+    }
+
+    public final void onBusEvent(final RecentsActivityStartingEvent event) {
+        int processUser = sSystemServicesProxy.getProcessUser();
+        if (sSystemServicesProxy.isSystemUser(processUser)) {
+            final Divider divider = getComponent(Divider.class);
+            if (divider != null) {
+                divider.onRecentsActivityStarting();
+            }
+        } else {
+            postToSystemUser(new Runnable() {
+                @Override
+                public void run() {
+                    try {
+                        mUserToSystemCallbacks.sendLaunchRecentsEvent();
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "Callback failed", e);
+                    }
+                }
+            });
+        }
+    }
+
+    public final void onBusEvent(LaunchTaskFailedEvent event) {
+        // Reset the transition when tasks fail to launch
+        mImpl.setWaitingForTransitionStart(false);
+    }
+
+    public final void onBusEvent(ConfigurationChangedEvent event) {
+        // Update the configuration for the Recents component when the activity configuration
+        // changes as well
+        mImpl.onConfigurationChanged();
+    }
+
+    public final void onBusEvent(ShowUserToastEvent event) {
+        int currentUser = sSystemServicesProxy.getCurrentUser();
+        if (sSystemServicesProxy.isSystemUser(currentUser)) {
+            mImpl.onShowCurrentUserToast(event.msgResId, event.msgLength);
+        } else {
+            if (mSystemToUserCallbacks != null) {
+                IRecentsNonSystemUserCallbacks callbacks =
+                        mSystemToUserCallbacks.getNonSystemUserRecentsForUser(currentUser);
+                if (callbacks != null) {
+                    try {
+                        callbacks.showCurrentUserToast(event.msgResId, event.msgLength);
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "Callback failed", e);
+                    }
+                } else {
+                    Log.e(TAG, "No SystemUI callbacks found for user: " + currentUser);
+                }
+            }
+        }
+    }
+
+    public final void onBusEvent(SetWaitingForTransitionStartEvent event) {
+        int processUser = sSystemServicesProxy.getProcessUser();
+        if (sSystemServicesProxy.isSystemUser(processUser)) {
+            mImpl.setWaitingForTransitionStart(event.waitingForTransitionStart);
+        } else {
+            postToSystemUser(new Runnable() {
+                @Override
+                public void run() {
+                    try {
+                        mUserToSystemCallbacks.setWaitingForTransitionStartEvent(
+                                event.waitingForTransitionStart);
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "Callback failed", e);
+                    }
+                }
+            });
+        }
+    }
+
+    public final void onBusEvent(ExpandPipEvent event) {
+        PipUI pipUi = getComponent(PipUI.class);
+        pipUi.expandPip();
+    }
+
+    public final void onBusEvent(HidePipMenuEvent event) {
+        PipUI pipUi = getComponent(PipUI.class);
+        event.getAnimationTrigger().increment();
+        pipUi.hidePipMenu(() -> {
+                event.getAnimationTrigger().increment();
+            }, () -> {
+                event.getAnimationTrigger().decrement();
+            });
+        event.getAnimationTrigger().decrement();
+    }
+
+    /**
+     * Attempts to register with the system user.
+     */
+    private void registerWithSystemUser() {
+        final int processUser = sSystemServicesProxy.getProcessUser();
+        postToSystemUser(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    mUserToSystemCallbacks.registerNonSystemUserCallbacks(
+                            new RecentsImplProxy(mImpl), processUser);
+                } catch (RemoteException e) {
+                    Log.e(TAG, "Failed to register", e);
+                }
+            }
+        });
+    }
+
+    /**
+     * Runs the runnable in the system user's Recents context, connecting to the service if
+     * necessary.
+     */
+    private void postToSystemUser(final Runnable onConnectRunnable) {
+        mOnConnectRunnables.add(onConnectRunnable);
+        if (mUserToSystemCallbacks == null) {
+            Intent systemUserServiceIntent = new Intent();
+            systemUserServiceIntent.setClass(mContext, RecentsSystemUserService.class);
+            boolean bound = mContext.bindServiceAsUser(systemUserServiceIntent,
+                    mUserToSystemServiceConnection, Context.BIND_AUTO_CREATE, UserHandle.SYSTEM);
+            EventLog.writeEvent(EventLogTags.SYSUI_RECENTS_CONNECTION,
+                    EventLogConstants.SYSUI_RECENTS_CONNECTION_USER_BIND_SERVICE,
+                    sSystemServicesProxy.getProcessUser());
+            if (!bound) {
+                // Retry after a fixed duration
+                mHandler.postDelayed(new Runnable() {
+                    @Override
+                    public void run() {
+                        registerWithSystemUser();
+                    }
+                }, BIND_TO_SYSTEM_USER_RETRY_DELAY);
+            }
+        } else {
+            runAndFlushOnConnectRunnables();
+        }
+    }
+
+    /**
+     * Runs all the queued runnables after a service connection is made.
+     */
+    private void runAndFlushOnConnectRunnables() {
+        for (Runnable r : mOnConnectRunnables) {
+            r.run();
+        }
+        mOnConnectRunnables.clear();
+    }
+
+    private <T> T getComponent(Class<T> clazz) {
+        return mSysUiServiceProvider.getComponent(clazz);
+    }
+
+    @Override
+    public void dump(PrintWriter pw) {
+        pw.println("Recents");
+        pw.println("  currentUserId=" + SystemServicesProxy.getInstance(mContext).getCurrentUser());
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/RecentsActivity.java
similarity index 94%
rename from packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/RecentsActivity.java
index 36a1255..cec97ab 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/RecentsActivity.java
@@ -87,16 +87,15 @@
 import com.android.systemui.recents.events.ui.focus.NavigateTaskViewEvent;
 import com.android.systemui.recents.events.ui.focus.NavigateTaskViewEvent.Direction;
 import com.android.systemui.recents.misc.SystemServicesProxy;
-import com.android.systemui.shared.recents.utilities.Utilities;
-import com.android.systemui.shared.recents.model.RecentsTaskLoadPlan;
-import com.android.systemui.shared.recents.model.RecentsTaskLoader;
+import com.android.systemui.recents.utilities.Utilities;
+import com.android.systemui.recents.model.RecentsTaskLoadPlan;
+import com.android.systemui.recents.model.RecentsTaskLoader;
 import com.android.systemui.shared.recents.model.Task;
-import com.android.systemui.shared.recents.model.TaskStack;
+import com.android.systemui.recents.model.TaskStack;
 import com.android.systemui.recents.views.RecentsView;
 import com.android.systemui.recents.views.SystemBarScrimViews;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 
-import com.android.systemui.shared.system.WindowManagerWrapper;
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 
@@ -109,7 +108,7 @@
     private final static String TAG = "RecentsActivity";
     private final static boolean DEBUG = false;
 
-    public final static int EVENT_BUS_PRIORITY = Recents.EVENT_BUS_PRIORITY + 1;
+    public final static int EVENT_BUS_PRIORITY = LegacyRecentsImpl.EVENT_BUS_PRIORITY + 1;
     public final static int INCOMPATIBLE_APP_ALPHA_DURATION = 150;
 
     private PackageMonitor mPackageMonitor = new PackageMonitor() {
@@ -217,8 +216,8 @@
                                 LatencyTracker.ACTION_TOGGLE_RECENTS));
                     }
                     DejankUtils.postAfterTraversal(() -> {
-                        Recents.getTaskLoader().startLoader(RecentsActivity.this);
-                        Recents.getTaskLoader().getHighResThumbnailLoader().setVisible(true);
+                        LegacyRecentsImpl.getTaskLoader().startLoader(RecentsActivity.this);
+                        LegacyRecentsImpl.getTaskLoader().getHighResThumbnailLoader().setVisible(true);
                     });
                     return true;
                 }
@@ -228,7 +227,7 @@
      * Dismisses recents if we are already visible and the intent is to toggle the recents view.
      */
     boolean dismissRecentsToFocusedTask(int logCategory) {
-        SystemServicesProxy ssp = Recents.getSystemServices();
+        SystemServicesProxy ssp = LegacyRecentsImpl.getSystemServices();
         if (ssp.isRecentsActivityVisible()) {
             // If we have a focused Task, launch that Task now
             if (mRecentsView.launchFocusedTask(logCategory)) return true;
@@ -240,7 +239,7 @@
      * Dismisses recents back to the launch target task.
      */
     boolean dismissRecentsToLaunchTargetTaskOrHome() {
-        SystemServicesProxy ssp = Recents.getSystemServices();
+        SystemServicesProxy ssp = LegacyRecentsImpl.getSystemServices();
         if (ssp.isRecentsActivityVisible()) {
             // If we have a focused Task, launch that Task now
             if (mRecentsView.launchPreviousTask()) return true;
@@ -254,7 +253,7 @@
      * Dismisses recents if we are already visible and the intent is to toggle the recents view.
      */
     boolean dismissRecentsToFocusedTaskOrHome() {
-        SystemServicesProxy ssp = Recents.getSystemServices();
+        SystemServicesProxy ssp = LegacyRecentsImpl.getSystemServices();
         if (ssp.isRecentsActivityVisible()) {
             // If we have a focused Task, launch that Task now
             if (mRecentsView.launchFocusedTask(0 /* logCategory */)) return true;
@@ -289,7 +288,7 @@
 
     /** Dismisses Recents directly to Home if we currently aren't transitioning. */
     boolean dismissRecentsToHomeIfVisible(boolean animated) {
-        SystemServicesProxy ssp = Recents.getSystemServices();
+        SystemServicesProxy ssp = LegacyRecentsImpl.getSystemServices();
         if (ssp.isRecentsActivityVisible()) {
             // Return to Home
             dismissRecentsToHome(animated);
@@ -306,7 +305,7 @@
 
         // In the case that the activity starts up before the Recents component has initialized
         // (usually when debugging/pushing the SysUI apk), just finish this activity.
-        SystemServicesProxy ssp = Recents.getSystemServices();
+        SystemServicesProxy ssp = LegacyRecentsImpl.getSystemServices();
         if (ssp == null) {
             mFinishedOnStartup = true;
             finish();
@@ -335,7 +334,7 @@
         mScrimViews = new SystemBarScrimViews(this);
         getWindow().getAttributes().privateFlags |=
                 WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY;
-        if (Recents.getConfiguration().isLowRamDevice) {
+        if (LegacyRecentsImpl.getConfiguration().isLowRamDevice) {
             getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
         }
 
@@ -384,7 +383,7 @@
         // reset launch state with dock, app and home set to false
         Object isRelaunching = getLastNonConfigurationInstance();
         if (isRelaunching != null && isRelaunching instanceof Boolean && (boolean) isRelaunching) {
-            RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
+            RecentsActivityLaunchState launchState = LegacyRecentsImpl.getConfiguration().getLaunchState();
             launchState.launchedViaDockGesture = false;
             launchState.launchedFromApp = false;
             launchState.launchedFromHome = false;
@@ -418,14 +417,14 @@
     private void reloadStackView() {
         // If the Recents component has preloaded a load plan, then use that to prevent
         // reconstructing the task stack
-        RecentsTaskLoader loader = Recents.getTaskLoader();
+        RecentsTaskLoader loader = LegacyRecentsImpl.getTaskLoader();
         RecentsTaskLoadPlan loadPlan = RecentsImpl.consumeInstanceLoadPlan();
         if (loadPlan == null) {
             loadPlan = new RecentsTaskLoadPlan(this);
         }
 
         // Start loading tasks according to the load plan
-        RecentsConfiguration config = Recents.getConfiguration();
+        RecentsConfiguration config = LegacyRecentsImpl.getConfiguration();
         RecentsActivityLaunchState launchState = config.getLaunchState();
         if (!loadPlan.hasTasks()) {
             loader.preloadTasks(loadPlan, launchState.launchedToTaskId);
@@ -538,7 +537,7 @@
         mIsVisible = false;
         EventBus.getDefault().send(new RecentsVisibilityChangedEvent(this, false));
         MetricsLogger.hidden(this, MetricsEvent.OVERVIEW_ACTIVITY);
-        Recents.getTaskLoader().getHighResThumbnailLoader().setVisible(false);
+        LegacyRecentsImpl.getTaskLoader().getHighResThumbnailLoader().setVisible(false);
 
         // When recents starts again before onStop, do not reset launch flags so entrance animation
         // can run
@@ -546,13 +545,13 @@
             // Workaround for b/22542869, if the RecentsActivity is started again, but without going
             // through SystemUI, we need to reset the config launch flags to ensure that we do not
             // wait on the system to send a signal that was never queued.
-            RecentsConfiguration config = Recents.getConfiguration();
+            RecentsConfiguration config = LegacyRecentsImpl.getConfiguration();
             RecentsActivityLaunchState launchState = config.getLaunchState();
             launchState.reset();
         }
 
         // Force a gc to attempt to clean up bitmap references more quickly (b/38258699)
-        Recents.getSystemServices().gc();
+        LegacyRecentsImpl.getSystemServices().gc();
     }
 
     @Override
@@ -587,7 +586,7 @@
 
     @Override
     public void onTrimMemory(int level) {
-        RecentsTaskLoader loader = Recents.getTaskLoader();
+        RecentsTaskLoader loader = LegacyRecentsImpl.getTaskLoader();
         if (loader != null) {
             loader.onTrimMemory(level);
         }
@@ -656,7 +655,7 @@
     /**** EventBus events ****/
 
     public final void onBusEvent(ToggleRecentsEvent event) {
-        RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
+        RecentsActivityLaunchState launchState = LegacyRecentsImpl.getConfiguration().getLaunchState();
         if (launchState.launchedFromHome) {
             dismissRecentsToHome(true /* animateTaskViews */);
         } else {
@@ -700,7 +699,7 @@
     }
 
     public final void onBusEvent(CancelEnterRecentsWindowAnimationEvent event) {
-        RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
+        RecentsActivityLaunchState launchState = LegacyRecentsImpl.getConfiguration().getLaunchState();
         int launchToTaskId = launchState.launchedToTaskId;
         if (launchToTaskId != -1 &&
                 (event.launchTask == null || launchToTaskId != event.launchTask.key.id)) {
@@ -748,7 +747,7 @@
 
     public final void onBusEvent(DeleteTaskDataEvent event) {
         // Remove any stored data from the loader
-        RecentsTaskLoader loader = Recents.getTaskLoader();
+        RecentsTaskLoader loader = LegacyRecentsImpl.getTaskLoader();
         loader.deleteTaskData(event.task, false);
 
         // Remove the task from activity manager
@@ -760,7 +759,7 @@
     }
 
     public final void onBusEvent(AllTaskViewsDismissedEvent event) {
-        SystemServicesProxy ssp = Recents.getSystemServices();
+        SystemServicesProxy ssp = LegacyRecentsImpl.getSystemServices();
         if (ssp.hasDockedTask()) {
             mRecentsView.showEmptyView(event.msgResId);
         } else {
@@ -808,9 +807,9 @@
 
     private void reloadTaskStack(boolean isInMultiWindowMode, boolean sendConfigChangedEvent) {
         // Reload the task stack completely
-        RecentsConfiguration config = Recents.getConfiguration();
+        RecentsConfiguration config = LegacyRecentsImpl.getConfiguration();
         RecentsActivityLaunchState launchState = config.getLaunchState();
-        RecentsTaskLoader loader = Recents.getTaskLoader();
+        RecentsTaskLoader loader = LegacyRecentsImpl.getTaskLoader();
         RecentsTaskLoadPlan loadPlan = new RecentsTaskLoadPlan(this);
         loader.preloadTasks(loadPlan, -1 /* runningTaskId */);
 
@@ -839,7 +838,7 @@
     }
 
     public void onPackageChanged(String packageName, int userId) {
-        Recents.getTaskLoader().onPackageChanged(packageName);
+        LegacyRecentsImpl.getTaskLoader().onPackageChanged(packageName);
         EventBus.getDefault().send(new PackagesChangedEvent(packageName, userId));
     }
 
@@ -847,7 +846,7 @@
     public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
         super.dump(prefix, fd, writer, args);
         EventBus.getDefault().dump(prefix, writer);
-        Recents.getTaskLoader().dump(prefix, writer);
+        LegacyRecentsImpl.getTaskLoader().dump(prefix, writer);
 
         String id = Integer.toHexString(System.identityHashCode(this));
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/RecentsActivityLaunchState.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/RecentsActivityLaunchState.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/RecentsConfiguration.java
similarity index 95%
rename from packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/RecentsConfiguration.java
index 68df1d5..ee53734 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
+++ b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/RecentsConfiguration.java
@@ -26,7 +26,6 @@
 import com.android.systemui.R;
 import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.recents.views.DockState;
-import com.android.systemui.shared.recents.model.TaskStack;
 
 /**
  * Represents the dock regions for each orientation.
@@ -86,7 +85,7 @@
     public RecentsConfiguration(Context context) {
         // Load only resources that can not change after the first load either through developer
         // settings or via multi window
-        SystemServicesProxy ssp = Recents.getSystemServices();
+        SystemServicesProxy ssp = LegacyRecentsImpl.getSystemServices();
         mAppContext = context.getApplicationContext();
         Resources res = mAppContext.getResources();
         fakeShadows = res.getBoolean(R.bool.config_recents_fake_shadows);
@@ -116,7 +115,7 @@
     public DockState[] getDockStatesForCurrentOrientation() {
         boolean isLandscape = mAppContext.getResources().getConfiguration().orientation ==
                 Configuration.ORIENTATION_LANDSCAPE;
-        RecentsConfiguration config = Recents.getConfiguration();
+        RecentsConfiguration config = LegacyRecentsImpl.getConfiguration();
         if (config.isLargeScreen) {
             return isLandscape ? DockRegion.TABLET_LANDSCAPE : DockRegion.TABLET_PORTRAIT;
         } else {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/RecentsDebugFlags.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/RecentsDebugFlags.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/RecentsImpl.java
similarity index 93%
rename from packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/RecentsImpl.java
index d95c731..3e5acab 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/RecentsImpl.java
@@ -47,7 +47,6 @@
 import android.widget.Toast;
 
 import com.android.systemui.Dependency;
-import com.android.systemui.OverviewProxyService;
 import com.android.systemui.SysUiServiceProvider;
 import com.android.systemui.pip.phone.ForegroundThread;
 import com.google.android.collect.Lists;
@@ -55,7 +54,6 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.policy.DockedDividerUtils;
 import com.android.systemui.R;
-import com.android.systemui.SystemUIApplication;
 import com.android.systemui.recents.events.EventBus;
 import com.android.systemui.recents.events.activity.DockedTopTaskEvent;
 import com.android.systemui.recents.events.activity.EnterRecentsWindowLastAnimationFrameEvent;
@@ -75,11 +73,11 @@
 import com.android.systemui.recents.misc.DozeTrigger;
 import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.recents.misc.SysUiTaskStackChangeListener;
-import com.android.systemui.shared.recents.model.RecentsTaskLoadPlan;
-import com.android.systemui.shared.recents.model.RecentsTaskLoader;
+import com.android.systemui.recents.model.RecentsTaskLoadPlan;
+import com.android.systemui.recents.model.RecentsTaskLoader;
 import com.android.systemui.shared.recents.model.Task;
 import com.android.systemui.shared.recents.model.Task.TaskKey;
-import com.android.systemui.shared.recents.model.TaskStack;
+import com.android.systemui.recents.model.TaskStack;
 import com.android.systemui.shared.recents.model.ThumbnailData;
 import com.android.systemui.recents.views.TaskStackLayoutAlgorithm;
 import com.android.systemui.recents.views.TaskStackLayoutAlgorithm.VisibilityReport;
@@ -143,7 +141,7 @@
             }
 
             // Preloads the next task
-            RecentsConfiguration config = Recents.getConfiguration();
+            RecentsConfiguration config = LegacyRecentsImpl.getConfiguration();
             if (config.svelteLevel == RecentsTaskLoader.SVELTE_NONE) {
                 Rect windowRect = getWindowRect(null /* windowRectOverride */);
                 if (windowRect.isEmpty()) {
@@ -153,7 +151,7 @@
                 // Load the next task only if we aren't svelte
                 ActivityManager.RunningTaskInfo runningTaskInfo =
                         ActivityManagerWrapper.getInstance().getRunningTask();
-                RecentsTaskLoader loader = Recents.getTaskLoader();
+                RecentsTaskLoader loader = LegacyRecentsImpl.getTaskLoader();
                 RecentsTaskLoadPlan plan = new RecentsTaskLoadPlan(mContext);
                 loader.preloadTasks(plan, -1);
                 TaskStack stack = plan.getTaskStack();
@@ -195,8 +193,8 @@
 
             // This time needs to be fetched the same way the last active time is fetched in
             // {@link TaskRecord#touchActiveTime}
-            Recents.getConfiguration().getLaunchState().launchedFromPipApp = true;
-            Recents.getConfiguration().getLaunchState().launchedWithNextPipApp = false;
+            LegacyRecentsImpl.getConfiguration().getLaunchState().launchedFromPipApp = true;
+            LegacyRecentsImpl.getConfiguration().getLaunchState().launchedWithNextPipApp = false;
             EventBus.getDefault().send(new ActivityPinnedEvent(taskId));
             consumeInstanceLoadPlan();
             sLastPipTime = System.currentTimeMillis();
@@ -278,7 +276,7 @@
         public void onConnectionChanged(boolean isConnected) {
             if (!isConnected) {
                 // Clear everything when the connection to the overview service
-                Recents.getTaskLoader().onTrimMemory(ComponentCallbacks2.TRIM_MEMORY_COMPLETE);
+                LegacyRecentsImpl.getTaskLoader().onTrimMemory(ComponentCallbacks2.TRIM_MEMORY_COMPLETE);
             }
         }
     };
@@ -313,7 +311,7 @@
 
         // When we start, preload the data associated with the previous recent tasks.
         // We can use a new plan since the caches will be the same.
-        RecentsTaskLoader loader = Recents.getTaskLoader();
+        RecentsTaskLoader loader = LegacyRecentsImpl.getTaskLoader();
         RecentsTaskLoadPlan plan = new RecentsTaskLoadPlan(mContext);
         loader.preloadTasks(plan, -1);
         RecentsTaskLoadPlan.Options launchOpts = new RecentsTaskLoadPlan.Options();
@@ -334,16 +332,16 @@
     /**
      * This is only called from the system user's Recents.  Secondary users will instead proxy their
      * visibility change events through to the system user via
-     * {@link Recents#onBusEvent(RecentsVisibilityChangedEvent)}.
+     * {@link LegacyRecentsImpl#onBusEvent(RecentsVisibilityChangedEvent)}.
      */
     public void onVisibilityChanged(Context context, boolean visible) {
-        Recents.getSystemServices().setRecentsVisibility(visible);
+        LegacyRecentsImpl.getSystemServices().setRecentsVisibility(visible);
     }
 
     /**
      * This is only called from the system user's Recents.  Secondary users will instead proxy their
      * visibility change events through to the system user via
-     * {@link Recents#onBusEvent(ScreenPinningRequestEvent)}.
+     * {@link LegacyRecentsImpl#onBusEvent(ScreenPinningRequestEvent)}.
      */
     public void onStartScreenPinning(Context context, int taskId) {
         final StatusBar statusBar = getStatusBar();
@@ -354,13 +352,13 @@
 
     public void showRecents(boolean triggeredFromAltTab, boolean draggingInRecents,
             boolean animate, int growTarget) {
-        final SystemServicesProxy ssp = Recents.getSystemServices();
+        final SystemServicesProxy ssp = LegacyRecentsImpl.getSystemServices();
         final MutableBoolean isHomeStackVisible = new MutableBoolean(true);
-        final boolean isRecentsVisible = Recents.getSystemServices().isRecentsActivityVisible(
+        final boolean isRecentsVisible = LegacyRecentsImpl.getSystemServices().isRecentsActivityVisible(
                 isHomeStackVisible);
         final boolean fromHome = isHomeStackVisible.value;
         final boolean launchedWhileDockingTask =
-                Recents.getSystemServices().getSplitScreenPrimaryStack() != null;
+                LegacyRecentsImpl.getSystemServices().getSplitScreenPrimaryStack() != null;
 
         mTriggeredFromAltTab = triggeredFromAltTab;
         mDraggingInRecents = draggingInRecents;
@@ -439,12 +437,12 @@
             MutableBoolean isHomeStackVisible = new MutableBoolean(true);
             long elapsedTime = SystemClock.elapsedRealtime() - mLastToggleTime;
 
-            SystemServicesProxy ssp = Recents.getSystemServices();
+            SystemServicesProxy ssp = LegacyRecentsImpl.getSystemServices();
             if (ssp.isRecentsActivityVisible(isHomeStackVisible)) {
-                RecentsConfiguration config = Recents.getConfiguration();
+                RecentsConfiguration config = LegacyRecentsImpl.getConfiguration();
                 RecentsActivityLaunchState launchState = config.getLaunchState();
                 if (!launchState.launchedWithAltTab) {
-                    if (Recents.getConfiguration().isGridEnabled) {
+                    if (LegacyRecentsImpl.getConfiguration().isGridEnabled) {
                         // Has the user tapped quickly?
                         boolean isQuickTap = elapsedTime < ViewConfiguration.getDoubleTapTimeout();
                         if (isQuickTap) {
@@ -509,7 +507,7 @@
         // RecentsActivity) only if there is a task to animate to.  Post this to ensure that we
         // don't block the touch feedback on the nav bar button which triggers this.
         mHandler.post(() -> {
-            SystemServicesProxy ssp = Recents.getSystemServices();
+            SystemServicesProxy ssp = LegacyRecentsImpl.getSystemServices();
             if (!ssp.isRecentsActivityVisible(null)) {
                 ActivityManager.RunningTaskInfo runningTask =
                         ActivityManagerWrapper.getInstance().getRunningTask();
@@ -517,7 +515,7 @@
                     return;
                 }
 
-                RecentsTaskLoader loader = Recents.getTaskLoader();
+                RecentsTaskLoader loader = LegacyRecentsImpl.getTaskLoader();
                 sInstanceLoadPlan = new RecentsTaskLoadPlan(mContext);
                 loader.preloadTasks(sInstanceLoadPlan, runningTask.id);
                 TaskStack stack = sInstanceLoadPlan.getTaskStack();
@@ -556,8 +554,8 @@
      * Transitions to the next recent task in the stack.
      */
     public void showNextTask() {
-        SystemServicesProxy ssp = Recents.getSystemServices();
-        RecentsTaskLoader loader = Recents.getTaskLoader();
+        SystemServicesProxy ssp = LegacyRecentsImpl.getSystemServices();
+        RecentsTaskLoader loader = LegacyRecentsImpl.getTaskLoader();
         RecentsTaskLoadPlan plan = new RecentsTaskLoadPlan(mContext);
         loader.preloadTasks(plan, -1);
         TaskStack focusedStack = plan.getTaskStack();
@@ -612,8 +610,8 @@
      * Transitions to the next affiliated task.
      */
     public void showRelativeAffiliatedTask(boolean showNextTask) {
-        SystemServicesProxy ssp = Recents.getSystemServices();
-        RecentsTaskLoader loader = Recents.getTaskLoader();
+        SystemServicesProxy ssp = LegacyRecentsImpl.getSystemServices();
+        RecentsTaskLoader loader = LegacyRecentsImpl.getTaskLoader();
         RecentsTaskLoadPlan plan = new RecentsTaskLoadPlan(mContext);
         loader.preloadTasks(plan, -1);
         TaskStack focusedStack = plan.getTaskStack();
@@ -678,20 +676,8 @@
                 null /* resultListener */, null /* resultCallbackHandler */);
     }
 
-    public void showNextAffiliatedTask() {
-        // Keep track of when the affiliated task is triggered
-        MetricsLogger.count(mContext, "overview_affiliated_task_next", 1);
-        showRelativeAffiliatedTask(true);
-    }
-
-    public void showPrevAffiliatedTask() {
-        // Keep track of when the affiliated task is triggered
-        MetricsLogger.count(mContext, "overview_affiliated_task_prev", 1);
-        showRelativeAffiliatedTask(false);
-    }
-
     public void splitPrimaryTask(int taskId, int stackCreateMode, Rect initialBounds) {
-        SystemServicesProxy ssp = Recents.getSystemServices();
+        SystemServicesProxy ssp = LegacyRecentsImpl.getSystemServices();
 
         // Make sure we inform DividerView before we actually start the activity so we can change
         // the resize mode already.
@@ -758,7 +744,7 @@
 
     private void updateDummyStackViewLayout(TaskStackLayoutAlgorithm stackLayout,
             TaskStack stack, Rect windowRect) {
-        SystemServicesProxy ssp = Recents.getSystemServices();
+        SystemServicesProxy ssp = LegacyRecentsImpl.getSystemServices();
         Rect displayRect = ssp.getDisplayRect();
         Rect systemInsets = new Rect();
         ssp.getStableInsets(systemInsets);
@@ -789,7 +775,7 @@
     private Rect getWindowRect(Rect windowRectOverride) {
        return windowRectOverride != null
                 ? new Rect(windowRectOverride)
-                : Recents.getSystemServices().getWindowRect();
+                : LegacyRecentsImpl.getSystemServices().getWindowRect();
     }
 
     /**
@@ -871,7 +857,7 @@
         launchOpts.runningTaskId = runningTaskId;
         launchOpts.loadThumbnails = false;
         launchOpts.onlyLoadForCache = true;
-        Recents.getTaskLoader().loadTasks(sInstanceLoadPlan, launchOpts);
+        LegacyRecentsImpl.getTaskLoader().loadTasks(sInstanceLoadPlan, launchOpts);
     }
 
     /**
@@ -900,7 +886,7 @@
     private Pair<ActivityOptions, AppTransitionAnimationSpecsFuture>
             getThumbnailTransitionActivityOptions(ActivityManager.RunningTaskInfo runningTask,
                     Rect windowOverrideRect) {
-        final boolean isLowRamDevice = Recents.getConfiguration().isLowRamDevice;
+        final boolean isLowRamDevice = LegacyRecentsImpl.getConfiguration().isLowRamDevice;
 
         // Update the destination rect
         Task toTask = new Task();
@@ -955,7 +941,7 @@
      */
     private Bitmap drawThumbnailTransitionBitmap(Task toTask,
             TaskViewTransform toTransform) {
-        SystemServicesProxy ssp = Recents.getSystemServices();
+        SystemServicesProxy ssp = LegacyRecentsImpl.getSystemServices();
         int width = (int) toTransform.rect.width();
         int height = (int) toTransform.rect.height();
         if (toTransform != null && toTask.key != null && width > 0 && height > 0) {
@@ -1007,8 +993,8 @@
 
     private void startRecentsActivity(ActivityManager.RunningTaskInfo runningTask,
             boolean isHomeStackVisible, boolean animate, int growTarget) {
-        RecentsTaskLoader loader = Recents.getTaskLoader();
-        RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
+        RecentsTaskLoader loader = LegacyRecentsImpl.getTaskLoader();
+        RecentsActivityLaunchState launchState = LegacyRecentsImpl.getConfiguration().getLaunchState();
 
         int runningTaskId = !mLaunchedWhileDocking && (runningTask != null)
                 ? runningTask.id
@@ -1087,10 +1073,10 @@
             return SystemServicesProxy.getInstance(mContext).getWindowRect();
         }
         Rect result = new Rect();
-        Rect displayRect = Recents.getSystemServices().getDisplayRect();
+        Rect displayRect = LegacyRecentsImpl.getSystemServices().getDisplayRect();
         DockedDividerUtils.calculateBoundsForPosition(growTarget, WindowManager.DOCKED_BOTTOM,
                 result, displayRect.width(), displayRect.height(),
-                Recents.getSystemServices().getDockedDividerSize(mContext));
+                LegacyRecentsImpl.getSystemServices().getDockedDividerSize(mContext));
         return result;
     }
 
@@ -1110,7 +1096,7 @@
                 | Intent.FLAG_ACTIVITY_TASK_ON_HOME);
         HidePipMenuEvent hideMenuEvent = new HidePipMenuEvent();
         hideMenuEvent.addPostAnimationCallback(() -> {
-            Recents.getSystemServices().startActivityAsUserAsync(intent, opts);
+            LegacyRecentsImpl.getSystemServices().startActivityAsUserAsync(intent, opts);
             EventBus.getDefault().send(new RecentsActivityStartingEvent());
             if (future != null) {
                 future.composeSpecsSynchronous();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImplProxy.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/RecentsImplProxy.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/RecentsImplProxy.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/RecentsImplProxy.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsSystemUser.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/RecentsSystemUser.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/RecentsSystemUser.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/RecentsSystemUser.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsSystemUserService.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/RecentsSystemUserService.java
similarity index 91%
rename from packages/SystemUI/src/com/android/systemui/recents/RecentsSystemUserService.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/RecentsSystemUserService.java
index b4212d3..b5a0181 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsSystemUserService.java
+++ b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/RecentsSystemUserService.java
@@ -22,7 +22,6 @@
 import android.util.Log;
 
 import com.android.systemui.SysUiServiceProvider;
-import com.android.systemui.SystemUIApplication;
 
 /**
  * A strictly system-user service that is started by the secondary user's Recents (with a limited
@@ -41,7 +40,7 @@
 
     @Override
     public IBinder onBind(Intent intent) {
-        Recents recents = SysUiServiceProvider.getComponent(this, Recents.class);
+        LegacyRecentsImpl recents = SysUiServiceProvider.getComponent(this, LegacyRecentsImpl.class);
         if (DEBUG) {
             Log.d(TAG, "onBind: " + recents);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/EventBus.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/EventBus.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/events/EventBus.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/EventBus.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/AppTransitionFinishedEvent.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/activity/AppTransitionFinishedEvent.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/events/activity/AppTransitionFinishedEvent.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/activity/AppTransitionFinishedEvent.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/CancelEnterRecentsWindowAnimationEvent.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/activity/CancelEnterRecentsWindowAnimationEvent.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/events/activity/CancelEnterRecentsWindowAnimationEvent.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/activity/CancelEnterRecentsWindowAnimationEvent.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/ConfigurationChangedEvent.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/activity/ConfigurationChangedEvent.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/events/activity/ConfigurationChangedEvent.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/activity/ConfigurationChangedEvent.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/DismissRecentsToHomeAnimationStarted.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/activity/DismissRecentsToHomeAnimationStarted.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/events/activity/DismissRecentsToHomeAnimationStarted.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/activity/DismissRecentsToHomeAnimationStarted.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/DockedFirstAnimationFrameEvent.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/activity/DockedFirstAnimationFrameEvent.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/events/activity/DockedFirstAnimationFrameEvent.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/activity/DockedFirstAnimationFrameEvent.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/DockedTopTaskEvent.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/activity/DockedTopTaskEvent.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/events/activity/DockedTopTaskEvent.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/activity/DockedTopTaskEvent.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/EnterRecentsWindowAnimationCompletedEvent.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/activity/EnterRecentsWindowAnimationCompletedEvent.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/events/activity/EnterRecentsWindowAnimationCompletedEvent.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/activity/EnterRecentsWindowAnimationCompletedEvent.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/EnterRecentsWindowLastAnimationFrameEvent.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/activity/EnterRecentsWindowLastAnimationFrameEvent.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/events/activity/EnterRecentsWindowLastAnimationFrameEvent.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/activity/EnterRecentsWindowLastAnimationFrameEvent.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/ExitRecentsWindowFirstAnimationFrameEvent.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/activity/ExitRecentsWindowFirstAnimationFrameEvent.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/events/activity/ExitRecentsWindowFirstAnimationFrameEvent.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/activity/ExitRecentsWindowFirstAnimationFrameEvent.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/HideRecentsEvent.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/activity/HideRecentsEvent.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/events/activity/HideRecentsEvent.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/activity/HideRecentsEvent.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/HideStackActionButtonEvent.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/activity/HideStackActionButtonEvent.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/events/activity/HideStackActionButtonEvent.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/activity/HideStackActionButtonEvent.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchMostRecentTaskRequestEvent.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/activity/LaunchMostRecentTaskRequestEvent.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchMostRecentTaskRequestEvent.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/activity/LaunchMostRecentTaskRequestEvent.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchNextTaskRequestEvent.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/activity/LaunchNextTaskRequestEvent.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchNextTaskRequestEvent.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/activity/LaunchNextTaskRequestEvent.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchTaskEvent.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/activity/LaunchTaskEvent.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchTaskEvent.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/activity/LaunchTaskEvent.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchTaskFailedEvent.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/activity/LaunchTaskFailedEvent.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchTaskFailedEvent.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/activity/LaunchTaskFailedEvent.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchTaskStartedEvent.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/activity/LaunchTaskStartedEvent.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchTaskStartedEvent.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/activity/LaunchTaskStartedEvent.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchTaskSucceededEvent.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/activity/LaunchTaskSucceededEvent.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchTaskSucceededEvent.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/activity/LaunchTaskSucceededEvent.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/MultiWindowStateChangedEvent.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/activity/MultiWindowStateChangedEvent.java
similarity index 95%
rename from packages/SystemUI/src/com/android/systemui/recents/events/activity/MultiWindowStateChangedEvent.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/activity/MultiWindowStateChangedEvent.java
index e4972b1..64eeafa 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/MultiWindowStateChangedEvent.java
+++ b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/activity/MultiWindowStateChangedEvent.java
@@ -17,7 +17,7 @@
 package com.android.systemui.recents.events.activity;
 
 import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.shared.recents.model.TaskStack;
+import com.android.systemui.recents.model.TaskStack;
 
 /**
  * This is sent by the activity whenever the multi-window state has changed.
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/PackagesChangedEvent.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/activity/PackagesChangedEvent.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/events/activity/PackagesChangedEvent.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/activity/PackagesChangedEvent.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/RecentsActivityStartingEvent.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/activity/RecentsActivityStartingEvent.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/events/activity/RecentsActivityStartingEvent.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/activity/RecentsActivityStartingEvent.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowEmptyViewEvent.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/activity/ShowEmptyViewEvent.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowEmptyViewEvent.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/activity/ShowEmptyViewEvent.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowStackActionButtonEvent.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/activity/ShowStackActionButtonEvent.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowStackActionButtonEvent.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/activity/ShowStackActionButtonEvent.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/TaskStackUpdatedEvent.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/activity/TaskStackUpdatedEvent.java
similarity index 94%
rename from packages/SystemUI/src/com/android/systemui/recents/events/activity/TaskStackUpdatedEvent.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/activity/TaskStackUpdatedEvent.java
index 51d02b5..0d614e8c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/TaskStackUpdatedEvent.java
+++ b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/activity/TaskStackUpdatedEvent.java
@@ -17,7 +17,7 @@
 package com.android.systemui.recents.events.activity;
 
 import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.shared.recents.model.TaskStack;
+import com.android.systemui.recents.model.TaskStack;
 
 /**
  * This is sent by the activity whenever the task stach has changed.
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/ToggleRecentsEvent.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/activity/ToggleRecentsEvent.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/events/activity/ToggleRecentsEvent.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/activity/ToggleRecentsEvent.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/UndockingTaskEvent.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/activity/UndockingTaskEvent.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/events/activity/UndockingTaskEvent.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/activity/UndockingTaskEvent.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/component/ActivityPinnedEvent.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/component/ActivityPinnedEvent.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/events/component/ActivityPinnedEvent.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/component/ActivityPinnedEvent.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/component/ActivityUnpinnedEvent.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/component/ActivityUnpinnedEvent.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/events/component/ActivityUnpinnedEvent.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/component/ActivityUnpinnedEvent.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/component/ExpandPipEvent.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/component/ExpandPipEvent.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/events/component/ExpandPipEvent.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/component/ExpandPipEvent.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/component/HidePipMenuEvent.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/component/HidePipMenuEvent.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/events/component/HidePipMenuEvent.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/component/HidePipMenuEvent.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/component/RecentsVisibilityChangedEvent.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/component/RecentsVisibilityChangedEvent.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/events/component/RecentsVisibilityChangedEvent.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/component/RecentsVisibilityChangedEvent.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/component/ScreenPinningRequestEvent.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/component/ScreenPinningRequestEvent.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/events/component/ScreenPinningRequestEvent.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/component/ScreenPinningRequestEvent.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/component/SetWaitingForTransitionStartEvent.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/component/SetWaitingForTransitionStartEvent.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/events/component/SetWaitingForTransitionStartEvent.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/component/SetWaitingForTransitionStartEvent.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/component/ShowUserToastEvent.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/component/ShowUserToastEvent.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/events/component/ShowUserToastEvent.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/component/ShowUserToastEvent.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/AllTaskViewsDismissedEvent.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/ui/AllTaskViewsDismissedEvent.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/events/ui/AllTaskViewsDismissedEvent.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/ui/AllTaskViewsDismissedEvent.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/DeleteTaskDataEvent.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/ui/DeleteTaskDataEvent.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/events/ui/DeleteTaskDataEvent.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/ui/DeleteTaskDataEvent.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/DismissAllTaskViewsEvent.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/ui/DismissAllTaskViewsEvent.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/events/ui/DismissAllTaskViewsEvent.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/ui/DismissAllTaskViewsEvent.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/DismissTaskViewEvent.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/ui/DismissTaskViewEvent.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/events/ui/DismissTaskViewEvent.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/ui/DismissTaskViewEvent.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/DraggingInRecentsEndedEvent.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/ui/DraggingInRecentsEndedEvent.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/events/ui/DraggingInRecentsEndedEvent.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/ui/DraggingInRecentsEndedEvent.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/DraggingInRecentsEvent.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/ui/DraggingInRecentsEvent.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/events/ui/DraggingInRecentsEvent.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/ui/DraggingInRecentsEvent.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/HideIncompatibleAppOverlayEvent.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/ui/HideIncompatibleAppOverlayEvent.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/events/ui/HideIncompatibleAppOverlayEvent.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/ui/HideIncompatibleAppOverlayEvent.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/RecentsDrawnEvent.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/ui/RecentsDrawnEvent.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/events/ui/RecentsDrawnEvent.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/ui/RecentsDrawnEvent.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/RecentsGrowingEvent.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/ui/RecentsGrowingEvent.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/events/ui/RecentsGrowingEvent.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/ui/RecentsGrowingEvent.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/ShowApplicationInfoEvent.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/ui/ShowApplicationInfoEvent.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/events/ui/ShowApplicationInfoEvent.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/ui/ShowApplicationInfoEvent.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/ShowIncompatibleAppOverlayEvent.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/ui/ShowIncompatibleAppOverlayEvent.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/events/ui/ShowIncompatibleAppOverlayEvent.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/ui/ShowIncompatibleAppOverlayEvent.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/StackViewScrolledEvent.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/ui/StackViewScrolledEvent.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/events/ui/StackViewScrolledEvent.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/ui/StackViewScrolledEvent.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/TaskSnapshotChangedEvent.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/ui/TaskSnapshotChangedEvent.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/events/ui/TaskSnapshotChangedEvent.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/ui/TaskSnapshotChangedEvent.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/TaskViewDismissedEvent.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/ui/TaskViewDismissedEvent.java
similarity index 94%
rename from packages/SystemUI/src/com/android/systemui/recents/events/ui/TaskViewDismissedEvent.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/ui/TaskViewDismissedEvent.java
index 881a64a..9738124 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/ui/TaskViewDismissedEvent.java
+++ b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/ui/TaskViewDismissedEvent.java
@@ -18,7 +18,7 @@
 
 import com.android.systemui.recents.events.EventBus;
 import com.android.systemui.shared.recents.model.Task;
-import com.android.systemui.shared.recents.utilities.AnimationProps;
+import com.android.systemui.recents.utilities.AnimationProps;
 import com.android.systemui.recents.views.TaskView;
 
 /**
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/UserInteractionEvent.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/ui/UserInteractionEvent.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/events/ui/UserInteractionEvent.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/ui/UserInteractionEvent.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/dragndrop/DragDropTargetChangedEvent.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/ui/dragndrop/DragDropTargetChangedEvent.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/events/ui/dragndrop/DragDropTargetChangedEvent.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/ui/dragndrop/DragDropTargetChangedEvent.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/dragndrop/DragEndCancelledEvent.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/ui/dragndrop/DragEndCancelledEvent.java
similarity index 95%
rename from packages/SystemUI/src/com/android/systemui/recents/events/ui/dragndrop/DragEndCancelledEvent.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/ui/dragndrop/DragEndCancelledEvent.java
index 297afc5..c11936e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/ui/dragndrop/DragEndCancelledEvent.java
+++ b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/ui/dragndrop/DragEndCancelledEvent.java
@@ -18,7 +18,7 @@
 
 import com.android.systemui.recents.events.EventBus;
 import com.android.systemui.shared.recents.model.Task;
-import com.android.systemui.shared.recents.model.TaskStack;
+import com.android.systemui.recents.model.TaskStack;
 import com.android.systemui.recents.views.TaskView;
 
 /**
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/dragndrop/DragEndEvent.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/ui/dragndrop/DragEndEvent.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/events/ui/dragndrop/DragEndEvent.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/ui/dragndrop/DragEndEvent.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/dragndrop/DragStartEvent.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/ui/dragndrop/DragStartEvent.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/events/ui/dragndrop/DragStartEvent.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/ui/dragndrop/DragStartEvent.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/dragndrop/DragStartInitializeDropTargetsEvent.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/ui/dragndrop/DragStartInitializeDropTargetsEvent.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/events/ui/dragndrop/DragStartInitializeDropTargetsEvent.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/ui/dragndrop/DragStartInitializeDropTargetsEvent.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/focus/DismissFocusedTaskViewEvent.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/ui/focus/DismissFocusedTaskViewEvent.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/events/ui/focus/DismissFocusedTaskViewEvent.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/ui/focus/DismissFocusedTaskViewEvent.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/focus/FocusNextTaskViewEvent.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/ui/focus/FocusNextTaskViewEvent.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/events/ui/focus/FocusNextTaskViewEvent.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/ui/focus/FocusNextTaskViewEvent.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/focus/FocusPreviousTaskViewEvent.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/ui/focus/FocusPreviousTaskViewEvent.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/events/ui/focus/FocusPreviousTaskViewEvent.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/ui/focus/FocusPreviousTaskViewEvent.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/focus/NavigateTaskViewEvent.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/ui/focus/NavigateTaskViewEvent.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/events/ui/focus/NavigateTaskViewEvent.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/events/ui/focus/NavigateTaskViewEvent.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/DozeTrigger.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/misc/DozeTrigger.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/misc/DozeTrigger.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/misc/DozeTrigger.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/FreePathInterpolator.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/misc/FreePathInterpolator.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/misc/FreePathInterpolator.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/misc/FreePathInterpolator.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/ReferenceCountedTrigger.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/misc/ReferenceCountedTrigger.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/misc/ReferenceCountedTrigger.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/misc/ReferenceCountedTrigger.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SysUiTaskStackChangeListener.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/misc/SysUiTaskStackChangeListener.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/misc/SysUiTaskStackChangeListener.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/misc/SysUiTaskStackChangeListener.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/misc/SystemServicesProxy.java
similarity index 98%
rename from packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index 350fe78..f8b61cd 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -34,7 +34,6 @@
 import android.app.IActivityTaskManager;
 import android.app.WindowConfiguration;
 import android.content.ComponentName;
-import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.IPackageManager;
@@ -51,10 +50,8 @@
 import android.graphics.drawable.Drawable;
 import android.os.RemoteException;
 import android.os.ServiceManager;
-import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.UserManager;
-import android.provider.Settings;
 import android.service.dreams.DreamService;
 import android.service.dreams.IDreamManager;
 import android.util.Log;
@@ -71,7 +68,7 @@
 import com.android.internal.os.BackgroundThread;
 import com.android.systemui.Dependency;
 import com.android.systemui.UiOffloadThread;
-import com.android.systemui.recents.Recents;
+import com.android.systemui.recents.LegacyRecentsImpl;
 import com.android.systemui.recents.RecentsImpl;
 import com.android.systemui.statusbar.policy.UserInfoController;
 
@@ -237,7 +234,7 @@
                     recentsStackInfo.topActivity : null;
             return (recentsStackVisibleNotOccluded && topActivity != null
                     && topActivity.getPackageName().equals(RecentsImpl.RECENTS_PACKAGE)
-                    && Recents.RECENTS_ACTIVITIES.contains(topActivity.getClassName()));
+                    && LegacyRecentsImpl.RECENTS_ACTIVITIES.contains(topActivity.getClassName()));
         } catch (RemoteException e) {
             e.printStackTrace();
         }
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/BackgroundTaskLoader.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/model/BackgroundTaskLoader.java
similarity index 96%
rename from packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/BackgroundTaskLoader.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/model/BackgroundTaskLoader.java
index 114d69e..e85a7fb 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/BackgroundTaskLoader.java
+++ b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/model/BackgroundTaskLoader.java
@@ -14,7 +14,7 @@
  * limitations under the License
  */
 
-package com.android.systemui.shared.recents.model;
+package com.android.systemui.recents.model;
 
 import android.content.Context;
 import android.graphics.drawable.Drawable;
@@ -22,12 +22,14 @@
 import android.os.HandlerThread;
 import android.util.Log;
 
+import com.android.systemui.shared.recents.model.IconLoader;
+import com.android.systemui.shared.recents.model.Task;
+import com.android.systemui.shared.recents.model.ThumbnailData;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 
 /**
  * Background task resource loader
  */
-@Deprecated
 class BackgroundTaskLoader implements Runnable {
     static String TAG = "BackgroundTaskLoader";
     static boolean DEBUG = false;
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/FilteredTaskList.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/model/FilteredTaskList.java
similarity index 97%
rename from packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/FilteredTaskList.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/model/FilteredTaskList.java
index 7e0f8fe..005be75 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/FilteredTaskList.java
+++ b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/model/FilteredTaskList.java
@@ -14,11 +14,12 @@
  * limitations under the License
  */
 
-package com.android.systemui.shared.recents.model;
+package com.android.systemui.recents.model;
 
 import android.util.ArrayMap;
 import android.util.SparseArray;
 
+import com.android.systemui.shared.recents.model.Task;
 import com.android.systemui.shared.recents.model.Task.TaskKey;
 
 import java.util.ArrayList;
@@ -27,7 +28,6 @@
 /**
  * A list of filtered tasks.
  */
-@Deprecated
 class FilteredTaskList {
 
     private final ArrayList<Task> mTasks = new ArrayList<>();
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/HighResThumbnailLoader.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/model/HighResThumbnailLoader.java
similarity index 97%
rename from packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/HighResThumbnailLoader.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/model/HighResThumbnailLoader.java
index f02bc5a..34bc334 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/HighResThumbnailLoader.java
+++ b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/model/HighResThumbnailLoader.java
@@ -14,7 +14,7 @@
  * limitations under the License
  */
 
-package com.android.systemui.shared.recents.model;
+package com.android.systemui.recents.model;
 
 import static android.os.Process.setThreadPriority;
 
@@ -25,7 +25,9 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.shared.recents.model.Task;
 import com.android.systemui.shared.recents.model.Task.TaskCallbacks;
+import com.android.systemui.shared.recents.model.ThumbnailData;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 
 import java.util.ArrayDeque;
@@ -34,7 +36,6 @@
 /**
  * Loader class that loads full-resolution thumbnails when appropriate.
  */
-@Deprecated
 public class HighResThumbnailLoader implements
         TaskCallbacks, BackgroundTaskLoader.OnIdleChangedListener {
 
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/RecentsTaskLoadPlan.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
similarity index 97%
rename from packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/RecentsTaskLoadPlan.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
index 8b3ae42..7c6a76f 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/RecentsTaskLoadPlan.java
+++ b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.systemui.shared.recents.model;
+package com.android.systemui.recents.model;
 
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
 
@@ -29,7 +29,9 @@
 import android.graphics.drawable.Drawable;
 import android.util.SparseBooleanArray;
 
+import com.android.systemui.shared.recents.model.Task;
 import com.android.systemui.shared.recents.model.Task.TaskKey;
+import com.android.systemui.shared.recents.model.ThumbnailData;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 
 import java.util.ArrayList;
@@ -45,7 +47,6 @@
  *   3) executePlan() will actually load and fill in the icons and thumbnails according to the load
  *      options specified, such that we can transition into the Recents activity seamlessly
  */
-@Deprecated
 public class RecentsTaskLoadPlan {
 
     /** The set of conditions to preload tasks. */
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/RecentsTaskLoader.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/model/RecentsTaskLoader.java
similarity index 97%
rename from packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/RecentsTaskLoader.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/model/RecentsTaskLoader.java
index b50aa76..012913a 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/RecentsTaskLoader.java
+++ b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/model/RecentsTaskLoader.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.systemui.shared.recents.model;
+package com.android.systemui.recents.model;
 
 import android.app.ActivityManager;
 import android.app.ActivityTaskManager;
@@ -29,10 +29,14 @@
 import android.util.LruCache;
 
 import com.android.internal.annotations.GuardedBy;
-import com.android.systemui.shared.recents.model.RecentsTaskLoadPlan.Options;
-import com.android.systemui.shared.recents.model.RecentsTaskLoadPlan.PreloadOptions;
+import com.android.systemui.recents.model.RecentsTaskLoadPlan.Options;
+import com.android.systemui.recents.model.RecentsTaskLoadPlan.PreloadOptions;
+import com.android.systemui.shared.recents.model.IconLoader;
+import com.android.systemui.shared.recents.model.Task;
 import com.android.systemui.shared.recents.model.Task.TaskKey;
+import com.android.systemui.shared.recents.model.TaskKeyLruCache;
 import com.android.systemui.shared.recents.model.TaskKeyLruCache.EvictionCallback;
+import com.android.systemui.shared.recents.model.ThumbnailData;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 
 import java.io.PrintWriter;
@@ -42,7 +46,6 @@
 /**
  * Recents task loader
  */
-@Deprecated
 public class RecentsTaskLoader {
     private static final String TAG = "RecentsTaskLoader";
     private static final boolean DEBUG = false;
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskFilter.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/model/TaskFilter.java
similarity index 90%
rename from packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskFilter.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/model/TaskFilter.java
index d378189..9b734ec 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskFilter.java
+++ b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/model/TaskFilter.java
@@ -14,14 +14,14 @@
  * limitations under the License
  */
 
-package com.android.systemui.shared.recents.model;
+package com.android.systemui.recents.model;
 
 import android.util.SparseArray;
+import com.android.systemui.shared.recents.model.Task;
 
 /**
  * An interface for a task filter to query whether a particular task should show in a stack.
  */
-@Deprecated
 public interface TaskFilter {
     /** Returns whether the filter accepts the specified task */
     boolean acceptTask(SparseArray<Task> taskIdMap, Task t, int index);
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskKeyStrongCache.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/model/TaskKeyStrongCache.java
similarity index 88%
rename from packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskKeyStrongCache.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/model/TaskKeyStrongCache.java
index 4408ece..27f2098 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskKeyStrongCache.java
+++ b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/model/TaskKeyStrongCache.java
@@ -14,12 +14,14 @@
  * limitations under the License
  */
 
-package com.android.systemui.shared.recents.model;
+package com.android.systemui.recents.model;
 
 import android.util.ArrayMap;
 
 import com.android.systemui.shared.recents.model.Task.TaskKey;
 
+import com.android.systemui.shared.recents.model.TaskKeyCache;
+import com.android.systemui.shared.recents.model.TaskKeyLruCache;
 import java.io.PrintWriter;
 
 /**
@@ -31,7 +33,7 @@
 
     private final ArrayMap<Integer, V> mCache = new ArrayMap<>();
 
-    final void copyEntries(TaskKeyStrongCache<V> other) {
+    public final void copyEntries(TaskKeyStrongCache<V> other) {
         for (int i = other.mKeys.size() - 1; i >= 0; i--) {
             TaskKey key = other.mKeys.valueAt(i);
             put(key, other.mCache.get(key.id));
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskResourceLoadQueue.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/model/TaskResourceLoadQueue.java
similarity index 93%
rename from packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskResourceLoadQueue.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/model/TaskResourceLoadQueue.java
index 6b9b9f5..fe89ad5 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskResourceLoadQueue.java
+++ b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/model/TaskResourceLoadQueue.java
@@ -14,14 +14,14 @@
  * limitations under the License
  */
 
-package com.android.systemui.shared.recents.model;
+package com.android.systemui.recents.model;
 
+import com.android.systemui.shared.recents.model.Task;
 import java.util.concurrent.ConcurrentLinkedQueue;
 
 /**
  * A Task load queue
  */
-@Deprecated
 class TaskResourceLoadQueue {
 
     private final ConcurrentLinkedQueue<Task> mQueue = new ConcurrentLinkedQueue<>();
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskStack.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/model/TaskStack.java
similarity index 98%
rename from packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskStack.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/model/TaskStack.java
index fd92bca..01e6ba3 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskStack.java
+++ b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/model/TaskStack.java
@@ -14,15 +14,16 @@
  * limitations under the License.
  */
 
-package com.android.systemui.shared.recents.model;
+package com.android.systemui.recents.model;
 
 import android.content.ComponentName;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.SparseArray;
 
+import com.android.systemui.shared.recents.model.Task;
 import com.android.systemui.shared.recents.model.Task.TaskKey;
-import com.android.systemui.shared.recents.utilities.AnimationProps;
+import com.android.systemui.recents.utilities.AnimationProps;
 import com.android.systemui.shared.system.PackageManagerWrapper;
 
 import java.io.PrintWriter;
@@ -33,7 +34,6 @@
 /**
  * The task stack contains a list of multiple tasks.
  */
-@Deprecated
 public class TaskStack {
 
     private static final String TAG = "TaskStack";
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/AnimationProps.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/utilities/AnimationProps.java
similarity index 98%
rename from packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/AnimationProps.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/utilities/AnimationProps.java
index 26f6b59..5463998 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/AnimationProps.java
+++ b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/utilities/AnimationProps.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.systemui.shared.recents.utilities;
+package com.android.systemui.recents.utilities;
 
 import android.animation.Animator;
 import android.animation.AnimatorSet;
@@ -34,7 +34,6 @@
  * The generic set of animation properties to animate a {@link View}. The animation can have
  * different interpolators, start delays and durations for each of the different properties.
  */
-@Deprecated
 public class AnimationProps {
 
     private static final Interpolator LINEAR_INTERPOLATOR = new LinearInterpolator();
diff --git a/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/utilities/Utilities.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/utilities/Utilities.java
new file mode 100644
index 0000000..ff58eba
--- /dev/null
+++ b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/utilities/Utilities.java
@@ -0,0 +1,339 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.recents.utilities;
+
+import android.animation.Animator;
+import android.animation.AnimatorSet;
+import android.animation.RectEvaluator;
+import android.annotation.FloatRange;
+import android.annotation.Nullable;
+import android.app.Activity;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.graphics.Color;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.graphics.drawable.Drawable;
+import android.os.Handler;
+import android.os.Message;
+import android.os.Trace;
+import android.util.ArraySet;
+import android.util.IntProperty;
+import android.util.Property;
+import android.util.TypedValue;
+import android.view.Surface;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewParent;
+import android.view.ViewRootImpl;
+import android.view.ViewStub;
+
+import com.android.systemui.shared.recents.utilities.RectFEvaluator;
+import java.util.ArrayList;
+import java.util.Collections;
+
+/* Common code */
+public class Utilities {
+
+    public static final Property<Drawable, Integer> DRAWABLE_ALPHA =
+            new IntProperty<Drawable>("drawableAlpha") {
+                @Override
+                public void setValue(Drawable object, int alpha) {
+                    object.setAlpha(alpha);
+                }
+
+                @Override
+                public Integer get(Drawable object) {
+                    return object.getAlpha();
+                }
+            };
+
+    public static final Property<Drawable, Rect> DRAWABLE_RECT =
+            new Property<Drawable, Rect>(Rect.class, "drawableBounds") {
+                @Override
+                public void set(Drawable object, Rect bounds) {
+                    object.setBounds(bounds);
+                }
+
+                @Override
+                public Rect get(Drawable object) {
+                    return object.getBounds();
+                }
+            };
+
+    public static final RectFEvaluator RECTF_EVALUATOR = new RectFEvaluator();
+    public static final RectEvaluator RECT_EVALUATOR = new RectEvaluator(new Rect());
+
+    /**
+     * @return the first parent walking up the view hierarchy that has the given class type.
+     *
+     * @param parentClass must be a class derived from {@link View}
+     */
+    public static <T extends View> T findParent(View v, Class<T> parentClass) {
+        ViewParent parent = v.getParent();
+        while (parent != null) {
+            if (parentClass.isAssignableFrom(parent.getClass())) {
+                return (T) parent;
+            }
+            parent = parent.getParent();
+        }
+        return null;
+    }
+
+    /**
+     * Initializes the {@param setOut} with the given object.
+     */
+    public static <T> ArraySet<T> objectToSet(T obj, ArraySet<T> setOut) {
+        setOut.clear();
+        if (obj != null) {
+            setOut.add(obj);
+        }
+        return setOut;
+    }
+
+    /**
+     * Replaces the contents of {@param setOut} with the contents of the {@param array}.
+     */
+    public static <T> ArraySet<T> arrayToSet(T[] array, ArraySet<T> setOut) {
+        setOut.clear();
+        if (array != null) {
+            Collections.addAll(setOut, array);
+        }
+        return setOut;
+    }
+
+    /**
+     * @return the clamped {@param value} between the provided {@param min} and {@param max}.
+     */
+    public static int clamp(int value, int min, int max) {
+        return Math.max(min, Math.min(max, value));
+    }
+
+    /**
+     * @return the clamped {@param value} between 0 and 1.
+     */
+    public static float clamp01(float value) {
+        return Math.max(0f, Math.min(1f, value));
+    }
+
+    /**
+     * Scales the {@param value} to be proportionally between the {@param min} and
+     * {@param max} values.
+     *
+     * @param value must be between 0 and 1
+     */
+    public static float mapRange(@FloatRange(from=0.0,to=1.0) float value, float min, float max) {
+        return min + (value * (max - min));
+    }
+
+    /**
+     * Scales the {@param value} proportionally from {@param min} and {@param max} to 0 and 1.
+     *
+     * @param value must be between {@param min} and {@param max}
+     */
+    public static float unmapRange(float value, float min, float max) {
+        return (value - min) / (max - min);
+    }
+
+    /** Scales a rect about its centroid */
+    public static void scaleRectAboutCenter(RectF r, float scale) {
+        if (scale != 1.0f) {
+            float cx = r.centerX();
+            float cy = r.centerY();
+            r.offset(-cx, -cy);
+            r.left *= scale;
+            r.top *= scale;
+            r.right *= scale;
+            r.bottom *= scale;
+            r.offset(cx, cy);
+        }
+    }
+
+    /** Returns the base color overlaid with another overlay color with a specified alpha. */
+    public static int getColorWithOverlay(int baseColor, int overlayColor, float overlayAlpha) {
+        return Color.rgb(
+            (int) (overlayAlpha * Color.red(baseColor) +
+                    (1f - overlayAlpha) * Color.red(overlayColor)),
+            (int) (overlayAlpha * Color.green(baseColor) +
+                    (1f - overlayAlpha) * Color.green(overlayColor)),
+            (int) (overlayAlpha * Color.blue(baseColor) +
+                    (1f - overlayAlpha) * Color.blue(overlayColor)));
+    }
+
+    /**
+     * Cancels an animation ensuring that if it has listeners, onCancel and onEnd
+     * are not called.
+     */
+    public static void cancelAnimationWithoutCallbacks(Animator animator) {
+        if (animator != null && animator.isStarted()) {
+            removeAnimationListenersRecursive(animator);
+            animator.cancel();
+        }
+    }
+
+    /**
+     * Recursively removes all the listeners of all children of this animator
+     */
+    public static void removeAnimationListenersRecursive(Animator animator) {
+        if (animator instanceof AnimatorSet) {
+            ArrayList<Animator> animators = ((AnimatorSet) animator).getChildAnimations();
+            for (int i = animators.size() - 1; i >= 0; i--) {
+                removeAnimationListenersRecursive(animators.get(i));
+            }
+        }
+        animator.removeAllListeners();
+    }
+
+    /**
+     * Sets the given {@link View}'s frame from its current translation.
+     */
+    public static void setViewFrameFromTranslation(View v) {
+        RectF taskViewRect = new RectF(v.getLeft(), v.getTop(), v.getRight(), v.getBottom());
+        taskViewRect.offset(v.getTranslationX(), v.getTranslationY());
+        v.setTranslationX(0);
+        v.setTranslationY(0);
+        v.setLeftTopRightBottom((int) taskViewRect.left, (int) taskViewRect.top,
+                (int) taskViewRect.right, (int) taskViewRect.bottom);
+    }
+
+    /**
+     * Returns a view stub for the given view id.
+     */
+    public static ViewStub findViewStubById(View v, int stubId) {
+        return (ViewStub) v.findViewById(stubId);
+    }
+
+    /**
+     * Returns a view stub for the given view id.
+     */
+    public static ViewStub findViewStubById(Activity a, int stubId) {
+        return (ViewStub) a.findViewById(stubId);
+    }
+
+    /**
+     * Used for debugging, converts DP to PX.
+     */
+    public static float dpToPx(Resources res, float dp) {
+        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, res.getDisplayMetrics());
+    }
+
+    /**
+     * Adds a trace event for debugging.
+     */
+    public static void addTraceEvent(String event) {
+        Trace.traceBegin(Trace.TRACE_TAG_VIEW, event);
+        Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+    }
+
+    /**
+     * Returns whether this view, or one of its descendants have accessibility focus.
+     */
+    public static boolean isDescendentAccessibilityFocused(View v) {
+        if (v.isAccessibilityFocused()) {
+            return true;
+        }
+
+        if (v instanceof ViewGroup) {
+            ViewGroup vg = (ViewGroup) v;
+            int childCount = vg.getChildCount();
+            for (int i = 0; i < childCount; i++) {
+                if (isDescendentAccessibilityFocused(vg.getChildAt(i))) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Returns the application configuration, which is independent of the activity's current
+     * configuration in multiwindow.
+     */
+    public static Configuration getAppConfiguration(Context context) {
+        return context.getApplicationContext().getResources().getConfiguration();
+    }
+
+    /**
+     * @return The next frame name for the specified surface or -1 if the surface is no longer
+     *         valid.
+     */
+    public static long getNextFrameNumber(Surface s) {
+        return s != null && s.isValid()
+                ? s.getNextFrameNumber()
+                : -1;
+
+    }
+
+    /**
+     * @return The surface for the specified view.
+     */
+    public static @Nullable Surface getSurface(View v) {
+        ViewRootImpl viewRoot = v.getViewRootImpl();
+        if (viewRoot == null) {
+            return null;
+        }
+        return viewRoot.mSurface;
+    }
+
+    /**
+     * Returns a lightweight dump of a rect.
+     */
+    public static String dumpRect(Rect r) {
+        if (r == null) {
+            return "N:0,0-0,0";
+        }
+        return r.left + "," + r.top + "-" + r.right + "," + r.bottom;
+    }
+
+    /**
+     * Posts a runnable on a handler at the front of the queue ignoring any sync barriers.
+     */
+    public static void postAtFrontOfQueueAsynchronously(Handler h, Runnable r) {
+        Message msg = h.obtainMessage().setCallback(r);
+        h.sendMessageAtFrontOfQueue(msg);
+    }
+
+    /** Calculates the constrast between two colors, using the algorithm provided by the WCAG v2. */
+    public static float computeContrastBetweenColors(int bg, int fg) {
+        float bgR = Color.red(bg) / 255f;
+        float bgG = Color.green(bg) / 255f;
+        float bgB = Color.blue(bg) / 255f;
+        bgR = (bgR < 0.03928f) ? bgR / 12.92f : (float) Math.pow((bgR + 0.055f) / 1.055f, 2.4f);
+        bgG = (bgG < 0.03928f) ? bgG / 12.92f : (float) Math.pow((bgG + 0.055f) / 1.055f, 2.4f);
+        bgB = (bgB < 0.03928f) ? bgB / 12.92f : (float) Math.pow((bgB + 0.055f) / 1.055f, 2.4f);
+        float bgL = 0.2126f * bgR + 0.7152f * bgG + 0.0722f * bgB;
+
+        float fgR = Color.red(fg) / 255f;
+        float fgG = Color.green(fg) / 255f;
+        float fgB = Color.blue(fg) / 255f;
+        fgR = (fgR < 0.03928f) ? fgR / 12.92f : (float) Math.pow((fgR + 0.055f) / 1.055f, 2.4f);
+        fgG = (fgG < 0.03928f) ? fgG / 12.92f : (float) Math.pow((fgG + 0.055f) / 1.055f, 2.4f);
+        fgB = (fgB < 0.03928f) ? fgB / 12.92f : (float) Math.pow((fgB + 0.055f) / 1.055f, 2.4f);
+        float fgL = 0.2126f * fgR + 0.7152f * fgG + 0.0722f * fgB;
+
+        return Math.abs((fgL + 0.05f) / (bgL + 0.05f));
+    }
+
+    /**
+     * @return the clamped {@param value} between the provided {@param min} and {@param max}.
+     */
+    public static float clamp(float value, float min, float max) {
+        return Math.max(min, Math.min(max, value));
+    }
+
+}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/view/AnimateableViewBounds.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/AnimateableViewBounds.java
similarity index 95%
rename from packages/SystemUI/shared/src/com/android/systemui/shared/recents/view/AnimateableViewBounds.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/AnimateableViewBounds.java
index 30bea32..e188506 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/view/AnimateableViewBounds.java
+++ b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/AnimateableViewBounds.java
@@ -14,20 +14,18 @@
  * limitations under the License.
  */
 
-package com.android.systemui.shared.recents.view;
+package com.android.systemui.recents.views;
 
 import android.graphics.Outline;
 import android.graphics.Rect;
 import android.view.View;
-import android.view.ViewDebug;
 import android.view.ViewOutlineProvider;
 
-import com.android.systemui.shared.recents.utilities.Utilities;
+import com.android.systemui.recents.utilities.Utilities;
 
 /**
  * An outline provider that has a clip and outline that can be animated.
  */
-@Deprecated
 public class AnimateableViewBounds extends ViewOutlineProvider {
 
     private static final float MIN_ALPHA = 0.1f;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/DockState.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/DockState.java
similarity index 98%
rename from packages/SystemUI/src/com/android/systemui/recents/views/DockState.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/DockState.java
index a246141..d9c921c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/DockState.java
+++ b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/DockState.java
@@ -45,8 +45,8 @@
 import com.android.internal.policy.DockedDividerUtils;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
-import com.android.systemui.recents.Recents;
-import com.android.systemui.shared.recents.utilities.Utilities;
+import com.android.systemui.recents.LegacyRecentsImpl;
+import com.android.systemui.recents.utilities.Utilities;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -132,7 +132,7 @@
         private ViewState(int areaAlpha, int hintAlpha, @TextOrientation int hintOrientation,
                 int hintTextResId) {
             dockAreaAlpha = areaAlpha;
-            dockAreaOverlay = new ColorDrawable(Recents.getConfiguration().isGridEnabled
+            dockAreaOverlay = new ColorDrawable(LegacyRecentsImpl.getConfiguration().isGridEnabled
                     ? DOCK_AREA_GRID_BG_COLOR : DOCK_AREA_BG_COLOR);
             dockAreaOverlay.setAlpha(0);
             hintTextAlpha = hintAlpha;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/DropTarget.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/DropTarget.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/views/DropTarget.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/DropTarget.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/FakeShadowDrawable.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/FakeShadowDrawable.java
similarity index 98%
rename from packages/SystemUI/src/com/android/systemui/recents/views/FakeShadowDrawable.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/FakeShadowDrawable.java
index 79a774f..86b4297 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/FakeShadowDrawable.java
+++ b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/FakeShadowDrawable.java
@@ -30,7 +30,7 @@
 import android.util.Log;
 
 import com.android.systemui.R;
-import com.android.systemui.recents.Recents;
+import com.android.systemui.recents.LegacyRecentsImpl;
 import com.android.systemui.recents.RecentsConfiguration;
 
 /**
@@ -91,7 +91,7 @@
         mCornerShadowPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
         mCornerShadowPaint.setStyle(Paint.Style.FILL);
         mCornerShadowPaint.setDither(true);
-        mCornerRadius = Recents.getConfiguration().isGridEnabled ?
+        mCornerRadius = LegacyRecentsImpl.getConfiguration().isGridEnabled ?
                 resources.getDimensionPixelSize(
                     R.dimen.recents_grid_task_view_rounded_corners_radius) :
                 resources.getDimensionPixelSize(R.dimen.recents_task_view_rounded_corners_radius);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/FixedSizeFrameLayout.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/FixedSizeFrameLayout.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/views/FixedSizeFrameLayout.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/FixedSizeFrameLayout.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/FixedSizeImageView.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/FixedSizeImageView.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/views/FixedSizeImageView.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/FixedSizeImageView.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsEntrancePathInterpolator.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/RecentsEntrancePathInterpolator.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/views/RecentsEntrancePathInterpolator.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/RecentsEntrancePathInterpolator.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionComposer.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/RecentsTransitionComposer.java
similarity index 97%
rename from packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionComposer.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/RecentsTransitionComposer.java
index 1c47430..ce66318 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionComposer.java
+++ b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/RecentsTransitionComposer.java
@@ -24,11 +24,10 @@
 
 import android.content.Context;
 import android.graphics.Bitmap;
-import android.graphics.GraphicBuffer;
 import android.graphics.Rect;
 import android.util.Log;
 
-import com.android.systemui.recents.Recents;
+import com.android.systemui.recents.LegacyRecentsImpl;
 import com.android.systemui.recents.RecentsDebugFlags;
 import com.android.systemui.shared.recents.model.Task;
 import com.android.systemui.shared.recents.view.AppTransitionAnimationSpecCompat;
@@ -71,7 +70,7 @@
         // height (stackView height) and when transitioning to fullscreen app, the code below would
         // force the task thumbnail to full stackView height immediately causing the transition
         // jarring.
-        if (!Recents.getConfiguration().isLowRamDevice && taskView.getTask() !=
+        if (!LegacyRecentsImpl.getConfiguration().isLowRamDevice && taskView.getTask() !=
                 stackView.getStack().getFrontMostTask()) {
             taskRect.bottom = taskRect.top + stackView.getMeasuredHeight();
         }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/RecentsView.java
similarity index 95%
rename from packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/RecentsView.java
index 5c925fd..0d758df 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/RecentsView.java
@@ -56,7 +56,7 @@
 import com.android.settingslib.Utils;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
-import com.android.systemui.recents.Recents;
+import com.android.systemui.recents.LegacyRecentsImpl;
 import com.android.systemui.recents.RecentsActivity;
 import com.android.systemui.recents.RecentsActivityLaunchState;
 import com.android.systemui.recents.RecentsConfiguration;
@@ -88,8 +88,8 @@
 import com.android.systemui.recents.misc.ReferenceCountedTrigger;
 import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.shared.recents.model.Task;
-import com.android.systemui.shared.recents.model.TaskStack;
-import com.android.systemui.shared.recents.utilities.Utilities;
+import com.android.systemui.recents.model.TaskStack;
+import com.android.systemui.recents.utilities.Utilities;
 import com.android.systemui.shared.recents.view.AppTransitionAnimationSpecCompat;
 import com.android.systemui.shared.recents.view.AppTransitionAnimationSpecsFuture;
 import com.android.systemui.shared.recents.view.RecentsTransition;
@@ -166,7 +166,7 @@
         super(context, attrs, defStyleAttr, defStyleRes);
         setWillNotDraw(false);
 
-        SystemServicesProxy ssp = Recents.getSystemServices();
+        SystemServicesProxy ssp = LegacyRecentsImpl.getSystemServices();
         mHandler = new Handler();
         mTransitionHelper = new RecentsTransitionComposer(getContext());
         mDividerSize = ssp.getDockedDividerSize(context);
@@ -182,7 +182,7 @@
         if (mStackActionButton != null) {
             removeView(mStackActionButton);
         }
-        mStackActionButton = (TextView) inflater.inflate(Recents.getConfiguration()
+        mStackActionButton = (TextView) inflater.inflate(LegacyRecentsImpl.getConfiguration()
                         .isLowRamDevice
                     ? R.layout.recents_low_ram_stack_action_button
                     : R.layout.recents_stack_action_button,
@@ -231,7 +231,7 @@
      * Called from RecentsActivity when it is relaunched.
      */
     public void onReload(TaskStack stack, boolean isResumingFromVisible) {
-        final RecentsConfiguration config = Recents.getConfiguration();
+        final RecentsConfiguration config = LegacyRecentsImpl.getConfiguration();
         final RecentsActivityLaunchState launchState = config.getLaunchState();
         final boolean isTaskStackEmpty = stack.getTaskCount() == 0;
 
@@ -350,7 +350,7 @@
 
     /** Launches the task that recents was launched from if possible */
     public boolean launchPreviousTask() {
-        if (Recents.getConfiguration().getLaunchState().launchedFromPipApp) {
+        if (LegacyRecentsImpl.getConfiguration().getLaunchState().launchedFromPipApp) {
             // If the app auto-entered PiP on the way to Recents, then just re-expand it
             EventBus.getDefault().send(new ExpandPipEvent());
             return true;
@@ -481,14 +481,14 @@
             mAwaitingFirstLayout = false;
             // If launched via dragging from the nav bar, then we should translate the whole view
             // down offscreen
-            RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
+            RecentsActivityLaunchState launchState = LegacyRecentsImpl.getConfiguration().getLaunchState();
             if (launchState.launchedViaDragGesture) {
                 setTranslationY(getMeasuredHeight());
             } else {
                 setTranslationY(0f);
             }
 
-            if (Recents.getConfiguration().isLowRamDevice
+            if (LegacyRecentsImpl.getConfiguration().isLowRamDevice
                     && mEmptyView.getVisibility() == View.VISIBLE) {
                 animateEmptyView(true /* show */, null /* postAnimationTrigger */);
             }
@@ -540,7 +540,7 @@
     public final void onBusEvent(LaunchTaskEvent event) {
         launchTaskFromRecents(getStack(), event.task, mTaskStackView, event.taskView,
                 event.screenPinningRequested, event.targetWindowingMode, event.targetActivityType);
-        if (Recents.getConfiguration().isLowRamDevice) {
+        if (LegacyRecentsImpl.getConfiguration().isLowRamDevice) {
             EventBus.getDefault().send(new HideStackActionButtonEvent(false /* translate */));
         }
     }
@@ -551,13 +551,13 @@
         EventBus.getDefault().send(new HideStackActionButtonEvent());
         animateBackgroundScrim(0f, taskViewExitToHomeDuration);
 
-        if (Recents.getConfiguration().isLowRamDevice) {
+        if (LegacyRecentsImpl.getConfiguration().isLowRamDevice) {
             animateEmptyView(false /* show */, event.getAnimationTrigger());
         }
     }
 
     public final void onBusEvent(DragStartEvent event) {
-        updateVisibleDockRegions(Recents.getConfiguration().getDockStatesForCurrentOrientation(),
+        updateVisibleDockRegions(LegacyRecentsImpl.getConfiguration().getDockStatesForCurrentOrientation(),
                 true /* isDefaultDockState */, DockState.NONE.viewState.dockAreaAlpha,
                 DockState.NONE.viewState.hintTextAlpha,
                 true /* animateAlpha */, false /* animateBounds */);
@@ -575,7 +575,7 @@
     public final void onBusEvent(DragDropTargetChangedEvent event) {
         if (event.dropTarget == null || !(event.dropTarget instanceof DockState)) {
             updateVisibleDockRegions(
-                    Recents.getConfiguration().getDockStatesForCurrentOrientation(),
+                    LegacyRecentsImpl.getConfiguration().getDockStatesForCurrentOrientation(),
                     true /* isDefaultDockState */, DockState.NONE.viewState.dockAreaAlpha,
                     DockState.NONE.viewState.hintTextAlpha,
                     true /* animateAlpha */, true /* animateBounds */);
@@ -695,7 +695,7 @@
     }
 
     public final void onBusEvent(EnterRecentsWindowAnimationCompletedEvent event) {
-        RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
+        RecentsActivityLaunchState launchState = LegacyRecentsImpl.getConfiguration().getLaunchState();
         if (!launchState.launchedViaDockGesture && !launchState.launchedFromApp
                 && getStack().getTaskCount() > 0) {
             animateBackgroundScrim(getOpaqueScrimAlpha(),
@@ -708,7 +708,7 @@
     }
 
     public final void onBusEvent(DismissAllTaskViewsEvent event) {
-        SystemServicesProxy ssp = Recents.getSystemServices();
+        SystemServicesProxy ssp = LegacyRecentsImpl.getSystemServices();
         if (!ssp.hasDockedTask()) {
             // Animate the background away only if we are dismissing Recents to home
             animateBackgroundScrim(0f, DEFAULT_UPDATE_SCRIM_DURATION);
@@ -741,7 +741,7 @@
             mStackActionButton.setAlpha(0f);
             if (translate) {
                 mStackActionButton.setTranslationY(mStackActionButton.getMeasuredHeight() *
-                        (Recents.getConfiguration().isLowRamDevice ? 1 : -0.25f));
+                        (LegacyRecentsImpl.getConfiguration().isLowRamDevice ? 1 : -0.25f));
             } else {
                 mStackActionButton.setTranslationY(0f);
             }
@@ -780,7 +780,7 @@
         if (mStackActionButton.getVisibility() == View.VISIBLE) {
             if (translate) {
                 mStackActionButton.animate().translationY(mStackActionButton.getMeasuredHeight()
-                        * (Recents.getConfiguration().isLowRamDevice ? 1 : -0.25f));
+                        * (LegacyRecentsImpl.getConfiguration().isLowRamDevice ? 1 : -0.25f));
             }
             mStackActionButton.animate()
                     .alpha(0f)
@@ -896,8 +896,8 @@
         Rect actionButtonRect = new Rect(
                 mTaskStackView.mLayoutAlgorithm.getStackActionButtonRect());
         int left, top;
-        if (Recents.getConfiguration().isLowRamDevice) {
-            Rect windowRect = Recents.getSystemServices().getWindowRect();
+        if (LegacyRecentsImpl.getConfiguration().isLowRamDevice) {
+            Rect windowRect = LegacyRecentsImpl.getSystemServices().getWindowRect();
             int spaceLeft = windowRect.width() - mSystemInsets.left - mSystemInsets.right;
             left = (spaceLeft - mStackActionButton.getMeasuredWidth()) / 2 + mSystemInsets.left;
             top = windowRect.height() - (mStackActionButton.getMeasuredHeight()
@@ -932,7 +932,7 @@
 
             // Fetch window rect here already in order not to be blocked on lock contention in WM
             // when the future calls it.
-            final Rect windowRect = Recents.getSystemServices().getWindowRect();
+            final Rect windowRect = LegacyRecentsImpl.getSystemServices().getWindowRect();
             transitionFuture = new AppTransitionAnimationSpecsFuture(stackView.getHandler()) {
                 @Override
                 public List<AppTransitionAnimationSpecCompat> composeSpecs() {
@@ -964,7 +964,7 @@
                         }, 350);
                     }
 
-                    if (!Recents.getConfiguration().isLowRamDevice) {
+                    if (!LegacyRecentsImpl.getConfiguration().isLowRamDevice) {
                         // Reset the state where we are waiting for the transition to start
                         EventBus.getDefault().send(new SetWaitingForTransitionStartEvent(false));
                     }
@@ -989,7 +989,7 @@
                     EventBus.getDefault().send(new ExitRecentsWindowFirstAnimationFrameEvent());
                     stackView.cancelAllTaskViewAnimations();
 
-                    if (!Recents.getConfiguration().isLowRamDevice) {
+                    if (!LegacyRecentsImpl.getConfiguration().isLowRamDevice) {
                         // Reset the state where we are waiting for the transition to start
                         EventBus.getDefault().send(new SetWaitingForTransitionStartEvent(false));
                     }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java
similarity index 97%
rename from packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java
index 53a91e5..1a827d5 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java
+++ b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java
@@ -16,7 +16,6 @@
 
 package com.android.systemui.recents.views;
 
-import android.app.ActivityManager;
 import android.app.ActivityTaskManager;
 import android.graphics.Point;
 import android.graphics.Rect;
@@ -28,7 +27,7 @@
 import android.view.ViewDebug;
 
 import com.android.internal.policy.DividerSnapAlgorithm;
-import com.android.systemui.recents.Recents;
+import com.android.systemui.recents.LegacyRecentsImpl;
 import com.android.systemui.recents.events.EventBus;
 import com.android.systemui.recents.events.activity.ConfigurationChangedEvent;
 import com.android.systemui.recents.events.activity.HideRecentsEvent;
@@ -115,7 +114,7 @@
     /**** Events ****/
 
     public final void onBusEvent(DragStartEvent event) {
-        SystemServicesProxy ssp = Recents.getSystemServices();
+        SystemServicesProxy ssp = LegacyRecentsImpl.getSystemServices();
         mRv.getParent().requestDisallowInterceptTouchEvent(true);
         mDragRequested = true;
         // We defer starting the actual drag handling until the user moves past the drag slop
@@ -140,13 +139,13 @@
         mVisibleDockStates.clear();
         if (ActivityTaskManager.supportsMultiWindow(mRv.getContext()) && !ssp.hasDockedTask()
                 && mDividerSnapAlgorithm.isSplitScreenFeasible()) {
-            Recents.logDockAttempt(mRv.getContext(), event.task.getTopComponent(),
+            LegacyRecentsImpl.logDockAttempt(mRv.getContext(), event.task.getTopComponent(),
                     event.task.resizeMode);
             if (!event.task.isDockable) {
                 EventBus.getDefault().send(new ShowIncompatibleAppOverlayEvent());
             } else {
                 // Add the dock state drop targets (these take priority)
-                DockState[] dockStates = Recents.getConfiguration()
+                DockState[] dockStates = LegacyRecentsImpl.getConfiguration()
                         .getDockStatesForCurrentOrientation();
                 for (DockState dockState : dockStates) {
                     registerDropTargetForCurrentDrag(dockState);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/SystemBarScrimViews.java
similarity index 94%
rename from packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/SystemBarScrimViews.java
index 170e39d..22c12b4 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java
+++ b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/SystemBarScrimViews.java
@@ -21,7 +21,7 @@
 
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
-import com.android.systemui.recents.Recents;
+import com.android.systemui.recents.LegacyRecentsImpl;
 import com.android.systemui.recents.RecentsActivity;
 import com.android.systemui.recents.events.activity.ConfigurationChangedEvent;
 import com.android.systemui.recents.events.activity.DismissRecentsToHomeAnimationStarted;
@@ -30,7 +30,7 @@
 import com.android.systemui.recents.events.activity.MultiWindowStateChangedEvent;
 import com.android.systemui.recents.events.ui.dragndrop.DragEndCancelledEvent;
 import com.android.systemui.recents.events.ui.dragndrop.DragEndEvent;
-import com.android.systemui.shared.recents.utilities.AnimationProps;
+import com.android.systemui.recents.utilities.AnimationProps;
 
 /** Manages the scrims for the various system bars. */
 public class SystemBarScrimViews {
@@ -53,8 +53,8 @@
         mNavBarScrimView.forceHasOverlappingRendering(false);
         mNavBarScrimEnterDuration = activity.getResources().getInteger(
                 R.integer.recents_nav_bar_scrim_enter_duration);
-        mHasNavBarScrim = Recents.getSystemServices().hasTransposedNavigationBar();
-        mHasDockedTasks = Recents.getSystemServices().hasDockedTask();
+        mHasNavBarScrim = LegacyRecentsImpl.getSystemServices().hasTransposedNavigationBar();
+        mHasDockedTasks = LegacyRecentsImpl.getSystemServices().hasDockedTask();
     }
 
     /**
@@ -147,7 +147,7 @@
 
     public final void onBusEvent(ConfigurationChangedEvent event) {
         if (event.fromDeviceOrientationChange) {
-            mHasNavBarScrim = Recents.getSystemServices().hasTransposedNavigationBar();
+            mHasNavBarScrim = LegacyRecentsImpl.getSystemServices().hasTransposedNavigationBar();
         }
         animateScrimToCurrentNavBarState(event.hasStackTasks);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
similarity index 97%
rename from packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
index 67d0978..5574934 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
+++ b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
@@ -28,7 +28,7 @@
 
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
-import com.android.systemui.recents.Recents;
+import com.android.systemui.recents.LegacyRecentsImpl;
 import com.android.systemui.recents.RecentsActivityLaunchState;
 import com.android.systemui.recents.RecentsConfiguration;
 import com.android.systemui.recents.RecentsDebugFlags;
@@ -36,9 +36,9 @@
 import com.android.systemui.recents.events.component.SetWaitingForTransitionStartEvent;
 import com.android.systemui.recents.misc.ReferenceCountedTrigger;
 import com.android.systemui.shared.recents.model.Task;
-import com.android.systemui.shared.recents.model.TaskStack;
+import com.android.systemui.recents.model.TaskStack;
 import com.android.systemui.recents.views.lowram.TaskStackLowRamLayoutAlgorithm;
-import com.android.systemui.shared.recents.utilities.AnimationProps;
+import com.android.systemui.recents.utilities.AnimationProps;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -115,7 +115,7 @@
 
     public TaskStackAnimationHelper(Context context, TaskStackView stackView) {
         mStackView = stackView;
-        mEnterAndExitFromHomeTranslationOffset = Recents.getConfiguration().isGridEnabled
+        mEnterAndExitFromHomeTranslationOffset = LegacyRecentsImpl.getConfiguration().isGridEnabled
                 ? 0 : DOUBLE_FRAME_OFFSET_MS;
     }
 
@@ -124,7 +124,7 @@
      * the in-app enter animations start (after the window-transition completes).
      */
     public void prepareForEnterAnimation() {
-        RecentsConfiguration config = Recents.getConfiguration();
+        RecentsConfiguration config = LegacyRecentsImpl.getConfiguration();
         RecentsActivityLaunchState launchState = config.getLaunchState();
         Resources res = mStackView.getResources();
         Resources appResources = mStackView.getContext().getApplicationContext().getResources();
@@ -148,7 +148,7 @@
                 == Configuration.ORIENTATION_LANDSCAPE;
 
         float top = 0;
-        final boolean isLowRamDevice = Recents.getConfiguration().isLowRamDevice;
+        final boolean isLowRamDevice = LegacyRecentsImpl.getConfiguration().isLowRamDevice;
         if (isLowRamDevice && launchState.launchedFromApp && !launchState.launchedViaDockGesture) {
             stackLayout.getStackTransform(launchTargetTask, stackScroller.getStackScroll(),
                     mTmpTransform, null /* frontTransform */);
@@ -212,7 +212,7 @@
      * depending on how Recents was triggered.
      */
     public void startEnterAnimation(final ReferenceCountedTrigger postAnimationTrigger) {
-        RecentsConfiguration config = Recents.getConfiguration();
+        RecentsConfiguration config = LegacyRecentsImpl.getConfiguration();
         RecentsActivityLaunchState launchState = config.getLaunchState();
         Resources res = mStackView.getResources();
         Resources appRes = mStackView.getContext().getApplicationContext().getResources();
@@ -227,7 +227,7 @@
             return;
         }
 
-        final boolean isLowRamDevice = Recents.getConfiguration().isLowRamDevice;
+        final boolean isLowRamDevice = LegacyRecentsImpl.getConfiguration().isLowRamDevice;
         int taskViewEnterFromAppDuration = res.getInteger(
                 R.integer.recents_task_enter_from_app_duration);
         int taskViewEnterFromAffiliatedAppDuration = res.getInteger(
@@ -342,7 +342,7 @@
                 taskAnimation = new AnimationProps()
                         .setDuration(AnimationProps.BOUNDS, EXIT_TO_HOME_TRANSLATION_DURATION)
                         .setListener(postAnimationTrigger.decrementOnAnimationEnd());
-                if (Recents.getConfiguration().isLowRamDevice) {
+                if (LegacyRecentsImpl.getConfiguration().isLowRamDevice) {
                     taskAnimation.setInterpolator(AnimationProps.BOUNDS,
                             Interpolators.FAST_OUT_SLOW_IN);
                 } else {
@@ -356,7 +356,7 @@
             }
 
             mTmpTransform.fillIn(tv);
-            if (Recents.getConfiguration().isLowRamDevice) {
+            if (LegacyRecentsImpl.getConfiguration().isLowRamDevice) {
                 taskAnimation.setInterpolator(AnimationProps.ALPHA,
                                 EXIT_TO_HOME_TRANSLATION_INTERPOLATOR)
                         .setDuration(AnimationProps.ALPHA, EXIT_TO_HOME_TRANSLATION_DURATION);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
similarity index 95%
rename from packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
index d9f79bb..58a3f12 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
+++ b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
@@ -29,15 +29,15 @@
 import android.view.ViewDebug;
 
 import com.android.systemui.R;
-import com.android.systemui.recents.Recents;
+import com.android.systemui.recents.LegacyRecentsImpl;
 import com.android.systemui.recents.RecentsActivityLaunchState;
 import com.android.systemui.recents.RecentsConfiguration;
 import com.android.systemui.recents.RecentsDebugFlags;
 import com.android.systemui.recents.misc.FreePathInterpolator;
 import com.android.systemui.recents.misc.SystemServicesProxy;
-import com.android.systemui.shared.recents.utilities.Utilities;
+import com.android.systemui.recents.utilities.Utilities;
 import com.android.systemui.shared.recents.model.Task;
-import com.android.systemui.shared.recents.model.TaskStack;
+import com.android.systemui.recents.model.TaskStack;
 import com.android.systemui.recents.views.lowram.TaskStackLowRamLayoutAlgorithm;
 import com.android.systemui.recents.views.grid.TaskGridLayoutAlgorithm;
 
@@ -149,7 +149,7 @@
      * @return True if we should use the grid layout.
      */
     boolean useGridLayout() {
-        return Recents.getConfiguration().isGridEnabled;
+        return LegacyRecentsImpl.getConfiguration().isGridEnabled;
     }
 
     // A report of the visibility state of the stack
@@ -432,7 +432,7 @@
      */
     public void update(TaskStack stack, ArraySet<Task.TaskKey> ignoreTasksSet,
             RecentsActivityLaunchState launchState, float lastScrollPPercent) {
-        SystemServicesProxy ssp = Recents.getSystemServices();
+        SystemServicesProxy ssp = LegacyRecentsImpl.getSystemServices();
 
         // Clear the progress map
         mTaskIndexMap.clear();
@@ -494,10 +494,10 @@
             int maxBottomOffset = mStackBottomOffset + mTaskRect.height();
             float maxBottomNormX = getNormalizedXFromUnfocusedY(maxBottomOffset, FROM_BOTTOM);
             mUnfocusedRange.offset(0f);
-            mMinScrollP = Recents.getConfiguration().isLowRamDevice
+            mMinScrollP = LegacyRecentsImpl.getConfiguration().isLowRamDevice
                     ? mTaskStackLowRamLayoutAlgorithm.getMinScrollP()
                     : 0;
-            mMaxScrollP = Recents.getConfiguration().isLowRamDevice
+            mMaxScrollP = LegacyRecentsImpl.getConfiguration().isLowRamDevice
                     ? mTaskStackLowRamLayoutAlgorithm.getMaxScrollP(taskCount)
                     : Math.max(mMinScrollP, (mNumStackTasks - 1) -
                     Math.max(0, mUnfocusedRange.getAbsoluteX(maxBottomNormX)));
@@ -508,7 +508,7 @@
                 mInitialScrollP = Utilities.clamp(launchTaskIndex, mMinScrollP, mMaxScrollP);
             } else if (0 <= lastScrollPPercent && lastScrollPPercent <= 1) {
                 mInitialScrollP = Utilities.mapRange(lastScrollPPercent, mMinScrollP, mMaxScrollP);
-            } else if (Recents.getConfiguration().isLowRamDevice) {
+            } else if (LegacyRecentsImpl.getConfiguration().isLowRamDevice) {
                 mInitialScrollP = mTaskStackLowRamLayoutAlgorithm.getInitialScrollP(mNumStackTasks,
                         scrollToFront);
             } else if (scrollToFront) {
@@ -527,7 +527,7 @@
      * Creates task overrides to ensure the initial stack layout if necessary.
      */
     public void setTaskOverridesForInitialState(TaskStack stack, boolean ignoreScrollToFront) {
-        RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
+        RecentsActivityLaunchState launchState = LegacyRecentsImpl.getConfiguration().getLaunchState();
 
         mTaskIndexOverrideMap.clear();
 
@@ -620,7 +620,7 @@
      */
     public float updateFocusStateOnScroll(float lastTargetStackScroll, float targetStackScroll,
             float lastStackScroll) {
-        if (targetStackScroll == lastStackScroll || Recents.getConfiguration().isLowRamDevice) {
+        if (targetStackScroll == lastStackScroll || LegacyRecentsImpl.getConfiguration().isLowRamDevice) {
             return targetStackScroll;
         }
 
@@ -665,8 +665,8 @@
      * Returns the default focus state.
      */
     public int getInitialFocusState() {
-        RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
-        RecentsDebugFlags debugFlags = Recents.getDebugFlags();
+        RecentsActivityLaunchState launchState = LegacyRecentsImpl.getConfiguration().getLaunchState();
+        RecentsDebugFlags debugFlags = LegacyRecentsImpl.getDebugFlags();
         if (launchState.launchedWithAltTab) {
             return STATE_FOCUSED;
         } else {
@@ -709,7 +709,7 @@
             return mTaskGridLayoutAlgorithm.computeStackVisibilityReport(tasks);
         }
 
-        if (Recents.getConfiguration().isLowRamDevice) {
+        if (LegacyRecentsImpl.getConfiguration().isLowRamDevice) {
             return mTaskStackLowRamLayoutAlgorithm.computeStackVisibilityReport(tasks);
         }
 
@@ -786,7 +786,7 @@
             int taskCount = mTaskIndexMap.size();
             mTaskGridLayoutAlgorithm.getTransform(taskIndex, taskCount, transformOut, this);
             return transformOut;
-        } else if (Recents.getConfiguration().isLowRamDevice) {
+        } else if (LegacyRecentsImpl.getConfiguration().isLowRamDevice) {
             if (task == null) {
                 transformOut.reset();
                 return transformOut;
@@ -832,7 +832,7 @@
             Rect windowOverrideRect) {
         Rect windowRect = windowOverrideRect != null
                 ? windowOverrideRect
-                : Recents.getSystemServices().getWindowRect();
+                : LegacyRecentsImpl.getSystemServices().getWindowRect();
         transformOut.rect.offset(windowRect.left, windowRect.top);
         if (useGridLayout()) {
             // Draw the thumbnail a little lower to perfectly coincide with the view we are
@@ -853,7 +853,7 @@
     public void getStackTransform(float taskProgress, float nonOverrideTaskProgress,
             float stackScroll, int focusState, TaskViewTransform transformOut,
             TaskViewTransform frontTransform, boolean ignoreSingleTaskCase, boolean forceUpdate) {
-        SystemServicesProxy ssp = Recents.getSystemServices();
+        SystemServicesProxy ssp = LegacyRecentsImpl.getSystemServices();
 
         // Ensure that the task is in range
         mUnfocusedRange.offset(stackScroll);
@@ -932,10 +932,12 @@
                 }
             }
             y = (mStackRect.top - mTaskRect.top) +
-                    (int) Utilities.mapRange(focusState, unfocusedY, focusedY);
+                    (int) com.android.systemui.recents.utilities.Utilities
+                            .mapRange(focusState, unfocusedY, focusedY);
             z = Utilities.mapRange(Utilities.clamp01(boundedScrollUnfocusedNonOverrideRangeX),
                     mMinTranslationZ, mMaxTranslationZ);
-            dimAlpha = Utilities.mapRange(focusState, unfocusedDim, focusedDim);
+            dimAlpha = com.android.systemui.recents.utilities.Utilities
+                    .mapRange(focusState, unfocusedDim, focusedDim);
             viewOutlineAlpha = Utilities.mapRange(Utilities.clamp01(boundedScrollUnfocusedRangeX),
                     OUTLINE_ALPHA_MIN_VALUE, OUTLINE_ALPHA_MAX_VALUE);
         }
@@ -966,7 +968,7 @@
      */
     float getStackScrollForTask(Task t) {
         Float overrideP = mTaskIndexOverrideMap.get(t.key.id, null);
-        if (Recents.getConfiguration().isLowRamDevice || overrideP == null) {
+        if (LegacyRecentsImpl.getConfiguration().isLowRamDevice || overrideP == null) {
             return (float) mTaskIndexMap.get(t.key.id, 0);
         }
         return overrideP;
@@ -985,8 +987,8 @@
      * offset (which is at the task's brightest point).
      */
     float getStackScrollForTaskAtInitialOffset(Task t) {
-        if (Recents.getConfiguration().isLowRamDevice) {
-            RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
+        if (LegacyRecentsImpl.getConfiguration().isLowRamDevice) {
+            RecentsActivityLaunchState launchState = LegacyRecentsImpl.getConfiguration().getLaunchState();
             return mTaskStackLowRamLayoutAlgorithm.getInitialScrollP(mNumStackTasks,
                     launchState.launchedFromHome || launchState.launchedFromPipApp
                             || launchState.launchedWithNextPipApp);
@@ -1003,7 +1005,7 @@
      * screen along the arc-length proportionally (1/arclength).
      */
     public float getDeltaPForY(int downY, int y) {
-        if (Recents.getConfiguration().isLowRamDevice) {
+        if (LegacyRecentsImpl.getConfiguration().isLowRamDevice) {
             return mTaskStackLowRamLayoutAlgorithm.scrollToPercentage(downY - y);
         }
         float deltaP = (float) (y - downY) / mStackRect.height() *
@@ -1016,7 +1018,7 @@
      * of the curve, map back to the screen y.
      */
     public int getYForDeltaP(float downScrollP, float p) {
-        if (Recents.getConfiguration().isLowRamDevice) {
+        if (LegacyRecentsImpl.getConfiguration().isLowRamDevice) {
             return mTaskStackLowRamLayoutAlgorithm.percentageToScroll(downScrollP - p);
         }
         int y = (int) ((p - downScrollP) * mStackRect.height() *
@@ -1068,7 +1070,7 @@
     public static int getDimensionForDevice(Context ctx, int phonePortResId, int phoneLandResId,
             int tabletPortResId, int tabletLandResId, int xlargeTabletPortResId,
             int xlargeTabletLandResId, int gridLayoutResId) {
-        RecentsConfiguration config = Recents.getConfiguration();
+        RecentsConfiguration config = LegacyRecentsImpl.getConfiguration();
         Resources res = ctx.getResources();
         boolean isLandscape = Utilities.getAppConfiguration(ctx).orientation ==
                 Configuration.ORIENTATION_LANDSCAPE;
@@ -1211,7 +1213,7 @@
         if (mStackRect.isEmpty()) {
             return;
         }
-        if (Recents.getConfiguration().isLowRamDevice) {
+        if (LegacyRecentsImpl.getConfiguration().isLowRamDevice) {
             mTaskStackLowRamLayoutAlgorithm.getBackOfStackTransform(mBackOfStackTransform, this);
             mTaskStackLowRamLayoutAlgorithm.getFrontOfStackTransform(mFrontOfStackTransform, this);
             return;
@@ -1233,7 +1235,7 @@
      * Returns the proper task rectangle according to the current grid state.
      */
     public Rect getTaskRect() {
-        if (Recents.getConfiguration().isLowRamDevice) {
+        if (LegacyRecentsImpl.getConfiguration().isLowRamDevice) {
             return mTaskStackLowRamLayoutAlgorithm.getTaskRect();
         }
         return useGridLayout() ? mTaskGridLayoutAlgorithm.getTaskGridRect() : mTaskRect;
@@ -1250,7 +1252,8 @@
         writer.print("insets="); writer.print(Utilities.dumpRect(mSystemInsets));
         writer.print(" stack="); writer.print(Utilities.dumpRect(mStackRect));
         writer.print(" task="); writer.print(Utilities.dumpRect(mTaskRect));
-        writer.print(" actionButton="); writer.print(Utilities.dumpRect(mStackActionButtonRect));
+        writer.print(" actionButton="); writer.print(
+                Utilities.dumpRect(mStackActionButtonRect));
         writer.println();
 
         writer.print(innerPrefix);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/TaskStackView.java
similarity index 97%
rename from packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/TaskStackView.java
index 89288d8..14fd149 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/TaskStackView.java
@@ -26,7 +26,6 @@
 import android.content.res.Resources;
 import android.graphics.Rect;
 import android.os.Bundle;
-import android.provider.Settings;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.MutableBoolean;
@@ -44,7 +43,7 @@
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
-import com.android.systemui.recents.Recents;
+import com.android.systemui.recents.LegacyRecentsImpl;
 import com.android.systemui.recents.RecentsActivity;
 import com.android.systemui.recents.RecentsActivityLaunchState;
 import com.android.systemui.recents.RecentsConfiguration;
@@ -87,10 +86,10 @@
 import com.android.systemui.recents.misc.DozeTrigger;
 import com.android.systemui.recents.misc.ReferenceCountedTrigger;
 import com.android.systemui.recents.misc.SystemServicesProxy;
-import com.android.systemui.shared.recents.utilities.AnimationProps;
-import com.android.systemui.shared.recents.utilities.Utilities;
+import com.android.systemui.recents.utilities.AnimationProps;
+import com.android.systemui.recents.utilities.Utilities;
 import com.android.systemui.shared.recents.model.Task;
-import com.android.systemui.shared.recents.model.TaskStack;
+import com.android.systemui.recents.model.TaskStack;
 import com.android.systemui.recents.views.grid.GridTaskView;
 import com.android.systemui.recents.views.grid.TaskGridLayoutAlgorithm;
 import com.android.systemui.recents.views.grid.TaskViewFocusFrame;
@@ -247,7 +246,7 @@
 
     public TaskStackView(Context context) {
         super(context);
-        SystemServicesProxy ssp = Recents.getSystemServices();
+        SystemServicesProxy ssp = LegacyRecentsImpl.getSystemServices();
         Resources res = context.getResources();
 
         // Set the stack first
@@ -259,7 +258,7 @@
         mStackScroller = new TaskStackViewScroller(context, this, mLayoutAlgorithm);
         mTouchHandler = new TaskStackViewTouchHandler(context, this, mStackScroller);
         mAnimationHelper = new TaskStackAnimationHelper(context, this);
-        mTaskCornerRadiusPx = Recents.getConfiguration().isGridEnabled ?
+        mTaskCornerRadiusPx = LegacyRecentsImpl.getConfiguration().isGridEnabled ?
                 res.getDimensionPixelSize(R.dimen.recents_grid_task_view_rounded_corners_radius) :
                 res.getDimensionPixelSize(R.dimen.recents_task_view_rounded_corners_radius);
         mFastFlingVelocity = res.getDimensionPixelSize(R.dimen.recents_fast_fling_velocity);
@@ -269,7 +268,7 @@
         mStackActionButtonVisible = false;
 
         // Create a frame to draw around the focused task view
-        if (Recents.getConfiguration().isGridEnabled) {
+        if (LegacyRecentsImpl.getConfiguration().isGridEnabled) {
             mTaskViewFocusFrame = new TaskViewFocusFrame(mContext, this,
                 mLayoutAlgorithm.mTaskGridLayoutAlgorithm);
             addView(mTaskViewFocusFrame);
@@ -762,7 +761,7 @@
      */
     private void clipTaskViews() {
         // We never clip task views in grid layout
-        if (Recents.getConfiguration().isGridEnabled) {
+        if (LegacyRecentsImpl.getConfiguration().isGridEnabled) {
             return;
         }
 
@@ -816,7 +815,7 @@
     }
 
     public void updateLayoutAlgorithm(boolean boundScrollToNewMinMax) {
-        updateLayoutAlgorithm(boundScrollToNewMinMax, Recents.getConfiguration().getLaunchState());
+        updateLayoutAlgorithm(boundScrollToNewMinMax, LegacyRecentsImpl.getConfiguration().getLaunchState());
     }
 
     /**
@@ -1142,7 +1141,7 @@
         if (mStackScroller.computeScroll()) {
             // Notify accessibility
             sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
-            Recents.getTaskLoader().getHighResThumbnailLoader().setFlingingFast(
+            LegacyRecentsImpl.getTaskLoader().getHighResThumbnailLoader().setFlingingFast(
                     mStackScroller.getScrollVelocity() > mFastFlingVelocity);
         }
         if (mDeferredTaskViewLayoutAnimation != null) {
@@ -1327,7 +1326,7 @@
 
         // Set the task focused state without requesting view focus, and leave the focus animations
         // until after the enter-animation
-        RecentsConfiguration config = Recents.getConfiguration();
+        RecentsConfiguration config = LegacyRecentsImpl.getConfiguration();
         RecentsActivityLaunchState launchState = config.getLaunchState();
 
         // We set the initial focused task view iff the following conditions are satisfied:
@@ -1474,7 +1473,7 @@
 
     @Override
     public TaskView createView(Context context) {
-        if (Recents.getConfiguration().isGridEnabled) {
+        if (LegacyRecentsImpl.getConfiguration().isGridEnabled) {
             return (GridTaskView) mInflater.inflate(R.layout.recents_grid_task_view, this, false);
         } else {
             return (TaskView) mInflater.inflate(R.layout.recents_task_view, this, false);
@@ -1565,7 +1564,7 @@
 
         // If the doze trigger has already fired, then update the state for this task view
         if (mUIDozeTrigger.isAsleep() ||
-                useGridLayout() || Recents.getConfiguration().isLowRamDevice) {
+                useGridLayout() || LegacyRecentsImpl.getConfiguration().isLowRamDevice) {
             tv.setNoUserInteractionState();
         }
 
@@ -1573,17 +1572,17 @@
             task.notifyTaskDataLoaded(task.thumbnail, task.icon);
         } else {
             // Load the task data
-            Recents.getTaskLoader().loadTaskData(task);
+            LegacyRecentsImpl.getTaskLoader().loadTaskData(task);
         }
-        Recents.getTaskLoader().getHighResThumbnailLoader().onTaskVisible(task);
+        LegacyRecentsImpl.getTaskLoader().getHighResThumbnailLoader().onTaskVisible(task);
     }
 
     private void unbindTaskView(TaskView tv, Task task) {
         if (task != mPrefetchingTask) {
             // Report that this task's data is no longer being used
-            Recents.getTaskLoader().unloadTaskData(task);
+            LegacyRecentsImpl.getTaskLoader().unloadTaskData(task);
         }
-        Recents.getTaskLoader().getHighResThumbnailLoader().onTaskInvisible(task);
+        LegacyRecentsImpl.getTaskLoader().getHighResThumbnailLoader().onTaskInvisible(task);
     }
 
     private void updatePrefetchingTask(ArrayList<Task> tasks, int frontIndex, int backIndex) {
@@ -1596,19 +1595,19 @@
             if (mPrefetchingTask != null) {
                 int index = tasks.indexOf(mPrefetchingTask);
                 if (index < backIndex || index > frontIndex) {
-                    Recents.getTaskLoader().unloadTaskData(mPrefetchingTask);
+                    LegacyRecentsImpl.getTaskLoader().unloadTaskData(mPrefetchingTask);
                 }
             }
             mPrefetchingTask = t;
             if (t != null) {
-                Recents.getTaskLoader().loadTaskData(t);
+                LegacyRecentsImpl.getTaskLoader().loadTaskData(t);
             }
         }
     }
 
     private void clearPrefetchingTask() {
         if (mPrefetchingTask != null) {
-            Recents.getTaskLoader().unloadTaskData(mPrefetchingTask);
+            LegacyRecentsImpl.getTaskLoader().unloadTaskData(mPrefetchingTask);
         }
         mPrefetchingTask = null;
     }
@@ -1644,7 +1643,7 @@
 
         // In grid layout, the stack action button always remains visible.
         if (mEnterAnimationComplete && !useGridLayout()) {
-            if (Recents.getConfiguration().isLowRamDevice) {
+            if (LegacyRecentsImpl.getConfiguration().isLowRamDevice) {
                 // Show stack button when user drags down to show older tasks on low ram devices
                 if (mStack.getTaskCount() > 0 && !mStackActionButtonVisible
                         && mTouchHandler.mIsScrolling && curScroll - prevScroll < 0) {
@@ -1727,7 +1726,7 @@
             return;
         }
 
-        if (!Recents.getConfiguration().getLaunchState().launchedFromPipApp
+        if (!LegacyRecentsImpl.getConfiguration().getLaunchState().launchedFromPipApp
                 && mStack.isNextLaunchTargetPip(RecentsImpl.getLastPipTime())) {
             // If the launch task is in the pinned stack, then expand the PiP now
             EventBus.getDefault().send(new ExpandPipEvent());
@@ -1831,7 +1830,7 @@
         // Remove the task from the stack
         mStack.removeTask(event.task, event.animation, false /* fromDockGesture */);
         EventBus.getDefault().send(new DeleteTaskDataEvent(event.task));
-        if (mStack.getTaskCount() > 0 && Recents.getConfiguration().isLowRamDevice) {
+        if (mStack.getTaskCount() > 0 && LegacyRecentsImpl.getConfiguration().isLowRamDevice) {
             EventBus.getDefault().send(new ShowStackActionButtonEvent(false /* translate */));
         }
 
@@ -1878,7 +1877,7 @@
         // Poke the doze trigger on user interaction
         mUIDozeTrigger.poke();
 
-        RecentsDebugFlags debugFlags = Recents.getDebugFlags();
+        RecentsDebugFlags debugFlags = LegacyRecentsImpl.getDebugFlags();
         if (mFocusedTask != null) {
             TaskView tv = getChildViewForTask(mFocusedTask);
             if (tv != null) {
@@ -2002,7 +2001,7 @@
                 // animate the focused state if we are alt-tabbing now, after the window enter
                 // animation is completed
                 if (mFocusedTask != null) {
-                    RecentsConfiguration config = Recents.getConfiguration();
+                    RecentsConfiguration config = LegacyRecentsImpl.getConfiguration();
                     RecentsActivityLaunchState launchState = config.getLaunchState();
                     setFocusedTask(mStack.indexOfTask(mFocusedTask),
                             false /* scrollToTask */, launchState.launchedWithAltTab);
@@ -2023,7 +2022,7 @@
             setTasks(event.stack, true /* allowNotifyStackChanges */);
         } else {
             // Reset the launch state before handling the multiwindow change
-            RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
+            RecentsActivityLaunchState launchState = LegacyRecentsImpl.getConfiguration().getLaunchState();
             launchState.reset();
 
             // Defer until the next frame to ensure that we have received all the system insets, and
@@ -2044,7 +2043,7 @@
     public final void onBusEvent(ConfigurationChangedEvent event) {
         if (event.fromDeviceOrientationChange) {
             mDisplayOrientation = Utilities.getAppConfiguration(mContext).orientation;
-            mDisplayRect = Recents.getSystemServices().getDisplayRect();
+            mDisplayRect = LegacyRecentsImpl.getSystemServices().getDisplayRect();
 
             // Always stop the scroller, otherwise, we may continue setting the stack scroll to the
             // wrong bounds in the new layout
@@ -2186,14 +2185,14 @@
      * Reads current system flags related to accessibility and screen pinning.
      */
     private void readSystemFlags() {
-        SystemServicesProxy ssp = Recents.getSystemServices();
+        SystemServicesProxy ssp = LegacyRecentsImpl.getSystemServices();
         mTouchExplorationEnabled = ssp.isTouchExplorationEnabled();
         mScreenPinningEnabled = ActivityManagerWrapper.getInstance().isScreenPinningEnabled()
                 && !ActivityManagerWrapper.getInstance().isLockToAppActive();
     }
 
     private void updateStackActionButtonVisibility() {
-        if (Recents.getConfiguration().isLowRamDevice) {
+        if (LegacyRecentsImpl.getConfiguration().isLowRamDevice) {
             return;
         }
 
@@ -2260,9 +2259,12 @@
         writer.print(" screenPinningOn="); writer.print(mScreenPinningEnabled ? "Y" : "N");
         writer.print(" numIgnoreTasks="); writer.print(mIgnoreTasks.size());
         writer.print(" numViewPool="); writer.print(mViewPool.getViews().size());
-        writer.print(" stableStackBounds="); writer.print(Utilities.dumpRect(mStableStackBounds));
-        writer.print(" stackBounds="); writer.print(Utilities.dumpRect(mStackBounds));
-        writer.print(" stableWindow="); writer.print(Utilities.dumpRect(mStableWindowRect));
+        writer.print(" stableStackBounds="); writer.print(
+                Utilities.dumpRect(mStableStackBounds));
+        writer.print(" stackBounds="); writer.print(
+                Utilities.dumpRect(mStackBounds));
+        writer.print(" stableWindow="); writer.print(
+                Utilities.dumpRect(mStableWindowRect));
         writer.print(" window="); writer.print(Utilities.dumpRect(mWindowRect));
         writer.print(" display="); writer.print(Utilities.dumpRect(mDisplayRect));
         writer.print(" orientation="); writer.print(mDisplayOrientation);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/TaskStackViewScroller.java
similarity index 97%
rename from packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/TaskStackViewScroller.java
index 6b23977..42efe59 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java
+++ b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/TaskStackViewScroller.java
@@ -31,9 +31,9 @@
 
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
-import com.android.systemui.recents.Recents;
-import com.android.systemui.shared.recents.utilities.AnimationProps;
-import com.android.systemui.shared.recents.utilities.Utilities;
+import com.android.systemui.recents.LegacyRecentsImpl;
+import com.android.systemui.recents.utilities.AnimationProps;
+import com.android.systemui.recents.utilities.Utilities;
 import com.android.systemui.recents.views.lowram.TaskStackLowRamLayoutAlgorithm;
 import com.android.systemui.statusbar.FlingAnimationUtils;
 
@@ -89,7 +89,7 @@
         mContext = context;
         mCb = cb;
         mScroller = new OverScroller(context);
-        if (Recents.getConfiguration().isLowRamDevice) {
+        if (LegacyRecentsImpl.getConfiguration().isLowRamDevice) {
             mScroller.setFriction(0.06f);
         }
         mLayoutAlgorithm = layoutAlgorithm;
@@ -206,7 +206,7 @@
         float stackScroll = getStackScroll();
 
         // Skip if not in low ram layout and if the scroll is out of min and max bounds
-        if (!Recents.getConfiguration().isLowRamDevice || stackScroll < mLayoutAlgorithm.mMinScrollP
+        if (!LegacyRecentsImpl.getConfiguration().isLowRamDevice || stackScroll < mLayoutAlgorithm.mMinScrollP
                 || stackScroll > mLayoutAlgorithm.mMaxScrollP) {
             return;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
similarity index 97%
rename from packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
index c91cdfc..dd6926c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
+++ b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
@@ -38,14 +38,14 @@
 import com.android.systemui.R;
 import com.android.systemui.SwipeHelper;
 import com.android.systemui.recents.Constants;
-import com.android.systemui.recents.Recents;
+import com.android.systemui.recents.LegacyRecentsImpl;
 import com.android.systemui.recents.events.EventBus;
 import com.android.systemui.recents.events.activity.HideRecentsEvent;
 import com.android.systemui.recents.events.ui.StackViewScrolledEvent;
 import com.android.systemui.recents.events.ui.TaskViewDismissedEvent;
 import com.android.systemui.recents.misc.FreePathInterpolator;
-import com.android.systemui.shared.recents.utilities.AnimationProps;
-import com.android.systemui.shared.recents.utilities.Utilities;
+import com.android.systemui.recents.utilities.AnimationProps;
+import com.android.systemui.recents.utilities.Utilities;
 import com.android.systemui.shared.recents.model.Task;
 import com.android.systemui.statusbar.FlingAnimationUtils;
 
@@ -296,7 +296,7 @@
                     if (curScrollP < minScrollP || curScrollP > maxScrollP) {
                         float clampedScrollP = Utilities.clamp(curScrollP, minScrollP, maxScrollP);
                         float overscrollP = (curScrollP - clampedScrollP);
-                        float maxOverscroll = Recents.getConfiguration().isLowRamDevice
+                        float maxOverscroll = LegacyRecentsImpl.getConfiguration().isLowRamDevice
                                 ? layoutAlgorithm.mTaskStackLowRamLayoutAlgorithm.getMaxOverscroll()
                                 : MAX_OVERSCROLL;
                         float overscrollX = Math.abs(overscrollP) / maxOverscroll;
@@ -339,7 +339,7 @@
                     if (mScroller.isScrollOutOfBounds()) {
                         mScroller.animateBoundScroll();
                     } else if (Math.abs(velocity) > mMinimumVelocity &&
-                            !Recents.getConfiguration().isLowRamDevice) {
+                            !LegacyRecentsImpl.getConfiguration().isLowRamDevice) {
                         float minY = mDownY + layoutAlgorithm.getYForDeltaP(mDownScrollP,
                                 layoutAlgorithm.mMaxScrollP);
                         float maxY = mDownY + layoutAlgorithm.getYForDeltaP(mDownScrollP,
@@ -352,7 +352,7 @@
                     // Reset the focused task after the user has scrolled, but we have no scrolling
                     // in grid layout and therefore we don't want to reset the focus there.
                     if (!mSv.mTouchExplorationEnabled && !mSv.useGridLayout()) {
-                        if (Recents.getConfiguration().isLowRamDevice) {
+                        if (LegacyRecentsImpl.getConfiguration().isLowRamDevice) {
                             mScroller.scrollToClosestTask(velocity);
                         } else {
                             mSv.resetFocusedTask(mSv.getFocusedTask());
@@ -493,7 +493,7 @@
             float prevAnchorTaskScroll = 0;
             boolean pullStackForward = mCurrentTasks.size() > 0;
             if (pullStackForward) {
-                if (Recents.getConfiguration().isLowRamDevice) {
+                if (LegacyRecentsImpl.getConfiguration().isLowRamDevice) {
                     float index = layoutAlgorithm.getStackScrollForTask(anchorTask);
                     prevAnchorTaskScroll = mSv.getStackAlgorithm().mTaskStackLowRamLayoutAlgorithm
                             .getScrollPForTask((int) index);
@@ -513,14 +513,14 @@
                 // Otherwise, offset the scroll by the movement of the anchor task
                 float anchorTaskScroll =
                         layoutAlgorithm.getStackScrollForTaskIgnoreOverrides(anchorTask);
-                if (Recents.getConfiguration().isLowRamDevice) {
+                if (LegacyRecentsImpl.getConfiguration().isLowRamDevice) {
                     float index = layoutAlgorithm.getStackScrollForTask(anchorTask);
                     anchorTaskScroll = mSv.getStackAlgorithm().mTaskStackLowRamLayoutAlgorithm
                             .getScrollPForTask((int) index);
                 }
                 float stackScrollOffset = (anchorTaskScroll - prevAnchorTaskScroll);
                 if (layoutAlgorithm.getFocusState() != TaskStackLayoutAlgorithm.STATE_FOCUSED
-                        && !Recents.getConfiguration().isLowRamDevice) {
+                        && !LegacyRecentsImpl.getConfiguration().isLowRamDevice) {
                     // If we are focused, we don't want the front task to move, but otherwise, we
                     // allow the back task to move up, and the front task to move back
                     stackScrollOffset *= 0.75f;
@@ -554,7 +554,7 @@
         // Only update the swipe progress for the surrounding tasks if the dismiss animation was not
         // preempted from a call to cancelNonDismissTaskAnimations
         if ((mActiveTaskView == v || mSwipeHelperAnimations.containsKey(v)) &&
-                !Recents.getConfiguration().isLowRamDevice) {
+                !LegacyRecentsImpl.getConfiguration().isLowRamDevice) {
             updateTaskViewTransforms(
                     Interpolators.FAST_OUT_SLOW_IN.getInterpolation(swipeProgress));
         }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/TaskView.java
similarity index 97%
rename from packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/TaskView.java
index f0278a6..ab0bf95 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/TaskView.java
@@ -39,7 +39,7 @@
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
-import com.android.systemui.recents.Recents;
+import com.android.systemui.recents.LegacyRecentsImpl;
 import com.android.systemui.recents.RecentsActivity;
 import com.android.systemui.recents.RecentsConfiguration;
 import com.android.systemui.recents.events.EventBus;
@@ -51,11 +51,10 @@
 import com.android.systemui.recents.events.ui.dragndrop.DragStartEvent;
 import com.android.systemui.recents.misc.ReferenceCountedTrigger;
 import com.android.systemui.recents.misc.SystemServicesProxy;
-import com.android.systemui.shared.recents.utilities.AnimationProps;
-import com.android.systemui.shared.recents.utilities.Utilities;
+import com.android.systemui.recents.utilities.AnimationProps;
+import com.android.systemui.recents.utilities.Utilities;
 import com.android.systemui.shared.recents.model.Task;
 import com.android.systemui.shared.recents.model.ThumbnailData;
-import com.android.systemui.shared.recents.view.AnimateableViewBounds;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -175,7 +174,7 @@
 
     public TaskView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
-        RecentsConfiguration config = Recents.getConfiguration();
+        RecentsConfiguration config = LegacyRecentsImpl.getConfiguration();
         Resources res = context.getResources();
         mViewBounds = createOutlineProvider();
         if (config.fakeShadows) {
@@ -283,7 +282,7 @@
 
     void updateViewPropertiesToTaskTransform(TaskViewTransform toTransform,
             AnimationProps toAnimation, ValueAnimator.AnimatorUpdateListener updateCallback) {
-        RecentsConfiguration config = Recents.getConfiguration();
+        RecentsConfiguration config = LegacyRecentsImpl.getConfiguration();
         cancelTransformAnimation();
 
         // Compose the animations for the transform
@@ -412,7 +411,7 @@
      * view.
      */
     boolean shouldClipViewInStack() {
-        if (getVisibility() != View.VISIBLE || Recents.getConfiguration().isLowRamDevice) {
+        if (getVisibility() != View.VISIBLE || LegacyRecentsImpl.getConfiguration().isLowRamDevice) {
             return false;
         }
         return mClipViewInStack;
@@ -601,7 +600,7 @@
 
     public void onTaskBound(Task t, boolean touchExplorationEnabled, int displayOrientation,
             Rect displayRect) {
-        SystemServicesProxy ssp = Recents.getSystemServices();
+        SystemServicesProxy ssp = LegacyRecentsImpl.getSystemServices();
         mTouchExplorationEnabled = touchExplorationEnabled;
         mTask = t;
         mTaskBound = true;
@@ -679,10 +678,10 @@
 
     @Override
     public boolean onLongClick(View v) {
-        if (!Recents.getConfiguration().dragToSplitEnabled) {
+        if (!LegacyRecentsImpl.getConfiguration().dragToSplitEnabled) {
             return false;
         }
-        SystemServicesProxy ssp = Recents.getSystemServices();
+        SystemServicesProxy ssp = LegacyRecentsImpl.getSystemServices();
         boolean inBounds = false;
         Rect clipBounds = new Rect(mViewBounds.getClipBounds());
         if (!clipBounds.isEmpty()) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewAccessibilityDelegate.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/TaskViewAccessibilityDelegate.java
similarity index 94%
rename from packages/SystemUI/src/com/android/systemui/recents/views/TaskViewAccessibilityDelegate.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/TaskViewAccessibilityDelegate.java
index 5bb5b2d..7bcad75 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewAccessibilityDelegate.java
+++ b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/TaskViewAccessibilityDelegate.java
@@ -25,7 +25,7 @@
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
 import com.android.systemui.R;
-import com.android.systemui.recents.Recents;
+import com.android.systemui.recents.LegacyRecentsImpl;
 import com.android.systemui.recents.events.EventBus;
 import com.android.systemui.recents.events.ui.dragndrop.DragEndEvent;
 import com.android.systemui.recents.events.ui.dragndrop.DragStartEvent;
@@ -56,8 +56,8 @@
     public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
         super.onInitializeAccessibilityNodeInfo(host, info);
         if (ActivityTaskManager.supportsSplitScreenMultiWindow(mTaskView.getContext())
-                && !Recents.getSystemServices().hasDockedTask()) {
-            DockState[] dockStates = Recents.getConfiguration()
+                && !LegacyRecentsImpl.getSystemServices().hasDockedTask()) {
+            DockState[] dockStates = LegacyRecentsImpl.getConfiguration()
                     .getDockStatesForCurrentOrientation();
             for (DockState dockState: dockStates) {
                 if (dockState == DockState.TOP) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/TaskViewHeader.java
similarity index 98%
rename from packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/TaskViewHeader.java
index de42914..21c0234 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
+++ b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/TaskViewHeader.java
@@ -53,14 +53,14 @@
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 import com.android.systemui.recents.Constants;
-import com.android.systemui.recents.Recents;
+import com.android.systemui.recents.LegacyRecentsImpl;
 import com.android.systemui.recents.events.EventBus;
 import com.android.systemui.recents.events.activity.LaunchTaskEvent;
 import com.android.systemui.recents.events.ui.ShowApplicationInfoEvent;
 import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.PackageManagerWrapper;
-import com.android.systemui.shared.recents.utilities.Utilities;
+import com.android.systemui.recents.utilities.Utilities;
 import com.android.systemui.shared.recents.model.Task;
 
 /* The task bar view */
@@ -212,7 +212,7 @@
         Resources res = context.getResources();
         mLightDismissDrawable = context.getDrawable(R.drawable.recents_dismiss_light);
         mDarkDismissDrawable = context.getDrawable(R.drawable.recents_dismiss_dark);
-        mCornerRadius = Recents.getConfiguration().isGridEnabled ?
+        mCornerRadius = LegacyRecentsImpl.getConfiguration().isGridEnabled ?
                 res.getDimensionPixelSize(R.dimen.recents_grid_task_view_rounded_corners_radius) :
                 res.getDimensionPixelSize(R.dimen.recents_task_view_rounded_corners_radius);
         mHighlightHeight = res.getDimensionPixelSize(R.dimen.recents_task_view_highlight);
@@ -246,7 +246,7 @@
 
     @Override
     protected void onFinishInflate() {
-        SystemServicesProxy ssp = Recents.getSystemServices();
+        SystemServicesProxy ssp = LegacyRecentsImpl.getSystemServices();
 
         // Initialize the icon and description views
         mIconView = findViewById(R.id.icon);
@@ -605,7 +605,7 @@
      */
     private void showAppOverlay() {
         // Skip early if the task is invalid
-        SystemServicesProxy ssp = Recents.getSystemServices();
+        SystemServicesProxy ssp = LegacyRecentsImpl.getSystemServices();
         ComponentName cn = mTask.key.getComponent();
         int userId = mTask.key.userId;
         ActivityInfo activityInfo = PackageManagerWrapper.getInstance().getActivityInfo(cn, userId);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/TaskViewThumbnail.java
similarity index 99%
rename from packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/TaskViewThumbnail.java
index 4152b05..68f85a5 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
+++ b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/TaskViewThumbnail.java
@@ -37,7 +37,7 @@
 import com.android.systemui.R;
 import com.android.systemui.recents.events.EventBus;
 import com.android.systemui.recents.events.ui.TaskSnapshotChangedEvent;
-import com.android.systemui.shared.recents.utilities.Utilities;
+import com.android.systemui.recents.utilities.Utilities;
 import com.android.systemui.shared.recents.model.Task;
 import com.android.systemui.shared.recents.model.ThumbnailData;
 import java.io.PrintWriter;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/TaskViewTransform.java
similarity index 97%
rename from packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/TaskViewTransform.java
index 9b717e0..48a7336 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java
+++ b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/TaskViewTransform.java
@@ -24,8 +24,8 @@
 import android.util.Property;
 import android.view.View;
 
-import com.android.systemui.shared.recents.utilities.AnimationProps;
-import com.android.systemui.shared.recents.utilities.Utilities;
+import com.android.systemui.recents.utilities.AnimationProps;
+import com.android.systemui.recents.utilities.Utilities;
 
 import java.util.ArrayList;
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/ViewPool.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/ViewPool.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/views/ViewPool.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/ViewPool.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/grid/AnimateableGridViewBounds.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/grid/AnimateableGridViewBounds.java
similarity index 93%
rename from packages/SystemUI/src/com/android/systemui/recents/views/grid/AnimateableGridViewBounds.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/grid/AnimateableGridViewBounds.java
index 3bdad31..a029478 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/grid/AnimateableGridViewBounds.java
+++ b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/grid/AnimateableGridViewBounds.java
@@ -17,7 +17,7 @@
 package com.android.systemui.recents.views.grid;
 
 import android.view.View;
-import com.android.systemui.shared.recents.view.AnimateableViewBounds;
+import com.android.systemui.recents.views.AnimateableViewBounds;
 
 /* An outline provider for grid-based task views. */
 class AnimateableGridViewBounds extends AnimateableViewBounds {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/grid/GridTaskView.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/grid/GridTaskView.java
similarity index 97%
rename from packages/SystemUI/src/com/android/systemui/recents/views/grid/GridTaskView.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/grid/GridTaskView.java
index 0d51154..8b4700c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/grid/GridTaskView.java
+++ b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/grid/GridTaskView.java
@@ -19,7 +19,7 @@
 import android.content.Context;
 import android.util.AttributeSet;
 import com.android.systemui.R;
-import com.android.systemui.shared.recents.view.AnimateableViewBounds;
+import com.android.systemui.recents.views.AnimateableViewBounds;
 import com.android.systemui.recents.views.TaskView;
 
 public class GridTaskView extends TaskView {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/grid/GridTaskViewThumbnail.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/grid/GridTaskViewThumbnail.java
similarity index 100%
rename from packages/SystemUI/src/com/android/systemui/recents/views/grid/GridTaskViewThumbnail.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/grid/GridTaskViewThumbnail.java
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/grid/TaskGridLayoutAlgorithm.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/grid/TaskGridLayoutAlgorithm.java
similarity index 99%
rename from packages/SystemUI/src/com/android/systemui/recents/views/grid/TaskGridLayoutAlgorithm.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/grid/TaskGridLayoutAlgorithm.java
index ccda4b5..719eaa7 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/grid/TaskGridLayoutAlgorithm.java
+++ b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/grid/TaskGridLayoutAlgorithm.java
@@ -26,7 +26,7 @@
 
 import com.android.systemui.R;
 import com.android.systemui.recents.events.ui.focus.NavigateTaskViewEvent.Direction;
-import com.android.systemui.shared.recents.utilities.Utilities;
+import com.android.systemui.recents.utilities.Utilities;
 import com.android.systemui.shared.recents.model.Task;
 import com.android.systemui.recents.views.TaskStackLayoutAlgorithm;
 import com.android.systemui.recents.views.TaskViewTransform;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/grid/TaskViewFocusFrame.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/grid/TaskViewFocusFrame.java
similarity index 98%
rename from packages/SystemUI/src/com/android/systemui/recents/views/grid/TaskViewFocusFrame.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/grid/TaskViewFocusFrame.java
index fe6bafb..1655f6c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/grid/TaskViewFocusFrame.java
+++ b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/grid/TaskViewFocusFrame.java
@@ -23,7 +23,7 @@
 
 import android.view.ViewTreeObserver.OnGlobalFocusChangeListener;
 import com.android.systemui.R;
-import com.android.systemui.shared.recents.model.TaskStack;
+import com.android.systemui.recents.model.TaskStack;
 import com.android.systemui.recents.views.TaskStackView;
 
 public class TaskViewFocusFrame extends View implements OnGlobalFocusChangeListener {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/lowram/TaskStackLowRamLayoutAlgorithm.java b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/lowram/TaskStackLowRamLayoutAlgorithm.java
similarity index 97%
rename from packages/SystemUI/src/com/android/systemui/recents/views/lowram/TaskStackLowRamLayoutAlgorithm.java
rename to packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/lowram/TaskStackLowRamLayoutAlgorithm.java
index 49cac26..15c7c87 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/lowram/TaskStackLowRamLayoutAlgorithm.java
+++ b/packages/SystemUI/legacy/recents/src/com/android/systemui/recents/views/lowram/TaskStackLowRamLayoutAlgorithm.java
@@ -21,9 +21,9 @@
 import android.view.ViewConfiguration;
 
 import com.android.systemui.R;
-import com.android.systemui.recents.Recents;
+import com.android.systemui.recents.LegacyRecentsImpl;
 import com.android.systemui.recents.RecentsActivityLaunchState;
-import com.android.systemui.shared.recents.utilities.Utilities;
+import com.android.systemui.recents.utilities.Utilities;
 import com.android.systemui.shared.recents.model.Task;
 import com.android.systemui.recents.views.TaskStackLayoutAlgorithm;
 import com.android.systemui.recents.views.TaskViewTransform;
@@ -82,7 +82,7 @@
     }
 
     public VisibilityReport computeStackVisibilityReport(ArrayList<Task> tasks) {
-        RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
+        RecentsActivityLaunchState launchState = LegacyRecentsImpl.getConfiguration().getLaunchState();
         int maxVisible = launchState.launchedFromHome || launchState.launchedFromPipApp
                     || launchState.launchedWithNextPipApp
                 ? NUM_TASK_VISIBLE_LAUNCHED_FROM_HOME
diff --git a/packages/SystemUI/proguard.flags b/packages/SystemUI/proguard.flags
index fa4c8b5..ee94aed 100644
--- a/packages/SystemUI/proguard.flags
+++ b/packages/SystemUI/proguard.flags
@@ -10,6 +10,7 @@
   public void setGlowScale(float);
 }
 
+-keep class com.android.systemui.recents.OverviewProxyRecentsImpl
 -keep class com.android.systemui.statusbar.car.CarStatusBar
 -keep class com.android.systemui.statusbar.phone.StatusBar
 -keep class com.android.systemui.statusbar.tv.TvStatusBar
@@ -17,21 +18,6 @@
 -keep class com.android.systemui.SystemUIFactory
 -keep class * extends com.android.systemui.SystemUI
 
--keepclassmembers class ** {
-    public void onBusEvent(**);
-    public void onInterprocessBusEvent(**);
-}
--keepclassmembers class ** extends **.EventBus$InterprocessEvent {
-    public <init>(android.os.Bundle);
-}
-
--keep class com.android.systemui.recents.views.TaskView {
-    public int getDim();
-    public void setDim(int);
-    public float getTaskProgress();
-    public void setTaskProgress(float);
-}
-
 -keepclasseswithmembers class * {
     public <init>(android.content.Context, android.util.AttributeSet);
 }
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_status_area.xml b/packages/SystemUI/res-keyguard/layout/keyguard_status_area.xml
index 00f8f86..b51ad1c 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_status_area.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_status_area.xml
@@ -28,17 +28,6 @@
     android:clipToPadding="false"
     android:orientation="vertical"
     android:layout_centerHorizontal="true">
-    <view class="com.android.keyguard.KeyguardSliceView$TitleView"
-              android:id="@+id/title"
-              android:layout_width="match_parent"
-              android:layout_height="wrap_content"
-              android:layout_marginBottom="@dimen/widget_title_bottom_margin"
-              android:paddingStart="64dp"
-              android:paddingEnd="64dp"
-              android:visibility="gone"
-              android:textColor="?attr/wallpaperTextColor"
-              android:theme="@style/TextAppearance.Keyguard"
-    />
     <view class="com.android.keyguard.KeyguardSliceView$Row"
               android:id="@+id/row"
               android:layout_width="match_parent"
diff --git a/packages/SystemUI/res/layout/notification_info.xml b/packages/SystemUI/res/layout/notification_info.xml
index f138685..5c950ec 100644
--- a/packages/SystemUI/res/layout/notification_info.xml
+++ b/packages/SystemUI/res/layout/notification_info.xml
@@ -51,7 +51,7 @@
             android:layout_centerVertical="true"
             android:layout_toEndOf="@id/pkgicon" />
         <TextView
-            android:id="@+id/pkg_group_divider"
+            android:id="@+id/pkg_divider"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:textAppearance="@*android:style/TextAppearance.Material.Notification.Info"
@@ -61,7 +61,7 @@
             android:layout_centerVertical="true"
             android:layout_toEndOf="@id/pkgname" />
         <TextView
-            android:id="@+id/group_name"
+            android:id="@+id/delegate_name"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:textAppearance="@*android:style/TextAppearance.Material.Notification.Info"
@@ -70,7 +70,7 @@
             android:ellipsize="end"
             android:maxLines="1"
             android:layout_centerVertical="true"
-            android:layout_toEndOf="@id/pkg_group_divider" />
+            android:layout_toEndOf="@id/pkg_divider" />
         <!-- 24 dp icon with 16 dp padding all around to mirror notification content margins -->
         <ImageButton
             android:id="@+id/info"
@@ -101,13 +101,39 @@
             android:layout_marginStart="@*android:dimen/notification_content_margin_start"
             android:layout_marginEnd="@*android:dimen/notification_content_margin_start"
             android:orientation="vertical">
-            <!-- Channel Name -->
-            <TextView
-                android:id="@+id/channel_name"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_weight="1"
-                style="@android:style/TextAppearance.Material.Notification.Title" />
+            <RelativeLayout
+                android:id="@+id/names"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content">
+                <TextView
+                    android:id="@+id/group_name"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:textAppearance="@*android:style/TextAppearance.Material.Notification.Title"
+                    android:layout_marginStart="2dp"
+                    android:layout_marginEnd="2dp"
+                    android:ellipsize="end"
+                    android:maxLines="1"
+                    android:layout_centerVertical="true" />
+                <TextView
+                    android:id="@+id/pkg_group_divider"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:textAppearance="@*android:style/TextAppearance.Material.Notification.Title"
+                    android:layout_marginStart="2dp"
+                    android:layout_marginEnd="2dp"
+                    android:text="@*android:string/notification_header_divider_symbol"
+                    android:layout_centerVertical="true"
+                    android:layout_toEndOf="@id/group_name" />
+                <!-- Channel Name -->
+                <TextView
+                    android:id="@+id/channel_name"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_weight="1"
+                    style="@android:style/TextAppearance.Material.Notification.Title"
+                    android:layout_toEndOf="@id/pkg_group_divider"/>
+            </RelativeLayout>
             <!-- Question prompt -->
             <TextView
                 android:id="@+id/block_prompt"
diff --git a/packages/SystemUI/res/layout/status_bar_no_recent_apps.xml b/packages/SystemUI/res/layout/status_bar_no_recent_apps.xml
deleted file mode 100644
index adfaed13..0000000
--- a/packages/SystemUI/res/layout/status_bar_no_recent_apps.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-**
-** Copyright 2011, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<FrameLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_height="match_parent"
-    android:layout_width="match_parent"
-    >
-
-    <TextView
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:textSize="20dp"
-        android:textColor="@android:color/holo_blue_light"
-        android:text="@string/status_bar_no_recent_apps"
-        android:gravity="center_horizontal"
-        android:layout_gravity="center"
-    />
-</FrameLayout>
diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml
index eb5c180..8934183 100644
--- a/packages/SystemUI/res/values-sw600dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp/dimens.xml
@@ -88,7 +88,4 @@
 
     <!-- Keyboard shortcuts helper -->
     <dimen name="ksh_layout_width">488dp</dimen>
-
-    <!-- The offsets the tasks animate from when recents is launched while docking -->
-    <dimen name="recents_task_stack_animation_launched_while_docking_offset">192dp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml
index f50ef82..baaf9d6 100644
--- a/packages/SystemUI/res/values/attrs.xml
+++ b/packages/SystemUI/res/values/attrs.xml
@@ -30,12 +30,6 @@
     <declare-styleable name="NotificationLinearLayout">
         <attr name="insetLeft" format="dimension" />
     </declare-styleable>
-    <declare-styleable name="RecentsPanelView">
-        <attr name="recentItemLayout" format="reference" />
-        <!-- Style for the "Clear all" button. -->
-        <attr name="clearAllStyle" format="reference" />
-        <attr name="clearAllBackgroundColor" format="reference" />
-    </declare-styleable>
     <declare-styleable name="DeadZone">
         <attr name="minSize" format="dimension" />
         <attr name="maxSize" format="dimension" />
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index d1320a3..0027cc6 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -39,32 +39,6 @@
     <!-- Tint color for the content on the notification overflow card. -->
     <color name="keyguard_overflow_content_color">#ff686868</color>
 
-    <!-- The disabled recents task bar background color. -->
-    <color name="recents_task_bar_disabled_background_color">#ff676767</color>
-    <!-- The default recents task bar background color. -->
-    <color name="recents_task_bar_default_background_color">#ffe6e6e6</color>
-    <!-- The default recents task view background color. -->
-    <color name="recents_task_view_default_background_color">#fff3f3f3</color>
-    <!-- The recents task bar light text color to be drawn on top of dark backgrounds. -->
-    <color name="recents_task_bar_light_text_color">#ffeeeeee</color>
-    <!-- The recents task bar dark text color to be drawn on top of light backgrounds. -->
-    <color name="recents_task_bar_dark_text_color">#cc000000</color>
-    <!-- The recents task bar light dismiss icon color to be drawn on top of dark backgrounds. -->
-    <color name="recents_task_bar_light_icon_color">#ccffffff</color>
-    <!-- The recents task bar dark dismiss icon color to be drawn on top of light backgrounds. -->
-    <color name="recents_task_bar_dark_icon_color">#99000000</color>
-    <!-- The lock to task button background color. -->
-    <color name="recents_task_view_lock_to_app_button_background_color">#ffe6e6e6</color>
-    <!-- The lock to task button foreground color. -->
-    <color name="recents_task_view_lock_to_app_button_color">#ff666666</color>
-    <!-- The background color for the freeform workspace. -->
-    <color name="recents_freeform_workspace_bg_color">#33FFFFFF</color>
-
-    <!-- The background color for clear all button on light backgrounds if not transparent. -->
-    <color name="recents_clear_all_button_bg_light_color">#CCFFFFFF</color>
-    <!-- The background color for clear all button on dark backgrounds if not transparent. -->
-    <color name="recents_clear_all_button_bg_dark_color">#CC000000</color>
-
     <color name="keyguard_affordance">#ffffffff</color>
 
     <!-- The color of the legacy notification background -->
@@ -110,12 +84,6 @@
     <!-- The shadow color for light navigation bar icons. -->
     <color name="nav_key_button_shadow_color">#30000000</color>
 
-    <!-- Shadow color for the first pixels around the fake shadow for recents. -->
-    <color name="fake_shadow_start_color">#44000000</color>
-
-    <!-- Shadow color for the furthest pixels around the fake shadow for recents. -->
-    <color name="fake_shadow_end_color">#03000000</color>
-
     <color name="screen_pinning_request_window_bg">#80000000</color>
 
     <color name="segmented_buttons_background">#14FFFFFF</color><!-- 8% white -->
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 6378309..b31dc50 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -20,19 +20,6 @@
 <!-- These resources are around just to allow their values to be customized
      for different hardware and product builds. -->
 <resources>
-    <!-- Whether recents should use hardware layers for its taskviews. This flag can be enabled
-    for devices where the java drawing of round rects may be slow -->
-    <bool name="config_recents_use_hardware_layers">false</bool>
-
-    <!-- The number of app thumbnails we keep in memory -->
-    <integer name="config_recents_max_thumbnail_count">10</integer>
-
-    <!-- The number of app icons we keep in memory -->
-    <integer name="config_recents_max_icon_count">20</integer>
-
-    <!-- Whether to use cheap, less good looking shadows for recents -->
-    <bool name="config_recents_fake_shadows">false</bool>
-
     <!-- Whether to clip notification contents with a rounded rectangle. Might be expensive on
          certain GPU's and thus can be turned off with only minimal visual impact. -->
     <bool name="config_notifications_round_rect_clipping">true</bool>
@@ -45,6 +32,11 @@
      interface.  This name is in the ComponentName flattened format (package/class)  -->
     <string name="config_statusBarComponent" translatable="false">com.android.systemui.statusbar.phone.StatusBar</string>
 
+    <!-- Component to be used as the recents implementation.  Must implement the
+     RecentsImplementation interface.  This name is in the ComponentName flattened format
+     (package/class)  -->
+    <string name="config_recentsComponent" translatable="false">com.android.systemui.recents.OverviewProxyRecentsImpl</string>
+
     <!-- Whether or not we show the number in the bar. -->
     <bool name="config_statusBarShowNumber">false</bool>
 
@@ -163,30 +155,6 @@
     <!-- The number of milliseconds to extend ambient pulse by when prompted (e.g. on touch) -->
     <integer name="ambient_notification_extension_time">6000</integer>
 
-    <!-- The duration in seconds to wait before the dismiss buttons are shown. -->
-    <integer name="recents_task_bar_dismiss_delay_seconds">1000</integer>
-
-    <!-- The duration for animating the task decorations in after transitioning from an app. -->
-    <integer name="recents_task_enter_from_app_duration">200</integer>
-
-    <!-- The duration for animating the task decorations in after transitioning from an app. -->
-    <integer name="recents_task_enter_from_affiliated_app_duration">125</integer>
-
-    <!-- The duration for animating the task decorations out before transitioning to an app. -->
-    <integer name="recents_task_exit_to_app_duration">125</integer>
-
-    <!-- The min animation duration for animating the nav bar scrim in. -->
-    <integer name="recents_nav_bar_scrim_enter_duration">400</integer>
-
-    <!-- The animation duration for scrolling the stack to a particular item. -->
-    <integer name="recents_animate_task_stack_scroll_duration">200</integer>
-
-    <!-- The delay to enforce between each alt-tab key press. -->
-    <integer name="recents_alt_tab_key_delay">200</integer>
-
-    <!-- Svelte specific logic, see RecentsConfiguration.SVELTE_* constants. -->
-    <integer name="recents_svelte_level">0</integer>
-
     <!-- In multi-window, determines whether the stack where recents lives should grow from
          the smallest position when being launched. -->
     <bool name="recents_grow_in_multiwindow">true</bool>
@@ -194,16 +162,6 @@
     <!-- Animation duration when using long press on recents to dock -->
     <integer name="long_press_dock_anim_duration">250</integer>
 
-    <!-- Recents: The relative range of visible tasks from the current scroll position
-         while the stack is focused. -->
-    <item name="recents_layout_focused_range_min" format="float" type="integer">-3</item>
-    <item name="recents_layout_focused_range_max" format="float" type="integer">2</item>
-
-    <!-- Recents: The relative range of visible tasks from the current scroll position
-         while the stack is not focused. -->
-    <item name="recents_layout_unfocused_range_min" format="float" type="integer">-2</item>
-    <item name="recents_layout_unfocused_range_max" format="float" type="integer">2.5</item>
-
     <!-- Whether to enable KeyguardService or not -->
     <bool name="config_enableKeyguardService">true</bool>
 
@@ -362,7 +320,6 @@
     <string-array name="config_systemUIServiceComponentsPerUser" translatable="false">
         <item>com.android.systemui.Dependency</item>
         <item>com.android.systemui.util.NotificationChannels</item>
-        <item>com.android.systemui.recents.Recents</item>
     </string-array>
 
     <!-- Nav bar button default ordering/layout -->
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index ab7dec9..9fe7718 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -793,102 +793,11 @@
     <dimen name="ksh_item_padding">4dp</dimen>
     <dimen name="ksh_item_margin_start">4dp</dimen>
 
-<!-- Recents Layout -->
-
-    <!-- The amount to inset the stack, specifically at the top and the other sides.  We also
-         don't want this to change across configurations that Recents can be opened in, so we
-         define them statically for all display sizes. -->
-    <dimen name="recents_layout_min_margin">16dp</dimen>
-    <dimen name="recents_layout_top_margin_phone">16dp</dimen>
-    <dimen name="recents_layout_top_margin_tablet">32dp</dimen>
-    <dimen name="recents_layout_top_margin_tablet_xlarge">40dp</dimen>
-    <dimen name="recents_layout_bottom_margin">16dp</dimen>
-    <dimen name="recents_layout_side_margin_phone">16dp</dimen>
-    <dimen name="recents_layout_side_margin_tablet">48dp</dimen>
-    <dimen name="recents_layout_side_margin_tablet_docked">16dp</dimen>
-    <dimen name="recents_layout_side_margin_tablet_xlarge">64dp</dimen>
-    <dimen name="recents_layout_side_margin_tablet_xlarge_docked">16dp</dimen>
-
-    <!-- The height between the top margin and the top of the focused task. -->
-    <dimen name="recents_layout_top_peek_size">48dp</dimen>
-    <!-- The height between the bottom margin and the top of task in front of the focused task. -->
-    <dimen name="recents_layout_bottom_peek_size">56dp</dimen>
-
-    <!-- The offset from the top and bottom of the stack of the focused task.  The bottom offset
-         will be additionally offset by the bottom system insets since it goes under the nav bar
-         in certain orientations. -->
-    <dimen name="recents_layout_initial_top_offset_phone_port">128dp</dimen>
-    <dimen name="recents_layout_initial_bottom_offset_phone_port">80dp</dimen>
-    <dimen name="recents_layout_initial_top_offset_phone_land">72dp</dimen>
-    <dimen name="recents_layout_initial_bottom_offset_phone_land">72dp</dimen>
-    <dimen name="recents_layout_initial_top_offset_tablet">160dp</dimen>
-    <dimen name="recents_layout_initial_bottom_offset_tablet">112dp</dimen>
-
-    <!-- The min/max translationZ for the tasks in the stack. -->
-    <dimen name="recents_layout_z_min">3dp</dimen>
-    <dimen name="recents_layout_z_max">24dp</dimen>
-
-    <!-- The margin between the freeform and stack.  We also don't want this to change across
-         configurations that Recents can be opened in, so we define them statically for all
-         display sizes. -->
-    <dimen name="recents_freeform_layout_bottom_margin">16dp</dimen>
-
-    <!-- The padding between each freeform task. -->
-    <dimen name="recents_freeform_layout_task_padding">8dp</dimen>
-
-<!-- Recents Views -->
-
-    <!-- The height of a task view bar.  This has to be large enough to cover the action bar
-         height in either orientation at this smallest width. -->
-    <dimen name="recents_task_view_header_height">56dp</dimen>
-    <dimen name="recents_task_view_header_height_tablet_land">64dp</dimen>
-
-    <!-- The padding of a button in the recents task view header. -->
-    <dimen name="recents_task_view_header_button_padding">16dp</dimen>
-    <dimen name="recents_task_view_header_button_padding_tablet_land">20dp</dimen>
-
-    <!-- The radius of the rounded corners on a task view and its shadow (which can be larger
-         to create a softer corner effect. -->
-    <dimen name="recents_task_view_rounded_corners_radius">2dp</dimen>
-    <dimen name="recents_task_view_shadow_rounded_corners_radius">6dp</dimen>
-
-    <!-- The amount of highlight to make on each task view. -->
-    <dimen name="recents_task_view_highlight">1dp</dimen>
-
-    <!-- The size of the lock-to-app button and its icon. -->
-    <dimen name="recents_lock_to_app_size">56dp</dimen>
-    <dimen name="recents_lock_to_app_icon_size">28dp</dimen>
-
-    <!-- The amount of overscroll allowed when flinging to the end of the stack. -->
-    <dimen name="recents_fling_overscroll_distance">24dp</dimen>
-
-    <!-- The size of the drag hint text. -->
-    <dimen name="recents_drag_hint_text_size">14sp</dimen>
-
     <!-- The size of corner radius of the arrow in the onboarding toast. -->
     <dimen name="recents_onboarding_toast_arrow_corner_radius">2dp</dimen>
     <!-- The start margin of quick scrub onboarding toast. -->
     <dimen name="recents_quick_scrub_onboarding_margin_start">8dp</dimen>
 
-    <!-- The min alpha to apply to a task affiliation group color. -->
-    <item name="recents_task_affiliation_color_min_alpha_percentage" format="float" type="dimen">0.6</item>
-
-    <!-- The amount to offset when animating into an affiliate group. -->
-    <dimen name="recents_task_stack_animation_affiliate_enter_offset">32dp</dimen>
-
-    <!-- The offsets the tasks animate from when recents is launched while docking -->
-    <dimen name="recents_task_stack_animation_launched_while_docking_offset">144dp</dimen>
-
-    <!-- The amount to translate when animating the removal of a task. -->
-    <dimen name="recents_task_view_remove_anim_translation_x">100dp</dimen>
-
-    <!-- The alpha to apply to the recents row when it doesn't have focus -->
-    <item name="recents_recents_row_dim_alpha" format="float" type="dimen">0.5</item>
-
-    <!-- The speed in dp/s at which the user needs to be scrolling in recents such that we start
-         loading full resolution screenshots. -->
-    <dimen name="recents_fast_fling_velocity">600dp</dimen>
-
     <!-- The height of the gradient indicating the dismiss edge when moving a PIP. -->
     <dimen name="pip_dismiss_gradient_height">176dp</dimen>
 
diff --git a/packages/SystemUI/res/values/integers_car.xml b/packages/SystemUI/res/values/integers_car.xml
index 7513fd4..fc3623c 100644
--- a/packages/SystemUI/res/values/integers_car.xml
+++ b/packages/SystemUI/res/values/integers_car.xml
@@ -19,4 +19,9 @@
     <integer name="car_user_switcher_anim_cascade_delay_ms">27</integer>
     <!-- Full screen user switcher column number TODO: move to support library-->
     <integer name="user_fullscreen_switcher_num_col">3</integer>
+
+    <!-- Number of milliseconds user can spend driving with the keyguard up. After that, we switch to Guest. -->
+    <!-- If the number is negative, the feature is disabled.
+         If it's zero, we switch to guest immediately as we start driving. -->
+    <integer name="driving_on_keyguard_timeout_ms">30000</integer>
 </resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 42e19aa..0cf7306 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -24,26 +24,6 @@
          all of the currently visible notifications. [CHAR LIMIT=10]-->
     <string name="status_bar_clear_all_button">Clear</string>
 
-    <!-- Title shown in recents popup for removing an application from the list -->
-    <string name="status_bar_recent_remove_item_title">Remove from list</string>
-
-    <!-- Title shown in recents popup for inspecting an application's properties -->
-    <string name="status_bar_recent_inspect_item_title">App info</string>
-
-    <!-- Message shown in the middle of the screen after clicking on the recent apps button
-         when there are no recent apps to show. Also used for accessibility. [CHAR LIMIT=45]-->
-    <string name="status_bar_no_recent_apps">Your recent screens appear here</string>
-
-    <!-- Content description for the button to dismiss Recent Apps (only present on large
-         devices) -->
-    <string name="status_bar_accessibility_dismiss_recents">Dismiss recent apps</string>
-
-    <!-- Message that is read when you enter recent apps in TalkBack -->
-    <plurals name="status_bar_accessibility_recent_apps">
-        <item quantity="one">1 screen in Overview</item>
-        <item quantity="other">%d screens in Overview</item>
-    </plurals>
-
     <!-- The label in the bar at the top of the status bar when there are no notifications
          showing.  [CHAR LIMIT=40]-->
     <string name="status_bar_no_notifications_title">No notifications</string>
@@ -252,8 +232,6 @@
     <string name="voice_assist_label">open voice assist</string>
     <!-- Click action label for accessibility for the phone button. [CHAR LIMIT=NONE] -->
     <string name="camera_label">open camera</string>
-    <!-- Caption for "Recents resize" developer debug feature. [CHAR LIMIT=NONE] -->
-    <string name="recents_caption_resize">Select new task layout</string>
     <!-- Button name for "Cancel". [CHAR LIMIT=NONE] -->
     <string name="cancel">Cancel</string>
 
@@ -477,16 +455,6 @@
     <!-- Content description of the work mode icon in the notification panel for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_work_mode">@string/quick_settings_work_mode_label</string>
 
-    <!-- Content description to tell the user that this button will remove an application from recents -->
-    <string name="accessibility_recents_item_will_be_dismissed">Dismiss <xliff:g id="app" example="Calendar">%s</xliff:g>.</string>
-    <!-- Content description to tell the user an application has been removed from recents -->
-    <string name="accessibility_recents_item_dismissed"><xliff:g id="app" example="Calendar">%s</xliff:g> dismissed.</string>
-    <!-- Content description to tell the user all applications has been removed from recents -->
-    <string name="accessibility_recents_all_items_dismissed">All recent applications dismissed.</string>
-    <!-- Content description to tell the user that this button will open application info for an application in recents -->
-    <string name="accessibility_recents_item_open_app_info">Open <xliff:g id="app" example="Calendar">%s</xliff:g> application info.</string>
-    <!-- Content description to tell the user an application has been launched from recents -->
-    <string name="accessibility_recents_item_launched">Starting <xliff:g id="app" example="Calendar">%s</xliff:g>.</string>
     <!-- Content description to tell the user a notification has been removed from the notification shade -->
     <string name="accessibility_notification_dismissed">Notification dismissed.</string>
 
@@ -836,42 +804,10 @@
     <!-- QuickSettings: NFC (on) [CHAR LIMIT=NONE] -->
     <string name="quick_settings_nfc_on">NFC is enabled</string>
 
-    <!-- Recents: The empty recents string. [CHAR LIMIT=NONE] -->
-    <string name="recents_empty_message">No recent items</string>
-    <!-- Recents: The empty recents string after dismissing all tasks. [CHAR LIMIT=NONE] -->
-    <string name="recents_empty_message_dismissed_all">You\'ve cleared everything</string>
-    <!-- Recents: The info panel app info button string. [CHAR LIMIT=NONE] -->
-    <string name="recents_app_info_button_label">Application Info</string>
-    <!-- Recents: The screen pinning button. [CHAR LIMIT=NONE] -->
-    <string name="recents_lock_to_app_button_label">screen pinning</string>
-    <!-- Recents: Temporary string for the button in the recents search bar. [CHAR LIMIT=NONE] -->
-    <string name="recents_search_bar_label">search</string>
-    <!-- Recents: Launch error string. [CHAR LIMIT=NONE] -->
-    <string name="recents_launch_error_message">Could not start <xliff:g id="app" example="Calendar">%s</xliff:g>.</string>
-    <!-- Recents: Launch disabled string. [CHAR LIMIT=NONE] -->
-    <string name="recents_launch_disabled_message"><xliff:g id="app" example="Calendar">%s</xliff:g> is disabled in safe-mode.</string>
-    <!-- Recents: Stack action button string. [CHAR LIMIT=NONE] -->
-    <string name="recents_stack_action_button_label">Clear all</string>
-    <!-- Recents: Hint text that shows on the drop targets to start multiwindow. [CHAR LIMIT=NONE] -->
-    <string name="recents_drag_hint_message">Drag here to use split screen</string>
     <!-- Recents: Text that shows above the navigation bar after launching a few apps. [CHAR LIMIT=NONE] -->
     <string name="recents_swipe_up_onboarding">Swipe up to switch apps</string>
     <!-- Recents: Text that shows above the navigation bar after launching several apps. [CHAR LIMIT=NONE] -->
     <string name="recents_quick_scrub_onboarding">Drag right to quickly switch apps</string>
-
-    <!-- Recents: MultiStack add stack split horizontal radio button. [CHAR LIMIT=NONE] -->
-    <string name="recents_multistack_add_stack_dialog_split_horizontal">Split Horizontal</string>
-    <!-- Recents: MultiStack add stack split vertical radio button. [CHAR LIMIT=NONE] -->
-    <string name="recents_multistack_add_stack_dialog_split_vertical">Split Vertical</string>
-    <!-- Recents: MultiStack add stack split custom radio button. [CHAR LIMIT=NONE] -->
-    <string name="recents_multistack_add_stack_dialog_split_custom">Split Custom</string>
-    <!-- Recents: Accessibility split to the top -->
-    <string name="recents_accessibility_split_screen_top">Split screen to the top</string>
-    <!-- Recents: Accessibility split to the left -->
-    <string name="recents_accessibility_split_screen_left">Split screen to the left</string>
-    <!-- Recents: Accessibility split to the right -->
-    <string name="recents_accessibility_split_screen_right">Split screen to the right</string>
-
     <!-- QuickStep: Accessibility to toggle overview [CHAR LIMIT=40] -->
     <string name="quick_step_accessibility_toggle_overview">Toggle Overview</string>
 
@@ -1593,6 +1529,9 @@
     <!-- Notification: Control panel: Label that displays when the app's notifications cannot be blocked. -->
     <string name="notification_unblockable_desc">These notifications can\'t be turned off</string>
 
+    <!-- Notification: Control panel: Label for the app that posted this notification, if it's not the package that the notification was posted for -->
+    <string name="notification_delegate_header">via <xliff:g id="app_name" example="YouTube">%1$s</xliff:g></string>
+
     <!-- Notification Inline controls: describes what the app is doing in the background [CHAR_LIMIT=NONE] -->
     <string name="appops_camera">This app is using the camera.</string>
     <!-- Notification Inline controls: describes what the app is doing in the background [CHAR_LIMIT=NONE] -->
@@ -1915,6 +1854,9 @@
         <item>Don\'t show this icon</item>
     </string-array>
 
+    <!-- SysUI Tuner: Switch for showing low-priority notification icons in status bar [CHAR LIMIT=NONE] -->
+    <string name="tuner_low_priority">Show low-priority notification icons</string>
+
     <!-- SysUI Tuner: Other section -->
     <string name="other">Other</string>
 
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 6446367..6bc2a63 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -16,35 +16,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android">
 
-    <style name="RecentsTheme" parent="@android:style/Theme.Material">
-        <!-- NoTitle -->
-        <item name="android:windowNoTitle">true</item>
-        <!-- Misc -->
-        <item name="android:statusBarColor">@android:color/transparent</item>
-        <item name="android:navigationBarColor">@android:color/transparent</item>
-        <item name="android:windowDrawsSystemBarBackgrounds">true</item>
-        <item name="android:windowAnimationStyle">@null</item>
-        <item name="android:ambientShadowAlpha">0.35</item>
-    </style>
-
-    <!-- Recents theme -->
-    <style name="RecentsTheme.Wallpaper">
-        <item name="android:windowBackground">@*android:color/transparent</item>
-        <item name="android:colorBackgroundCacheHint">@null</item>
-        <item name="android:windowShowWallpaper">true</item>
-        <item name="android:windowDisablePreview">true</item>
-        <item name="clearAllStyle">@style/ClearAllButtonDefaultMargins</item>
-        <item name="clearAllBackgroundColor">@color/recents_clear_all_button_bg_dark_color</item>
-        <item name="wallpaperTextColor">@*android:color/primary_text_material_dark</item>
-        <item name="wallpaperTextColorSecondary">@*android:color/secondary_text_material_dark</item>
-    </style>
-
-    <style name="RecentsTheme.Wallpaper.Light">
-        <item name="clearAllBackgroundColor">@color/recents_clear_all_button_bg_light_color</item>
-        <item name="wallpaperTextColor">@*android:color/primary_text_material_light</item>
-        <item name="wallpaperTextColorSecondary">@*android:color/secondary_text_material_light</item>
-    </style>
-
     <style name="ClearAllButtonDefaultMargins">
         <item name="android:layout_marginStart">0dp</item>
         <item name="android:layout_marginTop">0dp</item>
@@ -52,13 +23,6 @@
         <item name="android:layout_marginBottom">0dp</item>
     </style>
 
-    <!-- Performance optimized Recents theme (no wallpaper) -->
-    <style name="RecentsTheme.NoWallpaper">
-        <item name="android:windowBackground">@android:color/black</item>
-        <item name="wallpaperTextColor">@android:color/white</item>
-        <item name="wallpaperTextColorSecondary">@android:color/white</item>
-    </style>
-
     <!-- Theme used for the activity that shows when the system forced an app to be resizable -->
     <style name="ForcedResizableTheme" parent="@android:style/Theme.Translucent.NoTitleBar">
         <item name="android:windowBackground">@drawable/forced_resizable_background</item>
@@ -293,11 +257,6 @@
         <item name="android:windowExitAnimation">@*android:anim/shrink_fade_out_from_bottom</item>
     </style>
 
-    <style name="Animation.RecentPanel">
-        <item name="android:windowEnterAnimation">@*android:anim/grow_fade_in_from_bottom</item>
-        <item name="android:windowExitAnimation">@*android:anim/shrink_fade_out_from_bottom</item>
-    </style>
-
     <style name="Animation.NavigationBarFadeIn">
         <item name="android:windowEnterAnimation">@anim/navbar_fade_in</item>
         <item name="android:windowExitAnimation">@null</item>
diff --git a/packages/SystemUI/res/xml/tuner_prefs.xml b/packages/SystemUI/res/xml/tuner_prefs.xml
index 46ea494..6eec5dc 100644
--- a/packages/SystemUI/res/xml/tuner_prefs.xml
+++ b/packages/SystemUI/res/xml/tuner_prefs.xml
@@ -98,6 +98,11 @@
             android:summary="%s"
             android:entries="@array/clock_options" />
 
+        <com.android.systemui.tuner.TunerSwitch
+            android:key="low_priority"
+            android:title="@string/tuner_low_priority"
+            sysui:defValue="false" />
+
     </PreferenceScreen>
 
     <PreferenceScreen
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManagerImpl.java b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManagerImpl.java
index 87f2934..82e8b3e 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManagerImpl.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginManagerImpl.java
@@ -246,7 +246,11 @@
                         SystemMessage.NOTE_PLUGIN, nb.build(), UserHandle.ALL);
             }
             if (clearClassLoader(pkg)) {
-                Toast.makeText(mContext, "Reloading " + pkg, Toast.LENGTH_LONG).show();
+                if (Build.IS_ENG) {
+                    Toast.makeText(mContext, "Reloading " + pkg, Toast.LENGTH_LONG).show();
+                } else {
+                    Log.v(TAG, "Reloading " + pkg);
+                }
             }
             if (!Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
                 for (PluginInstanceManager manager : mPluginMap.values()) {
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/Task.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/Task.java
index 368e503..7558efa 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/Task.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/Task.java
@@ -143,7 +143,7 @@
      * The temporary sort index in the stack, used when ordering the stack.
      */
     @Deprecated
-    int temporarySortIndexInStack;
+    public int temporarySortIndexInStack;
 
     /**
      * The icon is the task description icon (if provided), which falls back to the activity icon,
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskKeyLruCache.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskKeyLruCache.java
index 0ba2c3b..b2c79a4 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskKeyLruCache.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/TaskKeyLruCache.java
@@ -58,7 +58,7 @@
     }
 
     /** Trims the cache to a specific size */
-    final void trimToSize(int cacheSize) {
+    public final void trimToSize(int cacheSize) {
         mCache.trimToSize(cacheSize);
     }
 
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/Utilities.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/Utilities.java
index 7d159b7..7dffc26 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/Utilities.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/Utilities.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2018 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -16,158 +16,19 @@
 
 package com.android.systemui.shared.recents.utilities;
 
-import android.animation.Animator;
-import android.animation.AnimatorSet;
-import android.animation.RectEvaluator;
-import android.annotation.FloatRange;
-import android.annotation.Nullable;
-import android.app.Activity;
-import android.content.Context;
-import android.content.res.Configuration;
-import android.content.res.Resources;
 import android.graphics.Color;
-import android.graphics.Rect;
-import android.graphics.RectF;
-import android.graphics.drawable.Drawable;
 import android.os.Handler;
 import android.os.Message;
-import android.os.Trace;
-import android.util.ArraySet;
-import android.util.IntProperty;
-import android.util.Property;
-import android.util.TypedValue;
-import android.view.Surface;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewParent;
-import android.view.ViewRootImpl;
-import android.view.ViewStub;
-
-import java.util.ArrayList;
-import java.util.Collections;
 
 /* Common code */
 public class Utilities {
 
-    public static final Property<Drawable, Integer> DRAWABLE_ALPHA =
-            new IntProperty<Drawable>("drawableAlpha") {
-                @Override
-                public void setValue(Drawable object, int alpha) {
-                    object.setAlpha(alpha);
-                }
-
-                @Override
-                public Integer get(Drawable object) {
-                    return object.getAlpha();
-                }
-            };
-
-    public static final Property<Drawable, Rect> DRAWABLE_RECT =
-            new Property<Drawable, Rect>(Rect.class, "drawableBounds") {
-                @Override
-                public void set(Drawable object, Rect bounds) {
-                    object.setBounds(bounds);
-                }
-
-                @Override
-                public Rect get(Drawable object) {
-                    return object.getBounds();
-                }
-            };
-
-    public static final RectFEvaluator RECTF_EVALUATOR = new RectFEvaluator();
-    public static final RectEvaluator RECT_EVALUATOR = new RectEvaluator(new Rect());
-
     /**
-     * @return the first parent walking up the view hierarchy that has the given class type.
-     *
-     * @param parentClass must be a class derived from {@link View}
+     * Posts a runnable on a handler at the front of the queue ignoring any sync barriers.
      */
-    public static <T extends View> T findParent(View v, Class<T> parentClass) {
-        ViewParent parent = v.getParent();
-        while (parent != null) {
-            if (parentClass.isAssignableFrom(parent.getClass())) {
-                return (T) parent;
-            }
-            parent = parent.getParent();
-        }
-        return null;
-    }
-
-    /**
-     * Initializes the {@param setOut} with the given object.
-     */
-    public static <T> ArraySet<T> objectToSet(T obj, ArraySet<T> setOut) {
-        setOut.clear();
-        if (obj != null) {
-            setOut.add(obj);
-        }
-        return setOut;
-    }
-
-    /**
-     * Replaces the contents of {@param setOut} with the contents of the {@param array}.
-     */
-    public static <T> ArraySet<T> arrayToSet(T[] array, ArraySet<T> setOut) {
-        setOut.clear();
-        if (array != null) {
-            Collections.addAll(setOut, array);
-        }
-        return setOut;
-    }
-
-    /**
-     * @return the clamped {@param value} between the provided {@param min} and {@param max}.
-     */
-    public static float clamp(float value, float min, float max) {
-        return Math.max(min, Math.min(max, value));
-    }
-
-    /**
-     * @return the clamped {@param value} between the provided {@param min} and {@param max}.
-     */
-    public static int clamp(int value, int min, int max) {
-        return Math.max(min, Math.min(max, value));
-    }
-
-    /**
-     * @return the clamped {@param value} between 0 and 1.
-     */
-    public static float clamp01(float value) {
-        return Math.max(0f, Math.min(1f, value));
-    }
-
-    /**
-     * Scales the {@param value} to be proportionally between the {@param min} and
-     * {@param max} values.
-     *
-     * @param value must be between 0 and 1
-     */
-    public static float mapRange(@FloatRange(from=0.0,to=1.0) float value, float min, float max) {
-        return min + (value * (max - min));
-    }
-
-    /**
-     * Scales the {@param value} proportionally from {@param min} and {@param max} to 0 and 1.
-     *
-     * @param value must be between {@param min} and {@param max}
-     */
-    public static float unmapRange(float value, float min, float max) {
-        return (value - min) / (max - min);
-    }
-
-    /** Scales a rect about its centroid */
-    public static void scaleRectAboutCenter(RectF r, float scale) {
-        if (scale != 1.0f) {
-            float cx = r.centerX();
-            float cy = r.centerY();
-            r.offset(-cx, -cy);
-            r.left *= scale;
-            r.top *= scale;
-            r.right *= scale;
-            r.bottom *= scale;
-            r.offset(cx, cy);
-        }
+    public static void postAtFrontOfQueueAsynchronously(Handler h, Runnable r) {
+        Message msg = h.obtainMessage().setCallback(r);
+        h.sendMessageAtFrontOfQueue(msg);
     }
 
     /** Calculates the constrast between two colors, using the algorithm provided by the WCAG v2. */
@@ -179,7 +40,7 @@
         bgG = (bgG < 0.03928f) ? bgG / 12.92f : (float) Math.pow((bgG + 0.055f) / 1.055f, 2.4f);
         bgB = (bgB < 0.03928f) ? bgB / 12.92f : (float) Math.pow((bgB + 0.055f) / 1.055f, 2.4f);
         float bgL = 0.2126f * bgR + 0.7152f * bgG + 0.0722f * bgB;
-        
+
         float fgR = Color.red(fg) / 255f;
         float fgG = Color.green(fg) / 255f;
         float fgB = Color.blue(fg) / 255f;
@@ -191,147 +52,10 @@
         return Math.abs((fgL + 0.05f) / (bgL + 0.05f));
     }
 
-    /** Returns the base color overlaid with another overlay color with a specified alpha. */
-    public static int getColorWithOverlay(int baseColor, int overlayColor, float overlayAlpha) {
-        return Color.rgb(
-            (int) (overlayAlpha * Color.red(baseColor) +
-                    (1f - overlayAlpha) * Color.red(overlayColor)),
-            (int) (overlayAlpha * Color.green(baseColor) +
-                    (1f - overlayAlpha) * Color.green(overlayColor)),
-            (int) (overlayAlpha * Color.blue(baseColor) +
-                    (1f - overlayAlpha) * Color.blue(overlayColor)));
-    }
-
     /**
-     * Cancels an animation ensuring that if it has listeners, onCancel and onEnd
-     * are not called.
+     * @return the clamped {@param value} between the provided {@param min} and {@param max}.
      */
-    public static void cancelAnimationWithoutCallbacks(Animator animator) {
-        if (animator != null && animator.isStarted()) {
-            removeAnimationListenersRecursive(animator);
-            animator.cancel();
-        }
-    }
-
-    /**
-     * Recursively removes all the listeners of all children of this animator
-     */
-    public static void removeAnimationListenersRecursive(Animator animator) {
-        if (animator instanceof AnimatorSet) {
-            ArrayList<Animator> animators = ((AnimatorSet) animator).getChildAnimations();
-            for (int i = animators.size() - 1; i >= 0; i--) {
-                removeAnimationListenersRecursive(animators.get(i));
-            }
-        }
-        animator.removeAllListeners();
-    }
-
-    /**
-     * Sets the given {@link View}'s frame from its current translation.
-     */
-    public static void setViewFrameFromTranslation(View v) {
-        RectF taskViewRect = new RectF(v.getLeft(), v.getTop(), v.getRight(), v.getBottom());
-        taskViewRect.offset(v.getTranslationX(), v.getTranslationY());
-        v.setTranslationX(0);
-        v.setTranslationY(0);
-        v.setLeftTopRightBottom((int) taskViewRect.left, (int) taskViewRect.top,
-                (int) taskViewRect.right, (int) taskViewRect.bottom);
-    }
-
-    /**
-     * Returns a view stub for the given view id.
-     */
-    public static ViewStub findViewStubById(View v, int stubId) {
-        return (ViewStub) v.findViewById(stubId);
-    }
-
-    /**
-     * Returns a view stub for the given view id.
-     */
-    public static ViewStub findViewStubById(Activity a, int stubId) {
-        return (ViewStub) a.findViewById(stubId);
-    }
-
-    /**
-     * Used for debugging, converts DP to PX.
-     */
-    public static float dpToPx(Resources res, float dp) {
-        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, res.getDisplayMetrics());
-    }
-
-    /**
-     * Adds a trace event for debugging.
-     */
-    public static void addTraceEvent(String event) {
-        Trace.traceBegin(Trace.TRACE_TAG_VIEW, event);
-        Trace.traceEnd(Trace.TRACE_TAG_VIEW);
-    }
-
-    /**
-     * Returns whether this view, or one of its descendants have accessibility focus.
-     */
-    public static boolean isDescendentAccessibilityFocused(View v) {
-        if (v.isAccessibilityFocused()) {
-            return true;
-        }
-
-        if (v instanceof ViewGroup) {
-            ViewGroup vg = (ViewGroup) v;
-            int childCount = vg.getChildCount();
-            for (int i = 0; i < childCount; i++) {
-                if (isDescendentAccessibilityFocused(vg.getChildAt(i))) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Returns the application configuration, which is independent of the activity's current
-     * configuration in multiwindow.
-     */
-    public static Configuration getAppConfiguration(Context context) {
-        return context.getApplicationContext().getResources().getConfiguration();
-    }
-
-    /**
-     * @return The next frame name for the specified surface or -1 if the surface is no longer
-     *         valid.
-     */
-    public static long getNextFrameNumber(Surface s) {
-        return s != null && s.isValid()
-                ? s.getNextFrameNumber()
-                : -1;
-
-    }
-
-    /**
-     * @return The surface for the specified view.
-     */
-    public static @Nullable Surface getSurface(View v) {
-        ViewRootImpl viewRoot = v.getViewRootImpl();
-        if (viewRoot == null) {
-            return null;
-        }
-        return viewRoot.mSurface;
-    }
-
-    /**
-     * Returns a lightweight dump of a rect.
-     */
-    public static String dumpRect(Rect r) {
-        if (r == null) {
-            return "N:0,0-0,0";
-        }
-        return r.left + "," + r.top + "-" + r.right + "," + r.bottom;
-    }
-
-    /**
-     * Posts a runnable on a handler at the front of the queue ignoring any sync barriers.
-     */
-    public static void postAtFrontOfQueueAsynchronously(Handler h, Runnable r) {
-        Message msg = h.obtainMessage().setCallback(r);
-        h.sendMessageAtFrontOfQueue(msg);
+    public static float clamp(float value, float min, float max) {
+        return Math.max(min, Math.min(max, value));
     }
 }
diff --git a/packages/SystemUI/shared/tests/Android.mk b/packages/SystemUI/shared/tests/Android.mk
deleted file mode 100644
index 02774c9..0000000
--- a/packages/SystemUI/shared/tests/Android.mk
+++ /dev/null
@@ -1,59 +0,0 @@
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_USE_AAPT2 := true
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_JACK_FLAGS := --multi-dex native
-LOCAL_DX_FLAGS := --multi-dex
-
-LOCAL_PROTOC_OPTIMIZE_TYPE := nano
-LOCAL_PROTOC_FLAGS := -I$(LOCAL_PATH)/..
-LOCAL_PROTO_JAVA_OUTPUT_PARAMS := optional_field_style=accessors
-
-LOCAL_PACKAGE_NAME := SystemUISharedLibTests
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_COMPATIBILITY_SUITE := device-tests
-
-# Add local path sources as well as shared lib sources
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
-	SystemUISharedLib \
-    metrics-helper-lib \
-    android-support-test \
-    mockito-target-inline-minus-junit4 \
-    SystemUI-proto \
-    SystemUI-tags \
-    testables \
-    truth-prebuilt \
-
-LOCAL_MULTILIB := both
-
-LOCAL_JNI_SHARED_LIBRARIES := \
-    libdexmakerjvmtiagent \
-    libmultiplejvmtiagentsinterferenceagent
-
-LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common
-
-# sign this with platform cert, so this test is allowed to inject key events into
-# UI it doesn't own. This is necessary to allow screenshots to be taken
-LOCAL_CERTIFICATE := platform
-
-ifeq ($(EXCLUDE_SYSTEMUI_TESTS),)
-    include $(BUILD_PACKAGE)
-endif
diff --git a/packages/SystemUI/shared/tests/AndroidManifest.xml b/packages/SystemUI/shared/tests/AndroidManifest.xml
deleted file mode 100644
index 5974b76..0000000
--- a/packages/SystemUI/shared/tests/AndroidManifest.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.android.systemui.shared.tests">
-
-    <uses-permission android:name="android.permission.READ_FRAME_BUFFER" />
-
-    <application android:debuggable="true">
-        <uses-library android:name="android.test.runner" />
-    </application>
-
-    <instrumentation android:name="android.testing.TestableInstrumentation"
-        android:targetPackage="com.android.systemui.shared.tests"
-        android:label="Tests for SystemUISharedLib">
-    </instrumentation>
-</manifest>
diff --git a/packages/SystemUI/shared/tests/AndroidTest.xml b/packages/SystemUI/shared/tests/AndroidTest.xml
deleted file mode 100644
index b3de836..0000000
--- a/packages/SystemUI/shared/tests/AndroidTest.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-<configuration description="Runs Tests for SystemUISharedLib.">
-    <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
-        <option name="test-file-name" value="SystemUISharedLibTests.apk" />
-    </target_preparer>
-
-    <option name="test-suite-tag" value="apct" />
-    <option name="test-suite-tag" value="framework-base-presubmit" />
-    <option name="test-tag" value="SystemUISharedLibTests" />
-    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
-        <option name="package" value="com.android.systemui.shared.tests" />
-        <option name="runner" value="android.testing.TestableInstrumentation" />
-    </test>
-</configuration>
diff --git a/packages/SystemUI/shared/tests/src/com/android/systemui/shared/SysuiSharedLibTestCase.java b/packages/SystemUI/shared/tests/src/com/android/systemui/shared/SysuiSharedLibTestCase.java
deleted file mode 100644
index 04b341e..0000000
--- a/packages/SystemUI/shared/tests/src/com/android/systemui/shared/SysuiSharedLibTestCase.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.shared;
-
-import android.content.Context;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.MessageQueue;
-import android.support.test.InstrumentationRegistry;
-
-import org.junit.After;
-import org.junit.Before;
-
-/**
- * Base class that does System UI Shared Lib specific setup.
- */
-public abstract class SysuiSharedLibTestCase {
-
-    private static final String TAG = "SysuiSharedLibTestCase";
-
-    private Handler mHandler;
-    private Context mContext = InstrumentationRegistry.getContext();
-
-    @Before
-    public void SysuiSetup() throws Exception {
-        // Enable shared class loader to test package-private classes/methods
-        System.setProperty("dexmaker.share_classloader", "true");
-    }
-
-    @After
-    public void SysuiTeardown() {
-        // Do nothing
-    }
-
-    public Context getContext() {
-        return mContext;
-    }
-
-    protected void waitForIdleSync() {
-        if (mHandler == null) {
-            mHandler = new Handler(Looper.getMainLooper());
-        }
-        waitForIdleSync(mHandler);
-    }
-
-    public static void waitForIdleSync(Handler h) {
-        validateThread(h.getLooper());
-        Idler idler = new Idler(null);
-        h.getLooper().getQueue().addIdleHandler(idler);
-        // Ensure we are non-idle, so the idle handler can run.
-        h.post(new EmptyRunnable());
-        idler.waitForIdle();
-    }
-
-    private static final void validateThread(Looper l) {
-        if (Looper.myLooper() == l) {
-            throw new RuntimeException(
-                "This method can not be called from the looper being synced");
-        }
-    }
-
-    public static final class EmptyRunnable implements Runnable {
-        public void run() {
-        }
-    }
-
-    public static final class Idler implements MessageQueue.IdleHandler {
-        private final Runnable mCallback;
-        private boolean mIdle;
-
-        public Idler(Runnable callback) {
-            mCallback = callback;
-            mIdle = false;
-        }
-
-        @Override
-        public boolean queueIdle() {
-            if (mCallback != null) {
-                mCallback.run();
-            }
-            synchronized (this) {
-                mIdle = true;
-                notifyAll();
-            }
-            return false;
-        }
-
-        public void waitForIdle() {
-            synchronized (this) {
-                while (!mIdle) {
-                    try {
-                        wait();
-                    } catch (InterruptedException e) {
-                    }
-                }
-            }
-        }
-    }
-}
diff --git a/packages/SystemUI/shared/tests/src/com/android/systemui/shared/recents/model/HighResThumbnailLoaderTest.java b/packages/SystemUI/shared/tests/src/com/android/systemui/shared/recents/model/HighResThumbnailLoaderTest.java
deleted file mode 100644
index 3b647c1..0000000
--- a/packages/SystemUI/shared/tests/src/com/android/systemui/shared/recents/model/HighResThumbnailLoaderTest.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.shared.recents.model;
-
-import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.anyBoolean;
-import static org.mockito.Mockito.anyInt;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.ComponentName;
-import android.os.Looper;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-
-import com.android.systemui.shared.SysuiSharedLibTestCase;
-import com.android.systemui.shared.recents.model.Task.TaskKey;
-import com.android.systemui.shared.system.ActivityManagerWrapper;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-/**
- * runtest --path frameworks/base/packages/SystemUI/shared/tests/src/com/android/systemui/shared/recents/model/HighResThumbnailLoaderTest.java
- */
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class HighResThumbnailLoaderTest extends SysuiSharedLibTestCase {
-
-    private HighResThumbnailLoader mLoader;
-
-    @Mock
-    private ActivityManagerWrapper mMockActivityManagerWrapper;
-    @Mock
-    private Task mTask;
-
-    private ThumbnailData mThumbnailData = new ThumbnailData();
-
-    @Before
-    public void setUp() throws Exception {
-        MockitoAnnotations.initMocks(this);
-        mLoader = new HighResThumbnailLoader(mMockActivityManagerWrapper, Looper.getMainLooper(),
-                false /* reducedResolution */);
-        mTask.key = new TaskKey(0, WINDOWING_MODE_UNDEFINED, null, null, 0, 0);
-        when(mMockActivityManagerWrapper.getTaskThumbnail(anyInt(), anyBoolean()))
-                .thenReturn(mThumbnailData);
-        mLoader.setVisible(true);
-        mLoader.setTaskLoadQueueIdle(true);
-    }
-
-    @Test
-    public void testLoading() throws Exception {
-        mLoader.setVisible(true);
-        assertTrue(mLoader.isLoading());
-        mLoader.setVisible(false);
-        assertFalse(mLoader.isLoading());
-        mLoader.setVisible(true);
-        mLoader.setFlingingFast(true);
-        assertFalse(mLoader.isLoading());
-        mLoader.setFlingingFast(false);
-        assertTrue(mLoader.isLoading());
-        mLoader.setFlingingFast(false);
-        mLoader.setTaskLoadQueueIdle(false);
-        assertFalse(mLoader.isLoading());
-        mLoader.setTaskLoadQueueIdle(true);
-        assertTrue(mLoader.isLoading());
-    }
-
-    @Test
-    public void testLoad() throws Exception {
-        mLoader.onTaskVisible(mTask);
-        mLoader.waitForLoaderIdle();
-        waitForIdleSync();
-        verify(mTask).notifyTaskDataLoaded(mThumbnailData, null);
-    }
-
-    @Test
-    public void testFlinging_notLoaded() throws Exception {
-        mLoader.setFlingingFast(true);
-        mLoader.onTaskVisible(mTask);
-        mLoader.waitForLoaderIdle();
-        waitForIdleSync();
-        verify(mTask, never()).notifyTaskDataLoaded(mThumbnailData, null);
-    }
-
-    /**
-     * Tests whether task is loaded after stopping to fling
-     */
-    @Test
-    public void testAfterFlinging() throws Exception {
-        mLoader.setFlingingFast(true);
-        mLoader.onTaskVisible(mTask);
-        mLoader.setFlingingFast(false);
-        mLoader.waitForLoaderIdle();
-        waitForIdleSync();
-        verify(mTask).notifyTaskDataLoaded(mThumbnailData, null);
-    }
-
-    @Test
-    public void testAlreadyLoaded() throws Exception {
-        mTask.thumbnail = new ThumbnailData();
-        mTask.thumbnail.reducedResolution = false;
-        mLoader.onTaskVisible(mTask);
-        mLoader.waitForLoaderIdle();
-        waitForIdleSync();
-        verify(mTask, never()).notifyTaskDataLoaded(mThumbnailData, null);
-    }
-}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java
index a3862eb..a543d17 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java
@@ -102,7 +102,8 @@
                         findViewById(R.id.key9)
                 },
                 new View[]{
-                        null, findViewById(R.id.key0), findViewById(R.id.key_enter)
+                        findViewById(R.id.delete_button), findViewById(R.id.key0),
+                        findViewById(R.id.key_enter)
                 },
                 new View[]{
                         null, mEcaView, null
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
index 7479152..50b98a1 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
@@ -23,15 +23,12 @@
 import android.animation.PropertyValuesHolder;
 import android.annotation.ColorInt;
 import android.app.PendingIntent;
-import androidx.lifecycle.LiveData;
-import androidx.lifecycle.Observer;
 import android.content.Context;
 import android.graphics.Color;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.os.Trace;
 import android.provider.Settings;
-import android.text.Layout;
 import android.text.TextUtils;
 import android.text.TextUtils.TruncateAt;
 import android.util.AttributeSet;
@@ -41,25 +38,9 @@
 import android.view.animation.Animation;
 import android.widget.Button;
 import android.widget.LinearLayout;
-import android.widget.TextView;
 
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.graphics.ColorUtils;
-import com.android.settingslib.Utils;
-import com.android.systemui.Dependency;
-import com.android.systemui.Interpolators;
-import com.android.systemui.R;
-import com.android.systemui.keyguard.KeyguardSliceProvider;
-import com.android.systemui.statusbar.AlphaOptimizedTextView;
-import com.android.systemui.statusbar.policy.ConfigurationController;
-import com.android.systemui.tuner.TunerService;
-import com.android.systemui.util.wakelock.KeepAwakeAnimationListener;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.function.Consumer;
-
+import androidx.lifecycle.LiveData;
+import androidx.lifecycle.Observer;
 import androidx.slice.Slice;
 import androidx.slice.SliceItem;
 import androidx.slice.SliceViewManager;
@@ -69,6 +50,20 @@
 import androidx.slice.widget.SliceContent;
 import androidx.slice.widget.SliceLiveData;
 
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.graphics.ColorUtils;
+import com.android.settingslib.Utils;
+import com.android.systemui.Dependency;
+import com.android.systemui.Interpolators;
+import com.android.systemui.keyguard.KeyguardSliceProvider;
+import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.tuner.TunerService;
+import com.android.systemui.util.wakelock.KeepAwakeAnimationListener;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
 /**
  * View visible under the clock on the lock screen and AoD.
  */
@@ -80,8 +75,6 @@
 
     private final HashMap<View, PendingIntent> mClickActions;
     private Uri mKeyguardSliceUri;
-    @VisibleForTesting
-    TextView mTitle;
     private Row mRow;
     private int mTextColor;
     private float mDarkAmount = 0;
@@ -92,7 +85,6 @@
      * Runnable called whenever the view contents change.
      */
     private Runnable mContentChangeListener;
-    private boolean mHasHeader;
     private Slice mSlice;
     private boolean mPulsing;
 
@@ -128,7 +120,6 @@
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
-        mTitle = findViewById(R.id.title);
         mRow = findViewById(R.id.row);
         mTextColor = Utils.getColorAttrDefaultColor(mContext, R.attr.wallpaperTextColor);
         mIconSize = (int) mContext.getResources().getDimension(R.dimen.widget_icon_size);
@@ -154,7 +145,6 @@
     private void showSlice() {
         Trace.beginSection("KeyguardSliceView#showSlice");
         if (mPulsing || mSlice == null) {
-            mTitle.setVisibility(GONE);
             mRow.setVisibility(GONE);
             if (mContentChangeListener != null) {
                 mContentChangeListener.run();
@@ -164,8 +154,9 @@
 
         ListContent lc = new ListContent(getContext(), mSlice);
         SliceContent headerContent = lc.getHeader();
-        mHasHeader = headerContent != null && !headerContent.getSliceItem().hasHint(HINT_LIST_ITEM);
-        List<SliceContent> subItems = new ArrayList<SliceContent>();
+        boolean hasHeader = headerContent != null
+                && !headerContent.getSliceItem().hasHint(HINT_LIST_ITEM);
+        List<SliceContent> subItems = new ArrayList<>();
         for (int i = 0; i < lc.getRowItems().size(); i++) {
             SliceContent subItem = lc.getRowItems().get(i);
             String itemUri = subItem.getSliceItem().getSlice().getUri().toString();
@@ -174,21 +165,11 @@
                 subItems.add(subItem);
             }
         }
-        if (!mHasHeader) {
-            mTitle.setVisibility(GONE);
-        } else {
-            mTitle.setVisibility(VISIBLE);
-
-            RowContent header = lc.getHeader();
-            SliceItem mainTitle = header.getTitleItem();
-            CharSequence title = mainTitle != null ? mainTitle.getText() : null;
-            mTitle.setText(title);
-        }
 
         mClickActions.clear();
         final int subItemsCount = subItems.size();
         final int blendedColor = getTextColor();
-        final int startIndex = mHasHeader ? 1 : 0; // First item is header; skip it
+        final int startIndex = hasHeader ? 1 : 0; // First item is header; skip it
         mRow.setVisibility(subItemsCount > 0 ? VISIBLE : GONE);
         for (int i = startIndex; i < subItemsCount; i++) {
             RowContent rc = (RowContent) subItems.get(i);
@@ -200,7 +181,7 @@
                 button = new KeyguardSliceButton(mContext);
                 button.setTextColor(blendedColor);
                 button.setTag(itemTag);
-                final int viewIndex = i - (mHasHeader ? 1 : 0);
+                final int viewIndex = i - (hasHeader ? 1 : 0);
                 mRow.addView(button, viewIndex);
             }
 
@@ -303,7 +284,6 @@
 
     private void updateTextColors() {
         final int blendedColor = getTextColor();
-        mTitle.setTextColor(blendedColor);
         int childCount = mRow.getChildCount();
         for (int i = 0; i < childCount; i++) {
             View v = mRow.getChildAt(i);
@@ -333,10 +313,6 @@
         mContentChangeListener = contentChangeListener;
     }
 
-    public boolean hasHeader() {
-        return mHasHeader;
-    }
-
     /**
      * LiveData observer lifecycle.
      * @param slice the new slice content.
@@ -352,7 +328,7 @@
         setupUri(newValue);
     }
 
-    public void setupUri(String uriString) {
+    private void setupUri(String uriString) {
         if (uriString == null) {
             uriString = KeyguardSliceProvider.KEYGUARD_SLICE_URI;
         }
@@ -564,46 +540,6 @@
         }
     }
 
-    /**
-     * A text view that will split its contents in 2 lines when possible.
-     */
-    static class TitleView extends AlphaOptimizedTextView {
-
-        public TitleView(Context context) {
-            super(context);
-        }
-
-        public TitleView(Context context, AttributeSet attrs) {
-            super(context, attrs);
-        }
-
-        public TitleView(Context context, AttributeSet attrs, int defStyleAttr) {
-            super(context, attrs, defStyleAttr);
-        }
-
-        public TitleView(Context context, AttributeSet attrs, int defStyleAttr,
-                int defStyleRes) {
-            super(context, attrs, defStyleAttr, defStyleRes);
-        }
-
-        @Override
-        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-
-            Layout layout = getLayout();
-            int lineCount = layout.getLineCount();
-            boolean ellipsizing = layout.getEllipsisCount(lineCount - 1) != 0;
-            if (lineCount > 0 && !ellipsizing) {
-                CharSequence title = getText();
-                CharSequence bestLineBreak = findBestLineBreak(title);
-                if (!TextUtils.equals(title, bestLineBreak)) {
-                    setText(bestLineBreak);
-                    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-                }
-            }
-        }
-    }
-
     private class SliceViewTransitionListener implements LayoutTransition.TransitionListener {
         @Override
         public void startTransition(LayoutTransition transition, ViewGroup container, View view,
@@ -619,15 +555,6 @@
                             .setInterpolator(Interpolators.ALPHA_IN)
                             .start();
                     break;
-                case LayoutTransition.DISAPPEARING:
-                    if (view == mTitle) {
-                        // Translate the view to the inverse of its height, so the layout event
-                        // won't misposition it.
-                        LayoutParams params = (LayoutParams) mTitle.getLayoutParams();
-                        int margin = params.topMargin + params.bottomMargin;
-                        mTitle.setTranslationY(-mTitle.getHeight() - margin);
-                    }
-                    break;
             }
         }
 
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
index db78667..a403b75 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
@@ -200,10 +200,9 @@
      * Moves clock, adjusting margins when slice content changes.
      */
     private void onSliceContentChanged() {
-        boolean smallClock = mKeyguardSlice.hasHeader() || mPulsing;
         RelativeLayout.LayoutParams layoutParams =
                 (RelativeLayout.LayoutParams) mClockView.getLayoutParams();
-        layoutParams.bottomMargin = smallClock ? mSmallClockPadding : 0;
+        layoutParams.bottomMargin = mPulsing ? mSmallClockPadding : 0;
         mClockView.setLayoutParams(layoutParams);
     }
 
@@ -214,17 +213,15 @@
     public void onLayoutChange(View view, int left, int top, int right, int bottom,
             int oldLeft, int oldTop, int oldRight, int oldBottom) {
         int heightOffset = mPulsing || mWasPulsing ? 0 : getHeight() - mLastLayoutHeight;
-        boolean hasHeader = mKeyguardSlice.hasHeader();
-        boolean smallClock = hasHeader || mPulsing;
         long duration = KeyguardSliceView.DEFAULT_ANIM_DURATION;
-        long delay = smallClock || mWasPulsing ? 0 : duration / 4;
+        long delay = mPulsing || mWasPulsing ? 0 : duration / 4;
         mWasPulsing = false;
 
         boolean shouldAnimate = mKeyguardSlice.getLayoutTransition() != null
                 && mKeyguardSlice.getLayoutTransition().isRunning();
         if (view == mClockView) {
-            float clockScale = smallClock ? mSmallClockScale : 1;
-            Paint.Style style = smallClock ? Paint.Style.FILL_AND_STROKE : Paint.Style.FILL;
+            float clockScale = mPulsing ? mSmallClockScale : 1;
+            Paint.Style style = mPulsing ? Paint.Style.FILL_AND_STROKE : Paint.Style.FILL;
             mClockView.animate().cancel();
             if (shouldAnimate) {
                 mClockView.setY(oldTop + heightOffset);
@@ -431,11 +428,6 @@
             mWasPulsing = true;
         }
         mPulsing = pulsing;
-        // Animation can look really weird when the slice has a header, let's hide the views
-        // immediately instead of fading them away.
-        if (mKeyguardSlice.hasHeader()) {
-            animate = false;
-        }
         mKeyguardSlice.setPulsing(pulsing, animate);
         updateDozeVisibleViews();
     }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index c7685f8..6b0a7a9 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -88,6 +88,7 @@
 import com.android.settingslib.WirelessUtils;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.TaskStackChangeListener;
+
 import com.google.android.collect.Lists;
 
 import java.io.FileDescriptor;
@@ -236,6 +237,8 @@
     private boolean mIsDreaming;
     private final DevicePolicyManager mDevicePolicyManager;
     private boolean mLogoutEnabled;
+    private boolean mFingerprintLockedOut;
+    private boolean mFaceLockedOut;
 
     /**
      * Short delay before restarting biometric authentication after a successful try
@@ -624,7 +627,7 @@
         if (msgId == FingerprintManager.FINGERPRINT_ERROR_CANCELED
                 && mFingerprintRunningState == BIOMETRIC_STATE_CANCELLING_RESTARTING) {
             setFingerprintRunningState(BIOMETRIC_STATE_STOPPED);
-            startListeningForFingerprint();
+            updateFingerprintListeningState();
         } else {
             setFingerprintRunningState(BIOMETRIC_STATE_STOPPED);
         }
@@ -637,6 +640,11 @@
             }
         }
 
+        if (msgId == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT
+                || msgId == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT) {
+            mFingerprintLockedOut = true;
+        }
+
         if (msgId == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT) {
             mLockPatternUtils.requireStrongAuth(
                     LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT,
@@ -652,6 +660,7 @@
     }
 
     private void handleFingerprintLockoutReset() {
+        mFingerprintLockedOut = false;
         updateFingerprintListeningState();
     }
 
@@ -659,7 +668,7 @@
         boolean wasRunning = mFingerprintRunningState == BIOMETRIC_STATE_RUNNING;
         boolean isRunning = fingerprintRunningState == BIOMETRIC_STATE_RUNNING;
         mFingerprintRunningState = fingerprintRunningState;
-
+        if (DEBUG) Log.v(TAG, "Fingerprint State: " + mFingerprintRunningState);
         // Clients of KeyguardUpdateMonitor don't care about the internal state about the
         // asynchronousness of the cancel cycle. So only notify them if the actualy running state
         // has changed.
@@ -774,7 +783,7 @@
         if (msgId == FaceManager.FACE_ERROR_CANCELED
                 && mFaceRunningState == BIOMETRIC_STATE_CANCELLING_RESTARTING) {
             setFaceRunningState(BIOMETRIC_STATE_STOPPED);
-            startListeningForFace();
+            updateFaceListeningState();
         } else {
             setFaceRunningState(BIOMETRIC_STATE_STOPPED);
         }
@@ -787,6 +796,11 @@
             }
         }
 
+        if (msgId == FaceManager.FACE_ERROR_LOCKOUT
+                || msgId == FaceManager.FACE_ERROR_LOCKOUT_PERMANENT) {
+            mFaceLockedOut = true;
+        }
+
         if (msgId == FaceManager.FACE_ERROR_LOCKOUT_PERMANENT) {
             mLockPatternUtils.requireStrongAuth(
                     LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT,
@@ -803,6 +817,7 @@
     }
 
     private void handleFaceLockoutReset() {
+        mFaceLockedOut = false;
         updateFaceListeningState();
     }
 
@@ -810,7 +825,7 @@
         boolean wasRunning = mFaceRunningState == BIOMETRIC_STATE_RUNNING;
         boolean isRunning = faceRunningState == BIOMETRIC_STATE_RUNNING;
         mFaceRunningState = faceRunningState;
-
+        if (DEBUG) Log.v(TAG, "Face State: " + mFaceRunningState);
         // Clients of KeyguardUpdateMonitor don't care about the internal state or about the
         // asynchronousness of the cancel cycle. So only notify them if the actualy running state
         // has changed.
@@ -1557,7 +1572,7 @@
                 (mBouncer && !mKeyguardGoingAway) || mGoingToSleep ||
                 shouldListenForFingerprintAssistant() || (mKeyguardOccluded && mIsDreaming))
                 && !mSwitchingUser && !isFingerprintDisabled(getCurrentUser())
-                && !mKeyguardGoingAway;
+                && !mKeyguardGoingAway && !mFingerprintLockedOut;
     }
 
     private boolean shouldListenForFace() {
@@ -1565,7 +1580,7 @@
                 (mBouncer && !mKeyguardGoingAway) || mGoingToSleep ||
                 shouldListenForFaceAssistant() || (mKeyguardOccluded && mIsDreaming))
                 && !mSwitchingUser && !isFaceDisabled(getCurrentUser())
-                && !mKeyguardGoingAway && mFaceSettingEnabledForUser;
+                && !mKeyguardGoingAway && !mFaceLockedOut && mFaceSettingEnabledForUser;
     }
 
 
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index 494880e..b7844bc 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -22,6 +22,7 @@
 import android.os.Looper;
 import android.os.Process;
 import android.os.ServiceManager;
+import android.os.UserHandle;
 import android.util.ArrayMap;
 import android.util.DisplayMetrics;
 import android.view.IWindowManager;
@@ -33,14 +34,17 @@
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.util.Preconditions;
 import com.android.settingslib.bluetooth.LocalBluetoothManager;
+import com.android.systemui.appops.AppOpsController;
+import com.android.systemui.appops.AppOpsControllerImpl;
 import com.android.systemui.assist.AssistManager;
 import com.android.systemui.colorextraction.SysuiColorExtractor;
 import com.android.systemui.fragments.FragmentService;
 import com.android.systemui.keyguard.ScreenLifecycle;
 import com.android.systemui.keyguard.WakefulnessLifecycle;
 import com.android.systemui.plugins.ActivityStarter;
-import com.android.systemui.plugins.PluginInitializerImpl;
 import com.android.systemui.plugins.PluginDependencyProvider;
+import com.android.systemui.plugins.PluginInitializerImpl;
+import com.android.systemui.recents.OverviewProxyService;
 import com.android.systemui.shared.plugins.PluginManager;
 import com.android.systemui.shared.plugins.PluginManagerImpl;
 import com.android.systemui.plugins.VolumeDialogController;
@@ -49,18 +53,17 @@
 import com.android.systemui.power.PowerNotificationWarnings;
 import com.android.systemui.power.PowerUI;
 import com.android.systemui.statusbar.NotificationRemoteInputManager;
-import com.android.systemui.statusbar.notification.AppOpsListener;
 import com.android.systemui.statusbar.VibratorHelper;
 import com.android.systemui.statusbar.notification.NotificationData.KeyguardEnvironment;
 import com.android.systemui.statusbar.phone.ConfigurationControllerImpl;
 import com.android.systemui.statusbar.phone.DarkIconDispatcherImpl;
+import com.android.systemui.statusbar.phone.KeyguardEnvironmentImpl;
 import com.android.systemui.statusbar.phone.LightBarController;
 import com.android.systemui.statusbar.phone.LockscreenGestureLogger;
 import com.android.systemui.statusbar.phone.ManagedProfileController;
 import com.android.systemui.statusbar.phone.ManagedProfileControllerImpl;
 import com.android.systemui.statusbar.phone.ShadeController;
 import com.android.systemui.statusbar.phone.StatusBar;
-import com.android.systemui.statusbar.phone.KeyguardEnvironmentImpl;
 import com.android.systemui.statusbar.phone.StatusBarIconController;
 import com.android.systemui.statusbar.phone.StatusBarIconControllerImpl;
 import com.android.systemui.statusbar.phone.StatusBarRemoteInputCallback;
@@ -301,7 +304,8 @@
                 new PluginDependencyProvider(get(PluginManager.class)));
 
         mProviders.put(LocalBluetoothManager.class, () ->
-                LocalBluetoothManager.create(mContext, getDependency(BG_HANDLER)));
+                LocalBluetoothManager.create(mContext, getDependency(BG_HANDLER),
+                        UserHandle.ALL));
 
         mProviders.put(VolumeDialogController.class, () ->
                 new VolumeDialogControllerImpl(mContext));
@@ -336,8 +340,6 @@
 
         mProviders.put(EnhancedEstimates.class, () -> new EnhancedEstimatesImpl());
 
-        mProviders.put(AppOpsListener.class, () -> new AppOpsListener(mContext));
-
         mProviders.put(VibratorHelper.class, () -> new VibratorHelper(mContext));
 
         mProviders.put(IStatusBarService.class, () -> IStatusBarService.Stub.asInterface(
@@ -357,6 +359,9 @@
 
         mProviders.put(InitController.class, InitController::new);
 
+        mProviders.put(AppOpsController.class, () ->
+                new AppOpsControllerImpl(mContext, getDependency(BG_LOOPER)));
+
         // Put all dependencies above here so the factory can override them if it wants.
         SystemUIFactory.getInstance().injectDependencies(mProviders, mContext);
 
diff --git a/packages/SystemUI/src/com/android/systemui/RecentsComponent.java b/packages/SystemUI/src/com/android/systemui/RecentsComponent.java
deleted file mode 100644
index fb343f9..0000000
--- a/packages/SystemUI/src/com/android/systemui/RecentsComponent.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui;
-
-import android.graphics.Rect;
-import android.view.Display;
-import android.view.View;
-
-public interface RecentsComponent {
-    void showRecentApps(boolean triggeredFromAltTab);
-
-    /**
-     * Docks the top-most task and opens recents.
-     */
-    boolean splitPrimaryTask(int stackCreateMode, Rect initialBounds,
-            int metricsDockAction);
-}
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
index 3007b6e..c844496 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
@@ -207,11 +207,11 @@
 
         mOverlay.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
         mOverlay.setAlpha(0);
-        mOverlay.setAllowForceDark(false);
+        mOverlay.setForceDarkAllowed(false);
 
         mBottomOverlay.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
         mBottomOverlay.setAlpha(0);
-        mBottomOverlay.setAllowForceDark(false);
+        mBottomOverlay.setForceDarkAllowed(false);
 
         updateViews();
 
diff --git a/packages/SystemUI/src/com/android/systemui/appops/AppOpItem.java b/packages/SystemUI/src/com/android/systemui/appops/AppOpItem.java
new file mode 100644
index 0000000..9f363f6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/appops/AppOpItem.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.appops;
+
+/**
+ * Item to store information of active applications using different APP OPS
+ */
+public class AppOpItem {
+
+    private int mCode;
+    private int mUid;
+    private String mPackageName;
+    private long mTimeStarted;
+
+    public AppOpItem(int code, int uid, String packageName, long timeStarted) {
+        this.mCode = code;
+        this.mUid = uid;
+        this.mPackageName = packageName;
+        this.mTimeStarted = timeStarted;
+    }
+
+    public int getCode() {
+        return mCode;
+    }
+
+    public int getUid() {
+        return mUid;
+    }
+
+    public String getPackageName() {
+        return mPackageName;
+    }
+
+    public long getTimeStarted() {
+        return mTimeStarted;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/appops/AppOpsController.java b/packages/SystemUI/src/com/android/systemui/appops/AppOpsController.java
new file mode 100644
index 0000000..4966fc6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/appops/AppOpsController.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.appops;
+
+import java.util.List;
+
+/**
+ * Controller to keep track of applications that have requested access to given App Ops.
+ *
+ * It can be subscribed to with callbacks. Additionally, it passes on the information to
+ * NotificationPresenter to be displayed to the user.
+ */
+public interface AppOpsController {
+
+    /**
+     * Callback to notify when the state of active AppOps tracked by the controller has changed
+     */
+    interface Callback {
+        void onActiveStateChanged(int code, int uid, String packageName, boolean active);
+    }
+
+    /**
+     * Adds a callback that will get notified when an AppOp of the type the controller tracks
+     * changes
+     *
+     * @param opsCodes App Ops the callback was interested in checking
+     * @param cb Callback to report changes
+     *
+     * @see #removeCallback(int[], Callback)
+     */
+    void addCallback(int[] opsCodes, Callback cb);
+
+    /**
+     * Removes a callback from those notifified when an AppOp of the type the controller tracks
+     * changes
+     *
+     * @param opsCodes App Ops the callback is interested in checking
+     * @param cb Callback to stop reporting changes
+     *
+     * @see #addCallback(int[], Callback)
+     */
+    void removeCallback(int[] opsCodes, Callback cb);
+
+    /**
+     * Returns a copy of the list containing all the active AppOps that the controller tracks.
+     *
+     * @return List of active AppOps information
+     */
+    List<AppOpItem> getActiveAppOps();
+
+    /**
+     * Returns a copy of the list containing all the active AppOps that the controller tracks, for
+     * a given user id.
+     *
+     * @param userId User id to track
+     *
+     * @return List of active AppOps information for that user id
+     */
+    List<AppOpItem> getActiveAppOpsForUser(int userId);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java b/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
new file mode 100644
index 0000000..906a210
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
@@ -0,0 +1,223 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.appops;
+
+import android.app.AppOpsManager;
+import android.content.Context;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.UserHandle;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+import android.util.Log;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Controller to keep track of applications that have requested access to given App Ops
+ *
+ * It can be subscribed to with callbacks. Additionally, it passes on the information to
+ * NotificationPresenter to be displayed to the user.
+ */
+public class AppOpsControllerImpl implements AppOpsController,
+        AppOpsManager.OnOpActiveChangedListener {
+
+    private static final long LOCATION_TIME_DELAY_MS = 5000;
+    private static final String TAG = "AppOpsControllerImpl";
+    private static final boolean DEBUG = false;
+    private final Context mContext;
+
+    protected final AppOpsManager mAppOps;
+    private final H mBGHandler;
+    private final List<AppOpsController.Callback> mCallbacks = new ArrayList<>();
+    private final ArrayMap<Integer, Set<Callback>> mCallbacksByCode = new ArrayMap<>();
+    @GuardedBy("mActiveItems")
+    private final List<AppOpItem> mActiveItems = new ArrayList<>();
+
+    protected static final int[] OPS = new int[] {AppOpsManager.OP_CAMERA,
+            AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
+            AppOpsManager.OP_RECORD_AUDIO,
+            AppOpsManager.OP_COARSE_LOCATION,
+            AppOpsManager.OP_FINE_LOCATION};
+
+    public AppOpsControllerImpl(Context context, Looper bgLooper) {
+        mContext = context;
+        mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
+        mBGHandler = new H(bgLooper);
+        final int numOps = OPS.length;
+        for (int i = 0; i < numOps; i++) {
+            mCallbacksByCode.put(OPS[i], new ArraySet<>());
+        }
+    }
+
+    @VisibleForTesting
+    protected void setListening(boolean listening) {
+        if (listening) {
+            mAppOps.startWatchingActive(OPS, this);
+        } else {
+            mAppOps.stopWatchingActive(this);
+        }
+    }
+
+    /**
+     * Adds a callback that will get notifified when an AppOp of the type the controller tracks
+     * changes
+     *
+     * @param callback Callback to report changes
+     * @param opsCodes App Ops the callback is interested in checking
+     *
+     * @see #removeCallback(int[], Callback)
+     */
+    @Override
+    public void addCallback(int[] opsCodes, AppOpsController.Callback callback) {
+        boolean added = false;
+        final int numCodes = opsCodes.length;
+        for (int i = 0; i < numCodes; i++) {
+            if (mCallbacksByCode.containsKey(opsCodes[i])) {
+                mCallbacksByCode.get(opsCodes[i]).add(callback);
+                added = true;
+            } else {
+                if (DEBUG) Log.wtf(TAG, "APP_OP " + opsCodes[i] + " not supported");
+            }
+        }
+        if (added) mCallbacks.add(callback);
+        if (!mCallbacks.isEmpty()) setListening(true);
+    }
+
+    /**
+     * Removes a callback from those notified when an AppOp of the type the controller tracks
+     * changes
+     *
+     * @param callback Callback to stop reporting changes
+     * @param opsCodes App Ops the callback was interested in checking
+     *
+     * @see #addCallback(int[], Callback)
+     */
+    @Override
+    public void removeCallback(int[] opsCodes, AppOpsController.Callback callback) {
+        final int numCodes = opsCodes.length;
+        for (int i = 0; i < numCodes; i++) {
+            if (mCallbacksByCode.containsKey(opsCodes[i])) {
+                mCallbacksByCode.get(opsCodes[i]).remove(callback);
+            }
+        }
+        mCallbacks.remove(callback);
+        if (mCallbacks.isEmpty()) setListening(false);
+    }
+
+    private AppOpItem getAppOpItem(int code, int uid, String packageName) {
+        final int itemsQ = mActiveItems.size();
+        for (int i = 0; i < itemsQ; i++) {
+            AppOpItem item = mActiveItems.get(i);
+            if (item.getCode() == code && item.getUid() == uid
+                    && item.getPackageName().equals(packageName)) {
+                return item;
+            }
+        }
+        return null;
+    }
+
+    private boolean updateActives(int code, int uid, String packageName, boolean active) {
+        synchronized (mActiveItems) {
+            AppOpItem item = getAppOpItem(code, uid, packageName);
+            if (item == null && active) {
+                item = new AppOpItem(code, uid, packageName, System.currentTimeMillis());
+                mActiveItems.add(item);
+                if (code == AppOpsManager.OP_COARSE_LOCATION
+                        || code == AppOpsManager.OP_FINE_LOCATION) {
+                    mBGHandler.scheduleRemoval(item, LOCATION_TIME_DELAY_MS);
+                }
+                if (DEBUG) Log.w(TAG, "Added item: " + item.toString());
+                return true;
+            } else if (item != null && !active) {
+                mActiveItems.remove(item);
+                if (DEBUG) Log.w(TAG, "Removed item: " + item.toString());
+                return true;
+            } else if (item != null && active
+                    && (code == AppOpsManager.OP_COARSE_LOCATION
+                            || code == AppOpsManager.OP_FINE_LOCATION)) {
+                mBGHandler.scheduleRemoval(item, LOCATION_TIME_DELAY_MS);
+                return true;
+            }
+            return false;
+        }
+    }
+
+    /**
+     * Returns a copy of the list containing all the active AppOps that the controller tracks.
+     *
+     * @return List of active AppOps information
+     */
+    public List<AppOpItem> getActiveAppOps() {
+        synchronized (mActiveItems) {
+            return new ArrayList<>(mActiveItems);
+        }
+    }
+
+    /**
+     * Returns a copy of the list containing all the active AppOps that the controller tracks, for
+     * a given user id.
+     *
+     * @param userId User id to track
+     *
+     * @return List of active AppOps information for that user id
+     */
+    public List<AppOpItem> getActiveAppOpsForUser(int userId) {
+        List<AppOpItem> list = new ArrayList<>();
+        synchronized (mActiveItems) {
+            final int numActiveItems = mActiveItems.size();
+            for (int i = 0; i < numActiveItems; i++) {
+                AppOpItem item = mActiveItems.get(i);
+                if (UserHandle.getUserId(item.getUid()) == userId) {
+                    list.add(item);
+                }
+            }
+        }
+        return list;
+    }
+
+    @Override
+    public void onOpActiveChanged(int code, int uid, String packageName, boolean active) {
+        if (updateActives(code, uid, packageName, active)) {
+            for (Callback cb: mCallbacksByCode.get(code)) {
+                cb.onActiveStateChanged(code, uid, packageName, active);
+            }
+        }
+    }
+
+    private final class H extends Handler {
+        H(Looper looper) {
+            super(looper);
+        }
+
+        public void scheduleRemoval(AppOpItem item, long timeToRemoval) {
+            removeCallbacksAndMessages(item);
+            postDelayed(new Runnable() {
+                @Override
+                public void run() {
+                    onOpActiveChanged(item.getCode(), item.getUid(),
+                            item.getPackageName(), false);
+                }
+            }, item, timeToRemoval);
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogView.java b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogView.java
index 7d77929..d902b72 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDialogView.java
@@ -167,7 +167,6 @@
         final ImageView icon = mLayout.findViewById(R.id.biometric_icon);
 
         icon.setContentDescription(getResources().getString(getIconDescriptionResourceId()));
-        mErrorText.setText(getResources().getString(getHintStringResourceId()));
 
         setDismissesDialog(space);
         setDismissesDialog(leftSpace);
@@ -189,6 +188,8 @@
     public void onAttachedToWindow() {
         super.onAttachedToWindow();
 
+        mErrorText.setText(getHintStringResourceId());
+
         final TextView title = mLayout.findViewById(R.id.title);
         final TextView subtitle = mLayout.findViewById(R.id.subtitle);
         final TextView description = mLayout.findViewById(R.id.description);
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeReceiver.java b/packages/SystemUI/src/com/android/systemui/doze/DozeReceiver.java
index dcb3882..30dfd36 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeReceiver.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeReceiver.java
@@ -20,5 +20,19 @@
  * Interface for class that cares about doze states.
  */
 public interface DozeReceiver {
+
+    /**
+     * If device enters or leaves doze mode
+     */
     void setDozing(boolean dozing);
+
+    /**
+     * Invoked every time a minute is elapsed in doze mode
+     */
+    void dozeTimeTick();
+
+    /**
+     * When view is double tapped in doze mode.
+     */
+    void onDozeDoubleTap();
 }
diff --git a/packages/SystemUI/src/com/android/systemui/pip/BasePipManager.java b/packages/SystemUI/src/com/android/systemui/pip/BasePipManager.java
index 36dbb0f..e0fc31b 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/BasePipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/BasePipManager.java
@@ -21,9 +21,11 @@
 
 import java.io.PrintWriter;
 
-public interface  BasePipManager {
+public interface BasePipManager {
     void initialize(Context context);
     void showPictureInPictureMenu();
+    default void expandPip() {}
+    default void hidePipMenu(Runnable onStartCallback, Runnable onEndCallback) {}
     void onConfigurationChanged(Configuration newConfig);
-    void dump(PrintWriter pw);
+    default void dump(PrintWriter pw) {}
 }
diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipUI.java b/packages/SystemUI/src/com/android/systemui/pip/PipUI.java
index 864a6f9..70b581a 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/PipUI.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipUI.java
@@ -24,8 +24,6 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import com.android.systemui.SystemUI;
-import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.recents.events.component.ExpandPipEvent;
 import com.android.systemui.statusbar.CommandQueue;
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -68,7 +66,11 @@
     }
 
     public void expandPip() {
-        EventBus.getDefault().send(new ExpandPipEvent());
+        mPipManager.expandPip();
+    }
+
+    public void hidePipMenu(Runnable onStartCallback, Runnable onEndCallback) {
+        mPipManager.hidePipMenu(onStartCallback, onEndCallback);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
index 04746c1..08208e5 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
@@ -38,8 +38,6 @@
 import com.android.systemui.Dependency;
 import com.android.systemui.UiOffloadThread;
 import com.android.systemui.pip.BasePipManager;
-import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.recents.events.component.ExpandPipEvent;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.InputConsumerController;
 import com.android.systemui.shared.system.TaskStackChangeListener;
@@ -197,7 +195,6 @@
                 mMenuController, mInputConsumerController);
         mAppOpsListener = new PipAppOpsListener(context, mActivityManager,
                 mTouchHandler.getMotionHelper());
-        EventBus.getDefault().register(this);
     }
 
     /**
@@ -210,11 +207,20 @@
     /**
      * Expands the PIP.
      */
-    public final void onBusEvent(ExpandPipEvent event) {
+    @Override
+    public void expandPip() {
         mTouchHandler.getMotionHelper().expandPip(false /* skipAnimation */);
     }
 
     /**
+     * Hides the PIP menu.
+     */
+    @Override
+    public void hidePipMenu(Runnable onStartCallback, Runnable onEndCallback) {
+        mMenuController.hideMenu(onStartCallback, onEndCallback);
+    }
+
+    /**
      * Sent from KEYCODE_WINDOW handler in PhoneWindowManager, to request the menu to be shown.
      */
     public void showPictureInPictureMenu() {
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
index 2dc531a..b746c19 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
@@ -72,8 +72,6 @@
 
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
-import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.recents.events.component.HidePipMenuEvent;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -151,7 +149,7 @@
                     cancelDelayedFinish();
                     break;
                 case MESSAGE_HIDE_MENU:
-                    hideMenu();
+                    hideMenu((Runnable) msg.obj);
                     break;
                 case MESSAGE_UPDATE_ACTIONS: {
                     final Bundle data = (Bundle) msg.obj;
@@ -275,7 +273,6 @@
         super.onStop();
 
         cancelDelayedFinish();
-        EventBus.getDefault().unregister(this);
     }
 
     @Override
@@ -335,19 +332,6 @@
         // Do nothing
     }
 
-    public final void onBusEvent(HidePipMenuEvent event) {
-        if (mMenuState != MENU_STATE_NONE) {
-            // If the menu is visible in either the closed or full state, then hide the menu and
-            // trigger the animation trigger afterwards
-            event.getAnimationTrigger().increment();
-            hideMenu(() -> {
-                mHandler.post(() -> {
-                    event.getAnimationTrigger().decrement();
-                });
-            }, true /* notifyMenuVisibility */, false /* isDismissing */);
-        }
-    }
-
     private void showMenu(int menuState, Rect stackBounds, Rect movementBounds,
             boolean allowMenuTimeout, boolean resizeMenuOnShow) {
         mAllowMenuTimeout = allowMenuTimeout;
@@ -398,8 +382,11 @@
     }
 
     private void hideMenu() {
-        hideMenu(null /* animationFinishedRunnable */, true /* notifyMenuVisibility */,
-                false /* isDismissing */);
+        hideMenu(null);
+    }
+
+    private void hideMenu(Runnable animationEndCallback) {
+        hideMenu(animationEndCallback, true /* notifyMenuVisibility */, false /* isDismissing */);
     }
 
     private void hideMenu(final Runnable animationFinishedRunnable, boolean notifyMenuVisibility,
@@ -450,9 +437,6 @@
         }
         notifyActivityCallback(mMessenger);
 
-        // Register for HidePipMenuEvents once we notify the controller of this activity
-        EventBus.getDefault().register(this);
-
         ParceledListSlice actions = intent.getParcelableExtra(EXTRA_ACTIONS);
         if (actions != null) {
             mActions.clear();
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
index 360fe73..56b8324 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
@@ -19,9 +19,9 @@
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
 
-import android.app.ActivityTaskManager;
 import android.app.ActivityManager.StackInfo;
 import android.app.ActivityOptions;
+import android.app.ActivityTaskManager;
 import android.app.IActivityManager;
 import android.app.RemoteAction;
 import android.content.Context;
@@ -37,14 +37,8 @@
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.util.Log;
-import android.view.IWindowManager;
-
 import com.android.systemui.pip.phone.PipMediaController.ActionListener;
-import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.recents.events.component.HidePipMenuEvent;
-import com.android.systemui.recents.misc.ReferenceCountedTrigger;
 import com.android.systemui.shared.system.InputConsumerController;
-
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.List;
@@ -131,7 +125,7 @@
     // The dismiss fraction update is sent frequently, so use a temporary bundle for the message
     private Bundle mTmpDismissFractionData = new Bundle();
 
-    private ReferenceCountedTrigger mOnAttachDecrementTrigger;
+    private Runnable mOnAnimationEndRunnable;
     private boolean mStartActivityRequested;
     private long mStartActivityRequestedTime;
     private Messenger mToActivityMessenger;
@@ -171,9 +165,9 @@
                 case MESSAGE_UPDATE_ACTIVITY_CALLBACK: {
                     mToActivityMessenger = msg.replyTo;
                     setStartActivityRequested(false);
-                    if (mOnAttachDecrementTrigger != null) {
-                        mOnAttachDecrementTrigger.decrement();
-                        mOnAttachDecrementTrigger = null;
+                    if (mOnAnimationEndRunnable != null) {
+                        mOnAnimationEndRunnable.run();
+                        mOnAnimationEndRunnable = null;
                     }
                     // Mark the menu as invisible once the activity finishes as well
                     if (mToActivityMessenger == null) {
@@ -188,9 +182,9 @@
 
     private Runnable mStartActivityRequestedTimeoutRunnable = () -> {
         setStartActivityRequested(false);
-        if (mOnAttachDecrementTrigger != null) {
-            mOnAttachDecrementTrigger.decrement();
-            mOnAttachDecrementTrigger = null;
+        if (mOnAnimationEndRunnable != null) {
+            mOnAnimationEndRunnable.run();
+            mOnAnimationEndRunnable = null;
         }
         Log.e(TAG, "Expected start menu activity request timed out");
     };
@@ -209,8 +203,6 @@
         mActivityManager = activityManager;
         mMediaController = mediaController;
         mInputConsumerController = inputConsumerController;
-
-        EventBus.getDefault().register(this);
     }
 
     public boolean isMenuActivityVisible() {
@@ -353,6 +345,36 @@
     }
 
     /**
+     * Hides the menu activity.
+     */
+    public void hideMenu(Runnable onStartCallback, Runnable onEndCallback) {
+        if (mStartActivityRequested) {
+            // If the menu has been start-requested, but not actually started, then we defer the
+            // trigger callback until the menu has started and called back to the controller.
+            mOnAnimationEndRunnable = onEndCallback;
+            onStartCallback.run();
+
+            // Fallback for b/63752800, we have started the PipMenuActivity but it has not made any
+            // callbacks. Don't continue to wait for the menu to show past some timeout.
+            mHandler.removeCallbacks(mStartActivityRequestedTimeoutRunnable);
+            mHandler.postDelayed(mStartActivityRequestedTimeoutRunnable,
+                    START_ACTIVITY_REQUEST_TIMEOUT_MS);
+        } else if (mMenuState != MENU_STATE_NONE && mToActivityMessenger != null) {
+            // If the menu is visible in either the closed or full state, then hide the menu and
+            // trigger the animation trigger afterwards
+            onStartCallback.run();
+            Message m = Message.obtain();
+            m.what = PipMenuActivity.MESSAGE_HIDE_MENU;
+            m.obj = onEndCallback;
+            try {
+                mToActivityMessenger.send(m);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Could not notify hide menu", e);
+            }
+        }
+    }
+
+    /**
      * Preemptively mark the menu as invisible, used when we are directly manipulating the pinned
      * stack and don't want to trigger a resize which can animate the stack in a conflicting way
      * (ie. when manually expanding or dismissing).
@@ -496,21 +518,6 @@
         mStartActivityRequestedTime = requested ? SystemClock.uptimeMillis() : 0;
     }
 
-    public final void onBusEvent(HidePipMenuEvent event) {
-        if (mStartActivityRequested) {
-            // If the menu has been start-requested, but not actually started, then we defer the
-            // trigger callback until the menu has started and called back to the controller.
-            mOnAttachDecrementTrigger = event.getAnimationTrigger();
-            mOnAttachDecrementTrigger.increment();
-
-            // Fallback for b/63752800, we have started the PipMenuActivity but it has not made any
-            // callbacks. Don't continue to wait for the menu to show past some timeout.
-            mHandler.removeCallbacks(mStartActivityRequestedTimeoutRunnable);
-            mHandler.postDelayed(mStartActivityRequestedTimeoutRunnable,
-                    START_ACTIVITY_REQUEST_TIMEOUT_MS);
-        }
-    }
-
     public void dump(PrintWriter pw, String prefix) {
         final String innerPrefix = prefix + "  ";
         pw.println(prefix + TAG);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
index 43e9db7..e17e0bc 100755
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
@@ -758,9 +758,4 @@
             WindowManagerWrapper.getInstance().setPipVisibility(visible);
         });
     }
-
-    @Override
-    public void dump(PrintWriter pw) {
-        // Do nothing
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java
new file mode 100644
index 0000000..661b958
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.recents;
+
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
+
+import android.app.ActivityManager;
+import android.app.trust.TrustManager;
+import android.content.Context;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.hardware.display.DisplayManager;
+import android.os.Handler;
+import android.os.RemoteException;
+import android.util.Log;
+import android.view.Display;
+import android.widget.Toast;
+import com.android.systemui.Dependency;
+import com.android.systemui.R;
+import com.android.systemui.SysUiServiceProvider;
+import com.android.systemui.shared.recents.IOverviewProxy;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
+import com.android.systemui.stackdivider.Divider;
+import com.android.systemui.statusbar.phone.StatusBar;
+
+/**
+ * An implementation of the Recents interface which proxies to the OverviewProxyService.
+ */
+public class OverviewProxyRecentsImpl implements RecentsImplementation {
+
+    private final static String TAG = "OverviewProxyRecentsImpl";
+
+    private SysUiServiceProvider mSysUiServiceProvider;
+    private Context mContext;
+    private Handler mHandler;
+    private TrustManager mTrustManager;
+    private OverviewProxyService mOverviewProxyService;
+
+    @Override
+    public void onStart(Context context, SysUiServiceProvider sysUiServiceProvider) {
+        mContext = context;
+        mSysUiServiceProvider = sysUiServiceProvider;
+        mHandler = new Handler();
+        mTrustManager = (TrustManager) context.getSystemService(Context.TRUST_SERVICE);
+        mOverviewProxyService = Dependency.get(OverviewProxyService.class);
+    }
+
+    @Override
+    public void showRecentApps(boolean triggeredFromAltTab) {
+        IOverviewProxy overviewProxy = mOverviewProxyService.getProxy();
+        if (overviewProxy != null) {
+            try {
+                overviewProxy.onOverviewShown(triggeredFromAltTab);
+                return;
+            } catch (RemoteException e) {
+                Log.e(TAG, "Failed to send overview show event to launcher.", e);
+            }
+        } else {
+            // Do nothing
+        }
+    }
+
+    @Override
+    public void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) {
+        IOverviewProxy overviewProxy = mOverviewProxyService.getProxy();
+        if (overviewProxy != null) {
+            try {
+                overviewProxy.onOverviewHidden(triggeredFromAltTab, triggeredFromHomeKey);
+                return;
+            } catch (RemoteException e) {
+                Log.e(TAG, "Failed to send overview hide event to launcher.", e);
+            }
+        } else {
+            // Do nothing
+        }
+    }
+
+    @Override
+    public void toggleRecentApps() {
+        // If connected to launcher service, let it handle the toggle logic
+        IOverviewProxy overviewProxy = mOverviewProxyService.getProxy();
+        if (overviewProxy != null) {
+            final Runnable toggleRecents = () -> {
+                try {
+                    if (mOverviewProxyService.getProxy() != null) {
+                        mOverviewProxyService.getProxy().onOverviewToggle();
+                    }
+                } catch (RemoteException e) {
+                    Log.e(TAG, "Cannot send toggle recents through proxy service.", e);
+                }
+            };
+            // Preload only if device for current user is unlocked
+            final StatusBar statusBar = mSysUiServiceProvider.getComponent(StatusBar.class);
+            if (statusBar != null && statusBar.isKeyguardShowing()) {
+                statusBar.executeRunnableDismissingKeyguard(() -> {
+                        // Flush trustmanager before checking device locked per user
+                        mTrustManager.reportKeyguardShowingChanged();
+                        mHandler.post(toggleRecents);
+                    }, null,  true /* dismissShade */, false /* afterKeyguardGone */,
+                    true /* deferred */);
+            } else {
+                toggleRecents.run();
+            }
+            return;
+        } else {
+            // Do nothing
+        }
+    }
+
+    @Override
+    public boolean splitPrimaryTask(int stackCreateMode, Rect initialBounds,
+            int metricsDockAction) {
+        Point realSize = new Point();
+        if (initialBounds == null) {
+            mContext.getSystemService(DisplayManager.class).getDisplay(Display.DEFAULT_DISPLAY)
+                    .getRealSize(realSize);
+            initialBounds = new Rect(0, 0, realSize.x, realSize.y);
+        }
+
+        ActivityManager.RunningTaskInfo runningTask =
+                ActivityManagerWrapper.getInstance().getRunningTask();
+        final int activityType = runningTask != null
+                ? runningTask.configuration.windowConfiguration.getActivityType()
+                : ACTIVITY_TYPE_UNDEFINED;
+        boolean screenPinningActive = ActivityManagerWrapper.getInstance().isScreenPinningActive();
+        boolean isRunningTaskInHomeOrRecentsStack =
+                activityType == ACTIVITY_TYPE_HOME || activityType == ACTIVITY_TYPE_RECENTS;
+        if (runningTask != null && !isRunningTaskInHomeOrRecentsStack && !screenPinningActive) {
+            if (runningTask.supportsSplitScreenMultiWindow) {
+                if (ActivityManagerWrapper.getInstance().setTaskWindowingModeSplitScreenPrimary(
+                        runningTask.id, stackCreateMode, initialBounds)) {
+                    // The overview service is handling split screen, so just skip the wait for the
+                    // first draw and notify the divider to start animating now
+                    final Divider divider = mSysUiServiceProvider.getComponent(Divider.class);
+                    if (divider != null) {
+                        divider.onRecentsDrawn();
+                    }
+                    return true;
+                }
+            } else {
+                Toast.makeText(mContext, R.string.dock_non_resizeble_failed_to_dock_text,
+                        Toast.LENGTH_SHORT).show();
+            }
+        }
+        return false;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
similarity index 98%
rename from packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
rename to packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index 1bf8750..19f7675 100644
--- a/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -14,7 +14,7 @@
  * limitations under the License
  */
 
-package com.android.systemui;
+package com.android.systemui.recents;
 
 import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
 import static android.view.MotionEvent.ACTION_DOWN;
@@ -42,7 +42,11 @@
 import android.provider.Settings;
 import android.util.Log;
 import android.view.MotionEvent;
-import com.android.systemui.OverviewProxyService.OverviewProxyListener;
+import com.android.systemui.Dependency;
+import com.android.systemui.Dumpable;
+import com.android.systemui.Prefs;
+import com.android.systemui.SysUiServiceProvider;
+import com.android.systemui.recents.OverviewProxyService.OverviewProxyListener;
 import com.android.systemui.shared.recents.IOverviewProxy;
 import com.android.systemui.shared.recents.ISystemUiProxy;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
index 74f6c2d..de22d21 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
@@ -16,232 +16,29 @@
 
 package com.android.systemui.recents;
 
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
-import static com.android.systemui.statusbar.phone.StatusBar.SYSTEM_DIALOG_REASON_RECENT_APPS;
-
-import android.app.ActivityManager;
-import android.app.trust.TrustManager;
-import android.content.ComponentName;
 import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.content.pm.ActivityInfo;
 import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.graphics.Point;
 import android.graphics.Rect;
-import android.hardware.display.DisplayManager;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.os.UserHandle;
 import android.provider.Settings;
-import android.util.EventLog;
-import android.util.Log;
-import android.view.Display;
-import android.widget.Toast;
-
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.systemui.Dependency;
-import com.android.systemui.EventLogConstants;
-import com.android.systemui.EventLogTags;
-import com.android.systemui.OverviewProxyService;
 import com.android.systemui.R;
-import com.android.systemui.RecentsComponent;
-import com.android.systemui.SystemUIApplication;
-import com.android.systemui.recents.events.ui.RecentsGrowingEvent;
-import com.android.systemui.shared.recents.IOverviewProxy;
 import com.android.systemui.SystemUI;
-import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.recents.events.activity.ConfigurationChangedEvent;
-import com.android.systemui.recents.events.activity.DockedFirstAnimationFrameEvent;
-import com.android.systemui.recents.events.activity.DockedTopTaskEvent;
-import com.android.systemui.recents.events.activity.LaunchTaskFailedEvent;
-import com.android.systemui.recents.events.activity.RecentsActivityStartingEvent;
-import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
-import com.android.systemui.recents.events.component.ScreenPinningRequestEvent;
-import com.android.systemui.recents.events.component.SetWaitingForTransitionStartEvent;
-import com.android.systemui.recents.events.component.ShowUserToastEvent;
-import com.android.systemui.recents.events.ui.RecentsDrawnEvent;
-import com.android.systemui.recents.misc.SystemServicesProxy;
-import com.android.systemui.shared.recents.model.RecentsTaskLoader;
-import com.android.systemui.shared.system.ActivityManagerWrapper;
-import com.android.systemui.stackdivider.Divider;
 import com.android.systemui.statusbar.CommandQueue;
-
-import com.android.systemui.statusbar.phone.StatusBar;
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.Set;
-
 
 /**
- * An implementation of the SystemUI recents component, which supports both system and secondary
- * users.
+ * A proxy to a Recents implementation.
  */
-public class Recents extends SystemUI
-        implements RecentsComponent, CommandQueue.Callbacks {
+public class Recents extends SystemUI implements CommandQueue.Callbacks {
 
-    private final static String TAG = "Recents";
-
-    public final static int EVENT_BUS_PRIORITY = 1;
-    public final static int BIND_TO_SYSTEM_USER_RETRY_DELAY = 5000;
-
-    public final static Set<String> RECENTS_ACTIVITIES = new HashSet<>();
-    static {
-        RECENTS_ACTIVITIES.add(RecentsImpl.RECENTS_ACTIVITY);
-    }
-
-    private static final String COUNTER_WINDOW_SUPPORTED = "window_enter_supported";
-    private static final String COUNTER_WINDOW_UNSUPPORTED = "window_enter_unsupported";
-    private static final String COUNTER_WINDOW_INCOMPATIBLE = "window_enter_incompatible";
-
-    private static SystemServicesProxy sSystemServicesProxy;
-    private static RecentsDebugFlags sDebugFlags;
-    private static RecentsTaskLoader sTaskLoader;
-    private static RecentsConfiguration sConfiguration;
-
-    private OverviewProxyService mOverviewProxyService;
-
-    private Handler mHandler;
-    private RecentsImpl mImpl;
-    private TrustManager mTrustManager;
-    private int mDraggingInRecentsCurrentUser;
-
-    // Only For system user, this is the callbacks instance we return to each secondary user
-    private RecentsSystemUser mSystemToUserCallbacks;
-
-    // Only for secondary users, this is the callbacks instance provided by the system user to make
-    // calls back
-    private IRecentsSystemUserCallbacks mUserToSystemCallbacks;
-
-    // The set of runnables to run after binding to the system user's service.
-    private final ArrayList<Runnable> mOnConnectRunnables = new ArrayList<>();
-
-    // Only for secondary users, this is the death handler for the binder from the system user
-    private final IBinder.DeathRecipient mUserToSystemCallbacksDeathRcpt = new IBinder.DeathRecipient() {
-        @Override
-        public void binderDied() {
-            mUserToSystemCallbacks = null;
-            EventLog.writeEvent(EventLogTags.SYSUI_RECENTS_CONNECTION,
-                    EventLogConstants.SYSUI_RECENTS_CONNECTION_USER_SYSTEM_UNBOUND,
-                    sSystemServicesProxy.getProcessUser());
-
-            // Retry after a fixed duration
-            mHandler.postDelayed(new Runnable() {
-                @Override
-                public void run() {
-                    registerWithSystemUser();
-                }
-            }, BIND_TO_SYSTEM_USER_RETRY_DELAY);
-        }
-    };
-
-    // Only for secondary users, this is the service connection we use to connect to the system user
-    private final ServiceConnection mUserToSystemServiceConnection = new ServiceConnection() {
-        @Override
-        public void onServiceConnected(ComponentName name, IBinder service) {
-            if (service != null) {
-                mUserToSystemCallbacks = IRecentsSystemUserCallbacks.Stub.asInterface(
-                        service);
-                EventLog.writeEvent(EventLogTags.SYSUI_RECENTS_CONNECTION,
-                        EventLogConstants.SYSUI_RECENTS_CONNECTION_USER_SYSTEM_BOUND,
-                        sSystemServicesProxy.getProcessUser());
-
-                // Listen for system user's death, so that we can reconnect later
-                try {
-                    service.linkToDeath(mUserToSystemCallbacksDeathRcpt, 0);
-                } catch (RemoteException e) {
-                    Log.e(TAG, "Lost connection to (System) SystemUI", e);
-                }
-
-                // Run each of the queued runnables
-                runAndFlushOnConnectRunnables();
-            }
-
-            // Unbind ourselves now that we've registered our callbacks.  The
-            // binder to the system user are still valid at this point.
-            mContext.unbindService(this);
-        }
-
-        @Override
-        public void onServiceDisconnected(ComponentName name) {
-            // Do nothing
-        }
-    };
-
-    /**
-     * Returns the callbacks interface that non-system users can call.
-     */
-    public IBinder getSystemUserCallbacks() {
-        return mSystemToUserCallbacks;
-    }
-
-    public static RecentsTaskLoader getTaskLoader() {
-        return sTaskLoader;
-    }
-
-
-    public static SystemServicesProxy getSystemServices() {
-        return sSystemServicesProxy;
-    }
-
-    public static RecentsConfiguration getConfiguration() {
-        return sConfiguration;
-    }
-
-    public static RecentsDebugFlags getDebugFlags() {
-        return sDebugFlags;
-    }
+    private RecentsImplementation mImpl;
 
     @Override
     public void start() {
-        final Resources res = mContext.getResources();
-        final int defaultTaskBarBackgroundColor =
-                mContext.getColor(R.color.recents_task_bar_default_background_color);
-        final int defaultTaskViewBackgroundColor =
-                mContext.getColor(R.color.recents_task_view_default_background_color);
-        sDebugFlags = new RecentsDebugFlags();
-        sSystemServicesProxy = SystemServicesProxy.getInstance(mContext);
-        sConfiguration = new RecentsConfiguration(mContext);
-        sTaskLoader = new RecentsTaskLoader(mContext,
-                // TODO: Once we start building the AAR, move these into the loader
-                res.getInteger(R.integer.config_recents_max_thumbnail_count),
-                res.getInteger(R.integer.config_recents_max_icon_count),
-                res.getInteger(R.integer.recents_svelte_level));
-        sTaskLoader.setDefaultColors(defaultTaskBarBackgroundColor, defaultTaskViewBackgroundColor);
-        mHandler = new Handler();
-        mImpl = new RecentsImpl(mContext);
-        mOverviewProxyService = Dependency.get(OverviewProxyService.class);
-
-        // Register with the event bus
-        EventBus.getDefault().register(this, EVENT_BUS_PRIORITY);
-        EventBus.getDefault().register(sSystemServicesProxy, EVENT_BUS_PRIORITY);
-        EventBus.getDefault().register(sTaskLoader, EVENT_BUS_PRIORITY);
-
-        // Due to the fact that RecentsActivity is per-user, we need to establish and interface for
-        // the system user's Recents component to pass events (like show/hide/toggleRecents) to the
-        // secondary user, and vice versa (like visibility change, screen pinning).
-        final int processUser = sSystemServicesProxy.getProcessUser();
-        if (sSystemServicesProxy.isSystemUser(processUser)) {
-            // For the system user, initialize an instance of the interface that we can pass to the
-            // secondary user
-            getComponent(CommandQueue.class).addCallbacks(this);
-            mSystemToUserCallbacks = new RecentsSystemUser(mContext, mImpl);
-        } else {
-            // For the secondary user, bind to the primary user's service to get a persistent
-            // interface to register its implementation and to later update its state
-            registerWithSystemUser();
-        }
+        getComponent(CommandQueue.class).addCallbacks(this);
         putComponent(Recents.class, this);
-
-        mTrustManager = (TrustManager) mContext.getSystemService(Context.TRUST_SERVICE);
+        mImpl = createRecentsImplementationFromConfig();
+        mImpl.onStart(mContext, this);
     }
 
     @Override
@@ -249,13 +46,20 @@
         mImpl.onBootCompleted();
     }
 
-    public void growRecents() {
-        EventBus.getDefault().send(new RecentsGrowingEvent());
+    @Override
+    public void onConfigurationChanged(Configuration newConfig) {
+        mImpl.onConfigurationChanged(newConfig);
     }
 
-    /**
-     * Shows the Recents.
-     */
+    @Override
+    public void appTransitionFinished() {
+        mImpl.onAppTransitionFinished();
+    }
+
+    public void growRecents() {
+        mImpl.growRecents();
+    }
+
     @Override
     public void showRecentApps(boolean triggeredFromAltTab) {
         // Ensure the device has been provisioned before allowing the user to interact with
@@ -264,43 +68,9 @@
             return;
         }
 
-        IOverviewProxy overviewProxy = mOverviewProxyService.getProxy();
-        if (overviewProxy != null) {
-            try {
-                overviewProxy.onOverviewShown(triggeredFromAltTab);
-                return;
-            } catch (RemoteException e) {
-                Log.e(TAG, "Failed to send overview show event to launcher.", e);
-            }
-        }
-
-        ActivityManagerWrapper.getInstance().closeSystemWindows(SYSTEM_DIALOG_REASON_RECENT_APPS);
-        int recentsGrowTarget = getComponent(Divider.class).getView().growsRecents();
-        int currentUser = sSystemServicesProxy.getCurrentUser();
-        if (sSystemServicesProxy.isSystemUser(currentUser)) {
-            mImpl.showRecents(triggeredFromAltTab, false /* draggingInRecents */,
-                    true /* animate */, recentsGrowTarget);
-        } else {
-            if (mSystemToUserCallbacks != null) {
-                IRecentsNonSystemUserCallbacks callbacks =
-                        mSystemToUserCallbacks.getNonSystemUserRecentsForUser(currentUser);
-                if (callbacks != null) {
-                    try {
-                        callbacks.showRecents(triggeredFromAltTab, false /* draggingInRecents */,
-                                true /* animate */, recentsGrowTarget);
-                    } catch (RemoteException e) {
-                        Log.e(TAG, "Callback failed", e);
-                    }
-                } else {
-                    Log.e(TAG, "No SystemUI callbacks found for user: " + currentUser);
-                }
-            }
-        }
+        mImpl.showRecentApps(triggeredFromAltTab);
     }
 
-    /**
-     * Hides the Recents.
-     */
     @Override
     public void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) {
         // Ensure the device has been provisioned before allowing the user to interact with
@@ -309,39 +79,9 @@
             return;
         }
 
-        IOverviewProxy overviewProxy = mOverviewProxyService.getProxy();
-        if (overviewProxy != null) {
-            try {
-                overviewProxy.onOverviewHidden(triggeredFromAltTab, triggeredFromHomeKey);
-                return;
-            } catch (RemoteException e) {
-                Log.e(TAG, "Failed to send overview hide event to launcher.", e);
-            }
-        }
-
-        int currentUser = sSystemServicesProxy.getCurrentUser();
-        if (sSystemServicesProxy.isSystemUser(currentUser)) {
-            mImpl.hideRecents(triggeredFromAltTab, triggeredFromHomeKey);
-        } else {
-            if (mSystemToUserCallbacks != null) {
-                IRecentsNonSystemUserCallbacks callbacks =
-                        mSystemToUserCallbacks.getNonSystemUserRecentsForUser(currentUser);
-                if (callbacks != null) {
-                    try {
-                        callbacks.hideRecents(triggeredFromAltTab, triggeredFromHomeKey);
-                    } catch (RemoteException e) {
-                        Log.e(TAG, "Callback failed", e);
-                    }
-                } else {
-                    Log.e(TAG, "No SystemUI callbacks found for user: " + currentUser);
-                }
-            }
-        }
+        mImpl.hideRecentApps(triggeredFromAltTab, triggeredFromHomeKey);
     }
 
-    /**
-     * Toggles the Recents activity.
-     */
     @Override
     public void toggleRecentApps() {
         // Ensure the device has been provisioned before allowing the user to interact with
@@ -350,57 +90,9 @@
             return;
         }
 
-        // If connected to launcher service, let it handle the toggle logic
-        IOverviewProxy overviewProxy = mOverviewProxyService.getProxy();
-        if (overviewProxy != null) {
-            final Runnable toggleRecents = () -> {
-                try {
-                    if (mOverviewProxyService.getProxy() != null) {
-                        mOverviewProxyService.getProxy().onOverviewToggle();
-                    }
-                } catch (RemoteException e) {
-                    Log.e(TAG, "Cannot send toggle recents through proxy service.", e);
-                }
-            };
-            // Preload only if device for current user is unlocked
-            final StatusBar statusBar = getComponent(StatusBar.class);
-            if (statusBar != null && statusBar.isKeyguardShowing()) {
-                statusBar.executeRunnableDismissingKeyguard(() -> {
-                        // Flush trustmanager before checking device locked per user
-                        mTrustManager.reportKeyguardShowingChanged();
-                        mHandler.post(toggleRecents);
-                    }, null,  true /* dismissShade */, false /* afterKeyguardGone */,
-                    true /* deferred */);
-            } else {
-                toggleRecents.run();
-            }
-            return;
-        }
-
-        int growTarget = getComponent(Divider.class).getView().growsRecents();
-        int currentUser = sSystemServicesProxy.getCurrentUser();
-        if (sSystemServicesProxy.isSystemUser(currentUser)) {
-            mImpl.toggleRecents(growTarget);
-        } else {
-            if (mSystemToUserCallbacks != null) {
-                IRecentsNonSystemUserCallbacks callbacks =
-                        mSystemToUserCallbacks.getNonSystemUserRecentsForUser(currentUser);
-                if (callbacks != null) {
-                    try {
-                        callbacks.toggleRecents(growTarget);
-                    } catch (RemoteException e) {
-                        Log.e(TAG, "Callback failed", e);
-                    }
-                } else {
-                    Log.e(TAG, "No SystemUI callbacks found for user: " + currentUser);
-                }
-            }
-        }
+        mImpl.toggleRecentApps();
     }
 
-    /**
-     * Preloads info for the Recents activity.
-     */
     @Override
     public void preloadRecentApps() {
         // Ensure the device has been provisioned before allowing the user to interact with
@@ -409,29 +101,7 @@
             return;
         }
 
-        if (mOverviewProxyService.getProxy() != null) {
-            // TODO: Proxy to Launcher
-            return;
-        }
-
-        int currentUser = sSystemServicesProxy.getCurrentUser();
-        if (sSystemServicesProxy.isSystemUser(currentUser)) {
-            mImpl.preloadRecents();
-        } else {
-            if (mSystemToUserCallbacks != null) {
-                IRecentsNonSystemUserCallbacks callbacks =
-                        mSystemToUserCallbacks.getNonSystemUserRecentsForUser(currentUser);
-                if (callbacks != null) {
-                    try {
-                        callbacks.preloadRecents();
-                    } catch (RemoteException e) {
-                        Log.e(TAG, "Callback failed", e);
-                    }
-                } else {
-                    Log.e(TAG, "No SystemUI callbacks found for user: " + currentUser);
-                }
-            }
-        }
+        mImpl.preloadRecentApps();
     }
 
     @Override
@@ -442,32 +112,9 @@
             return;
         }
 
-        if (mOverviewProxyService.getProxy() != null) {
-            // TODO: Proxy to Launcher
-            return;
-        }
-
-        int currentUser = sSystemServicesProxy.getCurrentUser();
-        if (sSystemServicesProxy.isSystemUser(currentUser)) {
-            mImpl.cancelPreloadingRecents();
-        } else {
-            if (mSystemToUserCallbacks != null) {
-                IRecentsNonSystemUserCallbacks callbacks =
-                        mSystemToUserCallbacks.getNonSystemUserRecentsForUser(currentUser);
-                if (callbacks != null) {
-                    try {
-                        callbacks.cancelPreloadingRecents();
-                    } catch (RemoteException e) {
-                        Log.e(TAG, "Callback failed", e);
-                    }
-                } else {
-                    Log.e(TAG, "No SystemUI callbacks found for user: " + currentUser);
-                }
-            }
-        }
+        mImpl.cancelPreloadRecentApps();
     }
 
-    @Override
     public boolean splitPrimaryTask(int stackCreateMode, Rect initialBounds,
             int metricsDockAction) {
         // Ensure the device has been provisioned before allowing the user to interact with
@@ -476,380 +123,7 @@
             return false;
         }
 
-        Point realSize = new Point();
-        if (initialBounds == null) {
-            mContext.getSystemService(DisplayManager.class).getDisplay(Display.DEFAULT_DISPLAY)
-                    .getRealSize(realSize);
-            initialBounds = new Rect(0, 0, realSize.x, realSize.y);
-        }
-
-        int currentUser = sSystemServicesProxy.getCurrentUser();
-        ActivityManager.RunningTaskInfo runningTask =
-                ActivityManagerWrapper.getInstance().getRunningTask();
-        final int activityType = runningTask != null
-                ? runningTask.configuration.windowConfiguration.getActivityType()
-                : ACTIVITY_TYPE_UNDEFINED;
-        boolean screenPinningActive = ActivityManagerWrapper.getInstance().isScreenPinningActive();
-        boolean isRunningTaskInHomeOrRecentsStack =
-                activityType == ACTIVITY_TYPE_HOME || activityType == ACTIVITY_TYPE_RECENTS;
-        if (runningTask != null && !isRunningTaskInHomeOrRecentsStack && !screenPinningActive) {
-            logDockAttempt(mContext, runningTask.topActivity, runningTask.resizeMode);
-            if (runningTask.supportsSplitScreenMultiWindow) {
-                if (metricsDockAction != -1) {
-                    MetricsLogger.action(mContext, metricsDockAction,
-                            runningTask.topActivity.flattenToShortString());
-                }
-                if (sSystemServicesProxy.isSystemUser(currentUser)) {
-                    mImpl.splitPrimaryTask(runningTask.id, stackCreateMode, initialBounds);
-                } else {
-                    if (mSystemToUserCallbacks != null) {
-                        IRecentsNonSystemUserCallbacks callbacks =
-                                mSystemToUserCallbacks.getNonSystemUserRecentsForUser(currentUser);
-                        if (callbacks != null) {
-                            try {
-                                callbacks.splitPrimaryTask(runningTask.id, stackCreateMode,
-                                        initialBounds);
-                            } catch (RemoteException e) {
-                                Log.e(TAG, "Callback failed", e);
-                            }
-                        } else {
-                            Log.e(TAG, "No SystemUI callbacks found for user: " + currentUser);
-                        }
-                    }
-                }
-                mDraggingInRecentsCurrentUser = currentUser;
-
-                if (mOverviewProxyService.getProxy() != null) {
-                    // The overview service is handling split screen, so just skip the wait for the
-                    // first draw and notify the divider to start animating now
-                    EventBus.getDefault().post(new RecentsDrawnEvent());
-                }
-
-                return true;
-            } else {
-                EventBus.getDefault().send(new ShowUserToastEvent(
-                        R.string.dock_non_resizeble_failed_to_dock_text, Toast.LENGTH_SHORT));
-                return false;
-            }
-        } else {
-            return false;
-        }
-    }
-
-    public static void logDockAttempt(Context ctx, ComponentName activity, int resizeMode) {
-        if (resizeMode == ActivityInfo.RESIZE_MODE_UNRESIZEABLE) {
-            MetricsLogger.action(ctx, MetricsEvent.ACTION_WINDOW_DOCK_UNRESIZABLE,
-                    activity.flattenToShortString());
-        }
-        MetricsLogger.count(ctx, getMetricsCounterForResizeMode(resizeMode), 1);
-    }
-
-    private static String getMetricsCounterForResizeMode(int resizeMode) {
-        switch (resizeMode) {
-            case ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE:
-                return COUNTER_WINDOW_UNSUPPORTED;
-            case ActivityInfo.RESIZE_MODE_RESIZEABLE:
-            case ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION:
-                return COUNTER_WINDOW_SUPPORTED;
-            default:
-                return COUNTER_WINDOW_INCOMPATIBLE;
-        }
-    }
-
-    public void showNextAffiliatedTask() {
-        // Ensure the device has been provisioned before allowing the user to interact with
-        // recents
-        if (!isUserSetup()) {
-            return;
-        }
-
-        mImpl.showNextAffiliatedTask();
-    }
-
-    public void showPrevAffiliatedTask() {
-        // Ensure the device has been provisioned before allowing the user to interact with
-        // recents
-        if (!isUserSetup()) {
-            return;
-        }
-
-        mImpl.showPrevAffiliatedTask();
-    }
-
-    @Override
-    public void appTransitionFinished() {
-        if (!Recents.getConfiguration().isLowRamDevice) {
-            // Fallback, reset the flag once an app transition ends
-            EventBus.getDefault().send(new SetWaitingForTransitionStartEvent(
-                    false /* waitingForTransitionStart */));
-        }
-    }
-
-    /**
-     * Updates on configuration change.
-     */
-    public void onConfigurationChanged(Configuration newConfig) {
-        int currentUser = sSystemServicesProxy.getCurrentUser();
-        if (sSystemServicesProxy.isSystemUser(currentUser)) {
-            mImpl.onConfigurationChanged();
-        } else {
-            if (mSystemToUserCallbacks != null) {
-                IRecentsNonSystemUserCallbacks callbacks =
-                        mSystemToUserCallbacks.getNonSystemUserRecentsForUser(currentUser);
-                if (callbacks != null) {
-                    try {
-                        callbacks.onConfigurationChanged();
-                    } catch (RemoteException e) {
-                        Log.e(TAG, "Callback failed", e);
-                    }
-                } else {
-                    Log.e(TAG, "No SystemUI callbacks found for user: " + currentUser);
-                }
-            }
-        }
-    }
-
-    /**
-     * Handle Recents activity visibility changed.
-     */
-    public final void onBusEvent(final RecentsVisibilityChangedEvent event) {
-        SystemServicesProxy ssp = Recents.getSystemServices();
-        int processUser = ssp.getProcessUser();
-        if (ssp.isSystemUser(processUser)) {
-            mImpl.onVisibilityChanged(event.applicationContext, event.visible);
-        } else {
-            postToSystemUser(new Runnable() {
-                @Override
-                public void run() {
-                    try {
-                        mUserToSystemCallbacks.updateRecentsVisibility(event.visible);
-                    } catch (RemoteException e) {
-                        Log.e(TAG, "Callback failed", e);
-                    }
-                }
-            });
-        }
-
-        // This will catch the cases when a user launches from recents to another app
-        // (and vice versa) that is not in the recents stack (such as home or bugreport) and it
-        // would not reset the wait for transition flag. This will catch it and make sure that the
-        // flag is reset.
-        if (!event.visible) {
-            mImpl.setWaitingForTransitionStart(false);
-        }
-    }
-
-    public final void onBusEvent(DockedFirstAnimationFrameEvent event) {
-        SystemServicesProxy ssp = Recents.getSystemServices();
-        int processUser = ssp.getProcessUser();
-        if (ssp.isSystemUser(processUser)) {
-            final Divider divider = getComponent(Divider.class);
-            if (divider != null) {
-                divider.onDockedFirstAnimationFrame();
-            }
-        } else {
-            postToSystemUser(new Runnable() {
-                @Override
-                public void run() {
-                    try {
-                        mUserToSystemCallbacks.sendDockedFirstAnimationFrameEvent();
-                    } catch (RemoteException e) {
-                        Log.e(TAG, "Callback failed", e);
-                    }
-                }
-            });
-        }
-    }
-
-    /**
-     * Handle screen pinning request.
-     */
-    public final void onBusEvent(final ScreenPinningRequestEvent event) {
-        int processUser = sSystemServicesProxy.getProcessUser();
-        if (sSystemServicesProxy.isSystemUser(processUser)) {
-            mImpl.onStartScreenPinning(event.applicationContext, event.taskId);
-        } else {
-            postToSystemUser(new Runnable() {
-                @Override
-                public void run() {
-                    try {
-                        mUserToSystemCallbacks.startScreenPinning(event.taskId);
-                    } catch (RemoteException e) {
-                        Log.e(TAG, "Callback failed", e);
-                    }
-                }
-            });
-        }
-    }
-
-    public final void onBusEvent(final RecentsDrawnEvent event) {
-        int processUser = sSystemServicesProxy.getProcessUser();
-        if (sSystemServicesProxy.isSystemUser(processUser)) {
-            final Divider divider = getComponent(Divider.class);
-            if (divider != null) {
-                divider.onRecentsDrawn();
-            }
-        } else {
-            postToSystemUser(new Runnable() {
-                @Override
-                public void run() {
-                    try {
-                        mUserToSystemCallbacks.sendRecentsDrawnEvent();
-                    } catch (RemoteException e) {
-                        Log.e(TAG, "Callback failed", e);
-                    }
-                }
-            });
-        }
-    }
-
-    public final void onBusEvent(final DockedTopTaskEvent event) {
-        int processUser = sSystemServicesProxy.getProcessUser();
-        if (sSystemServicesProxy.isSystemUser(processUser)) {
-            final Divider divider = getComponent(Divider.class);
-            if (divider != null) {
-                divider.onDockedTopTask();
-            }
-        } else {
-            postToSystemUser(new Runnable() {
-                @Override
-                public void run() {
-                    try {
-                        mUserToSystemCallbacks.sendDockingTopTaskEvent(event.initialRect);
-                    } catch (RemoteException e) {
-                        Log.e(TAG, "Callback failed", e);
-                    }
-                }
-            });
-        }
-    }
-
-    public final void onBusEvent(final RecentsActivityStartingEvent event) {
-        int processUser = sSystemServicesProxy.getProcessUser();
-        if (sSystemServicesProxy.isSystemUser(processUser)) {
-            final Divider divider = getComponent(Divider.class);
-            if (divider != null) {
-                divider.onRecentsActivityStarting();
-            }
-        } else {
-            postToSystemUser(new Runnable() {
-                @Override
-                public void run() {
-                    try {
-                        mUserToSystemCallbacks.sendLaunchRecentsEvent();
-                    } catch (RemoteException e) {
-                        Log.e(TAG, "Callback failed", e);
-                    }
-                }
-            });
-        }
-    }
-
-    public final void onBusEvent(LaunchTaskFailedEvent event) {
-        // Reset the transition when tasks fail to launch
-        mImpl.setWaitingForTransitionStart(false);
-    }
-
-    public final void onBusEvent(ConfigurationChangedEvent event) {
-        // Update the configuration for the Recents component when the activity configuration
-        // changes as well
-        mImpl.onConfigurationChanged();
-    }
-
-    public final void onBusEvent(ShowUserToastEvent event) {
-        int currentUser = sSystemServicesProxy.getCurrentUser();
-        if (sSystemServicesProxy.isSystemUser(currentUser)) {
-            mImpl.onShowCurrentUserToast(event.msgResId, event.msgLength);
-        } else {
-            if (mSystemToUserCallbacks != null) {
-                IRecentsNonSystemUserCallbacks callbacks =
-                        mSystemToUserCallbacks.getNonSystemUserRecentsForUser(currentUser);
-                if (callbacks != null) {
-                    try {
-                        callbacks.showCurrentUserToast(event.msgResId, event.msgLength);
-                    } catch (RemoteException e) {
-                        Log.e(TAG, "Callback failed", e);
-                    }
-                } else {
-                    Log.e(TAG, "No SystemUI callbacks found for user: " + currentUser);
-                }
-            }
-        }
-    }
-
-    public final void onBusEvent(SetWaitingForTransitionStartEvent event) {
-        int processUser = sSystemServicesProxy.getProcessUser();
-        if (sSystemServicesProxy.isSystemUser(processUser)) {
-            mImpl.setWaitingForTransitionStart(event.waitingForTransitionStart);
-        } else {
-            postToSystemUser(new Runnable() {
-                @Override
-                public void run() {
-                    try {
-                        mUserToSystemCallbacks.setWaitingForTransitionStartEvent(
-                                event.waitingForTransitionStart);
-                    } catch (RemoteException e) {
-                        Log.e(TAG, "Callback failed", e);
-                    }
-                }
-            });
-        }
-    }
-
-    /**
-     * Attempts to register with the system user.
-     */
-    private void registerWithSystemUser() {
-        final int processUser = sSystemServicesProxy.getProcessUser();
-        postToSystemUser(new Runnable() {
-            @Override
-            public void run() {
-                try {
-                    mUserToSystemCallbacks.registerNonSystemUserCallbacks(
-                            new RecentsImplProxy(mImpl), processUser);
-                } catch (RemoteException e) {
-                    Log.e(TAG, "Failed to register", e);
-                }
-            }
-        });
-    }
-
-    /**
-     * Runs the runnable in the system user's Recents context, connecting to the service if
-     * necessary.
-     */
-    private void postToSystemUser(final Runnable onConnectRunnable) {
-        mOnConnectRunnables.add(onConnectRunnable);
-        if (mUserToSystemCallbacks == null) {
-            Intent systemUserServiceIntent = new Intent();
-            systemUserServiceIntent.setClass(mContext, RecentsSystemUserService.class);
-            boolean bound = mContext.bindServiceAsUser(systemUserServiceIntent,
-                    mUserToSystemServiceConnection, Context.BIND_AUTO_CREATE, UserHandle.SYSTEM);
-            EventLog.writeEvent(EventLogTags.SYSUI_RECENTS_CONNECTION,
-                    EventLogConstants.SYSUI_RECENTS_CONNECTION_USER_BIND_SERVICE,
-                    sSystemServicesProxy.getProcessUser());
-            if (!bound) {
-                // Retry after a fixed duration
-                mHandler.postDelayed(new Runnable() {
-                    @Override
-                    public void run() {
-                        registerWithSystemUser();
-                    }
-                }, BIND_TO_SYSTEM_USER_RETRY_DELAY);
-            }
-        } else {
-            runAndFlushOnConnectRunnables();
-        }
-    }
-
-    /**
-     * Runs all the queued runnables after a service connection is made.
-     */
-    private void runAndFlushOnConnectRunnables() {
-        for (Runnable r : mOnConnectRunnables) {
-            r.run();
-        }
-        mOnConnectRunnables.clear();
+        return mImpl.splitPrimaryTask(stackCreateMode, initialBounds, metricsDockAction);
     }
 
     /**
@@ -861,9 +135,30 @@
                 (Settings.Secure.getInt(cr, Settings.Secure.USER_SETUP_COMPLETE, 0) != 0);
     }
 
+    /**
+     * @return The recents implementation from the config.
+     */
+    private RecentsImplementation createRecentsImplementationFromConfig() {
+        final String clsName = mContext.getString(R.string.config_recentsComponent);
+        if (clsName == null || clsName.length() == 0) {
+            throw new RuntimeException("No recents component configured", null);
+        }
+        Class<?> cls = null;
+        try {
+            cls = mContext.getClassLoader().loadClass(clsName);
+        } catch (Throwable t) {
+            throw new RuntimeException("Error loading recents component: " + clsName, t);
+        }
+        try {
+            RecentsImplementation impl = (RecentsImplementation) cls.newInstance();
+            return impl;
+        } catch (Throwable t) {
+            throw new RuntimeException("Error creating recents component: " + clsName, t);
+        }
+    }
+
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        pw.println("Recents");
-        pw.println("  currentUserId=" + SystemServicesProxy.getInstance(mContext).getCurrentUser());
+        mImpl.dump(pw);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImplementation.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImplementation.java
new file mode 100644
index 0000000..8a04c11
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImplementation.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.recents;
+
+import android.content.Context;
+import android.content.res.Configuration;
+import android.graphics.Rect;
+import com.android.systemui.SysUiServiceProvider;
+import java.io.PrintWriter;
+
+interface RecentsImplementation {
+    default void onStart(Context context, SysUiServiceProvider sysUiServiceProvider) {}
+    default void onBootCompleted() {}
+    default void onAppTransitionFinished() {}
+    default void onConfigurationChanged(Configuration newConfig) {}
+
+    default void preloadRecentApps() {}
+    default void cancelPreloadRecentApps() {}
+    default void showRecentApps(boolean triggeredFromAltTab) {}
+    default void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) {}
+    default void toggleRecentApps() {}
+    default void growRecents() {}
+    default boolean splitPrimaryTask(int stackCreateMode, Rect initialBounds,
+            int metricsDockAction) {
+        return false;
+    }
+
+    default void dump(PrintWriter pw) {}
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
index db2b69f..af0ebdc 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
@@ -59,13 +59,11 @@
 import android.widget.ImageView;
 import android.widget.TextView;
 
-import com.android.systemui.OverviewProxyService;
 import com.android.systemui.Prefs;
 import com.android.systemui.R;
-import com.android.systemui.recents.misc.SysUiTaskStackChangeListener;
 import com.android.systemui.shared.recents.IOverviewProxy;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
-
+import com.android.systemui.shared.system.TaskStackChangeListener;
 import java.io.PrintWriter;
 import java.util.Collections;
 import java.util.HashSet;
@@ -119,7 +117,7 @@
     private int mNumAppsLaunchedSinceSwipeUpTipDismiss;
     private int mOverviewOpenedCountSinceQuickScrubTipDismiss;
 
-    private final SysUiTaskStackChangeListener mTaskListener = new SysUiTaskStackChangeListener() {
+    private final TaskStackChangeListener mTaskListener = new TaskStackChangeListener() {
         private String mLastPackageName;
 
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
index b7eee36..f92c50a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
@@ -29,7 +29,6 @@
 import android.os.Binder;
 import android.os.RemoteException;
 import android.util.DisplayMetrics;
-import android.view.ContextThemeWrapper;
 import android.view.Gravity;
 import android.view.View;
 import android.view.ViewGroup;
@@ -42,9 +41,9 @@
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
-import com.android.settingslib.Utils;
 import com.android.systemui.R;
 import com.android.systemui.SysUiServiceProvider;
+import com.android.systemui.shared.system.WindowManagerWrapper;
 import com.android.systemui.statusbar.phone.NavigationBarView;
 import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.util.leak.RotationUtils;
@@ -220,8 +219,7 @@
             mLayout.findViewById(R.id.screen_pinning_text_area)
                     .setLayoutDirection(View.LAYOUT_DIRECTION_LOCALE);
             View buttons = mLayout.findViewById(R.id.screen_pinning_buttons);
-            if (Recents.getSystemServices() != null &&
-                    Recents.getSystemServices().hasSoftNavigationBar()) {
+            if (WindowManagerWrapper.getInstance().hasSoftNavigationBar()) {
                 buttons.setLayoutDirection(View.LAYOUT_DIRECTION_LOCALE);
                 swapChildrenIfRtlAndVertical(buttons);
             } else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
index 178c5c5..427d169 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
@@ -15,6 +15,7 @@
  */
 package com.android.systemui.statusbar;
 
+import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
 import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED;
 
 import android.app.ActivityManager;
@@ -44,11 +45,10 @@
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.systemui.Dependency;
 import com.android.systemui.Dumpable;
-import com.android.systemui.OverviewProxyService;
+import com.android.systemui.recents.OverviewProxyService;
 import com.android.systemui.statusbar.StatusBarStateController.StateListener;
 import com.android.systemui.statusbar.notification.NotificationData;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
-import com.android.systemui.statusbar.phone.StatusBarRemoteInputCallback;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
 import com.android.systemui.statusbar.policy.KeyguardMonitor;
 
@@ -293,7 +293,8 @@
             return false;
         }
         return mShowLockscreenNotifications
-                && !getEntryManager().getNotificationData().isAmbient(sbn.getKey());
+                && getEntryManager().getNotificationData().getImportance(sbn.getKey())
+                >= IMPORTANCE_DEFAULT;
     }
 
     private void setShowLockscreenNotifications(boolean show) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index 8799341..c35e1da 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -17,6 +17,7 @@
 package com.android.systemui.statusbar.car;
 
 import android.app.ActivityTaskManager;
+import android.car.drivingstate.CarDrivingStateEvent;
 import android.graphics.PixelFormat;
 import android.graphics.drawable.Drawable;
 import android.util.Log;
@@ -82,6 +83,8 @@
     private DeviceProvisionedController mDeviceProvisionedController;
     private boolean mDeviceIsProvisioned = true;
     private HvacController mHvacController;
+    private DrivingStateHelper mDrivingStateHelper;
+    private SwitchToGuestTimer mSwitchToGuestTimer;
 
     @Override
     public void start() {
@@ -111,6 +114,12 @@
                         }
                     });
         }
+
+        // Register a listener for driving state changes.
+        mDrivingStateHelper = new DrivingStateHelper(mContext, this::onDrivingStateChanged);
+        mDrivingStateHelper.connectToCarService();
+
+        mSwitchToGuestTimer = new SwitchToGuestTimer(mContext);
     }
 
     /**
@@ -205,6 +214,7 @@
         mCarBatteryController.stopListening();
         mConnectedDeviceSignalController.stopListening();
         mActivityManagerWrapper.unregisterTaskStackListener(mTaskStackListener);
+        mDrivingStateHelper.disconnectFromCarService();
 
         if (mNavigationBarWindow != null) {
             mWindowManager.removeViewImmediate(mNavigationBarWindow);
@@ -476,6 +486,20 @@
         }
     }
 
+    private void onDrivingStateChanged(CarDrivingStateEvent notUsed) {
+        // Check if we need to start the timer every time driving state changes.
+        startSwitchToGuestTimerIfDrivingOnKeyguard();
+    }
+
+    private void startSwitchToGuestTimerIfDrivingOnKeyguard() {
+        if (mDrivingStateHelper.isCurrentlyDriving() && mState != StatusBarState.SHADE) {
+            // We're driving while keyguard is up.
+            mSwitchToGuestTimer.start();
+        } else {
+            mSwitchToGuestTimer.cancel();
+        }
+    }
+
     @Override
     protected void createUserSwitcher() {
         UserSwitcherController userSwitcherController =
@@ -491,6 +515,9 @@
     @Override
     public void onStateChanged(int newState) {
         super.onStateChanged(newState);
+
+        startSwitchToGuestTimerIfDrivingOnKeyguard();
+
         if (mFullscreenUserSwitcher == null) {
             return; // Not using the full screen user switcher.
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/DrivingStateHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/DrivingStateHelper.java
new file mode 100644
index 0000000..47941bf
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/DrivingStateHelper.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.car;
+
+import android.car.Car;
+import android.car.CarNotConnectedException;
+import android.car.drivingstate.CarDrivingStateEvent;
+import android.car.drivingstate.CarDrivingStateManager;
+import android.car.drivingstate.CarDrivingStateManager.CarDrivingStateEventListener;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.ServiceConnection;
+import android.os.IBinder;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+
+/**
+ * Helper class for connecting to the {@link CarDrivingStateManager} and listening for driving state
+ * changes.
+ */
+public class DrivingStateHelper {
+    public static final String TAG = "DrivingStateHelper";
+
+    private final Context mContext;
+    private CarDrivingStateManager mDrivingStateManager;
+    private Car mCar;
+    private CarDrivingStateEventListener mDrivingStateHandler;
+
+    public DrivingStateHelper(Context context,
+            @NonNull CarDrivingStateEventListener drivingStateHandler) {
+        mContext = context;
+        mDrivingStateHandler = drivingStateHandler;
+    }
+
+    /**
+     * Queries {@link CarDrivingStateManager} for current driving state. Returns {@code true} if car
+     * is idling or moving, {@code false} otherwise.
+     */
+    public boolean isCurrentlyDriving() {
+        try {
+            CarDrivingStateEvent currentState = mDrivingStateManager.getCurrentCarDrivingState();
+            if (currentState != null) {
+                return currentState.eventValue == CarDrivingStateEvent.DRIVING_STATE_IDLING
+                        || currentState.eventValue == CarDrivingStateEvent.DRIVING_STATE_MOVING;
+            }
+        } catch (CarNotConnectedException e) {
+            Log.e(TAG, "Cannot determine current driving state. Car not connected", e);
+        }
+
+        return false; // Default to false.
+    }
+
+    /**
+     * Establishes connection with the Car service.
+     */
+    public void connectToCarService() {
+        mCar = Car.createCar(mContext, mCarConnectionListener);
+        if (mCar != null) {
+            mCar.connect();
+        }
+    }
+
+    /**
+     * Disconnects from Car service and cleans up listeners.
+     */
+    public void disconnectFromCarService() {
+        if (mCar != null) {
+            mCar.disconnect();
+        }
+    }
+
+    private final ServiceConnection mCarConnectionListener =
+            new ServiceConnection() {
+                public void onServiceConnected(ComponentName name, IBinder service) {
+                    logD("Car Service connected");
+                    try {
+                        mDrivingStateManager = (CarDrivingStateManager) mCar.getCarManager(
+                                Car.CAR_DRIVING_STATE_SERVICE);
+                        if (mDrivingStateManager != null) {
+                            mDrivingStateManager.registerListener(mDrivingStateHandler);
+                            mDrivingStateHandler.onDrivingStateChanged(
+                                    mDrivingStateManager.getCurrentCarDrivingState());
+                        } else {
+                            Log.e(TAG, "CarDrivingStateService service not available");
+                        }
+                    } catch (CarNotConnectedException e) {
+                        Log.e(TAG, "Car not connected", e);
+                    }
+                }
+
+                @Override
+                public void onServiceDisconnected(ComponentName name) {
+                    destroyDrivingStateManager();
+                }
+            };
+
+    private void destroyDrivingStateManager() {
+        try {
+            if (mDrivingStateManager != null) {
+                mDrivingStateManager.unregisterListener();
+            }
+        } catch (CarNotConnectedException e) {
+            Log.e(TAG, "Error unregistering listeners", e);
+        }
+    }
+
+    private void logD(String message) {
+        if (Log.isLoggable(TAG, Log.DEBUG)) {
+            Log.d(TAG, message);
+        }
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/SwitchToGuestTimer.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/SwitchToGuestTimer.java
new file mode 100644
index 0000000..27a5d4b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/SwitchToGuestTimer.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.car;
+
+import android.car.userlib.CarUserManagerHelper;
+import android.content.Context;
+import android.os.CountDownTimer;
+import android.util.Log;
+
+import com.android.systemui.R;
+
+import androidx.annotation.GuardedBy;
+
+/**
+ * Wrapper for a countdown timer that switches to Guest if the user has been driving with
+ * the keyguard up for configurable number of seconds.
+ */
+public class SwitchToGuestTimer {
+    private static final String TAG = "SwitchToGuestTimer";
+
+    // After how many ms CountdownTimer.onTick gets triggered.
+    private static final int COUNTDOWN_INTERVAL_MS = 1000;
+
+    private final CarUserManagerHelper mCarUserManagerHelper;
+    private final Object mTimerLock;
+    private final String mGuestName;
+    private final int mTimeoutMs;
+    private final boolean mEnabled;
+
+    @GuardedBy("mTimerLock")
+    private CountDownTimer mSwitchToGuestTimer;
+
+    public SwitchToGuestTimer(Context context) {
+        mCarUserManagerHelper = new CarUserManagerHelper(context);
+        mGuestName = context.getResources().getString(R.string.car_guest);
+        mTimeoutMs = context.getResources().getInteger(R.integer.driving_on_keyguard_timeout_ms);
+
+        // Lock prevents multiple timers being started.
+        mTimerLock = new Object();
+
+        // If milliseconds to switch is a negative number, the feature is disabled.
+        mEnabled = mTimeoutMs >= 0;
+    }
+
+    /**
+     * Starts the timer if it's not already running.
+     */
+    public void start() {
+        if (!mEnabled) {
+            logD("Switching to guest after driving on keyguard is disabled.");
+            return;
+        }
+
+        synchronized (mTimerLock) {
+            if (mSwitchToGuestTimer != null) {
+                logD("Timer is already running.");
+                return;
+            }
+
+            mSwitchToGuestTimer = new CountDownTimer(mTimeoutMs, COUNTDOWN_INTERVAL_MS) {
+                @Override
+                public void onTick(long msUntilFinished) {
+                    logD("Ms until switching to guest: " + Long.toString(msUntilFinished));
+                }
+
+                @Override
+                public void onFinish() {
+                    mCarUserManagerHelper.startNewGuestSession(mGuestName);
+                    cancel();
+                }
+            };
+
+            logI("Starting timer");
+            mSwitchToGuestTimer.start();
+        }
+    }
+
+    /**
+     * Cancels the running timer.
+     */
+    public void cancel() {
+        synchronized (mTimerLock) {
+            if (mSwitchToGuestTimer != null) {
+                logI("Cancelling timer");
+                mSwitchToGuestTimer.cancel();
+                mSwitchToGuestTimer = null;
+            }
+        }
+    }
+
+    private void logD(String message) {
+        if (Log.isLoggable(TAG, Log.DEBUG)) {
+            Log.d(TAG, message);
+        }
+    }
+
+    private void logI(String message) {
+        if (Log.isLoggable(TAG, Log.INFO)) {
+            Log.i(TAG, message);
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/AppOpsListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/AppOpsListener.java
deleted file mode 100644
index 9e99fbb..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/AppOpsListener.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar.notification;
-
-import android.app.AppOpsManager;
-import android.content.Context;
-
-import com.android.systemui.Dependency;
-import com.android.systemui.ForegroundServiceController;
-import com.android.systemui.statusbar.NotificationPresenter;
-
-/**
- * This class handles listening to notification updates and passing them along to
- * NotificationPresenter to be displayed to the user.
- */
-public class AppOpsListener implements AppOpsManager.OnOpActiveChangedListener {
-    private static final String TAG = "NotificationListener";
-
-    // Dependencies:
-    private final ForegroundServiceController mFsc =
-            Dependency.get(ForegroundServiceController.class);
-    private final NotificationEntryManager mEntryManager =
-            Dependency.get(NotificationEntryManager.class);
-
-    private final Context mContext;
-    protected NotificationPresenter mPresenter;
-    protected final AppOpsManager mAppOps;
-
-    protected static final int[] OPS = new int[] {AppOpsManager.OP_CAMERA,
-            AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
-            AppOpsManager.OP_RECORD_AUDIO};
-
-    public AppOpsListener(Context context) {
-        mContext = context;
-        mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
-    }
-
-    public void setUpWithPresenter(NotificationPresenter presenter) {
-        mPresenter = presenter;
-        mAppOps.startWatchingActive(OPS, this);
-    }
-
-    public void destroy() {
-        mAppOps.stopWatchingActive(this);
-    }
-
-    @Override
-    public void onOpActiveChanged(int code, int uid, String packageName, boolean active) {
-        mFsc.onAppOpChanged(code, uid, packageName, active);
-        Dependency.get(Dependency.MAIN_HANDLER).post(() -> {
-          mEntryManager.updateNotificationsForAppOp(code, uid, packageName, active);
-        });
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
index 903c272..912a2f7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
@@ -72,6 +72,7 @@
     private String mPackageName;
     private String mAppName;
     private int mAppUid;
+    private String mDelegatePkg;
     private int mNumUniqueChannelsInRow;
     private NotificationChannel mSingleNotificationChannel;
     private int mStartingUserImportance;
@@ -193,6 +194,7 @@
                 (mSbn.getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE) != 0;
         mIsForBlockingHelper = isForBlockingHelper;
         mAppUid = mSbn.getUid();
+        mDelegatePkg = mSbn.getOpPkg();
         mIsDeviceProvisioned = isDeviceProvisioned;
 
         int numTotalChannels = mINotificationManager.getNumNotificationChannelsForPackage(
@@ -234,26 +236,8 @@
         ((ImageView) findViewById(R.id.pkgicon)).setImageDrawable(pkgicon);
         ((TextView) findViewById(R.id.pkgname)).setText(mAppName);
 
-        // Set group information if this channel has an associated group.
-        CharSequence groupName = null;
-        if (mSingleNotificationChannel != null && mSingleNotificationChannel.getGroup() != null) {
-            final NotificationChannelGroup notificationChannelGroup =
-                    mINotificationManager.getNotificationChannelGroupForPackage(
-                            mSingleNotificationChannel.getGroup(), mPackageName, mAppUid);
-            if (notificationChannelGroup != null) {
-                groupName = notificationChannelGroup.getName();
-            }
-        }
-        TextView groupNameView = findViewById(R.id.group_name);
-        TextView groupDividerView = findViewById(R.id.pkg_group_divider);
-        if (groupName != null) {
-            groupNameView.setText(groupName);
-            groupNameView.setVisibility(View.VISIBLE);
-            groupDividerView.setVisibility(View.VISIBLE);
-        } else {
-            groupNameView.setVisibility(View.GONE);
-            groupDividerView.setVisibility(View.GONE);
-        }
+        // Delegate
+        bindDelegate();
 
         // Settings button.
         final View settingsButton = findViewById(R.id.info);
@@ -273,9 +257,10 @@
         }
     }
 
-    private void bindPrompt() {
+    private void bindPrompt() throws RemoteException {
         final TextView blockPrompt = findViewById(R.id.block_prompt);
         bindName();
+        bindGroup();
         if (mIsNonblockable) {
             blockPrompt.setText(R.string.notification_unblockable_desc);
         } else {
@@ -298,6 +283,60 @@
         }
     }
 
+    private void bindDelegate() {
+        TextView delegateView = findViewById(R.id.delegate_name);
+        TextView dividerView = findViewById(R.id.pkg_divider);
+
+        CharSequence delegatePkg = null;
+        if (!TextUtils.equals(mPackageName, mDelegatePkg)) {
+            // this notification was posted by a delegate!
+            ApplicationInfo info;
+            try {
+                info = mPm.getApplicationInfo(
+                        mDelegatePkg,
+                        PackageManager.MATCH_UNINSTALLED_PACKAGES
+                                | PackageManager.MATCH_DISABLED_COMPONENTS
+                                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
+                                | PackageManager.MATCH_DIRECT_BOOT_AWARE);
+                if (info != null) {
+                    delegatePkg = String.valueOf(mPm.getApplicationLabel(info));
+                }
+            } catch (PackageManager.NameNotFoundException e) {}
+        }
+        if (delegatePkg != null) {
+            delegateView.setText(mContext.getResources().getString(
+                    R.string.notification_delegate_header, delegatePkg));
+            delegateView.setVisibility(View.VISIBLE);
+            dividerView.setVisibility(View.VISIBLE);
+        } else {
+            delegateView.setVisibility(View.GONE);
+            dividerView.setVisibility(View.GONE);
+        }
+    }
+
+    private void bindGroup() throws RemoteException {
+        // Set group information if this channel has an associated group.
+        CharSequence groupName = null;
+        if (mSingleNotificationChannel != null && mSingleNotificationChannel.getGroup() != null) {
+            final NotificationChannelGroup notificationChannelGroup =
+                    mINotificationManager.getNotificationChannelGroupForPackage(
+                            mSingleNotificationChannel.getGroup(), mPackageName, mAppUid);
+            if (notificationChannelGroup != null) {
+                groupName = notificationChannelGroup.getName();
+            }
+        }
+        TextView groupNameView = findViewById(R.id.group_name);
+        TextView groupDividerView = findViewById(R.id.pkg_group_divider);
+        if (groupName != null) {
+            groupNameView.setText(groupName);
+            groupNameView.setVisibility(View.VISIBLE);
+            groupDividerView.setVisibility(View.VISIBLE);
+        } else {
+            groupNameView.setVisibility(View.GONE);
+            groupDividerView.setVisibility(View.GONE);
+        }
+    }
+
     @VisibleForTesting
     void logBlockingHelperCounter(String counterTag) {
         if (mIsForBlockingHelper) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 30d1701..936c2b8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -18,6 +18,7 @@
 
 import static com.android.systemui.statusbar.notification.ActivityLaunchAnimator
         .ExpandAnimationParameters;
+import static com.android.systemui.statusbar.phone.NotificationIconAreaController.LOW_PRIORITY;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
@@ -27,6 +28,7 @@
 import android.animation.ValueAnimator;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.app.NotificationManager;
 import android.app.WallpaperManager;
 import android.content.Context;
 import android.content.Intent;
@@ -127,6 +129,7 @@
 import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
 import com.android.systemui.statusbar.policy.HeadsUpUtil;
 import com.android.systemui.statusbar.policy.ScrollAdapter;
+import com.android.systemui.tuner.TunerService;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -159,6 +162,7 @@
     private int mCurrentStackHeight = Integer.MAX_VALUE;
     private final Paint mBackgroundPaint = new Paint();
     private final boolean mShouldDrawNotificationBackground;
+    private boolean mLowPriorityBeforeSpeedBump;
 
     private float mExpandedHeight;
     private int mOwnScrollY;
@@ -515,6 +519,13 @@
             mDebugPaint.setStyle(Paint.Style.STROKE);
         }
         mClearAllEnabled = res.getBoolean(R.bool.config_enableNotificationsClearAll);
+
+        TunerService tunerService = Dependency.get(TunerService.class);
+        tunerService.addTunable((key, newValue) -> {
+            if (key.equals(LOW_PRIORITY)) {
+                mLowPriorityBeforeSpeedBump = "1".equals(newValue);
+            }
+        }, LOW_PRIORITY);
     }
 
     @Override
@@ -5087,8 +5098,16 @@
             }
             ExpandableNotificationRow row = (ExpandableNotificationRow) view;
             currentIndex++;
-            if (!mEntryManager.getNotificationData().isAmbient(
-                    row.getStatusBarNotification().getKey())) {
+            boolean beforeSpeedBump;
+            if (mLowPriorityBeforeSpeedBump) {
+                beforeSpeedBump = !mEntryManager.getNotificationData().isAmbient(
+                        row.getStatusBarNotification().getKey());
+            } else {
+                beforeSpeedBump = mEntryManager.getNotificationData().getImportance(
+                        row.getStatusBarNotification().getKey())
+                        >= NotificationManager.IMPORTANCE_DEFAULT;
+            }
+            if (beforeSpeedBump) {
                 speedBumpIndex = currentIndex;
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index 6edde07..329a33d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -19,7 +19,7 @@
 import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
 import static android.app.StatusBarManager.windowStateToString;
 
-import static com.android.systemui.OverviewProxyService.OverviewProxyListener;
+import static com.android.systemui.recents.OverviewProxyService.OverviewProxyListener;
 import static com.android.systemui.shared.system.NavigationBarCompat.InteractionType;
 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT;
 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_SEMI_TRANSPARENT;
@@ -74,7 +74,7 @@
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.util.LatencyTracker;
 import com.android.systemui.Dependency;
-import com.android.systemui.OverviewProxyService;
+import com.android.systemui.recents.OverviewProxyService;
 import com.android.systemui.R;
 import com.android.systemui.SysUiServiceProvider;
 import com.android.systemui.assist.AssistManager;
@@ -478,7 +478,9 @@
 
     private void setDisabled2Flags(int state2) {
         // Method only called on change of disable2 flags
-        mNavigationBarView.getRotateSuggestionButton().onDisable2FlagChanged(state2);
+        if (mNavigationBarView != null) {
+            mNavigationBarView.getRotateSuggestionButton().onDisable2FlagChanged(state2);
+        }
     }
 
     // ----- Internal stuffz -----
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
index 52134d9..22b6ba6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
@@ -34,7 +34,7 @@
 import android.widget.Space;
 
 import com.android.systemui.Dependency;
-import com.android.systemui.OverviewProxyService;
+import com.android.systemui.recents.OverviewProxyService;
 import com.android.systemui.R;
 import com.android.systemui.plugins.PluginListener;
 import com.android.systemui.shared.plugins.PluginManager;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 2ab5958..6728f08 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -57,7 +57,7 @@
 import com.android.systemui.Dependency;
 import com.android.systemui.DockedStackExistsListener;
 import com.android.systemui.Interpolators;
-import com.android.systemui.OverviewProxyService;
+import com.android.systemui.recents.OverviewProxyService;
 import com.android.systemui.R;
 import com.android.systemui.SysUiServiceProvider;
 import com.android.systemui.plugins.PluginListener;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
index 21b98db..5960b13 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
@@ -1,29 +1,31 @@
 package com.android.systemui.statusbar.phone;
 
+import android.app.NotificationManager;
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Color;
 import android.graphics.Rect;
-import androidx.annotation.NonNull;
-import androidx.collection.ArrayMap;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.FrameLayout;
 
+import androidx.annotation.NonNull;
+import androidx.collection.ArrayMap;
+
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.internal.util.ContrastColorUtil;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
-import com.android.systemui.statusbar.notification.NotificationData;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.NotificationShelf;
 import com.android.systemui.statusbar.StatusBarIconView;
+import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.NotificationUtils;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.policy.DarkIconDispatcher;
 import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver;
-import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
+import com.android.systemui.tuner.TunerService;
 
 import java.util.ArrayList;
 import java.util.function.Function;
@@ -33,9 +35,23 @@
  * normally reserved for notifications.
  */
 public class NotificationIconAreaController implements DarkReceiver {
+
+    public static final String LOW_PRIORITY = "low_priority";
+
     private final ContrastColorUtil mContrastColorUtil;
     private final NotificationEntryManager mEntryManager;
     private final Runnable mUpdateStatusBarIcons = this::updateStatusBarIcons;
+    private final TunerService.Tunable mTunable = new TunerService.Tunable() {
+        @Override
+        public void onTuningChanged(String key, String newValue) {
+            if (key.equals(LOW_PRIORITY)) {
+                mShowLowPriority = "1".equals(newValue);
+                if (mNotificationScrollLayout != null) {
+                    updateStatusBarIcons();
+                }
+            }
+        }
+    };
 
     private int mIconSize;
     private int mIconHPadding;
@@ -49,6 +65,7 @@
     private ViewGroup mNotificationScrollLayout;
     private Context mContext;
     private boolean mFullyDark;
+    private boolean mShowLowPriority;
 
     public NotificationIconAreaController(Context context, StatusBar statusBar) {
         mStatusBar = statusBar;
@@ -56,6 +73,8 @@
         mContext = context;
         mEntryManager = Dependency.get(NotificationEntryManager.class);
 
+        Dependency.get(TunerService.class).addTunable(mTunable, LOW_PRIORITY);
+
         initializeNotificationAreaViews(context);
     }
 
@@ -142,10 +161,16 @@
     }
 
     protected boolean shouldShowNotificationIcon(NotificationData.Entry entry,
-            boolean showAmbient, boolean hideDismissed, boolean hideRepliedMessages) {
+            boolean showAmbient, boolean showLowPriority, boolean hideDismissed,
+            boolean hideRepliedMessages) {
         if (mEntryManager.getNotificationData().isAmbient(entry.key) && !showAmbient) {
             return false;
         }
+        if (!showLowPriority
+                && mEntryManager.getNotificationData().getImportance(entry.key)
+                < NotificationManager.IMPORTANCE_DEFAULT) {
+            return false;
+        }
         if (!StatusBar.isTopLevelChild(entry)) {
             return false;
         }
@@ -181,13 +206,14 @@
 
     private void updateShelfIcons() {
         updateIconsForLayout(entry -> entry.expandedIcon, mShelfIcons,
-                NotificationShelf.SHOW_AMBIENT_ICONS, false /* hideDismissed */,
-                mFullyDark /* hideRepliedMessages */);
+                NotificationShelf.SHOW_AMBIENT_ICONS, !mFullyDark /* showLowPriority */,
+                false /* hideDismissed */, mFullyDark /* hideRepliedMessages */);
     }
 
     public void updateStatusBarIcons() {
         updateIconsForLayout(entry -> entry.icon, mNotificationIcons,
-                false /* showAmbient */, true /* hideDismissed */, true /* hideRepliedMessages */);
+                false /* showAmbient */, false /* showLowPriority */, true /* hideDismissed */,
+                true /* hideRepliedMessages */);
     }
 
     /**
@@ -200,8 +226,8 @@
      * @param hideRepliedMessages should messages that have been replied to be hidden
      */
     private void updateIconsForLayout(Function<NotificationData.Entry, StatusBarIconView> function,
-            NotificationIconContainer hostLayout, boolean showAmbient, boolean hideDismissed,
-            boolean hideRepliedMessages) {
+            NotificationIconContainer hostLayout, boolean showAmbient, boolean showLowPriority,
+            boolean hideDismissed, boolean hideRepliedMessages) {
         ArrayList<StatusBarIconView> toShow = new ArrayList<>(
                 mNotificationScrollLayout.getChildCount());
 
@@ -210,7 +236,7 @@
             View view = mNotificationScrollLayout.getChildAt(i);
             if (view instanceof ExpandableNotificationRow) {
                 NotificationData.Entry ent = ((ExpandableNotificationRow) view).getEntry();
-                if (shouldShowNotificationIcon(ent, showAmbient, hideDismissed,
+                if (shouldShowNotificationIcon(ent, showAmbient, showLowPriority, hideDismissed,
                         hideRepliedMessages)) {
                     toShow.add(function.apply(ent));
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index 57c2439..f29b7ca 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -227,6 +227,16 @@
         mUnlockFalsingThreshold = res.getDimensionPixelSize(R.dimen.unlock_falsing_threshold);
     }
 
+    private void addMovement(MotionEvent event) {
+        // Add movement to velocity tracker using raw screen X and Y coordinates instead
+        // of window coordinates because the window frame may be moving at the same time.
+        float deltaX = event.getRawX() - event.getX();
+        float deltaY = event.getRawY() - event.getY();
+        event.offsetLocation(deltaX, deltaY);
+        mVelocityTracker.addMovement(event);
+        event.offsetLocation(-deltaX, -deltaY);
+    }
+
     public void setTouchAndAnimationDisabled(boolean disabled) {
         mTouchDisabled = disabled;
         if (mTouchDisabled) {
@@ -307,7 +317,7 @@
                 mTouchAboveFalsingThreshold = false;
                 mCollapsedAndHeadsUpOnDown = isFullyCollapsed()
                         && mHeadsUpManager.hasPinnedHeadsUp();
-                mVelocityTracker.addMovement(event);
+                addMovement(event);
                 if (!mGestureWaitForTouchSlop || (mHeightAnimator != null && !mHintAnimationRunning)
                         || mPeekAnimator != null) {
                     mTouchSlopExceeded = (mHeightAnimator != null && !mHintAnimationRunning)
@@ -341,7 +351,7 @@
                 }
                 break;
             case MotionEvent.ACTION_MOVE:
-                mVelocityTracker.addMovement(event);
+                addMovement(event);
                 float h = y - mInitialTouchY;
 
                 // If the panel was collapsed when touching, we only need to check for the
@@ -386,7 +396,7 @@
 
             case MotionEvent.ACTION_UP:
             case MotionEvent.ACTION_CANCEL:
-                mVelocityTracker.addMovement(event);
+                addMovement(event);
                 endMotionEvent(event, x, y, false /* forceCancel */);
                 break;
         }
@@ -573,7 +583,7 @@
                 mHasLayoutedSinceDown = false;
                 mUpdateFlingOnLayout = false;
                 mTouchAboveFalsingThreshold = false;
-                mVelocityTracker.addMovement(event);
+                addMovement(event);
                 break;
             case MotionEvent.ACTION_POINTER_UP:
                 final int upPointer = event.getPointerId(event.getActionIndex());
@@ -593,7 +603,7 @@
                 break;
             case MotionEvent.ACTION_MOVE:
                 final float h = y - mInitialTouchY;
-                mVelocityTracker.addMovement(event);
+                addMovement(event);
                 if (scrolledToBottom || mTouchStartedInEmptyArea || mAnimatingOnDown) {
                     float hAbs = Math.abs(h);
                     if ((h < -mTouchSlop || (mAnimatingOnDown && hAbs > mTouchSlop))
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
index fd5403f..3980126 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
@@ -20,8 +20,8 @@
 import static android.view.WindowManagerPolicyConstants.NAV_BAR_LEFT;
 import static com.android.systemui.Interpolators.ALPHA_IN;
 import static com.android.systemui.Interpolators.ALPHA_OUT;
-import static com.android.systemui.OverviewProxyService.DEBUG_OVERVIEW_PROXY;
-import static com.android.systemui.OverviewProxyService.TAG_OPS;
+import static com.android.systemui.recents.OverviewProxyService.DEBUG_OVERVIEW_PROXY;
+import static com.android.systemui.recents.OverviewProxyService.TAG_OPS;
 import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_DEAD_ZONE;
 import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_HOME;
 
@@ -56,7 +56,7 @@
 import android.view.WindowManagerGlobal;
 import com.android.systemui.Dependency;
 import com.android.systemui.Interpolators;
-import com.android.systemui.OverviewProxyService;
+import com.android.systemui.recents.OverviewProxyService;
 import com.android.systemui.R;
 import com.android.systemui.SysUiServiceProvider;
 import com.android.systemui.plugins.statusbar.phone.NavGesture.GestureHelper;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationContextButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationContextButton.java
index 855592f..c6e98e0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationContextButton.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationContextButton.java
@@ -44,8 +44,8 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.R;
-import com.android.systemui.recents.misc.SysUiTaskStackChangeListener;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
+import com.android.systemui.shared.system.TaskStackChangeListener;
 import com.android.systemui.statusbar.policy.KeyButtonDrawable;
 import com.android.systemui.statusbar.policy.RotationLockController;
 
@@ -400,7 +400,7 @@
         }
     }
 
-    private class TaskStackListenerImpl extends SysUiTaskStackChangeListener {
+    private class TaskStackListenerImpl extends TaskStackChangeListener {
         // Invalidate any rotation suggestion on task change or activity orientation change
         // Note: all callbacks happen on main thread
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index b9ca949..2b661ab 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -29,7 +29,6 @@
 import static com.android.systemui.shared.system.WindowManagerWrapper.NAV_BAR_POS_INVALID;
 import static com.android.systemui.shared.system.WindowManagerWrapper.NAV_BAR_POS_LEFT;
 import static com.android.systemui.statusbar.NotificationLockscreenUserManager.PERMISSION_SELF;
-import static com.android.systemui.statusbar.NotificationMediaManager.DEBUG_MEDIA;
 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT;
 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT;
 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_OPAQUE;
@@ -46,6 +45,7 @@
 import android.app.ActivityOptions;
 import android.app.ActivityTaskManager;
 import android.app.AlarmManager;
+import android.app.AppOpsManager;
 import android.app.IWallpaperManager;
 import android.app.KeyguardManager;
 import android.app.Notification;
@@ -130,14 +130,15 @@
 import com.android.systemui.Dependency;
 import com.android.systemui.Dumpable;
 import com.android.systemui.EventLogTags;
+import com.android.systemui.ForegroundServiceController;
 import com.android.systemui.InitController;
 import com.android.systemui.Interpolators;
 import com.android.systemui.Prefs;
 import com.android.systemui.R;
-import com.android.systemui.RecentsComponent;
 import com.android.systemui.SystemUI;
 import com.android.systemui.SystemUIFactory;
 import com.android.systemui.UiOffloadThread;
+import com.android.systemui.appops.AppOpsController;
 import com.android.systemui.assist.AssistManager;
 import com.android.systemui.charging.WirelessChargingAnimation;
 import com.android.systemui.classifier.FalsingLog;
@@ -183,7 +184,6 @@
 import com.android.systemui.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.VibratorHelper;
 import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
-import com.android.systemui.statusbar.notification.AppOpsListener;
 import com.android.systemui.statusbar.notification.NotificationData;
 import com.android.systemui.statusbar.notification.NotificationData.Entry;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
@@ -228,7 +228,8 @@
         OnHeadsUpChangedListener, CommandQueue.Callbacks, ZenModeController.Callback,
         ColorExtractor.OnColorsChangedListener, ConfigurationListener,
         StatusBarStateController.StateListener, ShadeController,
-        ActivityLaunchAnimator.Callback, AmbientPulseManager.OnAmbientChangedListener {
+        ActivityLaunchAnimator.Callback, AmbientPulseManager.OnAmbientChangedListener,
+        AppOpsController.Callback {
     public static final boolean MULTIUSER_DEBUG = false;
 
     public static final boolean ENABLE_CHILD_NOTIFICATIONS
@@ -372,7 +373,8 @@
     protected NotificationLogger mNotificationLogger;
     protected NotificationEntryManager mEntryManager;
     protected NotificationViewHierarchyManager mViewHierarchyManager;
-    protected AppOpsListener mAppOpsListener;
+    protected ForegroundServiceController mForegroundServiceController;
+    protected AppOpsController mAppOpsController;
     protected KeyguardViewMediator mKeyguardViewMediator;
     private ZenModeController mZenController;
 
@@ -564,6 +566,20 @@
     protected NotificationPresenter mPresenter;
 
     @Override
+    public void onActiveStateChanged(int code, int uid, String packageName, boolean active) {
+        mForegroundServiceController.onAppOpChanged(code, uid, packageName, active);
+        Dependency.get(Dependency.MAIN_HANDLER).post(() -> {
+            mEntryManager.updateNotificationsForAppOp(code, uid, packageName, active);
+        });
+    }
+
+    protected static final int[] APP_OPS = new int[] {AppOpsManager.OP_CAMERA,
+            AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
+            AppOpsManager.OP_RECORD_AUDIO,
+            AppOpsManager.OP_COARSE_LOCATION,
+            AppOpsManager.OP_FINE_LOCATION};
+
+    @Override
     public void start() {
         mGroupManager = Dependency.get(NotificationGroupManager.class);
         mVisualStabilityManager = Dependency.get(VisualStabilityManager.class);
@@ -585,7 +601,8 @@
         mMediaManager = Dependency.get(NotificationMediaManager.class);
         mEntryManager = Dependency.get(NotificationEntryManager.class);
         mViewHierarchyManager = Dependency.get(NotificationViewHierarchyManager.class);
-        mAppOpsListener = Dependency.get(AppOpsListener.class);
+        mForegroundServiceController = Dependency.get(ForegroundServiceController.class);
+        mAppOpsController = Dependency.get(AppOpsController.class);
         mZenController = Dependency.get(ZenModeController.class);
         mKeyguardViewMediator = getComponent(KeyguardViewMediator.class);
         mColorExtractor = Dependency.get(SysuiColorExtractor.class);
@@ -984,7 +1001,7 @@
         mPresenter = new StatusBarNotificationPresenter(mContext, mNotificationPanel,
                 mHeadsUpManager, mStatusBarWindow, mStackScroller, mDozeScrimController,
                 mScrimController, this);
-        mAppOpsListener.setUpWithPresenter(mPresenter);
+        mAppOpsController.addCallback(APP_OPS, this);
         mNotificationListener.setUpWithPresenter(mPresenter);
         mNotificationShelf.setOnActivatedListener(mPresenter);
         mRemoteInputManager.getController().addCallback(mStatusBarWindowController);
@@ -2853,7 +2870,7 @@
         mDeviceProvisionedController.removeCallback(mUserSetupObserver);
         Dependency.get(ConfigurationController.class).removeCallback(this);
         mZenController.removeCallback(this);
-        mAppOpsListener.destroy();
+        mAppOpsController.removeCallback(APP_OPS, this);
     }
 
     private boolean mDemoModeAllowed;
@@ -3944,6 +3961,9 @@
         @Override
         public void dozeTimeTick() {
             mNotificationPanel.dozeTimeTick();
+            if (mAmbientIndicationContainer instanceof DozeReceiver) {
+                ((DozeReceiver) mAmbientIndicationContainer).dozeTimeTick();
+            }
         }
 
         @Override
@@ -4010,7 +4030,8 @@
                 float viewY = screenY - mTmpInt2[1];
                 if (0 <= viewX && viewX <= mAmbientIndicationContainer.getWidth()
                         && 0 <= viewY && viewY <= mAmbientIndicationContainer.getHeight()) {
-                    dispatchDoubleTap(viewX, viewY);
+                    if (mAmbientIndicationContainer instanceof DozeReceiver)
+                    ((DozeReceiver) mAmbientIndicationContainer).onDozeDoubleTap();
                 }
             }
         }
@@ -4025,17 +4046,6 @@
             mScrimController.setAodFrontScrimAlpha(scrimOpacity);
         }
 
-        public void dispatchDoubleTap(float viewX, float viewY) {
-            dispatchTap(mAmbientIndicationContainer, viewX, viewY);
-            dispatchTap(mAmbientIndicationContainer, viewX, viewY);
-        }
-
-        private void dispatchTap(View view, float x, float y) {
-            long now = SystemClock.elapsedRealtime();
-            dispatchTouchEvent(view, x, y, now, MotionEvent.ACTION_DOWN);
-            dispatchTouchEvent(view, x, y, now, MotionEvent.ACTION_UP);
-        }
-
         private void dispatchTouchEvent(View view, float x, float y, long now, int action) {
             MotionEvent ev = MotionEvent.obtain(now, now, action, x, y, 0 /* meta */);
             view.dispatchTouchEvent(ev);
@@ -4103,7 +4113,7 @@
 
     protected Display mDisplay;
 
-    protected RecentsComponent mRecents;
+    protected Recents mRecents;
 
     protected NotificationShelf mNotificationShelf;
     protected EmptyShadeView mEmptyShadeView;
@@ -4261,12 +4271,9 @@
         }
     }
 
-    public void startPendingIntentDismissingKeyguard(final PendingIntent intent) {
+    public void executeActionDismissingKeyguard(Runnable action, boolean afterKeyguardGone) {
         if (!mDeviceProvisionedController.isDeviceProvisioned()) return;
 
-        final boolean afterKeyguardGone = intent.isActivity()
-                && PreviewInflater.wouldLaunchResolverActivity(mContext, intent.getIntent(),
-                mLockscreenUserManager.getCurrentUserId());
         dismissKeyguardThenExecute(() -> {
             new Thread(() -> {
                 try {
@@ -4277,25 +4284,35 @@
                     ActivityManager.getService().resumeAppSwitches();
                 } catch (RemoteException e) {
                 }
-                try {
-                    intent.send(null, 0, null, null, null, null, getActivityOptions(
-                            null /* animationAdapter */));
-                } catch (PendingIntent.CanceledException e) {
-                    // the stack trace isn't very helpful here.
-                    // Just log the exception message.
-                    Log.w(TAG, "Sending intent failed: " + e);
-
-                    // TODO: Dismiss Keyguard.
-                }
-                if (intent.isActivity()) {
-                    mAssistManager.hideAssist();
-                }
+                action.run();
             }).start();
 
             return collapsePanel();
         }, afterKeyguardGone);
     }
 
+    public void startPendingIntentDismissingKeyguard(final PendingIntent intent) {
+        final boolean afterKeyguardGone = intent.isActivity()
+                && PreviewInflater.wouldLaunchResolverActivity(mContext, intent.getIntent(),
+                mLockscreenUserManager.getCurrentUserId());
+
+        executeActionDismissingKeyguard(() -> {
+            try {
+                intent.send(null, 0, null, null, null, null, getActivityOptions(
+                        null /* animationAdapter */));
+            } catch (PendingIntent.CanceledException e) {
+                // the stack trace isn't very helpful here.
+                // Just log the exception message.
+                Log.w(TAG, "Sending intent failed: " + e);
+
+                // TODO: Dismiss Keyguard.
+            }
+            if (intent.isActivity()) {
+                mAssistManager.hideAssist();
+            }
+        }, afterKeyguardGone);
+    }
+
     public static Bundle getActivityOptions(@Nullable RemoteAnimationAdapter animationAdapter) {
         ActivityOptions options;
         if (animationAdapter != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
index 384a6e7..4c24a21 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
@@ -101,7 +101,8 @@
         boolean vpnVisible = mSecurityController.isVpnEnabled();
         int vpnIconId = currentVpnIconId(mSecurityController.isVpnBranded());
 
-        mIconController.setIcon(mSlotVpn, vpnIconId, null);
+        mIconController.setIcon(mSlotVpn, vpnIconId,
+                mContext.getResources().getString(R.string.accessibility_vpn_on));
         mIconController.setIconVisibility(mSlotVpn, vpnVisible);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
index 298a93e..6fa73ef 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
@@ -34,7 +34,6 @@
 import android.os.SystemClock;
 import android.util.AttributeSet;
 import android.util.TypedValue;
-import android.view.Display;
 import android.view.HapticFeedbackConstants;
 import android.view.InputDevice;
 import android.view.KeyCharacterMap;
@@ -49,7 +48,7 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.Dependency;
-import com.android.systemui.OverviewProxyService;
+import com.android.systemui.recents.OverviewProxyService;
 import com.android.systemui.R;
 import com.android.systemui.plugins.statusbar.phone.NavBarButtonProvider.ButtonInterface;
 import com.android.systemui.shared.system.NavigationBarCompat;
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSliceViewTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSliceViewTest.java
index 4ec30fd..b98ce39 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSliceViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSliceViewTest.java
@@ -73,17 +73,6 @@
     }
 
     @Test
-    public void hasHeader_readsSliceData() {
-        ListBuilder builder = new ListBuilder(getContext(), mSliceUri, ListBuilder.INFINITY);
-        mKeyguardSliceView.onChanged(builder.build());
-        Assert.assertFalse("View should not have a header", mKeyguardSliceView.hasHeader());
-
-        builder.setHeader(new ListBuilder.HeaderBuilder().setTitle("header title!"));
-        mKeyguardSliceView.onChanged(builder.build());
-        Assert.assertTrue("View should have a header", mKeyguardSliceView.hasHeader());
-    }
-
-    @Test
     public void refresh_replacesSliceContentAndNotifiesListener() {
         AtomicBoolean notified = new AtomicBoolean();
         mKeyguardSliceView.setContentChangeListener(()-> notified.set(true));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java
new file mode 100644
index 0000000..b699163
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.appops;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.app.AppOpsManager;
+import android.os.UserHandle;
+import android.support.test.filters.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import com.android.systemui.Dependency;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.NotificationPresenter;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class AppOpsControllerTest extends SysuiTestCase {
+    private static final String TEST_PACKAGE_NAME = "test";
+    private static final int TEST_UID = 0;
+    private static final int TEST_UID_OTHER = 500000;
+
+    @Mock private NotificationPresenter mPresenter;
+    @Mock private AppOpsManager mAppOpsManager;
+    @Mock private AppOpsController.Callback mCallback;
+
+    private AppOpsControllerImpl mController;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        getContext().addMockSystemService(AppOpsManager.class, mAppOpsManager);
+
+        mController = new AppOpsControllerImpl(mContext, Dependency.get(Dependency.BG_LOOPER));
+    }
+
+    @Test
+    public void testOnlyListenForFewOps() {
+        mController.setListening(true);
+        verify(mAppOpsManager, times(1)).startWatchingActive(AppOpsControllerImpl.OPS, mController);
+    }
+
+    @Test
+    public void testStopListening() {
+        mController.setListening(false);
+        verify(mAppOpsManager, times(1)).stopWatchingActive(mController);
+    }
+
+    @Test
+    public void addCallback_includedCode() {
+        mController.addCallback(new int[]{AppOpsManager.OP_RECORD_AUDIO}, mCallback);
+        mController.onOpActiveChanged(
+                AppOpsManager.OP_RECORD_AUDIO, TEST_UID, TEST_PACKAGE_NAME, true);
+        verify(mCallback).onActiveStateChanged(AppOpsManager.OP_RECORD_AUDIO,
+                TEST_UID, TEST_PACKAGE_NAME, true);
+    }
+
+    @Test
+    public void addCallback_notIncludedCode() {
+        mController.addCallback(new int[]{AppOpsManager.OP_FINE_LOCATION}, mCallback);
+        mController.onOpActiveChanged(
+                AppOpsManager.OP_RECORD_AUDIO, TEST_UID, TEST_PACKAGE_NAME, true);
+        verify(mCallback, never()).onActiveStateChanged(
+                anyInt(), anyInt(), anyString(), anyBoolean());
+    }
+
+    @Test
+    public void removeCallback_sameCode() {
+        mController.addCallback(new int[]{AppOpsManager.OP_RECORD_AUDIO}, mCallback);
+        mController.removeCallback(new int[]{AppOpsManager.OP_RECORD_AUDIO}, mCallback);
+        mController.onOpActiveChanged(
+                AppOpsManager.OP_RECORD_AUDIO, TEST_UID, TEST_PACKAGE_NAME, true);
+        verify(mCallback, never()).onActiveStateChanged(
+                anyInt(), anyInt(), anyString(), anyBoolean());
+    }
+
+    @Test
+    public void addCallback_notSameCode() {
+        mController.addCallback(new int[]{AppOpsManager.OP_RECORD_AUDIO}, mCallback);
+        mController.removeCallback(new int[]{AppOpsManager.OP_FINE_LOCATION}, mCallback);
+        mController.onOpActiveChanged(
+                AppOpsManager.OP_RECORD_AUDIO, TEST_UID, TEST_PACKAGE_NAME, true);
+        verify(mCallback).onActiveStateChanged(AppOpsManager.OP_RECORD_AUDIO,
+                TEST_UID, TEST_PACKAGE_NAME, true);
+    }
+
+    @Test
+    public void getActiveItems_sameDetails() {
+        mController.onOpActiveChanged(AppOpsManager.OP_RECORD_AUDIO,
+                TEST_UID, TEST_PACKAGE_NAME, true);
+        mController.onOpActiveChanged(AppOpsManager.OP_RECORD_AUDIO,
+                TEST_UID, TEST_PACKAGE_NAME, true);
+        assertEquals(1, mController.getActiveAppOps().size());
+    }
+
+    @Test
+    public void getActiveItems_differentDetails() {
+        mController.onOpActiveChanged(AppOpsManager.OP_RECORD_AUDIO,
+                TEST_UID, TEST_PACKAGE_NAME, true);
+        mController.onOpActiveChanged(AppOpsManager.OP_CAMERA,
+                TEST_UID, TEST_PACKAGE_NAME, true);
+        assertEquals(2, mController.getActiveAppOps().size());
+    }
+
+    @Test public void getActiveItemsForUser() {
+        mController.onOpActiveChanged(AppOpsManager.OP_RECORD_AUDIO,
+                TEST_UID, TEST_PACKAGE_NAME, true);
+        mController.onOpActiveChanged(AppOpsManager.OP_CAMERA,
+                TEST_UID_OTHER, TEST_PACKAGE_NAME, true);
+        assertEquals(1,
+                mController.getActiveAppOpsForUser(UserHandle.getUserId(TEST_UID)).size());
+        assertEquals(1,
+                mController.getActiveAppOpsForUser(UserHandle.getUserId(TEST_UID)).size());
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/recents/IRecentsNonSystemUserCallbacks.aidl b/packages/SystemUI/tests/src/com/android/systemui/recents/IRecentsNonSystemUserCallbacks.aidl
deleted file mode 120000
index 0ea3e91..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/recents/IRecentsNonSystemUserCallbacks.aidl
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../../src/com/android/systemui/recents/IRecentsNonSystemUserCallbacks.aidl
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/recents/IRecentsSystemUserCallbacks.aidl b/packages/SystemUI/tests/src/com/android/systemui/recents/IRecentsSystemUserCallbacks.aidl
deleted file mode 120000
index b1a0963..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/recents/IRecentsSystemUserCallbacks.aidl
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../../src/com/android/systemui/recents/IRecentsSystemUserCallbacks.aidl
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/recents/RecentsTest.java b/packages/SystemUI/tests/src/com/android/systemui/recents/RecentsTest.java
deleted file mode 100644
index 2160f9a..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/recents/RecentsTest.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.recents;
-
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
-
-import static com.android.systemui.recents.RecentsImpl.RECENTS_ACTIVITY;
-import static com.android.systemui.recents.RecentsImpl.RECENTS_PACKAGE;
-
-import static org.junit.Assert.fail;
-
-import android.app.ActivityManager.RunningTaskInfo;
-import android.app.ActivityTaskManager;
-import android.app.IActivityTaskManager;
-import android.os.SystemClock;
-import android.support.test.filters.MediumTest;
-import android.support.test.runner.AndroidJUnit4;
-
-import com.android.systemui.SysuiTestCase;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.List;
-
-@RunWith(AndroidJUnit4.class)
-@MediumTest
-public class RecentsTest extends SysuiTestCase {
-
-    @Test
-    public void testRecentsActivityType() throws Exception {
-        // Clear the state
-        final IActivityTaskManager atm = ActivityTaskManager.getService();
-        atm.removeStacksWithActivityTypes(new int[] { ACTIVITY_TYPE_RECENTS });
-
-        // Toggle recents, use a shell command because it is not exported
-        runShellCommand("am start -n " + RECENTS_PACKAGE + "/" + RECENTS_ACTIVITY);
-
-        // Verify that an activity was launched with the right activity type
-        int retryCount = 0;
-        while (retryCount < 10) {
-            List<RunningTaskInfo> tasks = atm.getTasks(Integer.MAX_VALUE);
-            for (RunningTaskInfo info : tasks) {
-                if (info.configuration.windowConfiguration.getActivityType()
-                        == ACTIVITY_TYPE_RECENTS) {
-                    // Found a recents activity with the right activity type
-                    return;
-                }
-            }
-            SystemClock.sleep(50);
-            retryCount++;
-        }
-        fail("Expected Recents activity with ACTIVITY_TYPE_RECENTS");
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NonPhoneDependencyTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NonPhoneDependencyTest.java
index fe0a7c7..2e280d3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NonPhoneDependencyTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NonPhoneDependencyTest.java
@@ -19,7 +19,6 @@
 import static org.junit.Assert.assertFalse;
 
 import android.os.Handler;
-import android.os.Looper;
 import android.support.test.filters.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
@@ -38,6 +37,7 @@
 import com.android.systemui.statusbar.policy.HeadsUpManager;
 
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
@@ -51,6 +51,7 @@
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 @TestableLooper.RunWithLooper(setAsMainLooper = true)
+@Ignore("b/118400112")
 public class NonPhoneDependencyTest extends SysuiTestCase {
     @Mock private NotificationPresenter mPresenter;
     @Mock private NotificationListContainer mListContainer;
@@ -69,6 +70,7 @@
     }
 
     @Test
+    @Ignore("b/118400112")
     public void testNotificationManagementCodeHasNoDependencyOnStatusBarWindowManager() {
         mDependency.injectMockDependency(ShadeController.class);
         NotificationEntryManager entryManager = Dependency.get(NotificationEntryManager.class);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/AppOpsListenerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/AppOpsListenerTest.java
deleted file mode 100644
index b405a5c..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/AppOpsListenerTest.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar.notification;
-
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-import android.app.AppOpsManager;
-import android.os.Handler;
-import android.os.Looper;
-import android.support.test.filters.SmallTest;
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
-
-import com.android.systemui.Dependency;
-import com.android.systemui.ForegroundServiceController;
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.statusbar.NotificationPresenter;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-@SmallTest
-@RunWith(AndroidTestingRunner.class)
-@TestableLooper.RunWithLooper
-public class AppOpsListenerTest extends SysuiTestCase {
-    private static final String TEST_PACKAGE_NAME = "test";
-    private static final int TEST_UID = 0;
-
-    @Mock private NotificationPresenter mPresenter;
-    @Mock private AppOpsManager mAppOpsManager;
-
-    // Dependency mocks:
-    @Mock private NotificationEntryManager mEntryManager;
-    @Mock private ForegroundServiceController mFsc;
-
-    private AppOpsListener mListener;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        mDependency.injectTestDependency(NotificationEntryManager.class, mEntryManager);
-        mDependency.injectTestDependency(ForegroundServiceController.class, mFsc);
-        getContext().addMockSystemService(AppOpsManager.class, mAppOpsManager);
-        mDependency.injectTestDependency(Dependency.MAIN_HANDLER,
-                Handler.createAsync(Looper.myLooper()));
-
-        mListener = new AppOpsListener(mContext);
-    }
-
-    @Test
-    public void testOnlyListenForFewOps() {
-        mListener.setUpWithPresenter(mPresenter);
-
-        verify(mAppOpsManager, times(1)).startWatchingActive(AppOpsListener.OPS, mListener);
-    }
-
-    @Test
-    public void testStopListening() {
-        mListener.destroy();
-        verify(mAppOpsManager, times(1)).stopWatchingActive(mListener);
-    }
-
-    @Test
-    public void testInformEntryMgrOnAppOpsChange() {
-        mListener.setUpWithPresenter(mPresenter);
-        mListener.onOpActiveChanged(
-                AppOpsManager.OP_RECORD_AUDIO, TEST_UID, TEST_PACKAGE_NAME, true);
-        TestableLooper.get(this).processAllMessages();
-        verify(mEntryManager, times(1)).updateNotificationsForAppOp(
-                AppOpsManager.OP_RECORD_AUDIO, TEST_UID, TEST_PACKAGE_NAME, true);
-    }
-
-    @Test
-    public void testInformFscOnAppOpsChange() {
-        mListener.setUpWithPresenter(mPresenter);
-        mListener.onOpActiveChanged(
-                AppOpsManager.OP_RECORD_AUDIO, TEST_UID, TEST_PACKAGE_NAME, true);
-        TestableLooper.get(this).processAllMessages();
-        verify(mFsc, times(1)).onAppOpChanged(
-                AppOpsManager.OP_RECORD_AUDIO, TEST_UID, TEST_PACKAGE_NAME, true);
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
index ca968a8..02a618b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
@@ -129,7 +129,7 @@
                 .thenReturn(packageInfo);
         final ApplicationInfo applicationInfo = new ApplicationInfo();
         applicationInfo.uid = TEST_UID;  // non-zero
-        when(mMockPackageManager.getApplicationInfo(anyString(), anyInt())).thenReturn(
+        when(mMockPackageManager.getApplicationInfo(eq(TEST_PACKAGE_NAME), anyInt())).thenReturn(
                 applicationInfo);
         final PackageInfo systemPackageInfo = new PackageInfo();
         systemPackageInfo.packageName = TEST_SYSTEM_PACKAGE_NAME;
@@ -190,6 +190,35 @@
     }
 
     @Test
+    public void testBindNotification_noDelegate() throws Exception {
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+        final TextView nameView = mNotificationInfo.findViewById(R.id.delegate_name);
+        assertEquals(GONE, nameView.getVisibility());
+        final TextView dividerView = mNotificationInfo.findViewById(R.id.pkg_divider);
+        assertEquals(GONE, dividerView.getVisibility());
+    }
+
+    @Test
+    public void testBindNotification_delegate() throws Exception {
+        mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, "other", 0, null, TEST_UID, 0,
+                new Notification(), UserHandle.CURRENT, null, 0);
+        final ApplicationInfo applicationInfo = new ApplicationInfo();
+        applicationInfo.uid = 7;  // non-zero
+        when(mMockPackageManager.getApplicationInfo(eq("other"), anyInt())).thenReturn(
+                applicationInfo);
+        when(mMockPackageManager.getApplicationLabel(any())).thenReturn("Other");
+
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+        final TextView nameView = mNotificationInfo.findViewById(R.id.delegate_name);
+        assertEquals(VISIBLE, nameView.getVisibility());
+        assertTrue(nameView.getText().toString().contains("Other"));
+        final TextView dividerView = mNotificationInfo.findViewById(R.id.pkg_divider);
+        assertEquals(VISIBLE, dividerView.getVisibility());
+    }
+
+    @Test
     public void testBindNotification_GroupNameHiddenIfNoGroup() throws Exception {
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java
index 17df800..003d058 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java
@@ -27,7 +27,7 @@
 
 import com.android.systemui.Dependency;
 
-import com.android.systemui.OverviewProxyService;
+import com.android.systemui.recents.OverviewProxyService;
 import com.android.systemui.SysuiBaseFragmentTest;
 import com.android.systemui.recents.Recents;
 import com.android.systemui.stackdivider.Divider;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index 939245f..882f261 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -67,6 +67,8 @@
 import com.android.systemui.InitController;
 import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.appops.AppOpsController;
+import com.android.systemui.appops.AppOpsControllerImpl;
 import com.android.systemui.assist.AssistManager;
 import com.android.systemui.classifier.FalsingManager;
 import com.android.systemui.keyguard.KeyguardViewMediator;
@@ -84,7 +86,6 @@
 import com.android.systemui.statusbar.RemoteInputController;
 import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.StatusBarStateController;
-import com.android.systemui.statusbar.notification.AppOpsListener;
 import com.android.systemui.statusbar.notification.NotificationData;
 import com.android.systemui.statusbar.notification.NotificationData.Entry;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
@@ -157,7 +158,7 @@
         mDependency.injectTestDependency(VisualStabilityManager.class, mVisualStabilityManager);
         mDependency.injectTestDependency(NotificationListener.class, mNotificationListener);
         mDependency.injectTestDependency(KeyguardMonitor.class, mock(KeyguardMonitorImpl.class));
-        mDependency.injectTestDependency(AppOpsListener.class, mock(AppOpsListener.class));
+        mDependency.injectTestDependency(AppOpsController.class, mock(AppOpsControllerImpl.class));
         mDependency.injectTestDependency(StatusBarStateController.class, mStatusBarStateController);
         mDependency.injectTestDependency(DeviceProvisionedController.class,
                 mDeviceProvisionedController);
diff --git a/packages/overlays/ExperimentNavigationBarFloatingOverlay/Android.mk b/packages/overlays/ExperimentNavigationBarFloatingOverlay/Android.mk
new file mode 100644
index 0000000..ee2ddc8
--- /dev/null
+++ b/packages/overlays/ExperimentNavigationBarFloatingOverlay/Android.mk
@@ -0,0 +1,30 @@
+#
+#  Copyright 2018, The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_RRO_THEME := ExperimentNavigationBarFloating
+LOCAL_CERTIFICATE := platform
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+
+LOCAL_PACKAGE_NAME := ExperimentNavigationBarFloatingOverlay
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_RRO_PACKAGE)
\ No newline at end of file
diff --git a/packages/overlays/ExperimentNavigationBarFloatingOverlay/AndroidManifest.xml b/packages/overlays/ExperimentNavigationBarFloatingOverlay/AndroidManifest.xml
new file mode 100644
index 0000000..b4b2b16
--- /dev/null
+++ b/packages/overlays/ExperimentNavigationBarFloatingOverlay/AndroidManifest.xml
@@ -0,0 +1,27 @@
+<!--
+/**
+ * Copyright (c) 2018, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.internal.experiment.navbar.floating"
+        android:versionCode="1"
+        android:versionName="1.0">
+    <overlay android:targetPackage="android"
+        android:category="com.android.internal.experiment_navbar_floating"
+        android:priority="1"/>
+
+    <application android:label="@string/experiment_navigationbar_overlay" android:hasCode="false"/>
+</manifest>
\ No newline at end of file
diff --git a/packages/overlays/ExperimentNavigationBarFloatingOverlay/res/values/config.xml b/packages/overlays/ExperimentNavigationBarFloatingOverlay/res/values/config.xml
new file mode 100644
index 0000000..6a58453
--- /dev/null
+++ b/packages/overlays/ExperimentNavigationBarFloatingOverlay/res/values/config.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2018, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources>
+    <!-- Height of the bottom navigation / system bar. -->
+    <dimen name="navigation_bar_height">0dp</dimen>
+    <!-- Width of the navigation bar when it is placed vertically on the screen -->
+    <dimen name="navigation_bar_width">0dp</dimen>
+    <!-- Height of the bottom navigation / system bar frame; navigation buttons height. -->
+    <dimen name="navigation_bar_frame_height">48dp</dimen>
+    <!-- Width of the navigation bar frame when it is placed vertically on the screen -->
+    <dimen name="navigation_bar_frame_width">48dp</dimen>
+</resources>
\ No newline at end of file
diff --git a/packages/overlays/ExperimentNavigationBarFloatingOverlay/res/values/strings.xml b/packages/overlays/ExperimentNavigationBarFloatingOverlay/res/values/strings.xml
new file mode 100644
index 0000000..884846d
--- /dev/null
+++ b/packages/overlays/ExperimentNavigationBarFloatingOverlay/res/values/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2018, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- Name of overlay [CHAR LIMIT=64] -->
+    <string name="experiment_navigationbar_overlay">Floating Navigation Bar Experiment</string>
+</resources>
\ No newline at end of file
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/Android.mk b/packages/overlays/ExperimentNavigationBarSlimOverlay/Android.mk
new file mode 100644
index 0000000..e642a68
--- /dev/null
+++ b/packages/overlays/ExperimentNavigationBarSlimOverlay/Android.mk
@@ -0,0 +1,30 @@
+#
+#  Copyright 2018, The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_RRO_THEME := ExperimentNavigationBarSlim
+LOCAL_CERTIFICATE := platform
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+
+LOCAL_PACKAGE_NAME := ExperimentNavigationBarSlimOverlay
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_RRO_PACKAGE)
\ No newline at end of file
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/AndroidManifest.xml b/packages/overlays/ExperimentNavigationBarSlimOverlay/AndroidManifest.xml
new file mode 100644
index 0000000..a1bd582
--- /dev/null
+++ b/packages/overlays/ExperimentNavigationBarSlimOverlay/AndroidManifest.xml
@@ -0,0 +1,27 @@
+<!--
+/**
+ * Copyright (c) 2018, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.internal.experiment.navbar.slim"
+        android:versionCode="1"
+        android:versionName="1.0">
+    <overlay android:targetPackage="android"
+        android:category="com.android.internal.experiment_navbar_slim"
+        android:priority="1"/>
+
+    <application android:label="@string/experiment_navigationbar_overlay" android:hasCode="false"/>
+</manifest>
\ No newline at end of file
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values/config.xml b/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values/config.xml
new file mode 100644
index 0000000..4c3571a
--- /dev/null
+++ b/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values/config.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2018, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources>
+    <!-- Height of the bottom navigation / system bar. -->
+    <dimen name="navigation_bar_height">36dp</dimen>
+    <!-- Width of the navigation bar when it is placed vertically on the screen -->
+    <dimen name="navigation_bar_width">36dp</dimen>
+    <!-- Height of the bottom navigation / system bar frame; navigation buttons height. -->
+    <dimen name="navigation_bar_frame_width">36dp</dimen>
+    <!-- Width of the navigation bar frame when it is placed vertically on the screen -->
+    <dimen name="navigation_bar_frame_height">36dp</dimen>
+</resources>
\ No newline at end of file
diff --git a/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values/strings.xml b/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values/strings.xml
new file mode 100644
index 0000000..5ca9d15
--- /dev/null
+++ b/packages/overlays/ExperimentNavigationBarSlimOverlay/res/values/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2018, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- Name of overlay [CHAR LIMIT=64] -->
+    <string name="experiment_navigationbar_overlay">Slim Navigation Bar Experiment</string>
+</resources>
\ No newline at end of file
diff --git a/proto/src/metrics_constants/metrics_constants.proto b/proto/src/metrics_constants/metrics_constants.proto
index da1fee3..d15b277 100644
--- a/proto/src/metrics_constants/metrics_constants.proto
+++ b/proto/src/metrics_constants/metrics_constants.proto
@@ -6569,6 +6569,11 @@
     // OS: Q
     LOCK_SCREEN_NOTIFICATION_CONTENT = 1584;
 
+    // ConfirmDeviceCredentials > BiometricPrompt
+    // CATEGORY: SETTINGS
+    // OS: Q
+    BIOMETRIC_FRAGMENT = 1585;
+
     // ---- End Q Constants, all Q constants go above this line ----
 
     // Add new aosp constants above this line.
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index fbceade..097405a 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -2068,7 +2068,9 @@
                 && componentNameToEnable.equals(userState.mServiceToEnableWithShortcut)) {
             return false;
         }
+
         userState.mServiceToEnableWithShortcut = componentNameToEnable;
+        scheduleNotifyClientsOfServicesStateChange(userState);
         return true;
     }
 
@@ -2343,10 +2345,10 @@
     @Override
     public void performAccessibilityShortcut() {
         if ((UserHandle.getAppId(Binder.getCallingUid()) != Process.SYSTEM_UID)
-                && (mContext.checkCallingPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
+                && (mContext.checkCallingPermission(Manifest.permission.MANAGE_ACCESSIBILITY)
                 != PackageManager.PERMISSION_GRANTED)) {
             throw new SecurityException(
-                    "performAccessibilityShortcut requires the WRITE_SECURE_SETTINGS permission");
+                    "performAccessibilityShortcut requires the MANAGE_ACCESSIBILITY permission");
         }
         final Map<ComponentName, ToggleableFrameworkFeatureInfo> frameworkFeatureMap =
                 AccessibilityShortcutController.getFrameworkShortcutFeaturesMap();
@@ -2381,6 +2383,19 @@
         }
     };
 
+    @Override
+    public String getAccessibilityShortcutService() {
+        if (mContext.checkCallingPermission(Manifest.permission.MANAGE_ACCESSIBILITY)
+                != PackageManager.PERMISSION_GRANTED) {
+            throw new SecurityException(
+                    "getAccessibilityShortcutService requires the MANAGE_ACCESSIBILITY permission");
+        }
+        synchronized(mLock) {
+            final UserState userState = getUserStateLocked(mCurrentUserId);
+            return userState.mServiceToEnableWithShortcut.flattenToString();
+        }
+    }
+
     /**
      * Enables accessibility service specified by {@param componentName} for the {@param userId}.
      */
diff --git a/services/backup/java/com/android/server/backup/Trampoline.java b/services/backup/java/com/android/server/backup/Trampoline.java
index 818154b..8e4c243 100644
--- a/services/backup/java/com/android/server/backup/Trampoline.java
+++ b/services/backup/java/com/android/server/backup/Trampoline.java
@@ -65,18 +65,17 @@
  */
 public class Trampoline extends IBackupManager.Stub {
     static final String TAG = "BackupManagerService";
-    static final boolean DEBUG_TRAMPOLINE = false;
 
     // When this file is present, the backup service is inactive
-    static final String BACKUP_SUPPRESS_FILENAME = "backup-suppress";
+    private static final String BACKUP_SUPPRESS_FILENAME = "backup-suppress";
 
     // Product-level suppression of backup/restore
-    static final String BACKUP_DISABLE_PROPERTY = "ro.backup.disable";
+    private static final String BACKUP_DISABLE_PROPERTY = "ro.backup.disable";
 
     final Context mContext;
-    final File mSuppressFile;   // existence testing & creating synchronized on 'this'
-    final boolean mGlobalDisable;
-    volatile BackupManagerService mService;
+    private final File mSuppressFile;   // existence testing & creating synchronized on 'this'
+    private final boolean mGlobalDisable;
+    private volatile BackupManagerService mService;
 
     private HandlerThread mHandlerThread;
 
diff --git a/services/backup/java/com/android/server/backup/encryption/chunking/ChunkEncryptor.java b/services/backup/java/com/android/server/backup/encryption/chunking/ChunkEncryptor.java
new file mode 100644
index 0000000..812cfbd
--- /dev/null
+++ b/services/backup/java/com/android/server/backup/encryption/chunking/ChunkEncryptor.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.backup.encryption.chunking;
+
+import com.android.server.backup.encryption.chunk.ChunkHash;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.GCMParameterSpec;
+
+/** Encrypts chunks of a file using AES/GCM. */
+public class ChunkEncryptor {
+    private static final String CIPHER_ALGORITHM = "AES/GCM/NoPadding";
+    private static final int GCM_NONCE_LENGTH_BYTES = 12;
+    private static final int GCM_TAG_LENGTH_BYTES = 16;
+
+    private final SecretKey mSecretKey;
+    private final SecureRandom mSecureRandom;
+
+    /**
+     * A new instance using {@code mSecretKey} to encrypt chunks and {@code mSecureRandom} to
+     * generate nonces.
+     */
+    public ChunkEncryptor(SecretKey secretKey, SecureRandom secureRandom) {
+        this.mSecretKey = secretKey;
+        this.mSecureRandom = secureRandom;
+    }
+
+    /**
+     * Transforms {@code plaintext} into an {@link EncryptedChunk}.
+     *
+     * @param plaintextHash The hash of the plaintext to encrypt, to attach as the key of the chunk.
+     * @param plaintext Bytes to encrypt.
+     * @throws InvalidKeyException If the given secret key is not a valid AES key for decryption.
+     * @throws IllegalBlockSizeException If the input data cannot be encrypted using
+     *     AES/GCM/NoPadding. This should never be the case.
+     */
+    public EncryptedChunk encrypt(ChunkHash plaintextHash, byte[] plaintext)
+            throws InvalidKeyException, IllegalBlockSizeException {
+        byte[] nonce = generateNonce();
+        Cipher cipher;
+        try {
+            cipher = Cipher.getInstance(CIPHER_ALGORITHM);
+            cipher.init(
+                    Cipher.ENCRYPT_MODE,
+                    mSecretKey,
+                    new GCMParameterSpec(GCM_TAG_LENGTH_BYTES * 8, nonce));
+        } catch (NoSuchAlgorithmException
+                | NoSuchPaddingException
+                | InvalidAlgorithmParameterException e) {
+            // This can not happen - AES/GCM/NoPadding is supported.
+            throw new AssertionError(e);
+        }
+        byte[] encryptedBytes;
+        try {
+            encryptedBytes = cipher.doFinal(plaintext);
+        } catch (BadPaddingException e) {
+            // This can not happen - BadPaddingException can only be thrown in decrypt mode.
+            throw new AssertionError("Impossible: threw BadPaddingException in encrypt mode.");
+        }
+
+        return EncryptedChunk.create(/*key=*/ plaintextHash, nonce, encryptedBytes);
+    }
+
+    private byte[] generateNonce() {
+        byte[] nonce = new byte[GCM_NONCE_LENGTH_BYTES];
+        mSecureRandom.nextBytes(nonce);
+        return nonce;
+    }
+}
diff --git a/services/backup/java/com/android/server/backup/encryption/chunking/ChunkHasher.java b/services/backup/java/com/android/server/backup/encryption/chunking/ChunkHasher.java
new file mode 100644
index 0000000..145b7bf
--- /dev/null
+++ b/services/backup/java/com/android/server/backup/encryption/chunking/ChunkHasher.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.backup.encryption.chunking;
+
+import com.android.server.backup.encryption.chunk.ChunkHash;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import javax.crypto.Mac;
+import javax.crypto.SecretKey;
+
+/** Computes the SHA-256 HMAC of a chunk of bytes. */
+public class ChunkHasher {
+    private static final String MAC_ALGORITHM = "HmacSHA256";
+
+    private final SecretKey mSecretKey;
+
+    /** Constructs a new hasher which computes the HMAC using the given secret key. */
+    public ChunkHasher(SecretKey secretKey) {
+        this.mSecretKey = secretKey;
+    }
+
+    /** Returns the SHA-256 over the given bytes. */
+    public ChunkHash computeHash(byte[] plaintext) throws InvalidKeyException {
+        try {
+            Mac mac = Mac.getInstance(MAC_ALGORITHM);
+            mac.init(mSecretKey);
+            return new ChunkHash(mac.doFinal(plaintext));
+        } catch (NoSuchAlgorithmException e) {
+            // This can not happen - AES/GCM/NoPadding is available as part of the framework.
+            throw new AssertionError(e);
+        }
+    }
+}
diff --git a/services/backup/java/com/android/server/backup/encryption/chunking/Chunker.java b/services/backup/java/com/android/server/backup/encryption/chunking/Chunker.java
new file mode 100644
index 0000000..b91913e
--- /dev/null
+++ b/services/backup/java/com/android/server/backup/encryption/chunking/Chunker.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.backup.encryption.chunking;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.GeneralSecurityException;
+
+/** Splits an input stream into chunks, which are to be encrypted separately. */
+public interface Chunker {
+    /**
+     * Splits the input stream into chunks.
+     *
+     * @param inputStream The input stream.
+     * @param chunkConsumer A function that processes each chunk as it is produced.
+     * @throws IOException If there is a problem reading the input stream.
+     * @throws GeneralSecurityException if the consumer function throws an error.
+     */
+    void chunkify(InputStream inputStream, ChunkConsumer chunkConsumer)
+            throws IOException, GeneralSecurityException;
+
+    /** Function that consumes chunks. */
+    interface ChunkConsumer {
+        /**
+         * Invoked for each chunk.
+         *
+         * @param chunk Plaintext bytes of chunk.
+         * @throws GeneralSecurityException if there is an issue encrypting the chunk.
+         */
+        void accept(byte[] chunk) throws GeneralSecurityException;
+    }
+}
diff --git a/services/backup/java/com/android/server/backup/encryption/chunking/RawBackupWriter.java b/services/backup/java/com/android/server/backup/encryption/chunking/RawBackupWriter.java
new file mode 100644
index 0000000..839dc7c
--- /dev/null
+++ b/services/backup/java/com/android/server/backup/encryption/chunking/RawBackupWriter.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.backup.encryption.chunking;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/** Writes data straight to an output stream. */
+public class RawBackupWriter implements BackupWriter {
+    private final OutputStream outputStream;
+    private long bytesWritten;
+
+    /** Constructs a new writer which writes bytes to the given output stream. */
+    public RawBackupWriter(OutputStream outputStream) {
+        this.outputStream = outputStream;
+    }
+
+    @Override
+    public void writeBytes(byte[] bytes) throws IOException {
+        outputStream.write(bytes);
+        bytesWritten += bytes.length;
+    }
+
+    @Override
+    public void writeChunk(long start, int length) throws IOException {
+        throw new UnsupportedOperationException("RawBackupWriter cannot write existing chunks");
+    }
+
+    @Override
+    public long getBytesWritten() {
+        return bytesWritten;
+    }
+
+    @Override
+    public void flush() throws IOException {
+        outputStream.flush();
+    }
+}
diff --git a/services/core/java/com/android/server/BinderCallsStatsService.java b/services/core/java/com/android/server/BinderCallsStatsService.java
index 872261a..dd96075 100644
--- a/services/core/java/com/android/server/BinderCallsStatsService.java
+++ b/services/core/java/com/android/server/BinderCallsStatsService.java
@@ -49,6 +49,7 @@
     private static final String PERSIST_SYS_BINDER_CALLS_DETAILED_TRACKING
             = "persist.sys.binder_calls_detailed_tracking";
 
+
     /** Listens for flag changes. */
     private static class SettingsObserver extends ContentObserver {
         private static final String SETTINGS_ENABLED_KEY = "enabled";
@@ -101,7 +102,14 @@
             final boolean enabled =
                     mParser.getBoolean(SETTINGS_ENABLED_KEY, BinderCallsStats.ENABLED_DEFAULT);
             if (mEnabled != enabled) {
-                Binder.setObserver(enabled ? mBinderCallsStats : null);
+                if (enabled) {
+                    Binder.setObserver(mBinderCallsStats);
+                    Binder.setProxyTransactListener(
+                            new Binder.PropagateWorkSourceTransactListener());
+                } else {
+                    Binder.setObserver(null);
+                    Binder.setProxyTransactListener(null);
+                }
                 mEnabled = enabled;
                 mBinderCallsStats.reset();
             }
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 1c8d99a..74c8023 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -215,7 +215,8 @@
     private static final String REQUEST_ARG = "requests";
 
     private static final boolean DBG = true;
-    private static final boolean VDBG = false;
+    private static final boolean DDBG = Log.isLoggable(TAG, Log.DEBUG);
+    private static final boolean VDBG = Log.isLoggable(TAG, Log.VERBOSE);
 
     private static final boolean LOGD_BLOCKED_NETWORKINFO = true;
 
@@ -1143,7 +1144,7 @@
         }
         synchronized (mVpns) {
             final Vpn vpn = mVpns.get(UserHandle.getUserId(uid));
-            if (vpn != null && vpn.isBlockingUid(uid)) {
+            if (vpn != null && vpn.getLockdown() && vpn.isBlockingUid(uid)) {
                 return true;
             }
         }
@@ -1736,7 +1737,7 @@
             // list all state depending on the return value of this function has to be recomputed.
             // TODO: add a trigger when the always-on VPN sets its blocked UIDs to reevaluate and
             // send the necessary onBlockedStatusChanged callbacks.
-            if (vpn != null && vpn.isBlockingUid(uid)) {
+            if (vpn != null && vpn.getLockdown() && vpn.isBlockingUid(uid)) {
                 return true;
             }
         }
@@ -2056,7 +2057,7 @@
         }
 
         try {
-            if (VDBG) log("Setting MTU size: " + iface + ", " + mtu);
+            if (VDBG || DDBG) log("Setting MTU size: " + iface + ", " + mtu);
             mNMS.setMtu(iface, mtu);
         } catch (Exception e) {
             Slog.e(TAG, "exception in setMtu()" + e);
@@ -2092,7 +2093,7 @@
         if (tcpBufferSizes.equals(mCurrentTcpBufferSizes)) return;
 
         try {
-            if (VDBG) Slog.d(TAG, "Setting tx/rx TCP buffers to " + tcpBufferSizes);
+            if (VDBG || DDBG) Slog.d(TAG, "Setting tx/rx TCP buffers to " + tcpBufferSizes);
 
             final String prefix = "/sys/kernel/ipv4/tcp_";
             FileUtils.stringToFile(prefix + "rmem_min", values[0]);
@@ -2931,7 +2932,7 @@
             if (nai != null) {
                 boolean wasBackgroundNetwork = nai.isBackgroundNetwork();
                 nai.removeRequest(nri.request.requestId);
-                if (VDBG) {
+                if (VDBG || DDBG) {
                     log(" Removing from current network " + nai.name() +
                             ", leaving " + nai.numNetworkRequests() + " requests.");
                 }
@@ -3154,7 +3155,7 @@
     }
 
     private void handlePromptUnvalidated(Network network) {
-        if (VDBG) log("handlePromptUnvalidated " + network);
+        if (VDBG || DDBG) log("handlePromptUnvalidated " + network);
         NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
 
         // Only prompt if the network is unvalidated and was explicitly selected by the user, and if
@@ -4843,7 +4844,7 @@
         // do this twice, adding non-next-hop routes first, then routes they are dependent on
         for (RouteInfo route : routeDiff.added) {
             if (route.hasGateway()) continue;
-            if (VDBG) log("Adding Route [" + route + "] to network " + netId);
+            if (VDBG || DDBG) log("Adding Route [" + route + "] to network " + netId);
             try {
                 mNMS.addRoute(netId, route);
             } catch (Exception e) {
@@ -4854,7 +4855,7 @@
         }
         for (RouteInfo route : routeDiff.added) {
             if (route.hasGateway() == false) continue;
-            if (VDBG) log("Adding Route [" + route + "] to network " + netId);
+            if (VDBG || DDBG) log("Adding Route [" + route + "] to network " + netId);
             try {
                 mNMS.addRoute(netId, route);
             } catch (Exception e) {
@@ -4865,7 +4866,7 @@
         }
 
         for (RouteInfo route : routeDiff.removed) {
-            if (VDBG) log("Removing Route [" + route + "] from network " + netId);
+            if (VDBG || DDBG) log("Removing Route [" + route + "] from network " + netId);
             try {
                 mNMS.removeRoute(netId, route);
             } catch (Exception e) {
@@ -5066,7 +5067,7 @@
         }
         // newLp is already a defensive copy.
         newLp.ensureDirectlyConnectedRoutes();
-        if (VDBG) {
+        if (VDBG || DDBG) {
             log("Update of LinkProperties for " + nai.name() +
                     "; created=" + nai.created +
                     "; everConnected=" + nai.everConnected);
@@ -5090,7 +5091,9 @@
     }
 
     private void sendUpdatedScoreToFactories(NetworkRequest networkRequest, int score) {
-        if (VDBG) log("sending new Min Network Score(" + score + "): " + networkRequest.toString());
+        if (VDBG || DDBG){
+            log("sending new Min Network Score(" + score + "): " + networkRequest.toString());
+        }
         for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
             nfi.asyncChannel.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK, score, 0,
                     networkRequest);
@@ -5168,6 +5171,7 @@
                 break;
             }
             case ConnectivityManager.CALLBACK_BLK_CHANGED: {
+                maybeLogBlockedStatusChanged(nri, networkAgent.network, arg1 != 0);
                 msg.arg1 = arg1;
                 break;
             }
@@ -5302,7 +5306,7 @@
         final boolean wasBackgroundNetwork = newNetwork.isBackgroundNetwork();
         final int score = newNetwork.getCurrentScore();
 
-        if (VDBG) log("rematching " + newNetwork.name());
+        if (VDBG || DDBG) log("rematching " + newNetwork.name());
 
         // Find and migrate to this Network any NetworkRequests for
         // which this network is now the best.
@@ -5333,7 +5337,7 @@
             if (satisfies) {
                 // next check if it's better than any current network we're using for
                 // this request
-                if (VDBG) {
+                if (VDBG || DDBG) {
                     log("currentScore = " +
                             (currentNetwork != null ? currentNetwork.getCurrentScore() : 0) +
                             ", newScore = " + score);
@@ -5341,12 +5345,14 @@
                 if (currentNetwork == null || currentNetwork.getCurrentScore() < score) {
                     if (VDBG) log("rematch for " + newNetwork.name());
                     if (currentNetwork != null) {
-                        if (VDBG) log("   accepting network in place of " + currentNetwork.name());
+                        if (VDBG || DDBG){
+                            log("   accepting network in place of " + currentNetwork.name());
+                        }
                         currentNetwork.removeRequest(nri.request.requestId);
                         currentNetwork.lingerRequest(nri.request, now, mLingerDelayMs);
                         affectedNetworks.add(currentNetwork);
                     } else {
-                        if (VDBG) log("   accepting network in place of null");
+                        if (VDBG || DDBG) log("   accepting network in place of null");
                     }
                     newNetwork.unlingerRequest(nri.request);
                     setNetworkForRequest(nri.request.requestId, newNetwork);
@@ -5699,7 +5705,7 @@
     }
 
     private void updateNetworkScore(NetworkAgentInfo nai, int score) {
-        if (VDBG) log("updateNetworkScore for " + nai.name() + " to " + score);
+        if (VDBG || DDBG) log("updateNetworkScore for " + nai.name() + " to " + score);
         if (score < 0) {
             loge("updateNetworkScore for " + nai.name() + " got a negative score (" + score +
                     ").  Bumping score to min of 0");
@@ -5845,7 +5851,7 @@
     }
 
     protected void notifyNetworkCallbacks(NetworkAgentInfo networkAgent, int notifyType, int arg1) {
-        if (VDBG) {
+        if (VDBG || DDBG) {
             String notification = ConnectivityManager.getCallbackName(notifyType);
             log("notifyType " + notification + " for " + networkAgent.name());
         }
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index f510d83..865a651 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -69,6 +69,7 @@
 import android.net.NetworkUtils;
 import android.net.RouteInfo;
 import android.net.UidRange;
+import android.net.UidRangeParcel;
 import android.net.util.NetdService;
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiConfiguration.KeyMgmt;
@@ -1743,7 +1744,6 @@
     public void setAllowOnlyVpnForUids(boolean add, UidRange[] uidRanges)
             throws ServiceSpecificException {
         mContext.enforceCallingOrSelfPermission(NETWORK_STACK, TAG);
-
         try {
             mNetdService.networkRejectNonSecureVpn(add, uidRanges);
         } catch (ServiceSpecificException e) {
@@ -1934,10 +1934,11 @@
     public void setFirewallEnabled(boolean enabled) {
         enforceSystemUid();
         try {
-            mConnector.execute("firewall", "enable", enabled ? "whitelist" : "blacklist");
+            mNetdService.firewallSetFirewallType(
+                    enabled ? INetd.FIREWALL_WHITELIST : INetd.FIREWALL_BLACKLIST);
             mFirewallEnabled = enabled;
-        } catch (NativeDaemonConnectorException e) {
-            throw e.rethrowAsParcelableException();
+        } catch (RemoteException | ServiceSpecificException e) {
+            throw new IllegalStateException(e);
         }
     }
 
@@ -1951,11 +1952,11 @@
     public void setFirewallInterfaceRule(String iface, boolean allow) {
         enforceSystemUid();
         Preconditions.checkState(mFirewallEnabled);
-        final String rule = allow ? "allow" : "deny";
         try {
-            mConnector.execute("firewall", "set_interface_rule", iface, rule);
-        } catch (NativeDaemonConnectorException e) {
-            throw e.rethrowAsParcelableException();
+            mNetdService.firewallSetInterfaceRule(iface,
+                    allow ? INetd.FIREWALL_RULE_ALLOW : INetd.FIREWALL_RULE_DENY);
+        } catch (RemoteException | ServiceSpecificException e) {
+            throw new IllegalStateException(e);
         }
     }
 
@@ -1966,7 +1967,7 @@
         int[] exemptUids;
 
         int numUids = 0;
-
+        if (DBG) Slog.d(TAG, "Closing sockets after enabling chain " + chainName);
         if (getFirewallType(chain) == FIREWALL_TYPE_WHITELIST) {
             // Close all sockets on all non-system UIDs...
             ranges = new UidRange[] {
@@ -2036,26 +2037,15 @@
                 setFirewallChainState(chain, enable);
             }
 
-            final String operation = enable ? "enable_chain" : "disable_chain";
-            final String chainName;
-            switch(chain) {
-                case FIREWALL_CHAIN_STANDBY:
-                    chainName = FIREWALL_CHAIN_NAME_STANDBY;
-                    break;
-                case FIREWALL_CHAIN_DOZABLE:
-                    chainName = FIREWALL_CHAIN_NAME_DOZABLE;
-                    break;
-                case FIREWALL_CHAIN_POWERSAVE:
-                    chainName = FIREWALL_CHAIN_NAME_POWERSAVE;
-                    break;
-                default:
-                    throw new IllegalArgumentException("Bad child chain: " + chain);
+            final String chainName = getFirewallChainName(chain);
+            if (chain == FIREWALL_CHAIN_NONE) {
+                throw new IllegalArgumentException("Bad child chain: " + chainName);
             }
 
             try {
-                mConnector.execute("firewall", operation, chainName);
-            } catch (NativeDaemonConnectorException e) {
-                throw e.rethrowAsParcelableException();
+                mNetdService.firewallEnableChildChain(chain, enable);
+            } catch (RemoteException | ServiceSpecificException e) {
+                throw new IllegalStateException(e);
             }
 
             // Close any sockets that were opened by the affected UIDs. This has to be done after
@@ -2063,12 +2053,24 @@
             // the connection and race with the iptables commands that enable the firewall. All
             // whitelist and blacklist chains allow RSTs through.
             if (enable) {
-                if (DBG) Slog.d(TAG, "Closing sockets after enabling chain " + chainName);
                 closeSocketsForFirewallChainLocked(chain, chainName);
             }
         }
     }
 
+    private String getFirewallChainName(int chain) {
+        switch (chain) {
+            case FIREWALL_CHAIN_STANDBY:
+                return FIREWALL_CHAIN_NAME_STANDBY;
+            case FIREWALL_CHAIN_DOZABLE:
+                return FIREWALL_CHAIN_NAME_DOZABLE;
+            case FIREWALL_CHAIN_POWERSAVE:
+                return FIREWALL_CHAIN_NAME_POWERSAVE;
+            default:
+                throw new IllegalArgumentException("Bad child chain: " + chain);
+        }
+    }
+
     private int getFirewallType(int chain) {
         switch (chain) {
             case FIREWALL_CHAIN_STANDBY:
@@ -2141,11 +2143,11 @@
 
     private void setFirewallUidRuleLocked(int chain, int uid, int rule) {
         if (updateFirewallUidRuleLocked(chain, uid, rule)) {
+            final int ruleType = getFirewallRuleType(chain, rule);
             try {
-                mConnector.execute("firewall", "set_uid_rule", getFirewallChainName(chain), uid,
-                        getFirewallRuleName(chain, rule));
-            } catch (NativeDaemonConnectorException e) {
-                throw e.rethrowAsParcelableException();
+                mNetdService.firewallSetUidRule(chain, uid, ruleType);
+            } catch (RemoteException | ServiceSpecificException e) {
+                throw new IllegalStateException(e);
             }
         }
     }
@@ -2212,19 +2214,12 @@
         }
     }
 
-    public @NonNull String getFirewallChainName(int chain) {
-        switch (chain) {
-            case FIREWALL_CHAIN_STANDBY:
-                return FIREWALL_CHAIN_NAME_STANDBY;
-            case FIREWALL_CHAIN_DOZABLE:
-                return FIREWALL_CHAIN_NAME_DOZABLE;
-            case FIREWALL_CHAIN_POWERSAVE:
-                return FIREWALL_CHAIN_NAME_POWERSAVE;
-            case FIREWALL_CHAIN_NONE:
-                return FIREWALL_CHAIN_NAME_NONE;
-            default:
-                throw new IllegalArgumentException("Unknown chain:" + chain);
+    private int getFirewallRuleType(int chain, int rule) {
+        if (rule == NetworkPolicyManager.FIREWALL_RULE_DEFAULT) {
+            return getFirewallType(chain) == FIREWALL_TYPE_WHITELIST
+                    ? INetd.FIREWALL_RULE_DENY : INetd.FIREWALL_RULE_ALLOW;
         }
+        return rule;
     }
 
     private static void enforceSystemUid() {
@@ -2554,18 +2549,18 @@
 
     @Override
     public void addInterfaceToLocalNetwork(String iface, List<RouteInfo> routes) {
-        modifyInterfaceInNetwork(MODIFY_OPERATION_ADD, INetd.NETID_LOCAL, iface);
+        modifyInterfaceInNetwork(MODIFY_OPERATION_ADD, INetd.LOCAL_NET_ID, iface);
 
         for (RouteInfo route : routes) {
             if (!route.isDefaultRoute()) {
-                modifyRoute(MODIFY_OPERATION_ADD, INetd.NETID_LOCAL, route);
+                modifyRoute(MODIFY_OPERATION_ADD, INetd.LOCAL_NET_ID, route);
             }
         }
     }
 
     @Override
     public void removeInterfaceFromLocalNetwork(String iface) {
-        modifyInterfaceInNetwork(MODIFY_OPERATION_REMOVE, INetd.NETID_LOCAL, iface);
+        modifyInterfaceInNetwork(MODIFY_OPERATION_REMOVE, INetd.LOCAL_NET_ID, iface);
     }
 
     @Override
@@ -2574,7 +2569,7 @@
 
         for (RouteInfo route : routes) {
             try {
-                modifyRoute(MODIFY_OPERATION_REMOVE, INetd.NETID_LOCAL, route);
+                modifyRoute(MODIFY_OPERATION_REMOVE, INetd.LOCAL_NET_ID, route);
             } catch (IllegalStateException e) {
                 failures++;
             }
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 858dced..5643a6a 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -112,7 +112,6 @@
 import android.util.Xml;
 
 import com.android.internal.annotations.GuardedBy;
-import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.os.AppFuseMount;
 import com.android.internal.os.BackgroundThread;
 import com.android.internal.os.FuseUnavailableMountException;
@@ -323,12 +322,6 @@
     @GuardedBy("mPackagesLock")
     private final SparseArray<ArraySet<String>> mPackages = new SparseArray<>();
 
-    @GuardedBy("mPackagesLock")
-    private final ArrayMap<String, Integer> mAppIds = new ArrayMap<>();
-
-    @GuardedBy("mPackagesLock")
-    private final SparseArray<String> mSandboxIds = new SparseArray<>();
-
     /**
      * List of volumes visible to any user.
      * TODO: may be have a map of userId -> volumes?
@@ -876,13 +869,12 @@
             try {
                 mVold.reset();
 
-                pushPackagesInfo();
                 // Tell vold about all existing and started users
                 for (UserInfo user : users) {
                     mVold.onUserAdded(user.id, user.serialNumber);
                 }
                 for (int userId : systemUnlockedUsers) {
-                    mVold.onUserStarted(userId, getPackagesArrayForUser(userId));
+                    sendUserStartedCallback(userId);
                     mStoraged.onUserStarted(userId);
                 }
                 mVold.onSecureKeyguardStateChanged(mSecureKeyguardShowing);
@@ -899,7 +891,7 @@
         // staging area is ready so it's ready for zygote-forked apps to
         // bind mount against.
         try {
-            mVold.onUserStarted(userId, getPackagesArrayForUser(userId));
+            sendUserStartedCallback(userId);
             mStoraged.onUserStarted(userId);
         } catch (Exception e) {
             Slog.wtf(TAG, e);
@@ -932,11 +924,52 @@
             Slog.wtf(TAG, e);
         }
 
+        synchronized (mPackagesLock) {
+            mPackages.delete(userId);
+        }
+
         synchronized (mLock) {
             mSystemUnlockedUsers = ArrayUtils.removeInt(mSystemUnlockedUsers, userId);
         }
     }
 
+    private void sendUserStartedCallback(int userId) throws Exception {
+        if (!ENABLE_ISOLATED_STORAGE) {
+            mVold.onUserStarted(userId, EmptyArray.STRING, EmptyArray.INT, EmptyArray.STRING);
+        }
+
+        final String[] packages;
+        final int[] appIds;
+        final String[] sandboxIds;
+        final SparseArray<String> sharedUserIds = mPmInternal.getAppsWithSharedUserIds();
+        final List<ApplicationInfo> appInfos =
+                mContext.getPackageManager().getInstalledApplicationsAsUser(
+                        PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
+        synchronized (mPackagesLock) {
+            final ArraySet<String> userPackages = new ArraySet<>();
+            final ArrayMap<String, Integer> packageToAppId = new ArrayMap<>();
+            for (int i = appInfos.size() - 1; i >= 0; --i) {
+                final ApplicationInfo appInfo = appInfos.get(i);
+                if (appInfo.isInstantApp()) {
+                    continue;
+                }
+                userPackages.add(appInfo.packageName);
+                packageToAppId.put(appInfo.packageName, UserHandle.getAppId(appInfo.uid));
+            }
+            mPackages.put(userId, userPackages);
+
+            packages = new String[userPackages.size()];
+            appIds = new int[userPackages.size()];
+            sandboxIds = new String[userPackages.size()];
+            for (int i = userPackages.size() - 1; i >= 0; --i) {
+                packages[i] = userPackages.valueAt(i);
+                appIds[i] = packageToAppId.get(packages[i]);
+                sandboxIds[i] = getSandboxId(packages[i], sharedUserIds.get(appIds[i]));
+            }
+        }
+        mVold.onUserStarted(userId, packages, appIds, sandboxIds);
+    }
+
     @Override
     public void onAwakeStateChanged(boolean isAwake) {
         // Ignored
@@ -1454,111 +1487,12 @@
     }
 
     private void start() {
-        collectPackagesInfo();
         connect();
     }
 
-    @VisibleForTesting
-    void collectPackagesInfo() {
-        if (!ENABLE_ISOLATED_STORAGE) return;
-
-        resetPackageData();
-        final SparseArray<String> sharedUserIds = mPmInternal.getAppsWithSharedUserIds();
-        final int[] userIds = mUmInternal.getUserIds();
-        for (int userId : userIds) {
-            final List<ApplicationInfo> appInfos
-                    = mContext.getPackageManager().getInstalledApplicationsAsUser(
-                            PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
-            synchronized (mPackagesLock) {
-                final ArraySet<String> userPackages = getAvailablePackagesForUserPL(userId);
-                for (int i = appInfos.size() - 1; i >= 0; --i) {
-                    if (appInfos.get(i).isInstantApp()) {
-                        continue;
-                    }
-                    final String packageName = appInfos.get(i).packageName;
-                    userPackages.add(packageName);
-
-                    final int appId = UserHandle.getAppId(appInfos.get(i).uid);
-                    mAppIds.put(packageName, appId);
-                    mSandboxIds.put(appId, getSandboxId(packageName, sharedUserIds.get(appId)));
-                }
-            }
-        }
-    }
-
-    private void resetPackageData() {
-        synchronized (mPackagesLock) {
-            mPackages.clear();
-            mAppIds.clear();
-            mSandboxIds.clear();
-        }
-    }
-
     private static String getSandboxId(String packageName, String sharedUserId) {
         return sharedUserId == null ? packageName : SHARED_SANDBOX_ID_PREFIX + sharedUserId;
     }
-    private void pushPackagesInfo() throws RemoteException {
-        if (!ENABLE_ISOLATED_STORAGE) return;
-
-        // Arrays to fill up from {@link #mAppIds}
-        final String[] allPackageNames;
-        final int[] appIdsForPackages;
-
-        // Arrays to fill up from {@link #mSandboxIds}
-        final int[] allAppIds;
-        final String[] sandboxIdsForApps;
-        synchronized (mPackagesLock) {
-            allPackageNames = new String[mAppIds.size()];
-            appIdsForPackages = new int[mAppIds.size()];
-            for (int i = mAppIds.size() - 1; i >= 0; --i) {
-                allPackageNames[i] = mAppIds.keyAt(i);
-                appIdsForPackages[i] = mAppIds.valueAt(i);
-            }
-
-            allAppIds = new int[mSandboxIds.size()];
-            sandboxIdsForApps = new String[mSandboxIds.size()];
-            for (int i = mSandboxIds.size() - 1; i >= 0; --i) {
-                allAppIds[i] = mSandboxIds.keyAt(i);
-                sandboxIdsForApps[i] = mSandboxIds.valueAt(i);
-            }
-        }
-        mVold.addAppIds(allPackageNames, appIdsForPackages);
-        mVold.addSandboxIds(allAppIds, sandboxIdsForApps);
-    }
-
-    @GuardedBy("mPackagesLock")
-    private ArraySet<String> getAvailablePackagesForUserPL(int userId) {
-        ArraySet<String> userPackages = mPackages.get(userId);
-        if (userPackages == null) {
-            userPackages = new ArraySet<>();
-            mPackages.put(userId, userPackages);
-        }
-        return userPackages;
-    }
-
-    private String[] getPackagesArrayForUser(int userId) {
-        if (!ENABLE_ISOLATED_STORAGE) return EmptyArray.STRING;
-
-        final ArraySet<String> userPackages;
-        synchronized (mPackagesLock) {
-            userPackages = getAvailablePackagesForUserPL(userId);
-            if (!userPackages.isEmpty()) {
-                return userPackages.toArray(new String[0]);
-            }
-        }
-        final List<ApplicationInfo> appInfos =
-                mContext.getPackageManager().getInstalledApplicationsAsUser(
-                        PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
-        synchronized (mPackagesLock) {
-            for (int i = appInfos.size() - 1; i >= 0; --i) {
-                if (appInfos.get(i).isInstantApp()) {
-                    continue;
-                }
-                userPackages.add(appInfos.get(i).packageName);
-            }
-            return userPackages.toArray(new String[0]);
-        }
-    }
 
     private void connect() {
         IBinder binder = ServiceManager.getService("storaged");
@@ -3122,15 +3056,8 @@
             throw new SecurityException("Shady looking path " + path);
         }
 
-        final int uid = mPmInternal.getPackageUid(packageName,
-                PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
-        final String sandboxId;
-        synchronized (mPackagesLock) {
-            sandboxId = mSandboxIds.get(UserHandle.getAppId(uid));
-        }
-        if (uid < 0 || sandboxId == null) {
-            throw new IllegalArgumentException("Unknown package " + packageName);
-        }
+        final String sharedUserId = mPmInternal.getSharedUserIdForPackage(packageName);
+        final String sandboxId = getSandboxId(packageName, sharedUserId);
 
         final Matcher m = PATTERN_TRANSLATE.matcher(path);
         if (m.matches()) {
@@ -3139,7 +3066,9 @@
 
             // Does path belong to any packages belonging to this UID? If so,
             // they get to go straight through to legacy paths.
-            final String[] pkgs = mContext.getPackageManager().getPackagesForUid(uid);
+            final String[] pkgs = (sharedUserId == null)
+                    ? new String[] {packageName}
+                    : mPmInternal.getPackagesForSharedUserId(sharedUserId, userId);
             for (String pkg : pkgs) {
                 if (devicePath.startsWith("Android/data/" + pkg + "/") ||
                         devicePath.startsWith("Android/media/" + pkg + "/") ||
@@ -3758,16 +3687,14 @@
                 int userId) {
             final String sandboxId;
             synchronized (mPackagesLock) {
-                final ArraySet<String> userPackages = getAvailablePackagesForUserPL(userId);
+                final ArraySet<String> userPackages = mPackages.get(userId);
                 // If userPackages is empty, it means the user is not started yet, so no need to
                 // do anything now.
-                if (userPackages.isEmpty() || userPackages.contains(packageName)) {
+                if (userPackages == null || userPackages.contains(packageName)) {
                     return;
                 }
                 userPackages.add(packageName);
-                mAppIds.put(packageName, appId);
                 sandboxId = getSandboxId(packageName, sharedUserId);
-                mSandboxIds.put(appId, sandboxId);
             }
 
             try {
@@ -3778,34 +3705,21 @@
         }
 
         @Override
-        public void destroySandboxForApp(String packageName, int userId) {
+        public void destroySandboxForApp(String packageName, String sharedUserId, int userId) {
             if (!ENABLE_ISOLATED_STORAGE) {
                 return;
             }
-            final int appId;
-            final String sandboxId;
+            final String sandboxId = getSandboxId(packageName, sharedUserId);
             synchronized (mPackagesLock) {
-                final ArraySet<String> userPackages = getAvailablePackagesForUserPL(userId);
-                userPackages.remove(packageName);
-                appId = mAppIds.get(packageName);
-                sandboxId = mSandboxIds.get(appId);
-
-                // If the package is not uninstalled in any other users, remove appId and sandboxId
-                // corresponding to it from the internal state.
-                boolean installedInAnyUser = false;
-                for (int i = mPackages.size() - 1; i >= 0; --i) {
-                    if (mPackages.valueAt(i).contains(packageName)) {
-                        installedInAnyUser = true;
-                        break;
-                    }
-                }
-                if (!installedInAnyUser) {
-                    mAppIds.remove(packageName);
-                    mSandboxIds.remove(appId);
+                final ArraySet<String> userPackages = mPackages.get(userId);
+                // If the userPackages is null, it means the user is not started but we still
+                // need to delete the sandbox data though.
+                if (userPackages != null) {
+                    userPackages.remove(packageName);
                 }
             }
             try {
-                mVold.destroySandboxForApp(packageName, appId, sandboxId, userId);
+                mVold.destroySandboxForApp(packageName, sandboxId, userId);
             } catch (Exception e) {
                 Slog.wtf(TAG, e);
             }
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 9c60b8c..e879efd 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -241,9 +241,6 @@
         private final HashMap<Account, AtomicReference<String>> previousNameCache =
                 new HashMap<Account, AtomicReference<String>>();
 
-        private int debugDbInsertionPoint = -1;
-        private SQLiteStatement statementForLogging; // TODO Move to AccountsDb
-
         UserAccounts(Context context, int userId, File preNDbFile, File deDbFile) {
             this.userId = userId;
             synchronized (dbLock) {
@@ -1299,7 +1296,6 @@
                 File preNDbFile = new File(mInjector.getPreNDatabaseName(userId));
                 File deDbFile = new File(mInjector.getDeDatabaseName(userId));
                 accounts = new UserAccounts(mContext, userId, preNDbFile, deDbFile);
-                initializeDebugDbSizeAndCompileSqlStatementForLogging(accounts);
                 mUsers.append(userId, accounts);
                 purgeOldGrants(accounts);
                 validateAccounts = true;
@@ -1400,7 +1396,7 @@
         if (accounts != null) {
             synchronized (accounts.dbLock) {
                 synchronized (accounts.cacheLock) {
-                    accounts.statementForLogging.close();
+                    accounts.accountsDb.closeDebugStatement();
                     accounts.accountsDb.close();
                 }
             }
@@ -5124,41 +5120,36 @@
 
             @Override
             public void run() {
-                SQLiteStatement logStatement = userAccount.statementForLogging;
-                logStatement.bindLong(1, accountId);
-                logStatement.bindString(2, action);
-                logStatement.bindString(3, mDateFormat.format(new Date()));
-                logStatement.bindLong(4, callingUid);
-                logStatement.bindString(5, tableName);
-                logStatement.bindLong(6, userDebugDbInsertionPoint);
-                try {
-                    logStatement.execute();
-                } catch (IllegalStateException e) {
-                    // Guard against crash, DB can already be closed
-                    // since this statement is executed on a handler thread
-                    Slog.w(TAG, "Failed to insert a log record. accountId=" + accountId
-                            + " action=" + action + " tableName=" + tableName + " Error: " + e);
-                } finally {
-                    logStatement.clearBindings();
+                synchronized (userAccount.accountsDb.mDebugStatementLock) {
+                    SQLiteStatement logStatement = userAccount.accountsDb.getStatementForLogging();
+                    if (logStatement == null) {
+                        return; // Can't log.
+                    }
+                    logStatement.bindLong(1, accountId);
+                    logStatement.bindString(2, action);
+                    logStatement.bindString(3, mDateFormat.format(new Date()));
+                    logStatement.bindLong(4, callingUid);
+                    logStatement.bindString(5, tableName);
+                    logStatement.bindLong(6, userDebugDbInsertionPoint);
+                    try {
+                        logStatement.execute();
+                    } catch (IllegalStateException e) {
+                        // Guard against crash, DB can already be closed
+                        // since this statement is executed on a handler thread
+                        Slog.w(TAG, "Failed to insert a log record. accountId=" + accountId
+                                + " action=" + action + " tableName=" + tableName + " Error: " + e);
+                    } finally {
+                        logStatement.clearBindings();
+                    }
                 }
             }
         }
-
-        LogRecordTask logTask = new LogRecordTask(action, tableName, accountId, userAccount,
-                callingUid, userAccount.debugDbInsertionPoint);
-        userAccount.debugDbInsertionPoint = (userAccount.debugDbInsertionPoint + 1)
-                % AccountsDb.MAX_DEBUG_DB_SIZE;
-        mHandler.post(logTask);
-    }
-
-    /*
-     * This should only be called once to compile the sql statement for logging
-     * and to find the insertion point.
-     */
-    private void initializeDebugDbSizeAndCompileSqlStatementForLogging(UserAccounts userAccount) {
-        userAccount.debugDbInsertionPoint = userAccount.accountsDb
-                .calculateDebugTableInsertionPoint();
-        userAccount.statementForLogging = userAccount.accountsDb.compileSqlStatementForLogging();
+        long insertionPoint = userAccount.accountsDb.reserveDebugDbInsertionPoint();
+        if (insertionPoint != -1) {
+            LogRecordTask logTask = new LogRecordTask(action, tableName, accountId, userAccount,
+                    callingUid, insertionPoint);
+            mHandler.post(logTask);
+        }
     }
 
     public IBinder onBind(@SuppressWarnings("unused") Intent intent) {
diff --git a/services/core/java/com/android/server/accounts/AccountsDb.java b/services/core/java/com/android/server/accounts/AccountsDb.java
index 0c3d268..712edcc 100644
--- a/services/core/java/com/android/server/accounts/AccountsDb.java
+++ b/services/core/java/com/android/server/accounts/AccountsDb.java
@@ -17,11 +17,13 @@
 package com.android.server.accounts;
 
 import android.accounts.Account;
+import android.annotation.Nullable;
 import android.content.ContentValues;
 import android.content.Context;
 import android.database.Cursor;
 import android.database.DatabaseUtils;
 import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteException;
 import android.database.sqlite.SQLiteOpenHelper;
 import android.database.sqlite.SQLiteStatement;
 import android.os.FileUtils;
@@ -183,6 +185,10 @@
     private final Context mContext;
     private final File mPreNDatabaseFile;
 
+    final Object mDebugStatementLock = new Object();
+    private volatile long mDebugDbInsertionPoint = -1;
+    private volatile SQLiteStatement mDebugStatementForLogging; // not thread safe.
+
     AccountsDb(DeDatabaseHelper deDatabase, Context context, File preNDatabaseFile) {
         mDeDatabase = deDatabase;
         mContext = context;
@@ -1278,31 +1284,72 @@
      * Finds the row key where the next insertion should take place. Returns number of rows
      * if it is less {@link #MAX_DEBUG_DB_SIZE}, otherwise finds the lowest number available.
      */
-    int calculateDebugTableInsertionPoint() {
-        SQLiteDatabase db = mDeDatabase.getReadableDatabase();
-        String queryCountDebugDbRows = "SELECT COUNT(*) FROM " + TABLE_DEBUG;
-        int size = (int) DatabaseUtils.longForQuery(db, queryCountDebugDbRows, null);
-        if (size < MAX_DEBUG_DB_SIZE) {
-            return size;
-        }
+    long calculateDebugTableInsertionPoint() {
+        try {
+            SQLiteDatabase db = mDeDatabase.getReadableDatabase();
+            String queryCountDebugDbRows = "SELECT COUNT(*) FROM " + TABLE_DEBUG;
+            int size = (int) DatabaseUtils.longForQuery(db, queryCountDebugDbRows, null);
+            if (size < MAX_DEBUG_DB_SIZE) {
+                return size;
+            }
 
-        // This query finds the smallest timestamp value (and if 2 records have
-        // same timestamp, the choose the lower id).
-        queryCountDebugDbRows = "SELECT " + DEBUG_TABLE_KEY +
-                " FROM " + TABLE_DEBUG +
-                " ORDER BY "  + DEBUG_TABLE_TIMESTAMP + "," + DEBUG_TABLE_KEY +
-                " LIMIT 1";
-        return (int) DatabaseUtils.longForQuery(db, queryCountDebugDbRows, null);
+            // This query finds the smallest timestamp value (and if 2 records have
+            // same timestamp, the choose the lower id).
+            queryCountDebugDbRows =
+                    "SELECT " + DEBUG_TABLE_KEY
+                    + " FROM " + TABLE_DEBUG
+                    + " ORDER BY "  + DEBUG_TABLE_TIMESTAMP + ","
+                    + DEBUG_TABLE_KEY
+                    + " LIMIT 1";
+            return DatabaseUtils.longForQuery(db, queryCountDebugDbRows, null);
+        } catch (SQLiteException e) {
+            Log.e(TAG, "Failed to open debug table" + e);
+            return -1;
+        }
     }
 
     SQLiteStatement compileSqlStatementForLogging() {
-        // TODO b/31708085 Fix debug logging - it eagerly opens database for write without a need
         SQLiteDatabase db = mDeDatabase.getWritableDatabase();
         String sql = "INSERT OR REPLACE INTO " + AccountsDb.TABLE_DEBUG
                 + " VALUES (?,?,?,?,?,?)";
         return db.compileStatement(sql);
     }
 
+    /**
+     * Returns statement for logging or {@code null} on database open failure.
+     * Returned value must be guarded by {link #debugStatementLock}
+     */
+    @Nullable SQLiteStatement getStatementForLogging() {
+        if (mDebugStatementForLogging != null) {
+            return mDebugStatementForLogging;
+        }
+        try {
+            mDebugStatementForLogging =  compileSqlStatementForLogging();
+            return mDebugStatementForLogging;
+        } catch (SQLiteException e) {
+            Log.e(TAG, "Failed to open debug table" + e);
+            return null;
+        }
+    }
+
+    void closeDebugStatement() {
+        synchronized (mDebugStatementLock) {
+            if (mDebugStatementForLogging != null) {
+                mDebugStatementForLogging.close();
+                mDebugStatementForLogging = null;
+            }
+        }
+    }
+
+    long reserveDebugDbInsertionPoint() {
+        if (mDebugDbInsertionPoint == -1) {
+            mDebugDbInsertionPoint = calculateDebugTableInsertionPoint();
+            return mDebugDbInsertionPoint;
+        }
+        mDebugDbInsertionPoint = (mDebugDbInsertionPoint + 1) % MAX_DEBUG_DB_SIZE;
+        return mDebugDbInsertionPoint;
+    }
+
     void dumpDebugTable(PrintWriter pw) {
         SQLiteDatabase db = mDeDatabase.getReadableDatabase();
         Cursor cursor = db.query(TABLE_DEBUG, null,
diff --git a/services/core/java/com/android/server/am/ActivityDisplay.java b/services/core/java/com/android/server/am/ActivityDisplay.java
index ede13ef..05293b5 100644
--- a/services/core/java/com/android/server/am/ActivityDisplay.java
+++ b/services/core/java/com/android/server/am/ActivityDisplay.java
@@ -163,6 +163,23 @@
         setBounds(0, 0, mTmpDisplaySize.x, mTmpDisplaySize.y);
     }
 
+    void onDisplayChanged() {
+        // The window policy is responsible for stopping activities on the default display.
+        final int displayId = mDisplay.getDisplayId();
+        if (displayId != DEFAULT_DISPLAY) {
+            final int displayState = mDisplay.getState();
+            if (displayState == Display.STATE_OFF && mOffToken == null) {
+                mOffToken = mSupervisor.mService.acquireSleepToken("Display-off", displayId);
+            } else if (displayState == Display.STATE_ON && mOffToken != null) {
+                mOffToken.release();
+                mOffToken = null;
+            }
+        }
+
+        updateBounds();
+        mWindowContainerController.onDisplayChanged();
+    }
+
     void addChild(ActivityStack stack, int position) {
         if (position == POSITION_BOTTOM) {
             position = 0;
@@ -356,7 +373,8 @@
         return getOrCreateStack(windowingMode, activityType, onTop);
     }
 
-    private int getNextStackId() {
+    @VisibleForTesting
+    int getNextStackId() {
         return sNextFreeStackId++;
     }
 
@@ -1021,6 +1039,12 @@
         releaseSelfIfNeeded();
 
         mSupervisor.getKeyguardController().onDisplayRemoved(mDisplayId);
+
+        if (!mAllSleepTokens.isEmpty()) {
+            mSupervisor.mSleepTokens.removeAll(mAllSleepTokens);
+            mAllSleepTokens.clear();
+            mSupervisor.mService.updateSleepIfNeededLocked();
+        }
     }
 
     private void releaseSelfIfNeeded() {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 1b74ed0..e8c6365 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -538,14 +538,23 @@
 
     BroadcastQueue mFgBroadcastQueue;
     BroadcastQueue mBgBroadcastQueue;
+    BroadcastQueue mOffloadBroadcastQueue;
     // Convenient for easy iteration over the queues. Foreground is first
     // so that dispatch of foreground broadcasts gets precedence.
-    final BroadcastQueue[] mBroadcastQueues = new BroadcastQueue[2];
+    final BroadcastQueue[] mBroadcastQueues = new BroadcastQueue[3];
 
     BroadcastStats mLastBroadcastStats;
     BroadcastStats mCurBroadcastStats;
 
     BroadcastQueue broadcastQueueForIntent(Intent intent) {
+        if (isOnOffloadQueue(intent.getFlags())) {
+            if (DEBUG_BROADCAST_BACKGROUND) {
+                Slog.i(TAG_BROADCAST,
+                        "Broadcast intent " + intent + " on offload queue");
+            }
+            return mOffloadBroadcastQueue;
+        }
+
         final boolean isFg = (intent.getFlags() & Intent.FLAG_RECEIVER_FOREGROUND) != 0;
         if (DEBUG_BROADCAST_BACKGROUND) Slog.i(TAG_BROADCAST,
                 "Broadcast intent " + intent + " on "
@@ -1361,14 +1370,6 @@
 
     private static String sTheRealBuildSerial = Build.UNKNOWN;
 
-    /**
-     * Current global configuration information. Contains general settings for the entire system,
-     * also corresponds to the merged configuration of the default display.
-     */
-    Configuration getGlobalConfiguration() {
-        return mActivityTaskManager.getGlobalConfiguration();
-    }
-
     final class UiHandler extends Handler {
         public UiHandler() {
             super(com.android.server.UiThread.get().getLooper(), null, true);
@@ -2174,8 +2175,11 @@
                 "foreground", BROADCAST_FG_TIMEOUT, false);
         mBgBroadcastQueue = new BroadcastQueue(this, mHandler,
                 "background", BROADCAST_BG_TIMEOUT, true);
+        mOffloadBroadcastQueue = new BroadcastQueue(this, mHandler,
+                "offload", BROADCAST_BG_TIMEOUT, true);
         mBroadcastQueues[0] = mFgBroadcastQueue;
         mBroadcastQueues[1] = mBgBroadcastQueue;
+        mBroadcastQueues[2] = mOffloadBroadcastQueue;
 
         mServices = new ActiveServices(this);
         mProviderMap = new ProviderMap(this);
@@ -3552,7 +3556,7 @@
 
                 if (appInfo != null) {
                     forceStopPackageLocked(packageName, appInfo.uid, "clear data");
-                    mActivityTaskManager.getRecentTasks().removeTasksByPackageName(packageName, resolvedUserId);
+                    mAtmInternal.removeRecentTasksByPackageName(packageName, resolvedUserId);
                 }
             }
 
@@ -5815,16 +5819,7 @@
 
     @Override
     public void updateLockTaskPackages(int userId, String[] packages) {
-        final int callingUid = Binder.getCallingUid();
-        if (callingUid != 0 && callingUid != SYSTEM_UID) {
-            enforceCallingPermission(android.Manifest.permission.UPDATE_LOCK_TASK_PACKAGES,
-                    "updateLockTaskPackages()");
-        }
-        synchronized (this) {
-            if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, "Whitelisting " + userId + ":" +
-                    Arrays.toString(packages));
-            mActivityTaskManager.getLockTaskController().updateLockTaskPackages(userId, packages);
-        }
+        mActivityTaskManager.updateLockTaskPackages(userId, packages);
     }
 
     @Override
@@ -6548,6 +6543,23 @@
         return cpr != null ? cpr.newHolder(conn) : null;
     }
 
+    private static final class StartActivityRunnable implements Runnable {
+        private final Context mContext;
+        private final Intent mIntent;
+        private final UserHandle mUserHandle;
+
+        StartActivityRunnable(Context context, Intent intent, UserHandle userHandle) {
+            this.mContext = context;
+            this.mIntent = intent;
+            this.mUserHandle = userHandle;
+        }
+
+        @Override
+        public void run() {
+            mContext.startActivityAsUser(mIntent, mUserHandle);
+        }
+    }
+
     private boolean requestTargetProviderPermissionsReviewIfNeededLocked(ProviderInfo cpi,
             ProcessRecord r, final int userId) {
         if (getPackageManagerInternalLocked().isPermissionsReviewRequired(
@@ -6574,12 +6586,7 @@
             }
 
             final UserHandle userHandle = new UserHandle(userId);
-            mHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    mContext.startActivityAsUser(intent, userHandle);
-                }
-            });
+            mHandler.post(new StartActivityRunnable(mContext, intent, userHandle));
 
             return false;
         }
@@ -7272,7 +7279,6 @@
         mBatteryStatsService.shutdown();
         synchronized (this) {
             mProcessStats.shutdownLocked();
-            mActivityTaskManager.notifyTaskPersisterLocked(null, true);
         }
 
         return timedout;
@@ -9153,6 +9159,11 @@
                 pw.println("-------------------------------------------------------------------------------");
             }
             dumpBinderProxies(pw);
+            pw.println();
+            if (dumpAll) {
+                pw.println("-------------------------------------------------------------------------------");
+            }
+            dumpLmkLocked(pw);
         }
     }
 
@@ -9343,6 +9354,10 @@
                 synchronized (this) {
                     dumpOomLocked(fd, pw, args, opti, true);
                 }
+            } else if ("lmk".equals(cmd)) {
+                synchronized (this) {
+                    dumpLmkLocked(pw);
+                }
             } else if ("permissions".equals(cmd) || "perm".equals(cmd)) {
                 synchronized (this) {
                     dumpPermissionsLocked(fd, pw, args, opti, true, null);
@@ -10372,15 +10387,42 @@
         dumpProcessesToGc(pw, needSep, null);
 
         pw.println();
-        pw.println("  mHomeProcess: " + mActivityTaskManager.mHomeProcess);
-        pw.println("  mPreviousProcess: " + mActivityTaskManager.mPreviousProcess);
-        if (mActivityTaskManager.mHeavyWeightProcess != null) {
-            pw.println("  mHeavyWeightProcess: " + mActivityTaskManager.mHeavyWeightProcess);
-        }
+        mAtmInternal.dumpForOom(pw);
 
         return true;
     }
 
+    private boolean reportLmkKillAtOrBelow(PrintWriter pw, int oom_adj) {
+        Integer cnt = ProcessList.getLmkdKillCount(0, oom_adj);
+        if (cnt != null) {
+            pw.println("    kills at or below oom_adj " + oom_adj + ": " + cnt);
+            return true;
+        }
+        return false;
+    }
+
+    boolean dumpLmkLocked(PrintWriter pw) {
+        pw.println("ACTIVITY MANAGER LMK KILLS (dumpsys activity lmk)");
+        Integer cnt = ProcessList.getLmkdKillCount(ProcessList.UNKNOWN_ADJ,
+                ProcessList.UNKNOWN_ADJ);
+        if (cnt == null) {
+            return false;
+        }
+        pw.println("  Total number of kills: " + cnt);
+
+        return reportLmkKillAtOrBelow(pw, ProcessList.CACHED_APP_MAX_ADJ) &&
+            reportLmkKillAtOrBelow(pw, ProcessList.CACHED_APP_MIN_ADJ) &&
+            reportLmkKillAtOrBelow(pw, ProcessList.SERVICE_B_ADJ) &&
+            reportLmkKillAtOrBelow(pw, ProcessList.PREVIOUS_APP_ADJ) &&
+            reportLmkKillAtOrBelow(pw, ProcessList.HOME_APP_ADJ) &&
+            reportLmkKillAtOrBelow(pw, ProcessList.SERVICE_ADJ) &&
+            reportLmkKillAtOrBelow(pw, ProcessList.HEAVY_WEIGHT_APP_ADJ) &&
+            reportLmkKillAtOrBelow(pw, ProcessList.BACKUP_APP_ADJ) &&
+            reportLmkKillAtOrBelow(pw, ProcessList.PERCEPTIBLE_APP_ADJ) &&
+            reportLmkKillAtOrBelow(pw, ProcessList.VISIBLE_APP_ADJ) &&
+            reportLmkKillAtOrBelow(pw, ProcessList.FOREGROUND_APP_ADJ);
+    }
+
     /**
      * There are three ways to call this:
      *  - no provider specified: dump all the providers
@@ -10403,7 +10445,7 @@
         return mProviderMap.dumpProviderProto(fd, pw, name, args);
     }
 
-    static class ItemMatcher {
+    public static class ItemMatcher {
         ArrayList<ComponentName> components;
         ArrayList<String> strings;
         ArrayList<Integer> objects;
@@ -13355,7 +13397,8 @@
 
     boolean isPendingBroadcastProcessLocked(int pid) {
         return mFgBroadcastQueue.isPendingBroadcastProcessLocked(pid)
-                || mBgBroadcastQueue.isPendingBroadcastProcessLocked(pid);
+                || mBgBroadcastQueue.isPendingBroadcastProcessLocked(pid)
+                || mOffloadBroadcastQueue.isPendingBroadcastProcessLocked(pid);
     }
 
     void skipPendingBroadcastLocked(int pid) {
@@ -13959,16 +14002,14 @@
                                     forceStopPackageLocked(list[i], -1, false, true, true,
                                             false, false, userId, "storage unmount");
                                 }
-                                mActivityTaskManager.getRecentTasks().cleanupLocked(
-                                        UserHandle.USER_ALL);
+                                mAtmInternal.cleanupRecentTasksForUser(UserHandle.USER_ALL);
                                 sendPackageBroadcastLocked(
                                         ApplicationThreadConstants.EXTERNAL_STORAGE_UNAVAILABLE,
                                         list, userId);
                             }
                             break;
                         case Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE:
-                            mActivityTaskManager.getRecentTasks().cleanupLocked(
-                                    UserHandle.USER_ALL);
+                            mAtmInternal.cleanupRecentTasksForUser(UserHandle.USER_ALL);
                             break;
                         case Intent.ACTION_PACKAGE_REMOVED:
                         case Intent.ACTION_PACKAGE_CHANGED:
@@ -14001,7 +14042,7 @@
                                         mUgmInternal.removeUriPermissionsForPackage(ssp, userId,
                                                 true, false);
 
-                                        mActivityTaskManager.getRecentTasks().removeTasksByPackageName(ssp, userId);
+                                        mAtmInternal.removeRecentTasksByPackageName(ssp, userId);
 
                                         mServices.forceStopPackageLocked(ssp, userId);
                                         mAtmInternal.onPackageUninstalled(ssp);
@@ -14031,10 +14072,8 @@
                             final int userHandle = intent.getIntExtra(
                                     Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
 
-                            synchronized(ActivityManagerService.this) {
-                                mActivityTaskManager.getRecentTasks().onPackagesSuspendedChanged(
-                                        packageNames, suspended, userHandle);
-                            }
+                            mAtmInternal.onPackagesSuspendedChanged(packageNames, suspended,
+                                    userHandle);
                             break;
                     }
                     break;
@@ -14601,10 +14640,16 @@
         try {
             boolean doNext = false;
             BroadcastRecord r;
+            BroadcastQueue queue;
 
             synchronized(this) {
-                BroadcastQueue queue = (flags & Intent.FLAG_RECEIVER_FOREGROUND) != 0
-                        ? mFgBroadcastQueue : mBgBroadcastQueue;
+                if (isOnOffloadQueue(flags)) {
+                    queue = mOffloadBroadcastQueue;
+                } else {
+                    queue = (flags & Intent.FLAG_RECEIVER_FOREGROUND) != 0
+                            ? mFgBroadcastQueue : mBgBroadcastQueue;
+                }
+
                 r = queue.getMatchingOrderedReceiver(who);
                 if (r != null) {
                     doNext = r.queue.finishReceiverLocked(r, resultCode,
@@ -15434,7 +15479,7 @@
             }
         }
 
-        if (wpc == mActivityTaskManager.mHomeProcess) {
+        if (wpc.isHomeProcess()) {
             if (adj > ProcessList.HOME_APP_ADJ) {
                 // This process is hosting what we currently consider to be the
                 // home app, so we don't want to let it go into the background.
@@ -15455,7 +15500,7 @@
             }
         }
 
-        if (wpc == mActivityTaskManager.mPreviousProcess && app.hasActivities()) {
+        if (wpc.isPreviousProcess() && app.hasActivities()) {
             if (adj > ProcessList.PREVIOUS_APP_ADJ) {
                 // This was the previous process that showed UI to the user.
                 // We want to try to keep it around more aggressively, to give
@@ -15532,7 +15577,7 @@
                                 "Raise procstate to started service: " + app);
                     }
                 }
-                if (app.hasShownUi && wpc != mActivityTaskManager.mHomeProcess) {
+                if (app.hasShownUi && !wpc.isHomeProcess()) {
                     // If this process has shown some UI, let it immediately
                     // go to the LRU list because it may be pretty heavy with
                     // UI stuff.  We'll tag it with a label just to help
@@ -15611,7 +15656,7 @@
                         if ((cr.flags&Context.BIND_ALLOW_OOM_MANAGEMENT) != 0) {
                             // Not doing bind OOM management, so treat
                             // this guy more like a started service.
-                            if (app.hasShownUi && wpc != mActivityTaskManager.mHomeProcess) {
+                            if (app.hasShownUi && !wpc.isHomeProcess()) {
                                 // If this process has shown some UI, let it immediately
                                 // go to the LRU list because it may be pretty heavy with
                                 // UI stuff.  We'll tag it with a label just to help
@@ -15644,7 +15689,7 @@
                             // about letting this process get into the LRU
                             // list to be killed and restarted if needed for
                             // memory.
-                            if (app.hasShownUi && wpc != mActivityTaskManager.mHomeProcess
+                            if (app.hasShownUi && !wpc.isHomeProcess()
                                     && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
                                 if (adj >= ProcessList.CACHED_APP_MIN_ADJ) {
                                     adjType = "cch-bound-ui-services";
@@ -15850,7 +15895,7 @@
                 }
                 String adjType = null;
                 if (adj > clientAdj) {
-                    if (app.hasShownUi && wpc != mActivityTaskManager.mHomeProcess
+                    if (app.hasShownUi && !wpc.isHomeProcess()
                             && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
                         adjType = "cch-ui-provider";
                     } else {
@@ -16078,6 +16123,60 @@
         return app.curAdj < prevAppAdj || app.getCurProcState() < prevProcState;
     }
 
+    private static final class RecordPssRunnable implements Runnable {
+        private final ActivityManagerService mService;
+        private final ProcessRecord mProc;
+        private final File mHeapdumpFile;
+
+        RecordPssRunnable(ActivityManagerService service, ProcessRecord proc, File heapdumpFile) {
+            this.mService = service;
+            this.mProc = proc;
+            this.mHeapdumpFile = heapdumpFile;
+        }
+
+        @Override
+        public void run() {
+            mService.revokeUriPermission(ActivityThread.currentActivityThread()
+                            .getApplicationThread(),
+                    null, DumpHeapActivity.JAVA_URI,
+                    Intent.FLAG_GRANT_READ_URI_PERMISSION
+                            | Intent.FLAG_GRANT_WRITE_URI_PERMISSION,
+                    UserHandle.myUserId());
+            ParcelFileDescriptor fd = null;
+            try {
+                mHeapdumpFile.delete();
+                fd = ParcelFileDescriptor.open(mHeapdumpFile,
+                        ParcelFileDescriptor.MODE_CREATE
+                        | ParcelFileDescriptor.MODE_TRUNCATE
+                        | ParcelFileDescriptor.MODE_WRITE_ONLY
+                        | ParcelFileDescriptor.MODE_APPEND);
+                IApplicationThread thread = mProc.thread;
+                if (thread != null) {
+                    try {
+                        if (DEBUG_PSS) {
+                            Slog.d(TAG_PSS, "Requesting dump heap from "
+                                    + mProc + " to " + mHeapdumpFile);
+                        }
+                        thread.dumpHeap(/* managed= */ true,
+                                /* mallocInfo= */ false, /* runGc= */ false,
+                                mHeapdumpFile.toString(), fd,
+                                /* finishCallback= */ null);
+                    } catch (RemoteException e) {
+                    }
+                }
+            } catch (FileNotFoundException e) {
+                e.printStackTrace();
+            } finally {
+                if (fd != null) {
+                    try {
+                        fd.close();
+                    } catch (IOException e) {
+                    }
+                }
+            }
+        }
+    }
+
     /**
      * Record new PSS sample for a process.
      */
@@ -16138,48 +16237,8 @@
                     mMemWatchDumpFile = heapdumpFile.toString();
                     mMemWatchDumpPid = proc.pid;
                     mMemWatchDumpUid = proc.uid;
-                    BackgroundThread.getHandler().post(new Runnable() {
-                        @Override
-                        public void run() {
-                            revokeUriPermission(ActivityThread.currentActivityThread()
-                                            .getApplicationThread(),
-                                    null, DumpHeapActivity.JAVA_URI,
-                                    Intent.FLAG_GRANT_READ_URI_PERMISSION
-                                            | Intent.FLAG_GRANT_WRITE_URI_PERMISSION,
-                                    UserHandle.myUserId());
-                            ParcelFileDescriptor fd = null;
-                            try {
-                                heapdumpFile.delete();
-                                fd = ParcelFileDescriptor.open(heapdumpFile,
-                                        ParcelFileDescriptor.MODE_CREATE |
-                                                ParcelFileDescriptor.MODE_TRUNCATE |
-                                                ParcelFileDescriptor.MODE_WRITE_ONLY |
-                                                ParcelFileDescriptor.MODE_APPEND);
-                                IApplicationThread thread = myProc.thread;
-                                if (thread != null) {
-                                    try {
-                                        if (DEBUG_PSS) Slog.d(TAG_PSS,
-                                                "Requesting dump heap from "
-                                                + myProc + " to " + heapdumpFile);
-                                        thread.dumpHeap(/* managed= */ true,
-                                                /* mallocInfo= */ false, /* runGc= */ false,
-                                                heapdumpFile.toString(), fd,
-                                                /* finishCallback= */ null);
-                                    } catch (RemoteException e) {
-                                    }
-                                }
-                            } catch (FileNotFoundException e) {
-                                e.printStackTrace();
-                            } finally {
-                                if (fd != null) {
-                                    try {
-                                        fd.close();
-                                    } catch (IOException e) {
-                                    }
-                                }
-                            }
-                        }
-                    });
+                    BackgroundThread.getHandler().post(
+                            new RecordPssRunnable(this, myProc, DumpHeapProvider.getJavaFile()));
                 } else {
                     Slog.w(TAG, "Process " + proc + " exceeded pss limit " + check
                             + ", but debugging not enabled");
@@ -16518,8 +16577,7 @@
                     if (curSchedGroup == ProcessList.SCHED_GROUP_TOP_APP) {
                         // do nothing if we already switched to RT
                         if (oldSchedGroup != ProcessList.SCHED_GROUP_TOP_APP) {
-                            mActivityTaskManager.onTopProcChangedLocked(
-                                    app.getWindowProcessController());
+                            app.getWindowProcessController().onTopProcChanged();
                             if (mUseFifoUiScheduling) {
                                 // Switch UI pipeline for app to SCHED_FIFO
                                 app.savedPriority = Process.getThreadPriority(app.pid);
@@ -16551,8 +16609,7 @@
                         }
                     } else if (oldSchedGroup == ProcessList.SCHED_GROUP_TOP_APP &&
                             curSchedGroup != ProcessList.SCHED_GROUP_TOP_APP) {
-                        mActivityTaskManager.onTopProcChangedLocked(
-                                app.getWindowProcessController());
+                        app.getWindowProcessController().onTopProcChanged();
                         if (mUseFifoUiScheduling) {
                             try {
                                 // Reset UI pipeline to SCHED_OTHER
@@ -17019,6 +17076,22 @@
         return success;
     }
 
+    private static final class ProcStatsRunnable implements Runnable {
+        private final ActivityManagerService mService;
+        private final ProcessStatsService mProcessStats;
+
+        ProcStatsRunnable(ActivityManagerService service, ProcessStatsService mProcessStats) {
+            this.mService = service;
+            this.mProcessStats = mProcessStats;
+        }
+
+        @Override public void run() {
+            synchronized (mService) {
+                mProcessStats.writeStateAsyncLocked();
+            }
+        }
+    }
+
     @GuardedBy("this")
     final void updateOomAdjLocked() {
         mOomAdjProfiler.oomAdjStarted();
@@ -17313,8 +17386,8 @@
             }
             int factor = numTrimming/3;
             int minFactor = 2;
-            if (mActivityTaskManager.mHomeProcess != null) minFactor++;
-            if (mActivityTaskManager.mPreviousProcess != null) minFactor++;
+            if (mAtmInternal.getHomeProcess() != null) minFactor++;
+            if (mAtmInternal.getPreviousProcess() != null) minFactor++;
             if (factor < minFactor) factor = minFactor;
             int curLevel = ComponentCallbacks2.TRIM_MEMORY_COMPLETE;
             for (int i=N-1; i>=0; i--) {
@@ -17507,13 +17580,7 @@
         }
 
         if (mProcessStats.shouldWriteNowLocked(now)) {
-            mHandler.post(new Runnable() {
-                @Override public void run() {
-                    synchronized (ActivityManagerService.this) {
-                        mProcessStats.writeStateAsyncLocked();
-                    }
-                }
-            });
+            mHandler.post(new ProcStatsRunnable(ActivityManagerService.this, mProcessStats));
         }
 
         if (DEBUG_OOM_ADJ) {
@@ -18612,7 +18679,8 @@
                                     memoryStat.rssInBytes,
                                     memoryStat.cacheInBytes,
                                     memoryStat.swapInBytes,
-                                    memoryStat.rssHighWatermarkInBytes);
+                                    memoryStat.rssHighWatermarkInBytes,
+                                    memoryStat.startTimeNanos);
                     processMemoryStates.add(processMemoryState);
                 }
             }
@@ -18635,7 +18703,7 @@
                 ProcessMemoryState processMemoryState = new ProcessMemoryState(uid, processName,
                         oomScore, memoryStat.pgfault, memoryStat.pgmajfault,
                         memoryStat.rssInBytes, memoryStat.cacheInBytes, memoryStat.swapInBytes,
-                        memoryStat.rssHighWatermarkInBytes);
+                        memoryStat.rssHighWatermarkInBytes, memoryStat.startTimeNanos);
                 processMemoryStates.add(processMemoryState);
             }
             return processMemoryStates;
@@ -19476,4 +19544,8 @@
             }
         }
     }
+
+    private boolean isOnOffloadQueue(int flags) {
+        return ((flags & Intent.FLAG_RECEIVER_OFFLOAD) != 0);
+    }
 }
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 96601a2..fe402ea 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -2736,7 +2736,7 @@
     int runWrite(PrintWriter pw) {
         mInternal.enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
                 "registerUidObserver()");
-        mInternal.mActivityTaskManager.getRecentTasks().flush();
+        mInternal.mAtmInternal.flushRecentTasks();
         pw.println("All tasks persisted.");
         return 0;
     }
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 026c5cc..0049e22 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -48,41 +48,7 @@
 
 import static com.android.server.am.ActivityDisplay.POSITION_BOTTOM;
 import static com.android.server.am.ActivityDisplay.POSITION_TOP;
-import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_ADD_REMOVE;
-import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_ALL;
-import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_APP;
-import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_CLEANUP;
-import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_CONTAINERS;
-import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_PAUSE;
-import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_RELEASE;
-import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_RESULTS;
-import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_SAVED_STATE;
-import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_STACK;
-import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_STATES;
-import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_SWITCH;
-import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_TASKS;
-import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_TRANSITION;
-import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_USER_LEAVING;
-import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_VISIBILITY;
-import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_ADD_REMOVE;
-import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_APP;
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CLEANUP;
-import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_CONTAINERS;
-import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_PAUSE;
-import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_RELEASE;
-import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_RESULTS;
-import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_SAVED_STATE;
-import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_STACK;
-import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_STATES;
-import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_SWITCH;
-import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_TASKS;
-import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_TRANSITION;
-import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_USER_LEAVING;
-import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_VISIBILITY;
-import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_ATM;
-import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
-import static com.android.server.am.ActivityTaskManagerService.RELAUNCH_REASON_FREE_RESIZE;
-import static com.android.server.am.ActivityTaskManagerService.RELAUNCH_REASON_WINDOWING_MODE_RESIZE;
 import static com.android.server.am.ActivityStack.ActivityState.DESTROYED;
 import static com.android.server.am.ActivityStack.ActivityState.DESTROYING;
 import static com.android.server.am.ActivityStack.ActivityState.FINISHING;
@@ -102,8 +68,42 @@
 import static com.android.server.am.ActivityStackSupervisor.PAUSE_IMMEDIATELY;
 import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
 import static com.android.server.am.ActivityStackSupervisor.REMOVE_FROM_RECENTS;
-
+import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_ADD_REMOVE;
+import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_ALL;
+import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_APP;
+import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_CLEANUP;
+import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_CONTAINERS;
+import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_PAUSE;
+import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_RELEASE;
+import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_RESULTS;
+import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_SAVED_STATE;
+import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_STACK;
+import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_STATES;
+import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_SWITCH;
+import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_TASKS;
+import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_TRANSITION;
+import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_USER_LEAVING;
+import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_VISIBILITY;
+import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_ADD_REMOVE;
+import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_APP;
+import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_CONTAINERS;
+import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_PAUSE;
+import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_RELEASE;
+import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_RESULTS;
+import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_SAVED_STATE;
+import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_STACK;
+import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_STATES;
+import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_SWITCH;
+import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_TASKS;
+import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_TRANSITION;
+import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_USER_LEAVING;
+import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_VISIBILITY;
+import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_ATM;
+import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.am.ActivityTaskManagerService.H.FIRST_ACTIVITY_STACK_MSG;
+import static com.android.server.am.ActivityTaskManagerService.RELAUNCH_REASON_FREE_RESIZE;
+import static com.android.server.am.ActivityTaskManagerService.RELAUNCH_REASON_WINDOWING_MODE_RESIZE;
+
 import static java.lang.Integer.MAX_VALUE;
 
 import android.app.Activity;
@@ -1807,13 +1807,6 @@
             return false;
         }
 
-        final ActivityRecord top = topRunningActivityLocked();
-        if (top == null && isInStackLocked(starting) == null && !isTopStackOnDisplay()) {
-            // Shouldn't be visible if you don't have any running activities, not starting one, and
-            // not the top stack on display.
-            return false;
-        }
-
         final ActivityDisplay display = getDisplay();
         boolean gotSplitScreenStack = false;
         boolean gotOpaqueSplitScreenPrimary = false;
@@ -1822,9 +1815,16 @@
         final boolean isAssistantType = isActivityTypeAssistant();
         for (int i = display.getChildCount() - 1; i >= 0; --i) {
             final ActivityStack other = display.getChildAt(i);
+            final boolean hasRunningActivities = other.topRunningActivityLocked() != null;
             if (other == this) {
-                // Should be visible if there is no other stack occluding it.
-                return true;
+                // Should be visible if there is no other stack occluding it, unless it doesn't
+                // have any running activities, not starting one and not home stack.
+                return hasRunningActivities || isInStackLocked(starting) != null
+                        || isActivityTypeHome();
+            }
+
+            if (!hasRunningActivities) {
+                continue;
             }
 
             final int otherWindowingMode = other.getWindowingMode();
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 257a004..17454b4 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -226,9 +226,6 @@
     static final int RESUME_TOP_ACTIVITY_MSG = FIRST_SUPERVISOR_STACK_MSG + 2;
     static final int SLEEP_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG + 3;
     static final int LAUNCH_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG + 4;
-    static final int HANDLE_DISPLAY_ADDED = FIRST_SUPERVISOR_STACK_MSG + 5;
-    static final int HANDLE_DISPLAY_CHANGED = FIRST_SUPERVISOR_STACK_MSG + 6;
-    static final int HANDLE_DISPLAY_REMOVED = FIRST_SUPERVISOR_STACK_MSG + 7;
     static final int LAUNCH_TASK_BEHIND_COMPLETE = FIRST_SUPERVISOR_STACK_MSG + 12;
     static final int REPORT_MULTI_WINDOW_MODE_CHANGED_MSG = FIRST_SUPERVISOR_STACK_MSG + 14;
     static final int REPORT_PIP_MODE_CHANGED_MSG = FIRST_SUPERVISOR_STACK_MSG + 15;
@@ -675,7 +672,7 @@
         setWindowContainerController(new RootWindowContainerController(this));
 
         mDisplayManager = mService.mContext.getSystemService(DisplayManager.class);
-        mDisplayManager.registerDisplayListener(this, null);
+        mDisplayManager.registerDisplayListener(this, mHandler);
         mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
 
         final Display[] displays = mDisplayManager.getDisplays();
@@ -4108,25 +4105,37 @@
     @Override
     public void onDisplayAdded(int displayId) {
         if (DEBUG_STACK) Slog.v(TAG, "Display added displayId=" + displayId);
-        mHandler.sendMessage(mHandler.obtainMessage(HANDLE_DISPLAY_ADDED, displayId, 0));
+        synchronized (mService.mGlobalLock) {
+            getActivityDisplayOrCreateLocked(displayId);
+            mService.startHomeActivityLocked(mCurrentUser, "displayAdded", displayId);
+        }
     }
 
     @Override
     public void onDisplayRemoved(int displayId) {
         if (DEBUG_STACK) Slog.v(TAG, "Display removed displayId=" + displayId);
-        mHandler.sendMessage(mHandler.obtainMessage(HANDLE_DISPLAY_REMOVED, displayId, 0));
+        if (displayId == DEFAULT_DISPLAY) {
+            throw new IllegalArgumentException("Can't remove the primary display.");
+        }
+
+        synchronized (mService.mGlobalLock) {
+            final ActivityDisplay activityDisplay = getActivityDisplay(displayId);
+            if (activityDisplay == null) {
+                return;
+            }
+
+            activityDisplay.remove();
+        }
     }
 
     @Override
     public void onDisplayChanged(int displayId) {
         if (DEBUG_STACK) Slog.v(TAG, "Display changed displayId=" + displayId);
-        mHandler.sendMessage(mHandler.obtainMessage(HANDLE_DISPLAY_CHANGED, displayId, 0));
-    }
-
-    private void handleDisplayAdded(int displayId) {
         synchronized (mService.mGlobalLock) {
-            getActivityDisplayOrCreateLocked(displayId);
-            mService.startHomeActivityLocked(mCurrentUser, "displayAdded", displayId);
+            final ActivityDisplay activityDisplay = getActivityDisplay(displayId);
+            if (activityDisplay != null) {
+                activityDisplay.onDisplayChanged();
+            }
         }
     }
 
@@ -4173,7 +4182,6 @@
         // The display hasn't been added to ActivityManager yet, create a new record now.
         activityDisplay = new ActivityDisplay(this, display);
         addChild(activityDisplay, ActivityDisplay.POSITION_BOTTOM);
-        mWindowManager.onDisplayAdded(displayId);
         return activityDisplay;
     }
 
@@ -4199,47 +4207,6 @@
         mDefaultMinSizeOfResizeableTaskDp = (int) (minimalSize / dm.density);
     }
 
-    private void handleDisplayRemoved(int displayId) {
-        if (displayId == DEFAULT_DISPLAY) {
-            throw new IllegalArgumentException("Can't remove the primary display.");
-        }
-
-        synchronized (mService.mGlobalLock) {
-            final ActivityDisplay activityDisplay = getActivityDisplay(displayId);
-            if (activityDisplay == null) {
-                return;
-            }
-
-            activityDisplay.remove();
-
-            releaseSleepTokens(activityDisplay);
-        }
-    }
-
-    private void handleDisplayChanged(int displayId) {
-        synchronized (mService.mGlobalLock) {
-            ActivityDisplay activityDisplay = getActivityDisplay(displayId);
-            // TODO: The following code block should be moved into {@link ActivityDisplay}.
-            if (activityDisplay != null) {
-                // The window policy is responsible for stopping activities on the default display
-                if (displayId != Display.DEFAULT_DISPLAY) {
-                    int displayState = activityDisplay.mDisplay.getState();
-                    if (displayState == Display.STATE_OFF && activityDisplay.mOffToken == null) {
-                        activityDisplay.mOffToken =
-                                mService.acquireSleepToken("Display-off", displayId);
-                    } else if (displayState == Display.STATE_ON
-                            && activityDisplay.mOffToken != null) {
-                        activityDisplay.mOffToken.release();
-                        activityDisplay.mOffToken = null;
-                    }
-                }
-
-                activityDisplay.updateBounds();
-            }
-            mWindowManager.onDisplayChanged(displayId);
-        }
-    }
-
     SleepToken createSleepTokenLocked(String tag, int displayId) {
         final ActivityDisplay display = getActivityDisplay(displayId);
         if (display == null) {
@@ -4264,18 +4231,6 @@
         }
     }
 
-    private void releaseSleepTokens(ActivityDisplay display) {
-        if (display.mAllSleepTokens.isEmpty()) {
-            return;
-        }
-        for (SleepToken token : display.mAllSleepTokens) {
-            mSleepTokens.remove(token);
-        }
-        display.mAllSleepTokens.clear();
-
-        mService.updateSleepIfNeededLocked();
-    }
-
     private StackInfo getStackInfo(ActivityStack stack) {
         final int displayId = stack.mDisplayId;
         final ActivityDisplay display = getActivityDisplay(displayId);
@@ -4597,15 +4552,6 @@
                         }
                     }
                 } break;
-                case HANDLE_DISPLAY_ADDED: {
-                    handleDisplayAdded(msg.arg1);
-                } break;
-                case HANDLE_DISPLAY_CHANGED: {
-                    handleDisplayChanged(msg.arg1);
-                } break;
-                case HANDLE_DISPLAY_REMOVED: {
-                    handleDisplayRemoved(msg.arg1);
-                } break;
                 case LAUNCH_TASK_BEHIND_COMPLETE: {
                     synchronized (mService.mGlobalLock) {
                         ActivityRecord r = ActivityRecord.forTokenLocked((IBinder) msg.obj);
diff --git a/services/core/java/com/android/server/am/ActivityTaskManagerDebugConfig.java b/services/core/java/com/android/server/am/ActivityTaskManagerDebugConfig.java
index cf72738..4f2a254 100644
--- a/services/core/java/com/android/server/am/ActivityTaskManagerDebugConfig.java
+++ b/services/core/java/com/android/server/am/ActivityTaskManagerDebugConfig.java
@@ -69,6 +69,7 @@
     static final boolean DEBUG_METRICS = DEBUG_ALL || false;
 
     static final String POSTFIX_APP = APPEND_CATEGORY_NAME ? "_App" : "";
+    static final String POSTFIX_CLEANUP = (APPEND_CATEGORY_NAME) ? "_Cleanup" : "";
     static final String POSTFIX_IDLE = APPEND_CATEGORY_NAME ? "_Idle" : "";
     static final String POSTFIX_RELEASE = APPEND_CATEGORY_NAME ? "_Release" : "";
     static final String POSTFIX_USER_LEAVING = APPEND_CATEGORY_NAME ? "_UserLeaving" : "";
diff --git a/services/core/java/com/android/server/am/ActivityTaskManagerService.java b/services/core/java/com/android/server/am/ActivityTaskManagerService.java
index 02707fb..5b0a4a9 100644
--- a/services/core/java/com/android/server/am/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityTaskManagerService.java
@@ -273,6 +273,7 @@
 import java.lang.ref.WeakReference;
 import java.text.DateFormat;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Date;
 import java.util.HashSet;
 import java.util.List;
@@ -397,7 +398,7 @@
     // VoiceInteractionManagerService
     ComponentName mActiveVoiceInteractionServiceComponent;
 
-    private VrController mVrController;
+    VrController mVrController;
     KeyguardController mKeyguardController;
     private final ClientLifecycleManager mLifecycleManager;
     private TaskChangeNotificationController mTaskChangeNotificationController;
@@ -611,23 +612,27 @@
         GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version", GL_ES_VERSION_UNDEFINED);
     }
 
-    void onSystemReady() {
-        mHasHeavyWeightFeature = mContext.getPackageManager().hasSystemFeature(
-                PackageManager.FEATURE_CANT_SAVE_STATE);
-        mAssistUtils = new AssistUtils(mContext);
-        mVrController.onSystemReady();
-        mRecentTasks.onSystemReadyLocked();
+    public void onSystemReady() {
+        synchronized (mGlobalLock) {
+            mHasHeavyWeightFeature = mContext.getPackageManager().hasSystemFeature(
+                    PackageManager.FEATURE_CANT_SAVE_STATE);
+            mAssistUtils = new AssistUtils(mContext);
+            mVrController.onSystemReady();
+            mRecentTasks.onSystemReadyLocked();
+        }
     }
 
-    void onInitPowerManagement() {
-        mStackSupervisor.initPowerManagement();
-        final PowerManager pm = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
-        mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
-        mVoiceWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*voice*");
-        mVoiceWakeLock.setReferenceCounted(false);
+    public void onInitPowerManagement() {
+        synchronized (mGlobalLock) {
+            mStackSupervisor.initPowerManagement();
+            final PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+            mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
+            mVoiceWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*voice*");
+            mVoiceWakeLock.setReferenceCounted(false);
+        }
     }
 
-    void installSystemProviders() {
+    public void installSystemProviders() {
         mFontScaleSettingObserver = new FontScaleSettingObserver();
     }
 
@@ -736,9 +741,11 @@
         mKeyguardController = mStackSupervisor.getKeyguardController();
     }
 
-    void onActivityManagerInternalAdded() {
-        mAmInternal = LocalServices.getService(ActivityManagerInternal.class);
-        mUgmInternal = LocalServices.getService(UriGrantsManagerInternal.class);
+    public void onActivityManagerInternalAdded() {
+        synchronized (mGlobalLock) {
+            mAmInternal = LocalServices.getService(ActivityManagerInternal.class);
+            mUgmInternal = LocalServices.getService(UriGrantsManagerInternal.class);
+        }
     }
 
     int increaseConfigurationSeqLocked() {
@@ -752,14 +759,18 @@
         return supervisor;
     }
 
-    void setWindowManager(WindowManagerService wm) {
-        mWindowManager = wm;
-        mLockTaskController.setWindowManager(wm);
-        mStackSupervisor.setWindowManager(wm);
+    public void setWindowManager(WindowManagerService wm) {
+        synchronized (mGlobalLock) {
+            mWindowManager = wm;
+            mLockTaskController.setWindowManager(wm);
+            mStackSupervisor.setWindowManager(wm);
+        }
     }
 
-    void setUsageStatsManager(UsageStatsManagerInternal usageStatsManager) {
-        mUsageStatsInternal = usageStatsManager;
+    public void setUsageStatsManager(UsageStatsManagerInternal usageStatsManager) {
+        synchronized (mGlobalLock) {
+            mUsageStatsInternal = usageStatsManager;
+        }
     }
 
     UserManagerService getUserManager() {
@@ -2135,7 +2146,7 @@
         }
     }
 
-    boolean isControllerAMonkey() {
+    public boolean isControllerAMonkey() {
         synchronized (mGlobalLock) {
             return mController != null && mControllerIsAMonkey;
         }
@@ -2512,6 +2523,20 @@
     }
 
     @Override
+    public void updateLockTaskPackages(int userId, String[] packages) {
+        final int callingUid = Binder.getCallingUid();
+        if (callingUid != 0 && callingUid != SYSTEM_UID) {
+            mAmInternal.enforceCallingPermission(Manifest.permission.UPDATE_LOCK_TASK_PACKAGES,
+                    "updateLockTaskPackages()");
+        }
+        synchronized (this) {
+            if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, "Whitelisting " + userId + ":"
+                    + Arrays.toString(packages));
+            getLockTaskController().updateLockTaskPackages(userId, packages);
+        }
+    }
+
+    @Override
     public boolean isInLockTaskMode() {
         return getLockTaskModeState() != LOCK_TASK_MODE_NONE;
     }
@@ -2880,7 +2905,7 @@
         });
     }
 
-    void onScreenAwakeChanged(boolean isAwake) {
+    public void onScreenAwakeChanged(boolean isAwake) {
         mH.post(() -> {
             for (int i = mScreenObservers.size() - 1; i >= 0; i--) {
                 mScreenObservers.get(i).onAwakeStateChanged(isAwake);
@@ -4355,10 +4380,6 @@
         mRecentTasks.notifyTaskPersisterLocked(task, flush);
     }
 
-    void onTopProcChangedLocked(WindowProcessController proc) {
-        mVrController.onTopProcChangedLocked(proc);
-    }
-
     boolean isKeyguardLocked() {
         return mKeyguardController.isKeyguardLocked();
     }
@@ -4617,17 +4638,6 @@
         }
     }
 
-    void updateUserConfiguration() {
-        synchronized (mGlobalLock) {
-            final Configuration configuration = new Configuration(getGlobalConfiguration());
-            final int currentUserId = mAmInternal.getCurrentUserId();
-            Settings.System.adjustConfigurationForUser(mContext.getContentResolver(), configuration,
-                    currentUserId, Settings.System.canWrite(mContext));
-            updateConfigurationLocked(configuration, null /* starting */, false /* initLocale */,
-                    false /* persistent */, currentUserId, false /* deferResume */);
-        }
-    }
-
     private boolean updateConfigurationLocked(Configuration values, ActivityRecord starting,
             boolean initLocale, boolean persistent, int userId, boolean deferResume) {
         return updateConfigurationLocked(values, starting, initLocale, persistent, userId,
@@ -4905,15 +4915,6 @@
         }
     }
 
-    boolean canShowErrorDialogs() {
-        return mShowDialogs && !mSleeping && !mShuttingDown
-                && !mKeyguardController.isKeyguardOrAodShowing(DEFAULT_DISPLAY)
-                && !hasUserRestriction(UserManager.DISALLOW_SYSTEM_ERROR_DIALOGS,
-                mAmInternal.getCurrentUserId())
-                && !(UserManager.isDeviceInDemoMode(mContext)
-                && mAmInternal.getCurrentUser().isDemo());
-    }
-
     static long getInputDispatchingTimeoutLocked(ActivityRecord r) {
         if (r == null || !r.hasProcess()) {
             return KEY_DISPATCHING_TIMEOUT_MS;
@@ -5908,6 +5909,7 @@
                 mShuttingDown = true;
                 mStackSupervisor.prepareForShutdownLocked();
                 updateEventDispatchingLocked(booted);
+                notifyTaskPersisterLocked(null, true);
                 return mStackSupervisor.shutdownLocked(timeout);
             }
         }
@@ -6588,6 +6590,17 @@
         }
 
         @Override
+        public void dumpForOom(PrintWriter pw) {
+            synchronized (mGlobalLock) {
+                pw.println("  mHomeProcess: " + mHomeProcess);
+                pw.println("  mPreviousProcess: " + mPreviousProcess);
+                if (mHeavyWeightProcess != null) {
+                    pw.println("  mHeavyWeightProcess: " + mHeavyWeightProcess);
+                }
+            }
+        }
+
+        @Override
         public boolean canGcNow() {
             synchronized (mGlobalLock) {
                 return isSleeping() || mStackSupervisor.allResumedActivitiesIdle();
@@ -6689,5 +6702,107 @@
                 mPendingTempWhitelist.remove(uid);
             }
         }
+
+        @Override
+        public boolean handleAppCrashInActivityController(String processName, int pid,
+                String shortMsg, String longMsg, long timeMillis, String stackTrace,
+                Runnable killCrashingAppCallback) {
+            synchronized (mGlobalLock) {
+                if (mController == null) {
+                    return false;
+                }
+
+                try {
+                    if (!mController.appCrashed(processName, pid, shortMsg, longMsg, timeMillis,
+                            stackTrace)) {
+                        killCrashingAppCallback.run();
+                        return true;
+                    }
+                } catch (RemoteException e) {
+                    mController = null;
+                    Watchdog.getInstance().setActivityController(null);
+                }
+                return false;
+            }
+        }
+
+        @Override
+        public void removeRecentTasksByPackageName(String packageName, int userId) {
+            synchronized (mGlobalLock) {
+                mRecentTasks.removeTasksByPackageName(packageName, userId);
+            }
+        }
+
+        @Override
+        public void cleanupRecentTasksForUser(int userId) {
+            synchronized (mGlobalLock) {
+                mRecentTasks.cleanupLocked(userId);
+            }
+        }
+
+        @Override
+        public void loadRecentTasksForUser(int userId) {
+            synchronized (mGlobalLock) {
+                mRecentTasks.loadUserRecentsLocked(userId);
+            }
+        }
+
+        @Override
+        public void onPackagesSuspendedChanged(String[] packages, boolean suspended, int userId) {
+            synchronized (mGlobalLock) {
+                mRecentTasks.onPackagesSuspendedChanged(packages, suspended, userId);
+            }
+        }
+
+        @Override
+        public void flushRecentTasks() {
+            mRecentTasks.flush();
+        }
+
+        @Override
+        public WindowProcessController getHomeProcess() {
+            synchronized (mGlobalLock) {
+                return mHomeProcess;
+            }
+        }
+
+        @Override
+        public WindowProcessController getPreviousProcess() {
+            synchronized (mGlobalLock) {
+                return mPreviousProcess;
+            }
+        }
+
+        @Override
+        public void clearLockedTasks(String reason) {
+            synchronized (mGlobalLock) {
+                getLockTaskController().clearLockedTasks(reason);
+            }
+        }
+
+        @Override
+        public void updateUserConfiguration() {
+            synchronized (mGlobalLock) {
+                final Configuration configuration = new Configuration(getGlobalConfiguration());
+                final int currentUserId = mAmInternal.getCurrentUserId();
+                Settings.System.adjustConfigurationForUser(mContext.getContentResolver(),
+                        configuration, currentUserId, Settings.System.canWrite(mContext));
+                updateConfigurationLocked(configuration, null /* starting */,
+                        false /* initLocale */, false /* persistent */, currentUserId,
+                        false /* deferResume */);
+            }
+        }
+
+        @Override
+        public boolean canShowErrorDialogs() {
+            synchronized (mGlobalLock) {
+                return mShowDialogs && !mSleeping && !mShuttingDown
+                        && !mKeyguardController.isKeyguardOrAodShowing(DEFAULT_DISPLAY)
+                        && !hasUserRestriction(UserManager.DISALLOW_SYSTEM_ERROR_DIALOGS,
+                        mAmInternal.getCurrentUserId())
+                        && !(UserManager.isDeviceInDemoMode(mContext)
+                        && mAmInternal.getCurrentUser().isDemo());
+            }
+        }
     }
 }
diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java
index e8ec057..44f69b1 100644
--- a/services/core/java/com/android/server/am/AppErrors.java
+++ b/services/core/java/com/android/server/am/AppErrors.java
@@ -474,7 +474,7 @@
                 mService.mProcessList.removeProcessLocked(r, false, true, "crash");
                 if (taskId != INVALID_TASK_ID) {
                     try {
-                        mService.mActivityTaskManager.startActivityFromRecents(taskId,
+                        mService.startActivityFromRecents(taskId,
                                 ActivityOptions.makeBasic().toBundle());
                     } catch (IllegalArgumentException e) {
                         // Hmm...that didn't work. Task should either be in recents or associated
@@ -526,41 +526,29 @@
                                                        String shortMsg, String longMsg,
                                                        String stackTrace, long timeMillis,
                                                        int callingPid, int callingUid) {
-        if (mService.mActivityTaskManager.mController == null) {
-            return false;
-        }
+        String name = r != null ? r.processName : null;
+        int pid = r != null ? r.pid : callingPid;
+        int uid = r != null ? r.info.uid : callingUid;
 
-        try {
-            String name = r != null ? r.processName : null;
-            int pid = r != null ? r.pid : callingPid;
-            int uid = r != null ? r.info.uid : callingUid;
-            if (!mService.mActivityTaskManager.mController.appCrashed(name, pid,
-                    shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
-                if ("1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"))
-                        && "Native crash".equals(crashInfo.exceptionClassName)) {
-                    Slog.w(TAG, "Skip killing native crashed app " + name
-                            + "(" + pid + ") during testing");
-                } else {
-                    Slog.w(TAG, "Force-killing crashed app " + name
-                            + " at watcher's request");
-                    if (r != null) {
-                        if (!makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace, null))
-                        {
-                            r.kill("crash", true);
-                        }
-                    } else {
-                        // Huh.
-                        Process.killProcess(pid);
-                        ProcessList.killProcessGroup(uid, pid);
+        return mService.mAtmInternal.handleAppCrashInActivityController(
+                name, pid, shortMsg, longMsg, timeMillis, crashInfo.stackTrace, () -> {
+            if ("1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"))
+                    && "Native crash".equals(crashInfo.exceptionClassName)) {
+                Slog.w(TAG, "Skip killing native crashed app " + name
+                        + "(" + pid + ") during testing");
+            } else {
+                Slog.w(TAG, "Force-killing crashed app " + name + " at watcher's request");
+                if (r != null) {
+                    if (!makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace, null)) {
+                        r.kill("crash", true);
                     }
+                } else {
+                    // Huh.
+                    Process.killProcess(pid);
+                    ProcessList.killProcessGroup(uid, pid);
                 }
-                return true;
             }
-        } catch (RemoteException e) {
-            mService.mActivityTaskManager.mController = null;
-            Watchdog.getInstance().setActivityController(null);
-        }
-        return false;
+        });
     }
 
     private boolean makeAppCrashingLocked(ProcessRecord app,
@@ -742,7 +730,7 @@
         // with a home activity running in the process to prevent a repeatedly crashing app
         // from blocking the user to manually clear the list.
         final WindowProcessController proc = app.getWindowProcessController();
-        final WindowProcessController homeProc = mService.mActivityTaskManager.mHomeProcess;
+        final WindowProcessController homeProc = mService.mAtmInternal.getHomeProcess();
         if (proc == homeProc && proc.hasActivities()
                 && (homeProc.mInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
             proc.clearPackagePreferredForHomeActivities();
@@ -806,7 +794,7 @@
                     mService.mUserController.getCurrentUserId()) != 0;
             final boolean crashSilenced = mAppsNotReportingCrashes != null &&
                     mAppsNotReportingCrashes.contains(proc.info.packageName);
-            if ((mService.mActivityTaskManager.canShowErrorDialogs() || showBackground)
+            if ((mService.mAtmInternal.canShowErrorDialogs() || showBackground)
                     && !crashSilenced
                     && (showFirstCrash || showFirstCrashDevOption || data.repeating)) {
                 proc.crashDialog = dialogToShow = new AppErrorDialog(mContext, mService, data);
@@ -859,7 +847,7 @@
 
             boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
                     Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
-            if (mService.mActivityTaskManager.canShowErrorDialogs() || showBackground) {
+            if (mService.mAtmInternal.canShowErrorDialogs() || showBackground) {
                 dialogToShow = new AppNotRespondingDialog(mService, mContext, data);
                 proc.anrDialog = dialogToShow;
             } else {
diff --git a/services/core/java/com/android/server/am/LockTaskController.java b/services/core/java/com/android/server/am/LockTaskController.java
index 5b31d5f..d5f2d34 100644
--- a/services/core/java/com/android/server/am/LockTaskController.java
+++ b/services/core/java/com/android/server/am/LockTaskController.java
@@ -78,7 +78,8 @@
  * mode that can be launched via System UI as well as the fully locked mode that can be achieved
  * on fully managed devices.
  *
- * Note: All methods in this class should only be called with the ActivityManagerService lock held.
+ * Note: All methods in this class should only be called with the ActivityTaskManagerService lock
+ * held.
  *
  * @see Activity#startLockTask()
  * @see Activity#stopLockTask()
diff --git a/services/core/java/com/android/server/am/MemoryStatUtil.java b/services/core/java/com/android/server/am/MemoryStatUtil.java
index 85ee7e6..f77be5b 100644
--- a/services/core/java/com/android/server/am/MemoryStatUtil.java
+++ b/services/core/java/com/android/server/am/MemoryStatUtil.java
@@ -23,6 +23,8 @@
 import android.annotation.Nullable;
 import android.os.FileUtils;
 import android.os.SystemProperties;
+import android.system.Os;
+import android.system.OsConstants;
 import android.util.Slog;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -36,7 +38,7 @@
 /**
  * Static utility methods related to {@link MemoryStat}.
  */
-final class MemoryStatUtil {
+public final class MemoryStatUtil {
     /**
      * Which native processes to create {@link MemoryStat} for.
      *
@@ -71,6 +73,7 @@
 
     static final int BYTES_IN_KILOBYTE = 1024;
     static final int PAGE_SIZE = 4096;
+    static final long JIFFY_NANOS = 1_000_000_000 / Os.sysconf(OsConstants._SC_CLK_TCK);
 
     private static final String TAG = TAG_WITH_CLASS_NAME ? "MemoryStatUtil" : TAG_AM;
 
@@ -103,6 +106,7 @@
 
     private static final int PGFAULT_INDEX = 9;
     private static final int PGMAJFAULT_INDEX = 11;
+    private static final int START_TIME_INDEX = 21;
     private static final int RSS_IN_PAGES_INDEX = 23;
 
     private MemoryStatUtil() {}
@@ -114,7 +118,7 @@
      * Returns null if no stats can be read.
      */
     @Nullable
-    static MemoryStat readMemoryStatFromFilesystem(int uid, int pid) {
+    public static MemoryStat readMemoryStatFromFilesystem(int uid, int pid) {
         return hasMemcg() ? readMemoryStatFromMemcg(uid, pid) : readMemoryStatFromProcfs(pid);
     }
 
@@ -238,6 +242,7 @@
             memoryStat.pgfault = Long.parseLong(splits[PGFAULT_INDEX]);
             memoryStat.pgmajfault = Long.parseLong(splits[PGMAJFAULT_INDEX]);
             memoryStat.rssInBytes = Long.parseLong(splits[RSS_IN_PAGES_INDEX]) * PAGE_SIZE;
+            memoryStat.startTimeNanos = Long.parseLong(splits[START_TIME_INDEX]) * JIFFY_NANOS;
             return memoryStat;
         } catch (NumberFormatException e) {
             Slog.e(TAG, "Failed to parse value", e);
@@ -266,7 +271,7 @@
         return DEVICE_HAS_PER_APP_MEMCG;
     }
 
-    static final class MemoryStat {
+    public static final class MemoryStat {
         /** Number of page faults */
         long pgfault;
         /** Number of major page faults */
@@ -279,5 +284,7 @@
         long swapInBytes;
         /** Number of bytes of peak anonymous and swap cache memory */
         long rssHighWatermarkInBytes;
+        /** Device time when the processes started. */
+        long startTimeNanos;
     }
 }
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 805b979b..6741dc0 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -99,14 +99,22 @@
 import java.io.File;
 import java.io.IOException;
 import java.io.OutputStream;
+import java.io.InputStream;
 import java.io.PrintWriter;
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
+import libcore.io.IoUtils;
+
 /**
  * Activity manager code dealing with processes.
+ *
+ * Method naming convention:
+ * <ul>
+ * <li> Methods suffixed with "LS" should be called within the {@link #sLmkdSocketLock} lock.
+ * </ul>
  */
 public final class ProcessList {
     private static final String TAG = TAG_WITH_CLASS_NAME ? "ProcessList" : TAG_AM;
@@ -229,10 +237,12 @@
     // LMK_PROCPRIO <pid> <uid> <prio>
     // LMK_PROCREMOVE <pid>
     // LMK_PROCPURGE
+    // LMK_GETKILLCNT
     static final byte LMK_TARGET = 0;
     static final byte LMK_PROCPRIO = 1;
     static final byte LMK_PROCREMOVE = 2;
     static final byte LMK_PROCPURGE = 3;
+    static final byte LMK_GETKILLCNT = 4;
 
     ActivityManagerService mService = null;
 
@@ -268,9 +278,17 @@
 
     private boolean mHaveDisplaySize;
 
+    private static Object sLmkdSocketLock = new Object();
+
+    @GuardedBy("sLmkdSocketLock")
     private static LocalSocket sLmkdSocket;
+
+    @GuardedBy("sLmkdSocketLock")
     private static OutputStream sLmkdOutputStream;
 
+    @GuardedBy("sLmkdSocketLock")
+    private static InputStream sLmkdInputStream;
+
     /**
      * Temporary to avoid allocations.  Protected by main lock.
      */
@@ -505,7 +523,7 @@
                 buf.putInt(mOomAdj[i]);
             }
 
-            writeLmkd(buf);
+            writeLmkd(buf, null);
             SystemProperties.set("sys.sysctl.extra_free_kbytes", Integer.toString(reserve));
         }
         // GB: 2048,3072,4096,6144,7168,8192
@@ -978,7 +996,7 @@
         buf.putInt(pid);
         buf.putInt(uid);
         buf.putInt(amt);
-        writeLmkd(buf);
+        writeLmkd(buf, null);
         long now = SystemClock.elapsedRealtime();
         if ((now-start) > 250) {
             Slog.w("ActivityManager", "SLOW OOM ADJ: " + (now-start) + "ms for pid " + pid
@@ -997,16 +1015,38 @@
         ByteBuffer buf = ByteBuffer.allocate(4 * 2);
         buf.putInt(LMK_PROCREMOVE);
         buf.putInt(pid);
-        writeLmkd(buf);
+        writeLmkd(buf, null);
     }
 
-    private static boolean openLmkdSocket() {
+    /*
+     * {@hide}
+     */
+    public static final Integer getLmkdKillCount(int min_oom_adj, int max_oom_adj) {
+        ByteBuffer buf = ByteBuffer.allocate(4 * 3);
+        ByteBuffer repl = ByteBuffer.allocate(4 * 2);
+        buf.putInt(LMK_GETKILLCNT);
+        buf.putInt(min_oom_adj);
+        buf.putInt(max_oom_adj);
+        if (writeLmkd(buf, repl)) {
+            int i = repl.getInt();
+            if (i != LMK_GETKILLCNT) {
+                Slog.e("ActivityManager", "Failed to get kill count, code mismatch");
+                return null;
+            }
+            return new Integer(repl.getInt());
+        }
+        return null;
+    }
+
+    @GuardedBy("sLmkdSocketLock")
+    private static boolean openLmkdSocketLS() {
         try {
             sLmkdSocket = new LocalSocket(LocalSocket.SOCKET_SEQPACKET);
             sLmkdSocket.connect(
                 new LocalSocketAddress("lmkd",
                         LocalSocketAddress.Namespace.RESERVED));
             sLmkdOutputStream = sLmkdSocket.getOutputStream();
+            sLmkdInputStream = sLmkdSocket.getInputStream();
         } catch (IOException ex) {
             Slog.w(TAG, "lowmemorykiller daemon socket open failed");
             sLmkdSocket = null;
@@ -1017,47 +1057,63 @@
     }
 
     // Never call directly, use writeLmkd() instead
-    private static boolean writeLmkdCommand(ByteBuffer buf) {
+    @GuardedBy("sLmkdSocketLock")
+    private static boolean writeLmkdCommandLS(ByteBuffer buf) {
         try {
             sLmkdOutputStream.write(buf.array(), 0, buf.position());
         } catch (IOException ex) {
             Slog.w(TAG, "Error writing to lowmemorykiller socket");
-
-            try {
-                sLmkdSocket.close();
-            } catch (IOException ex2) {
-            }
-
+            IoUtils.closeQuietly(sLmkdSocket);
             sLmkdSocket = null;
             return false;
         }
         return true;
     }
 
-    private static void writeLmkd(ByteBuffer buf) {
-
-        for (int i = 0; i < 3; i++) {
-            if (sLmkdSocket == null) {
-                if (openLmkdSocket() == false) {
-                    try {
-                        Thread.sleep(1000);
-                    } catch (InterruptedException ie) {
-                    }
-                    continue;
-                }
-
-                // Purge any previously registered pids
-                ByteBuffer purge_buf = ByteBuffer.allocate(4);
-                purge_buf.putInt(LMK_PROCPURGE);
-                if (writeLmkdCommand(purge_buf) == false) {
-                    // Write failed, skip the rest and retry
-                    continue;
-                }
+    // Never call directly, use writeLmkd() instead
+    @GuardedBy("sLmkdSocketLock")
+    private static boolean readLmkdReplyLS(ByteBuffer buf) {
+        int len;
+        try {
+            len = sLmkdInputStream.read(buf.array(), 0, buf.array().length);
+            if (len == buf.array().length) {
+                return true;
             }
-            if (writeLmkdCommand(buf)) {
-                return;
+        } catch (IOException ex) {
+            Slog.w(TAG, "Error reading from lowmemorykiller socket");
+        }
+
+        IoUtils.closeQuietly(sLmkdSocket);
+        sLmkdSocket = null;
+        return false;
+    }
+
+    private static boolean writeLmkd(ByteBuffer buf, ByteBuffer repl) {
+        synchronized (sLmkdSocketLock) {
+            for (int i = 0; i < 3; i++) {
+                if (sLmkdSocket == null) {
+                    if (openLmkdSocketLS() == false) {
+                        try {
+                            Thread.sleep(1000);
+                        } catch (InterruptedException ie) {
+                        }
+                        continue;
+                    }
+
+                    // Purge any previously registered pids
+                    ByteBuffer purge_buf = ByteBuffer.allocate(4);
+                    purge_buf.putInt(LMK_PROCPURGE);
+                    if (writeLmkdCommandLS(purge_buf) == false) {
+                        // Write failed, skip the rest and retry
+                        continue;
+                    }
+                }
+                if (writeLmkdCommandLS(buf) && (repl == null || readLmkdReplyLS(repl))) {
+                    return true;
+                }
             }
         }
+        return false;
     }
 
     static void killProcessGroup(int uid, int pid) {
@@ -1982,8 +2038,7 @@
             StatsLog.write(StatsLog.ISOLATED_UID_CHANGED, info.uid, uid,
                     StatsLog.ISOLATED_UID_CHANGED__EVENT__CREATED);
         }
-        final ProcessRecord r = new ProcessRecord(mService, info, proc, uid,
-                mService.getGlobalConfiguration());
+        final ProcessRecord r = new ProcessRecord(mService, info, proc, uid);
 
         if (!mService.mBooted && !mService.mBooting
                 && userId == UserHandle.USER_SYSTEM
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index fa7a08b..683754c 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -535,7 +535,7 @@
     }
 
     ProcessRecord(ActivityManagerService _service, ApplicationInfo _info, String _processName,
-            int _uid, Configuration config) {
+            int _uid) {
         mService = _service;
         info = _info;
         isolated = _info.uid != _uid;
@@ -549,7 +549,7 @@
         removed = false;
         lastStateTime = lastPssTime = nextPssTime = SystemClock.uptimeMillis();
         mWindowProcessController = new WindowProcessController(
-                mService.mActivityTaskManager, info, processName, uid, userId, this, this, config);
+                mService.mActivityTaskManager, info, processName, uid, userId, this, this);
         pkgList.put(_info.packageName, new ProcessStats.ProcessStateHolder(_info.longVersionCode));
     }
 
@@ -1244,19 +1244,7 @@
         ArrayList<Integer> firstPids = new ArrayList<>(5);
         SparseArray<Boolean> lastPids = new SparseArray<>(20);
 
-        if (mService.mActivityTaskManager.mController != null) {
-            try {
-                // 0 == continue, -1 = kill process immediately
-                int res = mService.mActivityTaskManager.mController.appEarlyNotResponding(
-                        processName, pid, annotation);
-                if (res < 0 && pid != MY_PID) {
-                    kill("anr", true);
-                }
-            } catch (RemoteException e) {
-                mService.mActivityTaskManager.mController = null;
-                Watchdog.getInstance().setActivityController(null);
-            }
-        }
+        mWindowProcessController.appEarlyNotResponding(annotation, () -> kill("anr", true));
 
         long anrTime = SystemClock.uptimeMillis();
         if (ActivityManagerService.MONITOR_CPU_USAGE) {
@@ -1271,7 +1259,7 @@
 
         synchronized (mService) {
             // PowerManager.reboot() can block for a long time, so ignore ANRs while shutting down.
-            if (mService.mActivityTaskManager.mShuttingDown) {
+            if (mService.mAtmInternal.isShuttingDown()) {
                 Slog.i(TAG, "During shutdown skipping ANR: " + this + " " + annotation);
                 return;
             } else if (isNotResponding()) {
@@ -1412,25 +1400,13 @@
         mService.addErrorToDropBox("anr", this, processName, activityShortComponentName,
                 parentShortComponentName, parentPr, annotation, cpuInfo, tracesFile, null);
 
-        if (mService.mActivityTaskManager.mController != null) {
-            try {
-                // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
-                int res = mService.mActivityTaskManager.mController.appNotResponding(
-                        processName, pid, info.toString());
-                if (res != 0) {
-                    if (res < 0 && pid != MY_PID) {
-                        kill("anr", true);
-                    } else {
-                        synchronized (mService) {
-                            mService.mServices.scheduleServiceTimeoutLocked(this);
-                        }
+        if (mWindowProcessController.appNotResponding(info.toString(), () -> kill("anr", true),
+                () -> {
+                    synchronized (mService) {
+                        mService.mServices.scheduleServiceTimeoutLocked(this);
                     }
-                    return;
-                }
-            } catch (RemoteException e) {
-                mService.mActivityTaskManager.mController = null;
-                Watchdog.getInstance().setActivityController(null);
-            }
+                })) {
+            return;
         }
 
         synchronized (mService) {
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index d2dd3db..353f787 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -22,14 +22,15 @@
 import static android.app.ActivityManager.USER_OP_ERROR_RELATED_USERS_CANNOT_STOP;
 import static android.app.ActivityManager.USER_OP_IS_CURRENT;
 import static android.app.ActivityManager.USER_OP_SUCCESS;
-import static android.os.Process.SHELL_UID;
-import static android.os.Process.SYSTEM_UID;
-import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_MU;
-import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
-import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static android.app.ActivityManagerInternal.ALLOW_FULL_ONLY;
 import static android.app.ActivityManagerInternal.ALLOW_NON_FULL;
 import static android.app.ActivityManagerInternal.ALLOW_NON_FULL_IN_PROFILE;
+import static android.os.Process.SHELL_UID;
+import static android.os.Process.SYSTEM_UID;
+
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_MU;
+import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
+import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.am.ActivityManagerService.MY_PID;
 import static com.android.server.am.UserState.STATE_BOOTING;
 import static com.android.server.am.UserState.STATE_RUNNING_LOCKED;
@@ -40,7 +41,6 @@
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.app.ActivityManager;
-import com.android.server.wm.ActivityTaskManagerInternal;
 import android.app.AppGlobals;
 import android.app.AppOpsManager;
 import android.app.Dialog;
@@ -99,6 +99,7 @@
 import com.android.server.LocalServices;
 import com.android.server.SystemServiceManager;
 import com.android.server.pm.UserManagerService;
+import com.android.server.wm.ActivityTaskManagerInternal;
 import com.android.server.wm.WindowManagerService;
 
 import java.io.PrintWriter;
@@ -549,7 +550,8 @@
         final Intent bootIntent = new Intent(Intent.ACTION_BOOT_COMPLETED, null);
         bootIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
         bootIntent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT
-                | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
+                | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND
+                | Intent.FLAG_RECEIVER_OFFLOAD);
         mInjector.broadcastIntent(bootIntent, null, new IIntentReceiver.Stub() {
                     @Override
                     public void performReceive(Intent intent, int resultCode, String data,
@@ -2189,7 +2191,7 @@
         }
 
         void updateUserConfiguration() {
-            mService.mActivityTaskManager.updateUserConfiguration();
+            mService.mAtmInternal.updateUserConfiguration();
         }
 
         void clearBroadcastQueueForUser(int userId) {
@@ -2199,9 +2201,7 @@
         }
 
         void loadUserRecents(int userId) {
-            synchronized (mService) {
-                mService.mActivityTaskManager.getRecentTasks().loadUserRecentsLocked(userId);
-            }
+            mService.mAtmInternal.loadRecentTasksForUser(userId);
         }
 
         void startPersistentApps(int matchFlags) {
@@ -2254,13 +2254,11 @@
         }
 
         protected void clearAllLockedTasks(String reason) {
-            synchronized (mService) {
-                mService.mActivityTaskManager.getLockTaskController().clearLockedTasks(reason);
-            }
+            mService.mAtmInternal.clearLockedTasks(reason);
         }
 
         protected boolean isCallerRecents(int callingUid) {
-            return mService.mActivityTaskManager.getRecentTasks().isCallerRecents(callingUid);
+            return mService.mAtmInternal.isCallerRecents(callingUid);
         }
     }
 }
diff --git a/services/core/java/com/android/server/am/WindowProcessController.java b/services/core/java/com/android/server/am/WindowProcessController.java
index 94f1002..1dd8c52 100644
--- a/services/core/java/com/android/server/am/WindowProcessController.java
+++ b/services/core/java/com/android/server/am/WindowProcessController.java
@@ -19,6 +19,7 @@
 import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
 import static android.view.Display.INVALID_DISPLAY;
 
+import static com.android.server.am.ActivityManagerService.MY_PID;
 import static com.android.server.am.ActivityStack.ActivityState.DESTROYED;
 import static com.android.server.am.ActivityStack.ActivityState.DESTROYING;
 import static com.android.server.am.ActivityStack.ActivityState.PAUSED;
@@ -53,6 +54,7 @@
 
 import com.android.internal.app.HeavyWeightSwitcherActivity;
 import com.android.internal.util.function.pooled.PooledLambda;
+import com.android.server.Watchdog;
 import com.android.server.wm.ConfigurationContainer;
 import com.android.server.wm.ConfigurationContainerListener;
 
@@ -155,8 +157,7 @@
     private int mDisplayId;
 
     WindowProcessController(ActivityTaskManagerService atm, ApplicationInfo info, String name,
-            int uid, int userId, Object owner, WindowProcessListener listener,
-            Configuration config) {
+            int uid, int userId, Object owner, WindowProcessListener listener) {
         mInfo = info;
         mName = name;
         mUid = uid;
@@ -166,8 +167,8 @@
         mAtm = atm;
         mLastReportedConfiguration = new Configuration();
         mDisplayId = INVALID_DISPLAY;
-        if (config != null) {
-            onConfigurationChanged(config);
+        if (atm != null) {
+            onConfigurationChanged(atm.getGlobalConfiguration());
         }
     }
 
@@ -807,6 +808,69 @@
         }
     }
 
+    public void appEarlyNotResponding(String annotation, Runnable killAppCallback) {
+        synchronized (mAtm.mGlobalLock) {
+            if (mAtm.mController == null) {
+                return;
+            }
+
+            try {
+                // 0 == continue, -1 = kill process immediately
+                int res = mAtm.mController.appEarlyNotResponding(mName, mPid, annotation);
+                if (res < 0 && mPid != MY_PID) {
+                    killAppCallback.run();
+                }
+            } catch (RemoteException e) {
+                mAtm.mController = null;
+                Watchdog.getInstance().setActivityController(null);
+            }
+        }
+    }
+
+    public boolean appNotResponding(String info, Runnable killAppCallback,
+            Runnable serviceTimeoutCallback) {
+        synchronized (mAtm.mGlobalLock) {
+            if (mAtm.mController == null) {
+                return false;
+            }
+
+            try {
+                // 0 == show dialog, 1 = keep waiting, -1 = kill process immediately
+                int res = mAtm.mController.appNotResponding(mName, mPid, info);
+                if (res != 0) {
+                    if (res < 0 && mPid != MY_PID) {
+                        killAppCallback.run();
+                    } else {
+                        serviceTimeoutCallback.run();
+                    }
+                    return true;
+                }
+            } catch (RemoteException e) {
+                mAtm.mController = null;
+                Watchdog.getInstance().setActivityController(null);
+            }
+            return false;
+        }
+    }
+
+    public void onTopProcChanged() {
+        synchronized (mAtm.mGlobalLock) {
+            mAtm.mVrController.onTopProcChangedLocked(this);
+        }
+    }
+
+    public boolean isHomeProcess() {
+        synchronized (mAtm.mGlobalLock) {
+            return this == mAtm.mHomeProcess;
+        }
+    }
+
+    public boolean isPreviousProcess() {
+        synchronized (mAtm.mGlobalLock) {
+            return this == mAtm.mPreviousProcess;
+        }
+    }
+
     public void dump(PrintWriter pw, String prefix) {
         synchronized (mAtm.mGlobalLock) {
             if (mActivities.size() > 0) {
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index f56d8e6..5103974 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -819,9 +819,9 @@
                 new String("AudioService ctor"),
                 0);
 
-        mSafeMediaVolumeState = new Integer(Settings.Global.getInt(mContentResolver,
-                                                        Settings.Global.AUDIO_SAFE_VOLUME_STATE,
-                                                        SAFE_MEDIA_VOLUME_NOT_CONFIGURED));
+        mSafeMediaVolumeState = Settings.Global.getInt(mContentResolver,
+                                            Settings.Global.AUDIO_SAFE_VOLUME_STATE,
+                                            SAFE_MEDIA_VOLUME_NOT_CONFIGURED);
         // The default safe volume index read here will be replaced by the actual value when
         // the mcc is read by onConfigureSafeVolume()
         mSafeMediaVolumeIndex = mContext.getResources().getInteger(
@@ -1657,7 +1657,7 @@
         }
 
         // reset any pending volume command
-        synchronized (mSafeMediaVolumeState) {
+        synchronized (mSafeMediaVolumeStateLock) {
             mPendingVolumeCommand = null;
         }
 
@@ -2017,7 +2017,7 @@
             return;
         }
 
-        synchronized (mSafeMediaVolumeState) {
+        synchronized (mSafeMediaVolumeStateLock) {
             // reset any pending volume command
             mPendingVolumeCommand = null;
 
@@ -3259,7 +3259,7 @@
         checkAllAliasStreamVolumes();
         checkMuteAffectedStreams();
 
-        synchronized (mSafeMediaVolumeState) {
+        synchronized (mSafeMediaVolumeStateLock) {
             mMusicActiveMs = MathUtils.constrain(Settings.Secure.getIntForUser(mContentResolver,
                     Settings.Secure.UNSAFE_VOLUME_MUSIC_ACTIVE_MS, 0, UserHandle.USER_CURRENT),
                     0, UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX);
@@ -4058,7 +4058,7 @@
     }
 
     private void onCheckMusicActive(String caller) {
-        synchronized (mSafeMediaVolumeState) {
+        synchronized (mSafeMediaVolumeStateLock) {
             if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_INACTIVE) {
                 int device = getDeviceForStream(AudioSystem.STREAM_MUSIC);
 
@@ -4119,7 +4119,7 @@
     }
 
     private void onConfigureSafeVolume(boolean force, String caller) {
-        synchronized (mSafeMediaVolumeState) {
+        synchronized (mSafeMediaVolumeStateLock) {
             int mcc = mContext.getResources().getConfiguration().mcc;
             if ((mMcc != mcc) || ((mMcc == 0) && force)) {
                 mSafeMediaVolumeIndex = mContext.getResources().getInteger(
@@ -6975,7 +6975,8 @@
     private static final int SAFE_MEDIA_VOLUME_DISABLED = 1;
     private static final int SAFE_MEDIA_VOLUME_INACTIVE = 2;  // confirmed
     private static final int SAFE_MEDIA_VOLUME_ACTIVE = 3;  // unconfirmed
-    private Integer mSafeMediaVolumeState;
+    private int mSafeMediaVolumeState;
+    private final Object mSafeMediaVolumeStateLock = new Object();
 
     private int mMcc = 0;
     // mSafeMediaVolumeIndex is the cached value of config_safe_media_volume_index property
@@ -7015,7 +7016,7 @@
     }
 
     private void setSafeMediaVolumeEnabled(boolean on, String caller) {
-        synchronized (mSafeMediaVolumeState) {
+        synchronized (mSafeMediaVolumeStateLock) {
             if ((mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_NOT_CONFIGURED) &&
                     (mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_DISABLED)) {
                 if (on && (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_INACTIVE)) {
@@ -7063,7 +7064,7 @@
     }
 
     private boolean checkSafeMediaVolume(int streamType, int index, int device) {
-        synchronized (mSafeMediaVolumeState) {
+        synchronized (mSafeMediaVolumeStateLock) {
             if ((mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE) &&
                     (mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC) &&
                     ((device & mSafeMediaVolumeDevices) != 0) &&
@@ -7077,7 +7078,7 @@
     @Override
     public void disableSafeMediaVolume(String callingPackage) {
         enforceVolumeController("disable the safe media volume");
-        synchronized (mSafeMediaVolumeState) {
+        synchronized (mSafeMediaVolumeStateLock) {
             setSafeMediaVolumeEnabled(false, callingPackage);
             if (mPendingVolumeCommand != null) {
                 onSetStreamVolume(mPendingVolumeCommand.mStreamType,
@@ -7359,7 +7360,7 @@
         mVolumeLogger.dump(pw);
     }
 
-    private static String safeMediaVolumeStateToString(Integer state) {
+    private static String safeMediaVolumeStateToString(int state) {
         switch(state) {
             case SAFE_MEDIA_VOLUME_NOT_CONFIGURED: return "SAFE_MEDIA_VOLUME_NOT_CONFIGURED";
             case SAFE_MEDIA_VOLUME_DISABLED: return "SAFE_MEDIA_VOLUME_DISABLED";
diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java
index b80dca6..278c55f 100644
--- a/services/core/java/com/android/server/biometrics/BiometricService.java
+++ b/services/core/java/com/android/server/biometrics/BiometricService.java
@@ -272,7 +272,7 @@
                 final int error = result.second;
 
                 // Check for errors, notify callback, and return
-                if (error != BiometricConstants.BIOMETRIC_ERROR_NONE) {
+                if (error != BiometricConstants.BIOMETRIC_SUCCESS) {
                     try {
                         final String hardwareUnavailable =
                                 getContext().getString(R.string.biometric_error_hw_unavailable);
@@ -540,7 +540,7 @@
             return new Pair<>(BIOMETRIC_NONE, BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE);
         }
 
-        return new Pair<>(modality, BiometricConstants.BIOMETRIC_ERROR_NONE);
+        return new Pair<>(modality, BiometricConstants.BIOMETRIC_SUCCESS);
     }
 
     private boolean isEnabledForApp(int modality) {
diff --git a/services/core/java/com/android/server/biometrics/face/FaceService.java b/services/core/java/com/android/server/biometrics/face/FaceService.java
index f6af52a..5d4263b 100644
--- a/services/core/java/com/android/server/biometrics/face/FaceService.java
+++ b/services/core/java/com/android/server/biometrics/face/FaceService.java
@@ -362,7 +362,7 @@
                 result = mDaemon != null ? mDaemon.setRequireAttention(requireAttention, byteToken)
                         : Status.INTERNAL_ERROR;
             } catch (RemoteException e) {
-                Slog.e(getTag(), "Unable to setRequireAttention to " + requireAttention);
+                Slog.e(getTag(), "Unable to setRequireAttention to " + requireAttention, e);
                 result = Status.INTERNAL_ERROR;
             }
 
@@ -382,10 +382,23 @@
             try {
                 result = mDaemon != null ? mDaemon.getRequireAttention(byteToken).value : true;
             } catch (RemoteException e) {
-                Slog.e(getTag(), "Unable to getRequireAttention");
+                Slog.e(getTag(), "Unable to getRequireAttention", e);
             }
             return result;
         }
+
+        @Override
+        public void userActivity() {
+            checkPermission(MANAGE_BIOMETRIC);
+
+            if (mDaemon != null) {
+                try {
+                    mDaemon.userActivity();
+                } catch (RemoteException e) {
+                    Slog.e(getTag(), "Unable to send userActivity", e);
+                }
+            }
+        }
     }
 
     /**
diff --git a/services/core/java/com/android/server/connectivity/Nat464Xlat.java b/services/core/java/com/android/server/connectivity/Nat464Xlat.java
index f523d59..f96f6e8 100644
--- a/services/core/java/com/android/server/connectivity/Nat464Xlat.java
+++ b/services/core/java/com/android/server/connectivity/Nat464Xlat.java
@@ -93,7 +93,9 @@
         // We only run clat on networks that don't have a native IPv4 address.
         final boolean hasIPv4Address =
                 (nai.linkProperties != null) && nai.linkProperties.hasIPv4Address();
-        return supported && connected && !hasIPv4Address;
+        final boolean skip464xlat =
+                (nai.networkMisc != null) && nai.networkMisc.skip464xlat;
+        return supported && connected && !hasIPv4Address && !skip464xlat;
     }
 
     /**
diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
index 30659c1..de4f2d8 100644
--- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java
@@ -227,6 +227,12 @@
     public static final int EVENT_PRIVATE_DNS_CONFIG_RESOLVED = BASE + 14;
     private static final int CMD_EVALUATE_PRIVATE_DNS = BASE + 15;
 
+    /**
+     * Message to self indicating captive portal detection is completed.
+     * obj = CaptivePortalProbeResult for detection result;
+     */
+    public static final int CMD_PROBE_COMPLETE = BASE + 16;
+
     // Start mReevaluateDelayMs at this value and double.
     private static final int INITIAL_REEVALUATE_DELAY_MS = 1000;
     private static final int MAX_REEVALUATE_DELAY_MS = 10*60*1000;
@@ -290,6 +296,7 @@
     private final State mEvaluatingState = new EvaluatingState();
     private final State mCaptivePortalState = new CaptivePortalState();
     private final State mEvaluatingPrivateDnsState = new EvaluatingPrivateDnsState();
+    private final State mProbingState = new ProbingState();
 
     private CustomIntentReceiver mLaunchCaptivePortalAppBroadcastReceiver = null;
 
@@ -304,6 +311,9 @@
     private final Random mRandom;
     private int mNextFallbackUrlIndex = 0;
 
+    private int mReevaluateDelayMs = INITIAL_REEVALUATE_DELAY_MS;
+    private int mEvaluateAttempts = 0;
+
     public NetworkMonitor(Context context, Handler handler, NetworkAgentInfo networkAgentInfo,
             NetworkRequest defaultRequest) {
         this(context, handler, networkAgentInfo, defaultRequest, new IpConnectivityLog(),
@@ -334,6 +344,7 @@
         addState(mDefaultState);
         addState(mMaybeNotifyState, mDefaultState);
             addState(mEvaluatingState, mMaybeNotifyState);
+                addState(mProbingState, mEvaluatingState);
             addState(mCaptivePortalState, mMaybeNotifyState);
         addState(mEvaluatingPrivateDnsState, mDefaultState);
         addState(mValidatedState, mDefaultState);
@@ -582,9 +593,6 @@
     // Being in the EvaluatingState State indicates the Network is being evaluated for internet
     // connectivity, or that the user has indicated that this network is unwanted.
     private class EvaluatingState extends State {
-        private int mReevaluateDelayMs;
-        private int mAttempts;
-
         @Override
         public void enter() {
             // If we have already started to track time spent in EvaluatingState
@@ -599,7 +607,7 @@
                 mUidResponsibleForReeval = INVALID_UID;
             }
             mReevaluateDelayMs = INITIAL_REEVALUATE_DELAY_MS;
-            mAttempts = 0;
+            mEvaluateAttempts = 0;
         }
 
         @Override
@@ -630,42 +638,15 @@
                         transitionTo(mValidatedState);
                         return HANDLED;
                     }
-                    mAttempts++;
-                    // Note: This call to isCaptivePortal() could take up to a minute. Resolving the
-                    // server's IP addresses could hit the DNS timeout, and attempting connections
-                    // to each of the server's several IP addresses (currently one IPv4 and one
-                    // IPv6) could each take SOCKET_TIMEOUT_MS.  During this time this StateMachine
-                    // will be unresponsive. isCaptivePortal() could be executed on another Thread
-                    // if this is found to cause problems.
-                    CaptivePortalProbeResult probeResult = isCaptivePortal();
-                    if (probeResult.isSuccessful()) {
-                        // Transit EvaluatingPrivateDnsState to get to Validated
-                        // state (even if no Private DNS validation required).
-                        transitionTo(mEvaluatingPrivateDnsState);
-                    } else if (probeResult.isPortal()) {
-                        notifyNetworkTestResultInvalid(probeResult.redirectUrl);
-                        mLastPortalProbeResult = probeResult;
-                        transitionTo(mCaptivePortalState);
-                    } else {
-                        final Message msg = obtainMessage(CMD_REEVALUATE, ++mReevaluateToken, 0);
-                        sendMessageDelayed(msg, mReevaluateDelayMs);
-                        logNetworkEvent(NetworkEvent.NETWORK_VALIDATION_FAILED);
-                        notifyNetworkTestResultInvalid(probeResult.redirectUrl);
-                        if (mAttempts >= BLAME_FOR_EVALUATION_ATTEMPTS) {
-                            // Don't continue to blame UID forever.
-                            TrafficStats.clearThreadStatsUid();
-                        }
-                        mReevaluateDelayMs *= 2;
-                        if (mReevaluateDelayMs > MAX_REEVALUATE_DELAY_MS) {
-                            mReevaluateDelayMs = MAX_REEVALUATE_DELAY_MS;
-                        }
-                    }
+                    mEvaluateAttempts++;
+
+                    transitionTo(mProbingState);
                     return HANDLED;
                 case CMD_FORCE_REEVALUATION:
                     // Before IGNORE_REEVALUATE_ATTEMPTS attempts are made,
                     // ignore any re-evaluation requests. After, restart the
                     // evaluation process via EvaluatingState#enter.
-                    return (mAttempts < IGNORE_REEVALUATE_ATTEMPTS) ? HANDLED : NOT_HANDLED;
+                    return (mEvaluateAttempts < IGNORE_REEVALUATE_ATTEMPTS) ? HANDLED : NOT_HANDLED;
                 default:
                     return NOT_HANDLED;
             }
@@ -852,6 +833,76 @@
         }
     }
 
+    private class ProbingState extends State {
+        private Thread mThread;
+
+        @Override
+        public void enter() {
+            mThread = new Thread(() -> sendMessage(obtainMessage(CMD_PROBE_COMPLETE,
+                    isCaptivePortal())));
+            mThread.start();
+        }
+
+        @Override
+        public boolean processMessage(Message message) {
+            switch (message.what) {
+                case CMD_PROBE_COMPLETE:
+                    // Currently, it's not possible to exit this state without mThread having
+                    // terminated. Therefore, this state can never get CMD_PROBE_COMPLETE from a
+                    // stale thread that is not mThread.
+                    // TODO: As soon as it's possible to exit this state without mThread having
+                    // terminated, ensure that CMD_PROBE_COMPLETE from stale threads are ignored.
+                    // This could be done via a sequence number, or by changing mThread to a class
+                    // that has a stopped volatile boolean or AtomicBoolean.
+                    final CaptivePortalProbeResult probeResult =
+                            (CaptivePortalProbeResult) message.obj;
+
+                    if (probeResult.isSuccessful()) {
+                        // Transit EvaluatingPrivateDnsState to get to Validated
+                        // state (even if no Private DNS validation required).
+                        transitionTo(mEvaluatingPrivateDnsState);
+                    } else if (probeResult.isPortal()) {
+                        notifyNetworkTestResultInvalid(probeResult.redirectUrl);
+                        mLastPortalProbeResult = probeResult;
+                        transitionTo(mCaptivePortalState);
+                    } else {
+                        final Message msg = obtainMessage(CMD_REEVALUATE, ++mReevaluateToken, 0);
+                        sendMessageDelayed(msg, mReevaluateDelayMs);
+                        logNetworkEvent(NetworkEvent.NETWORK_VALIDATION_FAILED);
+                        notifyNetworkTestResultInvalid(probeResult.redirectUrl);
+                        if (mEvaluateAttempts >= BLAME_FOR_EVALUATION_ATTEMPTS) {
+                            // Don't continue to blame UID forever.
+                            TrafficStats.clearThreadStatsUid();
+                        }
+                        mReevaluateDelayMs *= 2;
+                        if (mReevaluateDelayMs > MAX_REEVALUATE_DELAY_MS) {
+                            mReevaluateDelayMs = MAX_REEVALUATE_DELAY_MS;
+                        }
+                    }
+                    return HANDLED;
+                case CMD_REEVALUATE:
+                    // Leave the event to EvaluatingState. Defer this message will result in reset
+                    // of mReevaluateDelayMs and mEvaluateAttempts.
+                    return NOT_HANDLED;
+                default:
+                    // TODO: Some events may able to handle in this state, instead of deferring to
+                    // next state.
+                    deferMessage(message);
+                    return HANDLED;
+            }
+        }
+
+        @Override
+        public void exit() {
+            // If StateMachine get here, the probe started in enter() is guaranteed to have
+            // completed, because in this state, all messages except CMD_PROBE_COMPLETE and
+            // CMD_REEVALUATE are deferred. CMD_REEVALUATE cannot be in the queue, because it is
+            // only ever sent in EvaluatingState#enter, and the StateMachine reach this state by
+            // processing it. Therefore, there is no need to stop the thread.
+            mThread = null;
+        }
+    }
+
     // Limits the list of IP addresses returned by getAllByName or tried by openConnection to at
     // most one per address family. This ensures we only wait up to 20 seconds for TCP connections
     // to complete, regardless of how many IP addresses a host has.
@@ -1031,10 +1082,10 @@
                 result.isPortal() /* isCaptivePortal */,
                 startTime, endTime);
 
-        log("isCaptivePortal: isSuccessful()=" + result.isSuccessful() +
-                " isPortal()=" + result.isPortal() +
-                " RedirectUrl=" + result.redirectUrl +
-                " StartTime=" + startTime + " EndTime=" + endTime);
+        log("isCaptivePortal: isSuccessful()=" + result.isSuccessful()
+                + " isPortal()=" + result.isPortal()
+                + " RedirectUrl=" + result.redirectUrl
+                + " Time=" + (endTime - startTime) + "ms");
 
         return result;
     }
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 48082b6..b7ed2f9 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -381,6 +381,15 @@
     }
 
     /**
+     * Check whether to prevent all traffic outside of a VPN even when the VPN is not connected.
+     *
+     * @return {@code true} if VPN lockdown is enabled.
+     */
+    public boolean getLockdown() {
+        return mLockdown;
+    }
+
+    /**
      * Checks if a VPN app supports always-on mode.
      *
      * In order to support the always-on feature, an app has to
@@ -1533,17 +1542,15 @@
     }
 
     /**
-     * @return {@code true} if {@param uid} is blocked by an always-on VPN.
-     *         A UID is blocked if it's included in one of the mBlockedUsers ranges and the VPN is
-     *         not connected, or if the VPN is connected but does not apply to the UID.
+     * @param uid The target uid.
      *
+     * @return {@code true} if {@code uid} is included in one of the mBlockedUsers ranges and the
+     * VPN is not connected, or if the VPN is connected but does not apply to the {@code uid}.
+     *
+     * @apiNote This method don't check VPN lockdown status.
      * @see #mBlockedUsers
      */
     public synchronized boolean isBlockingUid(int uid) {
-        if (!mLockdown) {
-            return false;
-        }
-
         if (mNetworkInfo.isConnected()) {
             return !appliesToUid(uid);
         } else {
diff --git a/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java b/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java
index f488be7..3e5d5aa 100644
--- a/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java
+++ b/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java
@@ -399,9 +399,12 @@
         @Override
         public void onLinkPropertiesChanged(Network network, LinkProperties newLp) {
             handleLinkProp(network, newLp);
-            // TODO(b/110335330): reduce the number of times this is called by
-            // only recomputing on the LISTEN_ALL callback.
-            recomputeLocalPrefixes();
+            // Any non-LISTEN_ALL callback will necessarily concern a network that will
+            // also match the LISTEN_ALL callback by construction of the LISTEN_ALL callback.
+            // So it's not useful to do this work for non-LISTEN_ALL callbacks.
+            if (mCallbackType == CALLBACK_LISTEN_ALL) {
+                recomputeLocalPrefixes();
+            }
         }
 
         @Override
@@ -417,9 +420,12 @@
         @Override
         public void onLost(Network network) {
             handleLost(mCallbackType, network);
-            // TODO(b/110335330): reduce the number of times this is called by
-            // only recomputing on the LISTEN_ALL callback.
-            recomputeLocalPrefixes();
+            // Any non-LISTEN_ALL callback will necessarily concern a network that will
+            // also match the LISTEN_ALL callback by construction of the LISTEN_ALL callback.
+            // So it's not useful to do this work for non-LISTEN_ALL callbacks.
+            if (mCallbackType == CALLBACK_LISTEN_ALL) {
+                recomputeLocalPrefixes();
+            }
         }
     }
 
diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java
index 5698fdf..5ed6263 100644
--- a/services/core/java/com/android/server/content/ContentService.java
+++ b/services/core/java/com/android/server/content/ContentService.java
@@ -1615,6 +1615,15 @@
     }
 
     @Override
+    public void onDbCorruption(String tag, String message, String stacktrace) {
+        Slog.e(tag, message);
+        Slog.e(tag, "at " + stacktrace);
+
+        // TODO: Figure out a better way to report it. b/117886381
+        Slog.wtf(tag, message);
+    }
+
+    @Override
     public void onShellCommand(FileDescriptor in, FileDescriptor out,
             FileDescriptor err, String[] args, ShellCallback callback,
             ResultReceiver resultReceiver) {
diff --git a/services/core/java/com/android/server/content/SyncLogger.java b/services/core/java/com/android/server/content/SyncLogger.java
index 8c35e27..5cbe5b9 100644
--- a/services/core/java/com/android/server/content/SyncLogger.java
+++ b/services/core/java/com/android/server/content/SyncLogger.java
@@ -20,12 +20,17 @@
 import android.os.Build;
 import android.os.Environment;
 import android.os.FileUtils;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
 import android.os.SystemProperties;
 import android.text.format.DateUtils;
 import android.util.Log;
 import android.util.Slog;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.IntPair;
+import com.android.server.IoThread;
 
 import libcore.io.IoUtils;
 
@@ -65,10 +70,11 @@
      */
     public static synchronized SyncLogger getInstance() {
         if (sInstance == null) {
+            final String flag = SystemProperties.get("debug.synclog");
             final boolean enable =
-                    Build.IS_DEBUGGABLE
-                    || "1".equals(SystemProperties.get("debug.synclog"))
-                    || Log.isLoggable(TAG, Log.VERBOSE);
+                    (Build.IS_DEBUGGABLE
+                    || "1".equals(flag)
+                    || Log.isLoggable(TAG, Log.VERBOSE)) && !"0".equals(flag);
             if (enable) {
                 sInstance = new RotatingFileLogger();
             } else {
@@ -142,8 +148,11 @@
 
         private static final boolean DO_LOGCAT = Log.isLoggable(TAG, Log.DEBUG);
 
+        private final MyHandler mHandler;
+
         RotatingFileLogger() {
             mLogPath = new File(Environment.getDataSystemDirectory(), "syncmanager-log");
+            mHandler = new MyHandler(IoThread.get().getLooper());
         }
 
         @Override
@@ -163,8 +172,12 @@
             if (message == null) {
                 return;
             }
+            final long now = System.currentTimeMillis();
+            mHandler.log(now, message);
+        }
+
+        void logInner(long now, Object[] message) {
             synchronized (mLock) {
-                final long now = System.currentTimeMillis();
                 openLogLocked(now);
                 if (mLogWriter == null) {
                     return; // Couldn't open log file?
@@ -272,5 +285,28 @@
             } catch (IOException e) {
             }
         }
+
+        private class MyHandler extends Handler {
+            public static final int MSG_LOG_ID = 1;
+
+            MyHandler(Looper looper) {
+                super(looper);
+            }
+
+            public void log(long now, Object[] message) {
+                obtainMessage(MSG_LOG_ID, IntPair.first(now), IntPair.second(now), message)
+                        .sendToTarget();
+            }
+
+            @Override
+            public void handleMessage(Message msg) {
+                switch (msg.what) {
+                    case MSG_LOG_ID: {
+                        logInner(IntPair.of(msg.arg1, msg.arg2), (Object[]) msg.obj);
+                        break;
+                    }
+                }
+            }
+        }
     }
 }
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index e37153e..e3a1a91 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -1770,6 +1770,12 @@
     @Override
     public void addClient(IInputMethodClient client, IInputContext inputContext,
             int selfReportedDisplayId) {
+        // Here there are two scenarios where this method is called:
+        // A. IMM is being instantiated in a different process and this is an IPC from that process
+        // B. IMM is being instantiated in the same process but Binder.clearCallingIdentity() is
+        //    called in the caller side if necessary.
+        // In either case the following UID/PID should be the ones where InputMethodManager is
+        // actually running.
         final int callerUid = Binder.getCallingUid();
         final int callerPid = Binder.getCallingPid();
         synchronized (mMethodMap) {
@@ -1778,7 +1784,7 @@
                 if (state.uid == callerUid && state.pid == callerPid
                         && state.selfReportedDisplayId == selfReportedDisplayId) {
                     throw new SecurityException("uid=" + callerUid + "/pid=" + callerPid
-                            + " is already registered");
+                            + "/displayId=" + selfReportedDisplayId + " is already registered.");
                 }
             }
             final ClientDeathRecipient deathRecipient = new ClientDeathRecipient(this, client);
diff --git a/services/core/java/com/android/server/location/ContextHubClientBroker.java b/services/core/java/com/android/server/location/ContextHubClientBroker.java
index 99a04d7..1d0ab8f 100644
--- a/services/core/java/com/android/server/location/ContextHubClientBroker.java
+++ b/services/core/java/com/android/server/location/ContextHubClientBroker.java
@@ -16,6 +16,7 @@
 
 package com.android.server.location;
 
+import android.app.PendingIntent;
 import android.content.Context;
 import android.hardware.contexthub.V1_0.ContextHubMsg;
 import android.hardware.contexthub.V1_0.IContexthub;
@@ -138,6 +139,27 @@
     }
 
     /**
+     * @param intent the intent to register
+     * @param nanoAppId the ID of the nanoapp to send events for
+     * @return true on success, false otherwise
+     */
+    @Override
+    public boolean registerIntent(PendingIntent intent, long nanoAppId) {
+        // TODO: Implement this
+        return false;
+    }
+
+    /**
+     * @param intent the intent to unregister
+     * @return true on success, false otherwise
+     */
+    @Override
+    public boolean unregisterIntent(PendingIntent intent) {
+        // TODO: Implement this
+        return false;
+    }
+
+    /**
      * Closes the connection for this client with the service.
      */
     @Override
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index 3f03169..dc3bfbc 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -105,6 +105,7 @@
 import android.os.HandlerThread;
 import android.os.IBinder;
 import android.os.INetworkManagementService;
+import android.os.Looper;
 import android.os.Message;
 import android.os.Messenger;
 import android.os.PowerManager;
@@ -323,6 +324,12 @@
                 Clock.systemUTC());
     }
 
+    private static final class NetworkStatsHandler extends Handler {
+        NetworkStatsHandler(Looper looper, Handler.Callback callback) {
+            super(looper, callback);
+        }
+    }
+
     public static NetworkStatsService create(Context context,
                 INetworkManagementService networkManager) {
         AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
@@ -339,7 +346,7 @@
         HandlerThread handlerThread = new HandlerThread(TAG);
         Handler.Callback callback = new HandlerCallback(service);
         handlerThread.start();
-        Handler handler = new Handler(handlerThread.getLooper(), callback);
+        Handler handler = new NetworkStatsHandler(handlerThread.getLooper(), callback);
         service.setHandler(handler, callback);
         return service;
     }
@@ -1620,7 +1627,8 @@
         // fold tethering stats and operations into uid snapshot
         final NetworkStats tetherSnapshot = getNetworkStatsTethering(STATS_PER_UID);
         tetherSnapshot.filter(UID_ALL, ifaces, TAG_ALL);
-        NetworkStatsFactory.apply464xlatAdjustments(uidSnapshot, tetherSnapshot);
+        NetworkStatsFactory.apply464xlatAdjustments(uidSnapshot, tetherSnapshot,
+                mUseBpfTrafficStats);
         uidSnapshot.combineAllValues(tetherSnapshot);
 
         final TelephonyManager telephonyManager = (TelephonyManager) mContext.getSystemService(
@@ -1630,7 +1638,8 @@
         final NetworkStats vtStats = telephonyManager.getVtDataUsage(STATS_PER_UID);
         if (vtStats != null) {
             vtStats.filter(UID_ALL, ifaces, TAG_ALL);
-            NetworkStatsFactory.apply464xlatAdjustments(uidSnapshot, vtStats);
+            NetworkStatsFactory.apply464xlatAdjustments(uidSnapshot, vtStats,
+                    mUseBpfTrafficStats);
             uidSnapshot.combineAllValues(vtStats);
         }
 
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 93b83ae..8d581df 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -4332,19 +4332,20 @@
      *
      * Has side effects.
      */
-    private boolean checkDisqualifyingFeatures(int userId, int callingUid, int id, String tag,
+    private boolean checkDisqualifyingFeatures(int userId, int uid, int id, String tag,
             NotificationRecord r, boolean isAutogroup) {
         final String pkg = r.sbn.getPackageName();
         final boolean isSystemNotification =
-                isUidSystemOrPhone(callingUid) || ("android".equals(pkg));
+                isUidSystemOrPhone(uid) || ("android".equals(pkg));
         final boolean isNotificationFromListener = mListeners.isListenerPackage(pkg);
 
         // Limit the number of notifications that any given package except the android
         // package or a registered listener can enqueue.  Prevents DOS attacks and deals with leaks.
         if (!isSystemNotification && !isNotificationFromListener) {
             synchronized (mNotificationLock) {
+                final int callingUid = Binder.getCallingUid();
                 if (mNotificationsByKey.get(r.sbn.getKey()) == null
-                        && isCallerInstantApp(pkg, Binder.getCallingUid(), userId)) {
+                        && isCallerInstantApp(callingUid, userId)) {
                     // Ephemeral apps have some special constraints for notifications.
                     // They are not allowed to create new notifications however they are allowed to
                     // update notifications created by the system (e.g. a foreground service
@@ -6452,24 +6453,24 @@
     }
 
     @VisibleForTesting
-    boolean isCallerInstantApp(String pkg, int callingUid, int userId) {
+    boolean isCallerInstantApp(int callingUid, int userId) {
         // System is always allowed to act for ephemeral apps.
         if (isUidSystemOrPhone(callingUid)) {
             return false;
         }
 
-        mAppOps.checkPackage(callingUid, pkg);
-
         try {
-            ApplicationInfo ai = mPackageManager.getApplicationInfo(pkg, 0, userId);
-            if (ai == null) {
-                throw new SecurityException("Unknown package " + pkg);
-            }
-            return ai.isInstantApp();
-        } catch (RemoteException re) {
-            throw new SecurityException("Unknown package " + pkg, re);
-        }
+            final String pkg = mPackageManager.getNameForUid(callingUid);
+            mAppOps.checkPackage(callingUid, pkg);
 
+           ApplicationInfo ai = mPackageManager.getApplicationInfo(pkg, 0, userId);
+           if (ai == null) {
+               throw new SecurityException("Unknown package " + pkg);
+           }
+           return ai.isInstantApp();
+        } catch (RemoteException re) {
+            throw new SecurityException("Unknown uid " + callingUid, re);
+        }
     }
 
     private void checkCallerIsSameApp(String pkg) {
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index 3a0ab77..8fce5e3 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -515,8 +515,20 @@
         if (oldGroup != null) {
             group.setChannels(oldGroup.getChannels());
 
+            // apps can't update the blocked status or app overlay permission
             if (fromTargetApp) {
                 group.setBlocked(oldGroup.isBlocked());
+                group.setAllowAppOverlay(oldGroup.canOverlayApps());
+                group.unlockFields(group.getUserLockedFields());
+                group.lockFields(oldGroup.getUserLockedFields());
+            } else {
+                // but the system can
+                if (group.isBlocked() != oldGroup.isBlocked()) {
+                    group.lockFields(NotificationChannelGroup.USER_LOCKED_BLOCKED_STATE);
+                }
+                if (group.canOverlayApps() != oldGroup.canOverlayApps()) {
+                    group.lockFields(NotificationChannelGroup.USER_LOCKED_ALLOW_APP_OVERLAY);
+                }
             }
         }
         r.groups.put(group.getId(), group);
@@ -1071,6 +1083,9 @@
         if (original.canShowBadge() != update.canShowBadge()) {
             update.lockFields(NotificationChannel.USER_LOCKED_SHOW_BADGE);
         }
+        if (original.isAppOverlayAllowed() != update.isAppOverlayAllowed()) {
+            update.lockFields(NotificationChannel.USER_LOCKED_ALLOW_APP_OVERLAY);
+        }
     }
 
     public void dump(PrintWriter pw, String prefix,
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 006ea75..51225a7 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -682,6 +682,7 @@
                         if (PackageInstaller.ENABLE_REVOCABLE_FD) {
                             mFds.remove(fd);
                         } else {
+                            bridge.forceClose();
                             mBridges.remove(bridge);
                         }
                     }
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 9399ebf..b988c6a 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -322,6 +322,7 @@
 import dalvik.system.VMRuntime;
 
 import libcore.io.IoUtils;
+import libcore.util.EmptyArray;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -846,23 +847,9 @@
     final ParallelPackageParserCallback mParallelPackageParserCallback =
             new ParallelPackageParserCallback();
 
-    public static final class SharedLibraryEntry {
-        public final @Nullable String path;
-        public final @Nullable String apk;
-        public final @NonNull SharedLibraryInfo info;
-
-        SharedLibraryEntry(String _path, String _apk, String name, long version, int type,
-                String declaringPackageName, long declaringPackageVersionCode) {
-            path = _path;
-            apk = _apk;
-            info = new SharedLibraryInfo(name, version, type, new VersionedPackage(
-                    declaringPackageName, declaringPackageVersionCode), null);
-        }
-    }
-
     // Currently known shared libraries.
-    final ArrayMap<String, LongSparseArray<SharedLibraryEntry>> mSharedLibraries = new ArrayMap<>();
-    final ArrayMap<String, LongSparseArray<SharedLibraryEntry>> mStaticLibsByDeclaringPackage =
+    final ArrayMap<String, LongSparseArray<SharedLibraryInfo>> mSharedLibraries = new ArrayMap<>();
+    final ArrayMap<String, LongSparseArray<SharedLibraryInfo>> mStaticLibsByDeclaringPackage =
             new ArrayMap<>();
 
     // Mapping from instrumentation class names to info about them.
@@ -3325,11 +3312,15 @@
 
     private @NonNull String getRequiredSharedLibraryLPr(String name, int version) {
         synchronized (mPackages) {
-            SharedLibraryEntry libraryEntry = getSharedLibraryEntryLPr(name, version);
-            if (libraryEntry == null) {
+            SharedLibraryInfo libraryInfo = getSharedLibraryInfoLPr(name, version);
+            if (libraryInfo == null) {
                 throw new IllegalStateException("Missing required shared library:" + name);
             }
-            return libraryEntry.apk;
+            String packageName = libraryInfo.getPackageName();
+            if (packageName == null) {
+                throw new IllegalStateException("Expected a package for shared library " + name);
+            }
+            return packageName;
         }
     }
 
@@ -4078,9 +4069,9 @@
             return false;
         }
 
-        final SharedLibraryEntry libEntry = getSharedLibraryEntryLPr(ps.pkg.staticSharedLibName,
+        final SharedLibraryInfo libraryInfo = getSharedLibraryInfoLPr(ps.pkg.staticSharedLibName,
                 ps.pkg.staticSharedLibVersion);
-        if (libEntry == null) {
+        if (libraryInfo == null) {
             return false;
         }
 
@@ -4097,11 +4088,11 @@
             PackageSetting uidPs = mSettings.getPackageLPr(uidPackageName);
             if (uidPs != null) {
                 final int index = ArrayUtils.indexOf(uidPs.usesStaticLibraries,
-                        libEntry.info.getName());
+                        libraryInfo.getName());
                 if (index < 0) {
                     continue;
                 }
-                if (uidPs.pkg.usesStaticLibrariesVersions[index] == libEntry.info.getLongVersion()) {
+                if (uidPs.pkg.usesStaticLibrariesVersions[index] == libraryInfo.getLongVersion()) {
                     return false;
                 }
             }
@@ -4498,14 +4489,14 @@
             final int[] allUsers = sUserManager.getUserIds();
             final int libCount = mSharedLibraries.size();
             for (int i = 0; i < libCount; i++) {
-                final LongSparseArray<SharedLibraryEntry> versionedLib
+                final LongSparseArray<SharedLibraryInfo> versionedLib
                         = mSharedLibraries.valueAt(i);
                 if (versionedLib == null) {
                     continue;
                 }
                 final int versionCount = versionedLib.size();
                 for (int j = 0; j < versionCount; j++) {
-                    SharedLibraryInfo libInfo = versionedLib.valueAt(j).info;
+                    SharedLibraryInfo libInfo = versionedLib.valueAt(j);
                     // Skip packages that are not static shared libs.
                     if (!libInfo.isStatic()) {
                         break;
@@ -4846,14 +4837,14 @@
 
             final int libCount = mSharedLibraries.size();
             for (int i = 0; i < libCount; i++) {
-                LongSparseArray<SharedLibraryEntry> versionedLib = mSharedLibraries.valueAt(i);
+                LongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.valueAt(i);
                 if (versionedLib == null) {
                     continue;
                 }
 
                 final int versionCount = versionedLib.size();
                 for (int j = 0; j < versionCount; j++) {
-                    SharedLibraryInfo libInfo = versionedLib.valueAt(j).info;
+                    SharedLibraryInfo libInfo = versionedLib.valueAt(j);
                     if (!canSeeStaticLibraries && libInfo.isStatic()) {
                         break;
                     }
@@ -4869,10 +4860,10 @@
                         Binder.restoreCallingIdentity(identity);
                     }
 
-                    SharedLibraryInfo resLibInfo = new SharedLibraryInfo(libInfo.getName(),
-                            libInfo.getLongVersion(), libInfo.getType(),
-                            libInfo.getDeclaringPackage(), getPackagesUsingSharedLibraryLPr(libInfo,
-                            flags, userId));
+                    SharedLibraryInfo resLibInfo = new SharedLibraryInfo(libInfo.getPath(),
+                            libInfo.getPackageName(), libInfo.getName(), libInfo.getLongVersion(),
+                            libInfo.getType(), libInfo.getDeclaringPackage(),
+                            getPackagesUsingSharedLibraryLPr(libInfo, flags, userId));
 
                     if (result == null) {
                         result = new ArrayList<>();
@@ -4988,28 +4979,28 @@
             Set<String> libs = null;
             final int libCount = mSharedLibraries.size();
             for (int i = 0; i < libCount; i++) {
-                LongSparseArray<SharedLibraryEntry> versionedLib = mSharedLibraries.valueAt(i);
+                LongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.valueAt(i);
                 if (versionedLib == null) {
                     continue;
                 }
                 final int versionCount = versionedLib.size();
                 for (int j = 0; j < versionCount; j++) {
-                    SharedLibraryEntry libEntry = versionedLib.valueAt(j);
-                    if (!libEntry.info.isStatic()) {
+                    SharedLibraryInfo libraryInfo = versionedLib.valueAt(j);
+                    if (!libraryInfo.isStatic()) {
                         if (libs == null) {
                             libs = new ArraySet<>();
                         }
-                        libs.add(libEntry.info.getName());
+                        libs.add(libraryInfo.getName());
                         break;
                     }
-                    PackageSetting ps = mSettings.getPackageLPr(libEntry.apk);
+                    PackageSetting ps = mSettings.getPackageLPr(libraryInfo.getPackageName());
                     if (ps != null && !filterSharedLibPackageLPr(ps, Binder.getCallingUid(),
                             UserHandle.getUserId(Binder.getCallingUid()),
                             PackageManager.MATCH_STATIC_SHARED_LIBRARIES)) {
                         if (libs == null) {
                             libs = new ArraySet<>();
                         }
-                        libs.add(libEntry.info.getName());
+                        libs.add(libraryInfo.getName());
                         break;
                     }
                 }
@@ -9326,24 +9317,24 @@
 
     private PackageParser.Package findSharedNonSystemLibrary(String name, long version) {
         synchronized (mPackages) {
-            SharedLibraryEntry libEntry = getSharedLibraryEntryLPr(name, version);
-            if (libEntry != null) {
-                return mPackages.get(libEntry.apk);
+            SharedLibraryInfo libraryInfo = getSharedLibraryInfoLPr(name, version);
+            if (libraryInfo != null) {
+                return mPackages.get(libraryInfo.getPackageName());
             }
             return null;
         }
     }
 
-    private SharedLibraryEntry getSharedLibraryEntryLPr(String name, long version) {
-        LongSparseArray<SharedLibraryEntry> versionedLib = mSharedLibraries.get(name);
+    private SharedLibraryInfo getSharedLibraryInfoLPr(String name, long version) {
+        LongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get(name);
         if (versionedLib == null) {
             return null;
         }
         return versionedLib.get(version);
     }
 
-    private SharedLibraryEntry getLatestSharedLibraVersionLPr(PackageParser.Package pkg) {
-        LongSparseArray<SharedLibraryEntry> versionedLib = mSharedLibraries.get(
+    private SharedLibraryInfo getLatestSharedLibraVersionLPr(PackageParser.Package pkg) {
+        LongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get(
                 pkg.staticSharedLibName);
         if (versionedLib == null) {
             return null;
@@ -9540,7 +9531,8 @@
                     }
                 }
                 if (deleteSandboxData && getStorageManagerInternal() != null) {
-                    getStorageManagerInternal().destroySandboxForApp(pkg.packageName, realUserId);
+                    getStorageManagerInternal().destroySandboxForApp(pkg.packageName,
+                            pkg.mSharedUserId, realUserId);
                 }
             } catch (PackageManagerException e) {
                 // Should not happen
@@ -9603,14 +9595,15 @@
 
     @GuardedBy("mPackages")
     private void addSharedLibraryLPr(Set<String> usesLibraryFiles,
-            SharedLibraryEntry file,
+            SharedLibraryInfo file,
             PackageParser.Package changingLib) {
-        if (file.path != null) {
-            usesLibraryFiles.add(file.path);
+
+        if (file.getPath() != null) {
+            usesLibraryFiles.add(file.getPath());
             return;
         }
-        PackageParser.Package p = mPackages.get(file.apk);
-        if (changingLib != null && changingLib.packageName.equals(file.apk)) {
+        PackageParser.Package p = mPackages.get(file.getPackageName());
+        if (changingLib != null && changingLib.packageName.equals(file.getPackageName())) {
             // If we are doing this while in the middle of updating a library apk,
             // then we need to make sure to use that new apk for determining the
             // dependencies here.  (We haven't yet finished committing the new apk
@@ -9636,43 +9629,52 @@
         // The collection used here must maintain the order of addition (so
         // that libraries are searched in the correct order) and must have no
         // duplicates.
-        Set<String> usesLibraryFiles = null;
+        ArrayList<SharedLibraryInfo> usesLibraryInfos = null;
         if (pkg.usesLibraries != null) {
-            usesLibraryFiles = addSharedLibrariesLPw(pkg.usesLibraries,
-                    null, null, pkg.packageName, changingLib, true,
+            usesLibraryInfos = addSharedLibrariesLPw(pkg.usesLibraries,
+                    null, null, pkg.packageName, true,
                     pkg.applicationInfo.targetSdkVersion, null);
         }
         if (pkg.usesStaticLibraries != null) {
-            usesLibraryFiles = addSharedLibrariesLPw(pkg.usesStaticLibraries,
+            usesLibraryInfos = addSharedLibrariesLPw(pkg.usesStaticLibraries,
                     pkg.usesStaticLibrariesVersions, pkg.usesStaticLibrariesCertDigests,
-                    pkg.packageName, changingLib, true,
-                    pkg.applicationInfo.targetSdkVersion, usesLibraryFiles);
+                    pkg.packageName, true,
+                    pkg.applicationInfo.targetSdkVersion, usesLibraryInfos);
         }
         if (pkg.usesOptionalLibraries != null) {
-            usesLibraryFiles = addSharedLibrariesLPw(pkg.usesOptionalLibraries,
-                    null, null, pkg.packageName, changingLib, false,
-                    pkg.applicationInfo.targetSdkVersion, usesLibraryFiles);
+            usesLibraryInfos = addSharedLibrariesLPw(pkg.usesOptionalLibraries,
+                    null, null, pkg.packageName, false,
+                    pkg.applicationInfo.targetSdkVersion, usesLibraryInfos);
         }
-        if (!ArrayUtils.isEmpty(usesLibraryFiles)) {
+        if (usesLibraryInfos != null) {
+            pkg.usesLibraryInfos = usesLibraryInfos;
+            // Use LinkedHashSet to preserve the order of files added to
+            // usesLibraryFiles while eliminating duplicates.
+            Set<String> usesLibraryFiles = new LinkedHashSet<>();
+            for (SharedLibraryInfo libInfo : usesLibraryInfos) {
+                addSharedLibraryLPr(usesLibraryFiles, libInfo, changingLib);
+            }
             pkg.usesLibraryFiles = usesLibraryFiles.toArray(new String[usesLibraryFiles.size()]);
         } else {
+            pkg.usesLibraryInfos = null;
             pkg.usesLibraryFiles = null;
         }
     }
 
     @GuardedBy("mPackages")
-    private Set<String> addSharedLibrariesLPw(@NonNull List<String> requestedLibraries,
+    private ArrayList<SharedLibraryInfo> addSharedLibrariesLPw(
+            @NonNull List<String> requestedLibraries,
             @Nullable long[] requiredVersions, @Nullable String[][] requiredCertDigests,
-            @NonNull String packageName, @Nullable PackageParser.Package changingLib,
-            boolean required, int targetSdk, @Nullable Set<String> outUsedLibraries)
+            @NonNull String packageName, boolean required, int targetSdk,
+            @Nullable ArrayList<SharedLibraryInfo> outUsedLibraries)
             throws PackageManagerException {
         final int libCount = requestedLibraries.size();
         for (int i = 0; i < libCount; i++) {
             final String libName = requestedLibraries.get(i);
             final long libVersion = requiredVersions != null ? requiredVersions[i]
                     : SharedLibraryInfo.VERSION_UNDEFINED;
-            final SharedLibraryEntry libEntry = getSharedLibraryEntryLPr(libName, libVersion);
-            if (libEntry == null) {
+            final SharedLibraryInfo libraryInfo = getSharedLibraryInfoLPr(libName, libVersion);
+            if (libraryInfo == null) {
                 if (required) {
                     throw new PackageManagerException(INSTALL_FAILED_MISSING_SHARED_LIBRARY,
                             "Package " + packageName + " requires unavailable shared library "
@@ -9684,14 +9686,14 @@
                 }
             } else {
                 if (requiredVersions != null && requiredCertDigests != null) {
-                    if (libEntry.info.getLongVersion() != requiredVersions[i]) {
+                    if (libraryInfo.getLongVersion() != requiredVersions[i]) {
                         throw new PackageManagerException(INSTALL_FAILED_MISSING_SHARED_LIBRARY,
                             "Package " + packageName + " requires unavailable static shared"
                                     + " library " + libName + " version "
-                                    + libEntry.info.getLongVersion() + "; failing!");
+                                    + libraryInfo.getLongVersion() + "; failing!");
                     }
 
-                    PackageParser.Package libPkg = mPackages.get(libEntry.apk);
+                    PackageParser.Package libPkg = mPackages.get(libraryInfo.getPackageName());
                     if (libPkg == null) {
                         throw new PackageManagerException(INSTALL_FAILED_MISSING_SHARED_LIBRARY,
                                 "Package " + packageName + " requires unavailable static shared"
@@ -9748,11 +9750,9 @@
                 }
 
                 if (outUsedLibraries == null) {
-                    // Use LinkedHashSet to preserve the order of files added to
-                    // usesLibraryFiles while eliminating duplicates.
-                    outUsedLibraries = new LinkedHashSet<>();
+                    outUsedLibraries = new ArrayList<>();
                 }
-                addSharedLibraryLPr(outUsedLibraries, libEntry, changingLib);
+                outUsedLibraries.add(libraryInfo);
             }
         }
         return outUsedLibraries;
@@ -10167,9 +10167,9 @@
         // library in order to compare signatures.
         PackageSetting signatureCheckPs = pkgSetting;
         if (pkg.applicationInfo.isStaticSharedLibrary()) {
-            SharedLibraryEntry libraryEntry = getLatestSharedLibraVersionLPr(pkg);
-            if (libraryEntry != null) {
-                signatureCheckPs = mSettings.getPackageLPr(libraryEntry.apk);
+            SharedLibraryInfo libraryInfo = getLatestSharedLibraVersionLPr(pkg);
+            if (libraryInfo != null) {
+                signatureCheckPs = mSettings.getPackageLPr(libraryInfo.getPackageName());
             }
         }
 
@@ -11012,12 +11012,12 @@
                 long minVersionCode = Long.MIN_VALUE;
                 long maxVersionCode = Long.MAX_VALUE;
 
-                LongSparseArray<SharedLibraryEntry> versionedLib = mSharedLibraries.get(
+                LongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get(
                         pkg.staticSharedLibName);
                 if (versionedLib != null) {
                     final int versionCount = versionedLib.size();
                     for (int i = 0; i < versionCount; i++) {
-                        SharedLibraryInfo libInfo = versionedLib.valueAt(i).info;
+                        SharedLibraryInfo libInfo = versionedLib.valueAt(i);
                         final long libVersionCode = libInfo.getDeclaringPackage()
                                 .getLongVersionCode();
                         if (libInfo.getLongVersion() <  pkg.staticSharedLibVersion) {
@@ -11185,7 +11185,7 @@
 
     private boolean addSharedLibraryLPw(String path, String apk, String name, long version,
             int type, String declaringPackageName, long declaringVersionCode) {
-        LongSparseArray<SharedLibraryEntry> versionedLib = mSharedLibraries.get(name);
+        LongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get(name);
         if (versionedLib == null) {
             versionedLib = new LongSparseArray<>();
             mSharedLibraries.put(name, versionedLib);
@@ -11195,14 +11195,15 @@
         } else if (versionedLib.indexOfKey(version) >= 0) {
             return false;
         }
-        SharedLibraryEntry libEntry = new SharedLibraryEntry(path, apk, name,
-                version, type, declaringPackageName, declaringVersionCode);
-        versionedLib.put(version, libEntry);
+        SharedLibraryInfo libraryInfo = new SharedLibraryInfo(path, apk, name,
+                version, type, new VersionedPackage(declaringPackageName, declaringVersionCode),
+                null);
+        versionedLib.put(version, libraryInfo);
         return true;
     }
 
     private boolean removeSharedLibraryLPw(String name, long version) {
-        LongSparseArray<SharedLibraryEntry> versionedLib = mSharedLibraries.get(name);
+        LongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get(name);
         if (versionedLib == null) {
             return false;
         }
@@ -11210,12 +11211,12 @@
         if (libIdx < 0) {
             return false;
         }
-        SharedLibraryEntry libEntry = versionedLib.valueAt(libIdx);
+        SharedLibraryInfo libraryInfo = versionedLib.valueAt(libIdx);
         versionedLib.remove(version);
         if (versionedLib.size() <= 0) {
             mSharedLibraries.remove(name);
-            if (libEntry.info.getType() == SharedLibraryInfo.TYPE_STATIC) {
-                mStaticLibsByDeclaringPackage.remove(libEntry.info.getDeclaringPackage()
+            if (libraryInfo.getType() == SharedLibraryInfo.TYPE_STATIC) {
+                mStaticLibsByDeclaringPackage.remove(libraryInfo.getDeclaringPackage()
                         .getPackageName());
             }
         }
@@ -15847,9 +15848,9 @@
                 // the package setting for the latest library version.
                 PackageSetting signatureCheckPs = ps;
                 if (pkg.applicationInfo.isStaticSharedLibrary()) {
-                    SharedLibraryEntry libraryEntry = getLatestSharedLibraVersionLPr(pkg);
-                    if (libraryEntry != null) {
-                        signatureCheckPs = mSettings.getPackageLPr(libraryEntry.apk);
+                    SharedLibraryInfo libraryInfo = getLatestSharedLibraVersionLPr(pkg);
+                    if (libraryInfo != null) {
+                        signatureCheckPs = mSettings.getPackageLPr(libraryInfo.getPackageName());
                     }
                 }
 
@@ -16727,7 +16728,7 @@
         packageName = normalizedPackageName != null ? normalizedPackageName : packageName;
 
         // Is this a static library?
-        LongSparseArray<SharedLibraryEntry> versionedLib =
+        LongSparseArray<SharedLibraryInfo> versionedLib =
                 mStaticLibsByDeclaringPackage.get(packageName);
         if (versionedLib == null || versionedLib.size() <= 0) {
             return packageName;
@@ -16739,7 +16740,7 @@
         if (callingAppId != Process.SYSTEM_UID && callingAppId != Process.SHELL_UID
                 && callingAppId != Process.ROOT_UID) {
             versionsCallerCanSee = new LongSparseLongArray();
-            String libName = versionedLib.valueAt(0).info.getName();
+            String libName = versionedLib.valueAt(0).getName();
             String[] uidPackages = getPackagesForUid(Binder.getCallingUid());
             if (uidPackages != null) {
                 for (String uidPackage : uidPackages) {
@@ -16759,29 +16760,29 @@
         }
 
         // Find the version the caller can see and the app version code
-        SharedLibraryEntry highestVersion = null;
+        SharedLibraryInfo highestVersion = null;
         final int versionCount = versionedLib.size();
         for (int i = 0; i < versionCount; i++) {
-            SharedLibraryEntry libEntry = versionedLib.valueAt(i);
+            SharedLibraryInfo libraryInfo = versionedLib.valueAt(i);
             if (versionsCallerCanSee != null && versionsCallerCanSee.indexOfKey(
-                    libEntry.info.getLongVersion()) < 0) {
+                    libraryInfo.getLongVersion()) < 0) {
                 continue;
             }
-            final long libVersionCode = libEntry.info.getDeclaringPackage().getLongVersionCode();
+            final long libVersionCode = libraryInfo.getDeclaringPackage().getLongVersionCode();
             if (versionCode != PackageManager.VERSION_CODE_HIGHEST) {
                 if (libVersionCode == versionCode) {
-                    return libEntry.apk;
+                    return libraryInfo.getPackageName();
                 }
             } else if (highestVersion == null) {
-                highestVersion = libEntry;
-            } else if (libVersionCode  > highestVersion.info
+                highestVersion = libraryInfo;
+            } else if (libVersionCode  > highestVersion
                     .getDeclaringPackage().getLongVersionCode()) {
-                highestVersion = libEntry;
+                highestVersion = libraryInfo;
             }
         }
 
         if (highestVersion != null) {
-            return highestVersion.apk;
+            return highestVersion.getPackageName();
         }
 
         return packageName;
@@ -16943,19 +16944,19 @@
             allUsers = sUserManager.getUserIds();
 
             if (pkg != null && pkg.staticSharedLibName != null) {
-                SharedLibraryEntry libEntry = getSharedLibraryEntryLPr(pkg.staticSharedLibName,
+                SharedLibraryInfo libraryInfo = getSharedLibraryInfoLPr(pkg.staticSharedLibName,
                         pkg.staticSharedLibVersion);
-                if (libEntry != null) {
+                if (libraryInfo != null) {
                     for (int currUserId : allUsers) {
                         if (removeUser != UserHandle.USER_ALL && removeUser != currUserId) {
                             continue;
                         }
                         List<VersionedPackage> libClientPackages = getPackagesUsingSharedLibraryLPr(
-                                libEntry.info, 0, currUserId);
+                                libraryInfo, 0, currUserId);
                         if (!ArrayUtils.isEmpty(libClientPackages)) {
                             Slog.w(TAG, "Not removing package " + pkg.manifestPackageName
-                                    + " hosting lib " + libEntry.info.getName() + " version "
-                                    + libEntry.info.getLongVersion() + " used by " + libClientPackages
+                                    + " hosting lib " + libraryInfo.getName() + " version "
+                                    + libraryInfo.getLongVersion() + " used by " + libClientPackages
                                     + " for user " + currUserId);
                             return PackageManager.DELETE_FAILED_USED_SHARED_LIBRARY;
                         }
@@ -20224,14 +20225,14 @@
                 final Iterator<String> it = mSharedLibraries.keySet().iterator();
                 while (it.hasNext()) {
                     String libName = it.next();
-                    LongSparseArray<SharedLibraryEntry> versionedLib
+                    LongSparseArray<SharedLibraryInfo> versionedLib
                             = mSharedLibraries.get(libName);
                     if (versionedLib == null) {
                         continue;
                     }
                     final int versionCount = versionedLib.size();
                     for (int i = 0; i < versionCount; i++) {
-                        SharedLibraryEntry libEntry = versionedLib.valueAt(i);
+                        SharedLibraryInfo libraryInfo = versionedLib.valueAt(i);
                         if (!checkin) {
                             if (!printedHeader) {
                                 if (dumpState.onTitlePrinted())
@@ -20243,19 +20244,19 @@
                         } else {
                             pw.print("lib,");
                         }
-                        pw.print(libEntry.info.getName());
-                        if (libEntry.info.isStatic()) {
-                            pw.print(" version=" + libEntry.info.getLongVersion());
+                        pw.print(libraryInfo.getName());
+                        if (libraryInfo.isStatic()) {
+                            pw.print(" version=" + libraryInfo.getLongVersion());
                         }
                         if (!checkin) {
                             pw.print(" -> ");
                         }
-                        if (libEntry.path != null) {
+                        if (libraryInfo.getPath() != null) {
                             pw.print(" (jar) ");
-                            pw.print(libEntry.path);
+                            pw.print(libraryInfo.getPath());
                         } else {
                             pw.print(" (apk) ");
-                            pw.print(libEntry.apk);
+                            pw.print(libraryInfo.getPackageName());
                         }
                         pw.println();
                     }
@@ -20591,22 +20592,24 @@
         final int count = mSharedLibraries.size();
         for (int i = 0; i < count; i++) {
             final String libName = mSharedLibraries.keyAt(i);
-            LongSparseArray<SharedLibraryEntry> versionedLib = mSharedLibraries.get(libName);
+            LongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get(libName);
             if (versionedLib == null) {
                 continue;
             }
             final int versionCount = versionedLib.size();
             for (int j = 0; j < versionCount; j++) {
-                final SharedLibraryEntry libEntry = versionedLib.valueAt(j);
+                final SharedLibraryInfo libraryInfo = versionedLib.valueAt(j);
                 final long sharedLibraryToken =
                         proto.start(PackageServiceDumpProto.SHARED_LIBRARIES);
-                proto.write(PackageServiceDumpProto.SharedLibraryProto.NAME, libEntry.info.getName());
-                final boolean isJar = (libEntry.path != null);
+                proto.write(PackageServiceDumpProto.SharedLibraryProto.NAME, libraryInfo.getName());
+                final boolean isJar = (libraryInfo.getPath() != null);
                 proto.write(PackageServiceDumpProto.SharedLibraryProto.IS_JAR, isJar);
                 if (isJar) {
-                    proto.write(PackageServiceDumpProto.SharedLibraryProto.PATH, libEntry.path);
+                    proto.write(PackageServiceDumpProto.SharedLibraryProto.PATH,
+                            libraryInfo.getPath());
                 } else {
-                    proto.write(PackageServiceDumpProto.SharedLibraryProto.APK, libEntry.apk);
+                    proto.write(PackageServiceDumpProto.SharedLibraryProto.APK,
+                            libraryInfo.getPackageName());
                 }
                 proto.end(sharedLibraryToken);
             }
@@ -22941,6 +22944,20 @@
         }
 
         @Override
+        public String getSharedUserIdForPackage(String packageName) {
+            synchronized (mPackages) {
+                return getSharedUserIdForPackageLocked(packageName);
+            }
+        }
+
+        @Override
+        public String[] getPackagesForSharedUserId(String sharedUserId, int userId) {
+            synchronized (mPackages) {
+                return getPackagesForSharedUserIdLocked(sharedUserId, userId);
+            }
+        }
+
+        @Override
         public boolean isOnlyCoreApps() {
             return PackageManagerService.this.isOnlyCoreApps();
         }
@@ -22952,6 +22969,7 @@
         }
     }
 
+    @GuardedBy("mPackages")
     private SparseArray<String> getAppsWithSharedUserIdsLocked() {
         final SparseArray<String> sharedUserIds = new SparseArray<>();
         synchronized (mPackages) {
@@ -22962,6 +22980,38 @@
         return sharedUserIds;
     }
 
+    @GuardedBy("mPackages")
+    private String getSharedUserIdForPackageLocked(String packageName) {
+        final PackageSetting ps = mSettings.mPackages.get(packageName);
+        return (ps != null && ps.isSharedUser()) ? ps.sharedUser.name : null;
+    }
+
+    @GuardedBy("mPackages")
+    private String[] getPackagesForSharedUserIdLocked(String sharedUserId, int userId) {
+        try {
+            final SharedUserSetting sus = mSettings.getSharedUserLPw(
+                    sharedUserId, 0, 0, false);
+            if (sus == null) {
+                return EmptyArray.STRING;
+            }
+            String[] res = new String[sus.packages.size()];
+            final Iterator<PackageSetting> it = sus.packages.iterator();
+            int i = 0;
+            while (it.hasNext()) {
+                PackageSetting ps = it.next();
+                if (ps.getInstalled(userId)) {
+                    res[i++] = ps.name;
+                } else {
+                    res = ArrayUtils.removeElement(String.class, res, res[i]);
+                }
+            }
+            return res;
+        } catch (PackageManagerException e) {
+            // Should not happen
+        }
+        return EmptyArray.STRING;
+    }
+
     @Override
     public void grantDefaultPermissionsToEnabledCarrierApps(String[] packageNames, int userId) {
         enforceSystemOrPhoneCaller("grantPermissionsToEnabledCarrierApps");
diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
index e6a018a..45cb477 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -1194,6 +1194,7 @@
                 } else {
                     permissions.clear();
                 }
+                permissions.add(permissionGrant.name);
                 grantRuntimePermissions(pkg, permissions, permissionGrant.fixed, userId);
             }
         }
@@ -1359,7 +1360,7 @@
     private boolean isPermissionDangerous(String name) {
         try {
             final PermissionInfo pi = mContext.getPackageManager().getPermissionInfo(name, 0);
-            return (pi.getProtectionFlags() & PermissionInfo.PROTECTION_DANGEROUS) != 0;
+            return (pi.getProtection() == PermissionInfo.PROTECTION_DANGEROUS);
         } catch (NameNotFoundException e) {
             // When unknown assume it's dangerous to be on the safe side
             return true;
diff --git a/services/core/java/com/android/server/pm/permission/PermissionsState.java b/services/core/java/com/android/server/pm/permission/PermissionsState.java
index 82d6b22..c615ee5 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionsState.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionsState.java
@@ -30,6 +30,7 @@
 import java.util.Collections;
 import java.util.List;
 import java.util.Set;
+import com.android.internal.annotations.GuardedBy;
 
 /**
  * This class encapsulates the permissions for a package or a shared user.
@@ -62,6 +63,9 @@
 
     private static final int[] NO_GIDS = {};
 
+    private final Object mLock = new Object();
+
+    @GuardedBy("mLock")
     private ArrayMap<String, PermissionData> mPermissions;
 
     private int[] mGlobalGids = NO_GIDS;
@@ -96,22 +100,25 @@
         if (other == this) {
             return;
         }
-        if (mPermissions != null) {
-            if (other.mPermissions == null) {
-                mPermissions = null;
-            } else {
-                mPermissions.clear();
+
+        synchronized (mLock) {
+            if (mPermissions != null) {
+                if (other.mPermissions == null) {
+                    mPermissions = null;
+                } else {
+                    mPermissions.clear();
+                }
             }
-        }
-        if (other.mPermissions != null) {
-            if (mPermissions == null) {
-                mPermissions = new ArrayMap<>();
-            }
-            final int permissionCount = other.mPermissions.size();
-            for (int i = 0; i < permissionCount; i++) {
-                String name = other.mPermissions.keyAt(i);
-                PermissionData permissionData = other.mPermissions.valueAt(i);
-                mPermissions.put(name, new PermissionData(permissionData));
+            if (other.mPermissions != null) {
+                if (mPermissions == null) {
+                    mPermissions = new ArrayMap<>();
+                }
+                final int permissionCount = other.mPermissions.size();
+                for (int i = 0; i < permissionCount; i++) {
+                    String name = other.mPermissions.keyAt(i);
+                    PermissionData permissionData = other.mPermissions.valueAt(i);
+                    mPermissions.put(name, new PermissionData(permissionData));
+                }
             }
         }
 
@@ -154,13 +161,16 @@
         }
         final PermissionsState other = (PermissionsState) obj;
 
-        if (mPermissions == null) {
-            if (other.mPermissions != null) {
+        synchronized (mLock) {
+            if (mPermissions == null) {
+                if (other.mPermissions != null) {
+                    return false;
+                }
+            } else if (!mPermissions.equals(other.mPermissions)) {
                 return false;
             }
-        } else if (!mPermissions.equals(other.mPermissions)) {
-            return false;
         }
+
         if (mPermissionReviewRequired == null) {
             if (other.mPermissionReviewRequired != null) {
                 return false;
@@ -267,12 +277,15 @@
     public boolean hasPermission(String name, int userId) {
         enforceValidUserId(userId);
 
-        if (mPermissions == null) {
-            return false;
+        synchronized (mLock) {
+            if (mPermissions == null) {
+                return false;
+            }
+            PermissionData permissionData = mPermissions.get(name);
+
+            return permissionData != null && permissionData.isGranted(userId);
         }
 
-        PermissionData permissionData = mPermissions.get(name);
-        return permissionData != null && permissionData.isGranted(userId);
     }
 
     /**
@@ -280,14 +293,17 @@
      * whether or not it has been granted.
      */
     public boolean hasRequestedPermission(ArraySet<String> names) {
-        if (mPermissions == null) {
-            return false;
-        }
-        for (int i=names.size()-1; i>=0; i--) {
-            if (mPermissions.get(names.valueAt(i)) != null) {
-                return true;
+        synchronized (mLock) {
+            if (mPermissions == null) {
+                return false;
+            }
+            for (int i=names.size()-1; i>=0; i--) {
+                if (mPermissions.get(names.valueAt(i)) != null) {
+                    return true;
+                }
             }
         }
+
         return false;
     }
 
@@ -308,29 +324,31 @@
     public Set<String> getPermissions(int userId) {
         enforceValidUserId(userId);
 
-        if (mPermissions == null) {
-            return Collections.emptySet();
-        }
-
-        Set<String> permissions = new ArraySet<>(mPermissions.size());
-
-        final int permissionCount = mPermissions.size();
-        for (int i = 0; i < permissionCount; i++) {
-            String permission = mPermissions.keyAt(i);
-
-            if (hasInstallPermission(permission)) {
-                permissions.add(permission);
-                continue;
+        synchronized (mLock) {
+            if (mPermissions == null) {
+                return Collections.emptySet();
             }
 
-            if (userId != UserHandle.USER_ALL) {
-                if (hasRuntimePermission(permission, userId)) {
+            Set<String> permissions = new ArraySet<>(mPermissions.size());
+
+            final int permissionCount = mPermissions.size();
+            for (int i = 0; i < permissionCount; i++) {
+                String permission = mPermissions.keyAt(i);
+
+                if (hasInstallPermission(permission)) {
                     permissions.add(permission);
+                    continue;
+                }
+
+                if (userId != UserHandle.USER_ALL) {
+                    if (hasRuntimePermission(permission, userId)) {
+                        permissions.add(permission);
+                    }
                 }
             }
-        }
 
-        return permissions;
+            return permissions;
+        }
     }
 
     /**
@@ -407,14 +425,20 @@
 
         final boolean mayChangeFlags = flagValues != 0 || flagMask != 0;
 
-        if (mPermissions == null) {
-            if (!mayChangeFlags) {
-                return false;
+        synchronized (mLock) {
+            if (mPermissions == null) {
+                if (!mayChangeFlags) {
+                    return false;
+                }
+                ensurePermissionData(permission);
             }
-            ensurePermissionData(permission);
         }
 
-        PermissionData permissionData = mPermissions.get(permission.getName());
+        PermissionData permissionData = null;
+        synchronized (mLock) {
+            permissionData = mPermissions.get(permission.getName());
+        }
+
         if (permissionData == null) {
             if (!mayChangeFlags) {
                 return false;
@@ -447,14 +471,17 @@
     }
 
     private boolean hasPermissionRequiringReview(int userId) {
-        final int permissionCount = mPermissions.size();
-        for (int i = 0; i < permissionCount; i++) {
-            final PermissionData permission = mPermissions.valueAt(i);
-            if ((permission.getFlags(userId)
-                    & PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) != 0) {
-                return true;
+        synchronized (mLock) {
+            final int permissionCount = mPermissions.size();
+            for (int i = 0; i < permissionCount; i++) {
+                final PermissionData permission = mPermissions.valueAt(i);
+                if ((permission.getFlags(userId)
+                        & PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) != 0) {
+                    return true;
+                }
             }
         }
+
         return false;
     }
 
@@ -462,16 +489,19 @@
             int userId, int flagMask, int flagValues) {
         enforceValidUserId(userId);
 
-        if (mPermissions == null) {
-            return false;
+        synchronized (mLock) {
+            if (mPermissions == null) {
+                return false;
+            }
+            boolean changed = false;
+            final int permissionCount = mPermissions.size();
+            for (int i = 0; i < permissionCount; i++) {
+                PermissionData permissionData = mPermissions.valueAt(i);
+                changed |= permissionData.updateFlags(userId, flagMask, flagValues);
+            }
+
+            return changed;
         }
-        boolean changed = false;
-        final int permissionCount = mPermissions.size();
-        for (int i = 0; i < permissionCount; i++) {
-            PermissionData permissionData = mPermissions.valueAt(i);
-            changed |= permissionData.updateFlags(userId, flagMask, flagValues);
-        }
-        return changed;
     }
 
     /**
@@ -487,17 +517,19 @@
 
         int[] gids = mGlobalGids;
 
-        if (mPermissions != null) {
-            final int permissionCount = mPermissions.size();
-            for (int i = 0; i < permissionCount; i++) {
-                String permission = mPermissions.keyAt(i);
-                if (!hasPermission(permission, userId)) {
-                    continue;
-                }
-                PermissionData permissionData = mPermissions.valueAt(i);
-                final int[] permGids = permissionData.computeGids(userId);
-                if (permGids != NO_GIDS) {
-                    gids = appendInts(gids, permGids);
+        synchronized (mLock) {
+            if (mPermissions != null) {
+                final int permissionCount = mPermissions.size();
+                for (int i = 0; i < permissionCount; i++) {
+                    String permission = mPermissions.keyAt(i);
+                    if (!hasPermission(permission, userId)) {
+                        continue;
+                    }
+                    PermissionData permissionData = mPermissions.valueAt(i);
+                    final int[] permGids = permissionData.computeGids(userId);
+                    if (permGids != NO_GIDS) {
+                        gids = appendInts(gids, permGids);
+                    }
                 }
             }
         }
@@ -527,41 +559,50 @@
      */
     public void reset() {
         mGlobalGids = NO_GIDS;
-        mPermissions = null;
+
+        synchronized (mLock) {
+            mPermissions = null;
+        }
+
         mPermissionReviewRequired = null;
     }
 
     private PermissionState getPermissionState(String name, int userId) {
-        if (mPermissions == null) {
-            return null;
+        synchronized (mLock) {
+            if (mPermissions == null) {
+                return null;
+            }
+            PermissionData permissionData = mPermissions.get(name);
+            if (permissionData == null) {
+                return null;
+            }
+
+            return permissionData.getPermissionState(userId);
         }
-        PermissionData permissionData = mPermissions.get(name);
-        if (permissionData == null) {
-            return null;
-        }
-        return permissionData.getPermissionState(userId);
     }
 
     private List<PermissionState> getPermissionStatesInternal(int userId) {
         enforceValidUserId(userId);
 
-        if (mPermissions == null) {
-            return Collections.emptyList();
-        }
-
-        List<PermissionState> permissionStates = new ArrayList<>();
-
-        final int permissionCount = mPermissions.size();
-        for (int i = 0; i < permissionCount; i++) {
-            PermissionData permissionData = mPermissions.valueAt(i);
-
-            PermissionState permissionState = permissionData.getPermissionState(userId);
-            if (permissionState != null) {
-                permissionStates.add(permissionState);
+        synchronized (mLock) {
+            if (mPermissions == null) {
+                return Collections.emptyList();
             }
-        }
 
-        return permissionStates;
+            List<PermissionState> permissionStates = new ArrayList<>();
+
+            final int permissionCount = mPermissions.size();
+            for (int i = 0; i < permissionCount; i++) {
+                PermissionData permissionData = mPermissions.valueAt(i);
+
+                PermissionState permissionState = permissionData.getPermissionState(userId);
+                if (permissionState != null) {
+                    permissionStates.add(permissionState);
+                }
+            }
+
+            return permissionStates;
+        }
     }
 
     private int grantPermission(BasePermission permission, int userId) {
@@ -597,7 +638,10 @@
         final boolean hasGids = !ArrayUtils.isEmpty(permission.computeGids(userId));
         final int[] oldGids = hasGids ? computeGids(userId) : NO_GIDS;
 
-        PermissionData permissionData = mPermissions.get(permName);
+        PermissionData permissionData = null;
+        synchronized (mLock) {
+            permissionData = mPermissions.get(permName);
+        }
 
         if (!permissionData.revoke(userId)) {
             return PERMISSION_OPERATION_FAILURE;
@@ -635,25 +679,32 @@
 
     private PermissionData ensurePermissionData(BasePermission permission) {
         final String permName = permission.getName();
-        if (mPermissions == null) {
-            mPermissions = new ArrayMap<>();
+
+        synchronized (mLock) {
+            if (mPermissions == null) {
+                mPermissions = new ArrayMap<>();
+            }
+            PermissionData permissionData = mPermissions.get(permName);
+            if (permissionData == null) {
+                permissionData = new PermissionData(permission);
+                mPermissions.put(permName, permissionData);
+            }
+            return permissionData;
         }
-        PermissionData permissionData = mPermissions.get(permName);
-        if (permissionData == null) {
-            permissionData = new PermissionData(permission);
-            mPermissions.put(permName, permissionData);
-        }
-        return permissionData;
+
     }
 
     private void ensureNoPermissionData(String name) {
-        if (mPermissions == null) {
-            return;
+        synchronized (mLock) {
+            if (mPermissions == null) {
+                return;
+            }
+            mPermissions.remove(name);
+            if (mPermissions.isEmpty()) {
+                mPermissions = null;
+            }
         }
-        mPermissions.remove(name);
-        if (mPermissions.isEmpty()) {
-            mPermissions = null;
-        }
+
     }
 
     private static final class PermissionData {
diff --git a/services/core/java/com/android/server/policy/NavigationBarExperiments.java b/services/core/java/com/android/server/policy/NavigationBarExperiments.java
new file mode 100644
index 0000000..06772e3
--- /dev/null
+++ b/services/core/java/com/android/server/policy/NavigationBarExperiments.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.policy;
+
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
+import static android.view.WindowManagerPolicyConstants.NAV_BAR_BOTTOM;
+import static android.view.WindowManagerPolicyConstants.NAV_BAR_LEFT;
+import static android.view.WindowManagerPolicyConstants.NAV_BAR_RIGHT;
+
+import android.content.Context;
+import android.graphics.Rect;
+
+import com.android.server.policy.WindowManagerPolicy.WindowState;
+import com.android.server.wm.WindowFrames;
+
+/**
+ * This class acts as a proxy for Navigation Bar experiments enabled with custom overlays
+ * {@see OverlayManagerService}. By default with no overlays, this class will essentially do nothing
+ * and pass the original resource data back. By default the navigation bar height/width is the same
+ * as the frame height/width and therefore any offsets calculated will cancel out and do nothing.
+ * TODO(b/113952590): Remove class once experiment in bug is completed
+ */
+public class NavigationBarExperiments {
+
+    private int mNavigationBarHeight;
+    private int mNavigationBarWidth;
+
+    /**
+     * This represents the height of the navigation bar buttons. With no experiments or overlays
+     * enabled, the frame height is the same as the normal navigation bar height.
+     */
+    private int mNavigationBarFrameHeight;
+
+    /**
+     * This represents the width of the navigation bar buttons. With no experiments or overlays
+     * enabled, the frame width is the same as the normal navigation bar width.
+     */
+    private int mNavigationBarFrameWidth;
+
+    /**
+     * Call when configuration change to refresh resource dimensions
+     * @param systemUiContext to get the resource values
+     */
+    public void onConfigurationChanged(Context systemUiContext) {
+        // Cache all the values again
+        mNavigationBarHeight = systemUiContext.getResources().getDimensionPixelSize(
+                com.android.internal.R.dimen.navigation_bar_height);
+        mNavigationBarWidth = systemUiContext.getResources().getDimensionPixelSize(
+                com.android.internal.R.dimen.navigation_bar_width);
+        mNavigationBarFrameHeight = systemUiContext.getResources().getDimensionPixelSize(
+                com.android.internal.R.dimen.navigation_bar_frame_height);
+        mNavigationBarFrameWidth = systemUiContext.getResources().getDimensionPixelSize(
+                com.android.internal.R.dimen.navigation_bar_frame_width);
+    }
+
+    public int getNavigationBarHeight() {
+        return mNavigationBarHeight;
+    }
+
+    public int getNavigationBarWidth() {
+        return mNavigationBarWidth;
+    }
+
+    public int getNavigationBarFrameHeight() {
+        return mNavigationBarFrameHeight;
+    }
+
+    public int getNavigationBarFrameWidth() {
+        return mNavigationBarFrameWidth;
+    }
+
+    /**
+     * If navigation frame width/height is different than navigation bar width/height then only
+     * offset the ime's and home activity's window rects depending on the navigation bar position to
+     * add a gap where the navigation bar would have been drawn. With no experiments or overlays
+     * enabled, the height/width is the same as the frame height/width and the offsets calculated
+     * will be 0 and this function will do nothing.
+     * @param navPosition position of navigation bar (left, right or bottom)
+     * @param w the window that is being offset by experiment
+     */
+    public void offsetWindowFramesForNavBar(int navPosition, WindowState w) {
+        if (w.getAttrs().type != TYPE_INPUT_METHOD && w.getActivityType() != ACTIVITY_TYPE_HOME) {
+            return;
+        }
+
+        final WindowFrames windowFrames = w.getWindowFrames();
+        final Rect cf = windowFrames.mContentFrame;
+        switch (navPosition) {
+            case NAV_BAR_BOTTOM:
+                int navHeight = getNavigationBarFrameHeight() - getNavigationBarHeight();
+                if (navHeight > 0) {
+                    cf.bottom -= navHeight;
+                }
+                break;
+            case NAV_BAR_LEFT:
+            case NAV_BAR_RIGHT:
+                int navWidth = getNavigationBarFrameWidth() - getNavigationBarWidth();
+                if (navWidth > 0) {
+                    if (navPosition == NAV_BAR_LEFT) {
+                        cf.left += navWidth;
+                    } else {
+                        cf.right -= navWidth;
+                    }
+                }
+                break;
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index c5cee32..371ac4f 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -779,6 +779,10 @@
 
     private boolean mAodShowing;
 
+    // EXPERIMENT TODO(b/113952590): Remove once experiment in bug is completed
+    private NavigationBarExperiments mExperiments = new NavigationBarExperiments();
+    // EXPERIMENT END
+
     private static final int MSG_ENABLE_POINTER_LOCATION = 1;
     private static final int MSG_DISABLE_POINTER_LOCATION = 2;
     private static final int MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK = 3;
@@ -2607,6 +2611,10 @@
                     res.getDimensionPixelSize(
                             com.android.internal.R.dimen.navigation_bar_width_car_mode);
         }
+
+        // EXPERIMENT TODO(b/113952590): Remove once experiment in bug is completed
+        mExperiments.onConfigurationChanged(uiContext);
+        // EXPERIMENT END
     }
 
     @VisibleForTesting
@@ -4534,7 +4542,11 @@
             // It's a system nav bar or a portrait screen; nav bar goes on bottom.
             final int top = cutoutSafeUnrestricted.bottom
                     - getNavigationBarHeight(rotation, uiMode);
-            navigationFrame.set(0, top, displayWidth, displayFrames.mUnrestricted.bottom);
+            // EXPERIMENT TODO(b/113952590): Remove once experiment in bug is completed
+            final int topNavBar = cutoutSafeUnrestricted.bottom
+                    - mExperiments.getNavigationBarFrameHeight();
+            navigationFrame.set(0, topNavBar, displayWidth, displayFrames.mUnrestricted.bottom);
+            // EXPERIMENT END
             displayFrames.mStable.bottom = displayFrames.mStableFullscreen.bottom = top;
             if (transientNavBarShowing) {
                 mNavigationBarController.setBarShowingLw(true);
@@ -4557,7 +4569,11 @@
             // Landscape screen; nav bar goes to the right.
             final int left = cutoutSafeUnrestricted.right
                     - getNavigationBarWidth(rotation, uiMode);
-            navigationFrame.set(left, 0, displayFrames.mUnrestricted.right, displayHeight);
+            // EXPERIMENT TODO(b/113952590): Remove once experiment in bug is completed
+            final int leftNavBar = cutoutSafeUnrestricted.right
+                    - mExperiments.getNavigationBarFrameWidth();
+            navigationFrame.set(leftNavBar, 0, displayFrames.mUnrestricted.right, displayHeight);
+            // EXPERIMENT END
             displayFrames.mStable.right = displayFrames.mStableFullscreen.right = left;
             if (transientNavBarShowing) {
                 mNavigationBarController.setBarShowingLw(true);
@@ -4580,7 +4596,11 @@
             // Seascape screen; nav bar goes to the left.
             final int right = cutoutSafeUnrestricted.left
                     + getNavigationBarWidth(rotation, uiMode);
-            navigationFrame.set(displayFrames.mUnrestricted.left, 0, right, displayHeight);
+            // EXPERIMENT TODO(b/113952590): Remove once experiment in bug is completed
+            final int rightNavBar = cutoutSafeUnrestricted.left
+                    + mExperiments.getNavigationBarFrameWidth();
+            navigationFrame.set(displayFrames.mUnrestricted.left, 0, rightNavBar, displayHeight);
+            // EXPERIMENT END
             displayFrames.mStable.left = displayFrames.mStableFullscreen.left = right;
             if (transientNavBarShowing) {
                 mNavigationBarController.setBarShowingLw(true);
@@ -4790,6 +4810,12 @@
                     pf.left = df.left = of.left = cf.left = vf.left = displayFrames.mStable.left;
                 }
             }
+
+            // EXPERIMENT TODO(b/113952590): Remove once experiment in bug is completed
+            // Offset the ime to avoid overlapping with the nav bar
+            mExperiments.offsetWindowFramesForNavBar(mNavigationBarPosition, win);
+            // EXPERIMENT END
+
             // IM dock windows always go to the bottom of the screen.
             attrs.gravity = Gravity.BOTTOM;
             mDockLayer = win.getSurfaceLayer();
@@ -4930,6 +4956,10 @@
                     } else {
                         vf.set(cf);
                     }
+
+                    // EXPERIMENT TODO(b/113952590): Remove once experiment in bug is completed
+                    mExperiments.offsetWindowFramesForNavBar(mNavigationBarPosition, win);
+                    // EXPERIMENT END
                 }
             } else if (layoutInScreen || (sysUiFl
                     & (View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index db13cbc..e1c4acf 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -66,6 +66,7 @@
 import android.annotation.IntDef;
 import android.annotation.Nullable;
 import android.app.ActivityManager;
+import android.app.WindowConfiguration;
 import android.content.Context;
 import android.content.res.CompatibilityInfo;
 import android.content.res.Configuration;
@@ -437,6 +438,14 @@
         int getWindowingMode();
 
         /**
+         * Returns the {@link WindowConfiguration.ActivityType} associated with the configuration
+         * of this window.
+         */
+        default int getActivityType() {
+            return WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+        }
+
+        /**
          * Returns true if the window is current in multi-windowing mode. i.e. it shares the
          * screen with other application windows.
          */
diff --git a/services/core/java/com/android/server/role/RemoteRoleControllerService.java b/services/core/java/com/android/server/role/RemoteRoleControllerService.java
new file mode 100644
index 0000000..c737e8b
--- /dev/null
+++ b/services/core/java/com/android/server/role/RemoteRoleControllerService.java
@@ -0,0 +1,263 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.role;
+
+import android.annotation.MainThread;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.UserIdInt;
+import android.app.role.IRoleManagerCallback;
+import android.app.role.RoleManagerCallback;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.rolecontrollerservice.IRoleControllerService;
+import android.rolecontrollerservice.RoleControllerService;
+import android.util.Slog;
+
+import com.android.internal.util.function.pooled.PooledLambda;
+
+import java.util.ArrayDeque;
+import java.util.Queue;
+
+/**
+ * Handles connection with {@link RoleControllerService}.
+ */
+public class RemoteRoleControllerService {
+
+    private static final String LOG_TAG = RemoteRoleControllerService.class.getSimpleName();
+
+    @NonNull
+    private final Connection mConnection;
+
+    public RemoteRoleControllerService(@UserIdInt int userId, @NonNull Context context) {
+        mConnection = new Connection(userId, context);
+    }
+
+    /**
+     * Add a specific application to the holders of a role. If the role is exclusive, the previous
+     * holder will be replaced.
+     *
+     * @see RoleControllerService#onAddRoleHolder(String, String, RoleManagerCallback)
+     */
+    public void onAddRoleHolder(@NonNull String roleName, @NonNull String packageName,
+            @NonNull IRoleManagerCallback callback) {
+        mConnection.enqueueCall(new Connection.Call((service, callbackDelegate) ->
+                service.onAddRoleHolder(roleName, packageName, callbackDelegate), callback));
+    }
+
+    /**
+     * Remove a specific application from the holders of a role.
+     *
+     * @see RoleControllerService#onRemoveRoleHolder(String, String, RoleManagerCallback)
+     */
+    public void onRemoveRoleHolder(@NonNull String roleName, @NonNull String packageName,
+            @NonNull IRoleManagerCallback callback) {
+        mConnection.enqueueCall(new Connection.Call((service, callbackDelegate) ->
+                service.onRemoveRoleHolder(roleName, packageName, callbackDelegate), callback));
+    }
+
+    /**
+     * Remove all holders of a role.
+     *
+     * @see RoleControllerService#onClearRoleHolders(String, RoleManagerCallback)
+     */
+    public void onClearRoleHolders(@NonNull String roleName,
+            @NonNull IRoleManagerCallback callback) {
+        mConnection.enqueueCall(new Connection.Call((service, callbackDelegate) ->
+                service.onClearRoleHolders(roleName, callbackDelegate), callback));
+    }
+
+    private static final class Connection implements ServiceConnection {
+
+        private static final long UNBIND_DELAY_MILLIS = 15 * 1000;
+
+        @UserIdInt
+        private final int mUserId;
+
+        @NonNull
+        private final Context mContext;
+
+        private boolean mBound;
+
+        @Nullable
+        private IRoleControllerService mService;
+
+        @NonNull
+        private final Queue<Call> mPendingCalls = new ArrayDeque<>();
+
+        @NonNull
+        private final Runnable mUnbindRunnable = this::unbind;
+
+        Connection(@UserIdInt int userId, @NonNull Context context) {
+            mUserId = userId;
+            mContext = context;
+        }
+
+        @MainThread
+        @Override
+        public void onServiceConnected(@NonNull ComponentName name, @NonNull IBinder service) {
+            mService = IRoleControllerService.Stub.asInterface(service);
+            executePendingCalls();
+        }
+
+        @MainThread
+        private void executePendingCalls() {
+            while (!mPendingCalls.isEmpty()) {
+                Call call = mPendingCalls.poll();
+                call.execute(mService);
+            }
+            scheduleUnbind();
+        }
+
+        @MainThread
+        @Override
+        public void onServiceDisconnected(@NonNull ComponentName name) {
+            mService = null;
+        }
+
+        @MainThread
+        @Override
+        public void onBindingDied(@NonNull ComponentName name) {
+            unbind();
+        }
+
+        public void enqueueCall(@NonNull Call call) {
+            Handler.getMain().post(PooledLambda.obtainRunnable(this::executeCall, call));
+        }
+
+        @MainThread
+        private void executeCall(@NonNull Call call) {
+            ensureBound();
+            if (mService == null) {
+                mPendingCalls.offer(call);
+                return;
+            }
+            call.execute(mService);
+            scheduleUnbind();
+        }
+
+        @MainThread
+        private void ensureBound() {
+            Handler.getMain().removeCallbacks(mUnbindRunnable);
+            if (!mBound) {
+                Intent intent = new Intent(RoleControllerService.SERVICE_INTERFACE);
+                intent.setPackage(mContext.getPackageManager()
+                        .getPermissionControllerPackageName());
+                mBound = mContext.bindServiceAsUser(intent, this, Context.BIND_AUTO_CREATE,
+                        UserHandle.of(mUserId));
+            }
+        }
+
+        private void scheduleUnbind() {
+            Handler mainHandler = Handler.getMain();
+            mainHandler.removeCallbacks(mUnbindRunnable);
+            mainHandler.postDelayed(mUnbindRunnable, UNBIND_DELAY_MILLIS);
+        }
+
+        @MainThread
+        private void unbind() {
+            if (mBound) {
+                mService = null;
+                mContext.unbindService(this);
+                mBound = false;
+            }
+        }
+
+        public static class Call {
+
+            private static final int TIMEOUT_MILLIS = 15 * 1000;
+
+            @NonNull
+            private final CallExecutor mCallExecutor;
+
+            @NonNull
+            private final IRoleManagerCallback mCallback;
+
+            @NonNull
+            private final Handler mMainHandler = Handler.getMain();
+
+            @NonNull
+            private final Runnable mTimeoutRunnable = () -> notifyCallback(false);
+
+            private boolean mCallbackNotified;
+
+            private Call(@NonNull CallExecutor callExecutor,
+                    @NonNull IRoleManagerCallback callback) {
+                mCallExecutor = callExecutor;
+                mCallback = callback;
+            }
+
+            @MainThread
+            public void execute(IRoleControllerService service) {
+                try {
+                    mMainHandler.postDelayed(mTimeoutRunnable, TIMEOUT_MILLIS);
+                    mCallExecutor.execute(service, new CallbackDelegate());
+                } catch (RemoteException e) {
+                    Slog.e(LOG_TAG, "Error calling RoleControllerService", e);
+                    notifyCallback(false);
+                }
+            }
+
+            @MainThread
+            private void notifyCallback(boolean success) {
+                if (mCallbackNotified) {
+                    return;
+                }
+                mCallbackNotified = true;
+                mMainHandler.removeCallbacks(mTimeoutRunnable);
+                try {
+                    if (success) {
+                        mCallback.onSuccess();
+                    } else {
+                        mCallback.onFailure();
+                    }
+                } catch (RemoteException e) {
+                    Slog.e(LOG_TAG, "Error calling " + (success ? "onSuccess()" : "onFailure()")
+                            + " callback", e);
+                }
+            }
+
+            @FunctionalInterface
+            public interface CallExecutor {
+
+                @MainThread
+                void execute(IRoleControllerService service, IRoleManagerCallback callbackDelegate)
+                        throws RemoteException;
+            }
+
+            private class CallbackDelegate extends IRoleManagerCallback.Stub {
+
+                @Override
+                public void onSuccess() throws RemoteException {
+                    mMainHandler.post(PooledLambda.obtainRunnable(Call.this::notifyCallback, true));
+                }
+
+                @Override
+                public void onFailure() throws RemoteException {
+                    mMainHandler.post(PooledLambda.obtainRunnable(Call.this::notifyCallback,
+                            false));
+                }
+            }
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/role/RoleManagerService.java b/services/core/java/com/android/server/role/RoleManagerService.java
new file mode 100644
index 0000000..5c9cef5
--- /dev/null
+++ b/services/core/java/com/android/server/role/RoleManagerService.java
@@ -0,0 +1,261 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.role;
+
+import android.Manifest;
+import android.annotation.CheckResult;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.UserIdInt;
+import android.app.ActivityManager;
+import android.app.AppOpsManager;
+import android.app.role.IRoleManager;
+import android.app.role.IRoleManagerCallback;
+import android.app.role.RoleManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.UserHandle;
+import android.os.UserManagerInternal;
+import android.text.TextUtils;
+import android.util.ArraySet;
+import android.util.Slog;
+import android.util.SparseArray;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.Preconditions;
+import com.android.server.LocalServices;
+import com.android.server.SystemService;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Service for role management.
+ *
+ * @see RoleManager
+ */
+public class RoleManagerService extends SystemService {
+
+    private static final String LOG_TAG = RoleManagerService.class.getSimpleName();
+
+    @NonNull
+    private final UserManagerInternal mUserManagerInternal;
+    @NonNull
+    private final AppOpsManager mAppOpsManager;
+
+    @NonNull
+    private final Object mLock = new Object();
+
+    /**
+     * Maps user id to its state.
+     */
+    @GuardedBy("mLock")
+    @NonNull
+    private final SparseArray<RoleUserState> mUserStates = new SparseArray<>();
+
+    /**
+     * Maps user id to its controller service.
+     */
+    @GuardedBy("mLock")
+    @NonNull
+    private final SparseArray<RemoteRoleControllerService> mControllerServices =
+            new SparseArray<>();
+
+    public RoleManagerService(@NonNull Context context) {
+        super(context);
+
+        mUserManagerInternal = LocalServices.getService(UserManagerInternal.class);
+        mAppOpsManager = context.getSystemService(AppOpsManager.class);
+
+        registerUserRemovedReceiver();
+    }
+
+    private void registerUserRemovedReceiver() {
+        IntentFilter intentFilter = new IntentFilter();
+        intentFilter.addAction(Intent.ACTION_USER_REMOVED);
+        getContext().registerReceiverAsUser(new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                if (TextUtils.equals(intent.getAction(), Intent.ACTION_USER_REMOVED)) {
+                    int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
+                    onRemoveUser(userId);
+                }
+            }
+        }, UserHandle.ALL, intentFilter, null, null);
+    }
+
+    @Override
+    public void onStart() {
+        publishBinderService(Context.ROLE_SERVICE, new Stub());
+    }
+
+    @Override
+    public void onStartUser(@UserIdInt int userId) {
+        synchronized (mLock) {
+            getUserStateLocked(userId);
+        }
+    }
+
+    @GuardedBy("mLock")
+    @NonNull
+    private RoleUserState getUserStateLocked(@UserIdInt int userId) {
+        RoleUserState userState = mUserStates.get(userId);
+        if (userState == null) {
+            userState = new RoleUserState(userId);
+            userState.readSyncLocked();
+            mUserStates.put(userId, userState);
+        }
+        return userState;
+    }
+
+    @GuardedBy("mLock")
+    @NonNull
+    private RemoteRoleControllerService getControllerService(@UserIdInt int userId) {
+        RemoteRoleControllerService controllerService = mControllerServices.get(userId);
+        if (controllerService == null) {
+            controllerService = new RemoteRoleControllerService(userId, getContext());
+            mControllerServices.put(userId, controllerService);
+        }
+        return controllerService;
+    }
+
+    private void onRemoveUser(@UserIdInt int userId) {
+        synchronized (mLock) {
+            mControllerServices.remove(userId);
+            RoleUserState userState = mUserStates.removeReturnOld(userId);
+            if (userState != null) {
+                userState.destroySyncLocked();
+            }
+        }
+    }
+
+    private class Stub extends IRoleManager.Stub {
+
+        @Override
+        public boolean isRoleAvailable(@NonNull String roleName) {
+            Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
+
+            int userId = UserHandle.getUserId(getCallingUid());
+            synchronized (mLock) {
+                RoleUserState userState = getUserStateLocked(userId);
+                return userState.isRoleAvailableLocked(roleName);
+            }
+        }
+
+        @Override
+        public boolean isRoleHeld(@NonNull String roleName, @NonNull String packageName) {
+            Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
+            Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
+            int callingUid = getCallingUid();
+            mAppOpsManager.checkPackage(callingUid, packageName);
+
+            int userId = UserHandle.getUserId(callingUid);
+            ArraySet<String> roleHolders = getRoleHoldersInternal(roleName, userId);
+            if (roleHolders == null) {
+                return false;
+            }
+            return roleHolders.contains(packageName);
+        }
+
+        @NonNull
+        @Override
+        public List<String> getRoleHoldersAsUser(@NonNull String roleName, @UserIdInt int userId) {
+            Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
+            if (!mUserManagerInternal.exists(userId)) {
+                Slog.e(LOG_TAG, "user " + userId + " does not exist");
+                return Collections.emptyList();
+            }
+            userId = handleIncomingUser(userId, "getRoleHoldersAsUser");
+            getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS,
+                    "getRoleHoldersAsUser");
+
+            ArraySet<String> roleHolders = getRoleHoldersInternal(roleName, userId);
+            if (roleHolders == null) {
+                return Collections.emptyList();
+            }
+            return new ArrayList<>(roleHolders);
+        }
+
+        @Nullable
+        private ArraySet<String> getRoleHoldersInternal(@NonNull String roleName,
+                @UserIdInt int userId) {
+            synchronized (mLock) {
+                RoleUserState userState = getUserStateLocked(userId);
+                return userState.getRoleHoldersLocked(roleName);
+            }
+        }
+
+        @Override
+        public void addRoleHolderAsUser(@NonNull String roleName, @NonNull String packageName,
+                @UserIdInt int userId, @NonNull IRoleManagerCallback callback) {
+            Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
+            Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
+            Preconditions.checkNotNull(callback, "callback cannot be null");
+            if (!mUserManagerInternal.exists(userId)) {
+                Slog.e(LOG_TAG, "user " + userId + " does not exist");
+                return;
+            }
+            userId = handleIncomingUser(userId, "addRoleHolderAsUser");
+            getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS,
+                    "addRoleHolderAsUser");
+
+            getControllerService(userId).onAddRoleHolder(roleName, packageName, callback);
+        }
+
+        @Override
+        public void removeRoleHolderAsUser(@NonNull String roleName, @NonNull String packageName,
+                @UserIdInt int userId, @NonNull IRoleManagerCallback callback) {
+            Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
+            Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
+            Preconditions.checkNotNull(callback, "callback cannot be null");
+            if (!mUserManagerInternal.exists(userId)) {
+                Slog.e(LOG_TAG, "user " + userId + " does not exist");
+                return;
+            }
+            userId = handleIncomingUser(userId, "removeRoleHolderAsUser");
+            getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS,
+                    "removeRoleHolderAsUser");
+
+            getControllerService(userId).onRemoveRoleHolder(roleName, packageName,
+                    callback);
+        }
+
+        @Override
+        public void clearRoleHoldersAsUser(@NonNull String roleName, @UserIdInt int userId,
+                @NonNull IRoleManagerCallback callback) {
+            Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
+            Preconditions.checkNotNull(callback, "callback cannot be null");
+            if (!mUserManagerInternal.exists(userId)) {
+                Slog.e(LOG_TAG, "user " + userId + " does not exist");
+                return;
+            }
+            userId = handleIncomingUser(userId, "clearRoleHoldersAsUser");
+            getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS,
+                    "clearRoleHoldersAsUser");
+            getControllerService(userId).onClearRoleHolders(roleName, callback);
+        }
+
+        @CheckResult
+        private int handleIncomingUser(@UserIdInt int userId, @NonNull String name) {
+            return ActivityManager.handleIncomingUser(getCallingPid(), getCallingUid(), userId,
+                    false, true, name, null);
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/role/RoleUserState.java b/services/core/java/com/android/server/role/RoleUserState.java
new file mode 100644
index 0000000..bd54491
--- /dev/null
+++ b/services/core/java/com/android/server/role/RoleUserState.java
@@ -0,0 +1,370 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.role;
+
+import android.annotation.CheckResult;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.UserIdInt;
+import android.annotation.WorkerThread;
+import android.os.Environment;
+import android.os.Handler;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+import android.util.AtomicFile;
+import android.util.Slog;
+import android.util.Xml;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.os.BackgroundThread;
+import com.android.internal.util.function.pooled.PooledLambda;
+
+import libcore.io.IoUtils;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * Stores the state of roles for a user.
+ */
+public class RoleUserState {
+
+    private static final String LOG_TAG = RoleUserState.class.getSimpleName();
+
+    public static final int VERSION_UNDEFINED = -1;
+
+    private static final String ROLES_FILE_NAME = "roles.xml";
+
+    private static final String TAG_ROLES = "roles";
+    private static final String TAG_ROLE = "role";
+    private static final String TAG_HOLDER = "holder";
+    private static final String ATTRIBUTE_VERSION = "version";
+    private static final String ATTRIBUTE_NAME = "name";
+
+    @UserIdInt
+    private final int mUserId;
+
+    @GuardedBy("RoleManagerService.mLock")
+    private int mVersion = VERSION_UNDEFINED;
+
+    /**
+     * Maps role names to its holders' package names. The values should never be null.
+     */
+    @GuardedBy("RoleManagerService.mLock")
+    private ArrayMap<String, ArraySet<String>> mRoles = new ArrayMap<>();
+
+    @GuardedBy("RoleManagerService.mLock")
+    private boolean mDestroyed;
+
+    private final Handler mWriteHandler = new Handler(BackgroundThread.getHandler().getLooper());
+
+    public RoleUserState(@UserIdInt int userId) {
+        mUserId = userId;
+    }
+
+    /**
+     * Get the version of this user state.
+     */
+    @GuardedBy("RoleManagerService.mLock")
+    public int getVersionLocked() {
+        throwIfDestroyedLocked();
+        return mVersion;
+    }
+
+    /**
+     * Set the version of this user state.
+     *
+     * @param version the version to set
+     */
+    @GuardedBy("RoleManagerService.mLock")
+    public void setVersionLocked(int version) {
+        throwIfDestroyedLocked();
+        mVersion = version;
+    }
+
+    /**
+     * Get whether the role is available.
+     *
+     * @param roleName the name of the role to get the holders for
+     *
+     * @return whether the role is available
+     */
+    @GuardedBy("RoleManagerService.mLock")
+    public boolean isRoleAvailableLocked(@NonNull String roleName) {
+        throwIfDestroyedLocked();
+        return mRoles.containsKey(roleName);
+    }
+
+    /**
+     * Get the holders of a role.
+     *
+     * @param roleName the name of the role to query for
+     *
+     * @return the set of role holders. {@code null} should not be returned and indicates an issue.
+     */
+    @GuardedBy("RoleManagerService.mLock")
+    @Nullable
+    public ArraySet<String> getRoleHoldersLocked(@NonNull String roleName) {
+        throwIfDestroyedLocked();
+        return mRoles.get(roleName);
+    }
+
+    /**
+     * Add a holder to a role.
+     *
+     * @param roleName the name of the role to add the holder to
+     * @param packageName the package name of the new holder
+     *
+     * @return {@code false} only if the set of role holders is null, which should not happen and
+     *         indicates an issue.
+     */
+    @CheckResult
+    @GuardedBy("RoleManagerService.mLock")
+    public boolean addRoleHolderLocked(@NonNull String roleName, @NonNull String packageName) {
+        throwIfDestroyedLocked();
+        ArraySet<String> roleHolders = mRoles.get(roleName);
+        if (roleHolders == null) {
+            return false;
+        }
+        roleHolders.add(packageName);
+        return true;
+    }
+
+    /**
+     * Remove a holder from a role.
+     *
+     * @param roleName the name of the role to remove the holder from
+     * @param packageName the package name of the holder to remove
+     *
+     * @return {@code false} only if the set of role holders is null, which should not happen and
+     *         indicates an issue.
+     */
+    @CheckResult
+    @GuardedBy("RoleManagerService.mLock")
+    public boolean removeRoleHolderLocked(@NonNull String roleName, @NonNull String packageName) {
+        throwIfDestroyedLocked();
+        ArraySet<String> roleHolders = mRoles.get(roleName);
+        if (roleHolders == null) {
+            return false;
+        }
+        roleHolders.remove(packageName);
+        return true;
+    }
+
+    /**
+     * Remove all holders of a role.
+     *
+     * @param roleName the name of the role to remove all its holders
+     *
+     * @return {@code false} only if the set of role holders is null, which should not happen and
+     *         indicates an issue.
+     */
+    @GuardedBy("RoleManagerService.mLock")
+    public boolean clearRoleHolderLocked(@NonNull String roleName) {
+        throwIfDestroyedLocked();
+        ArraySet<String> roleHolders = mRoles.get(roleName);
+        if (roleHolders == null) {
+            return false;
+        }
+        roleHolders.clear();
+        return true;
+    }
+
+    /**
+     * Schedule writing the state to file.
+     */
+    @GuardedBy("RoleManagerService.mLock")
+    public void writeAsyncLocked() {
+        throwIfDestroyedLocked();
+        int version = mVersion;
+        ArrayMap<String, ArraySet<String>> roles = new ArrayMap<>();
+        for (int i = 0, size = mRoles.size(); i < size; ++i) {
+            String roleName = mRoles.keyAt(i);
+            ArraySet<String> roleHolders = mRoles.valueAt(i);
+            roleHolders = new ArraySet<>(roleHolders);
+            roles.put(roleName, roleHolders);
+        }
+        mWriteHandler.removeCallbacksAndMessages(null);
+        mWriteHandler.sendMessage(PooledLambda.obtainMessage(this::writeSync, version, roles));
+    }
+
+    @WorkerThread
+    private void writeSync(int version, @NonNull ArrayMap<String, ArraySet<String>> roles) {
+        AtomicFile destination = new AtomicFile(getFile(mUserId), "roles-" + mUserId);
+        FileOutputStream out = null;
+        try {
+            out = destination.startWrite();
+
+            XmlSerializer serializer = Xml.newSerializer();
+            serializer.setOutput(out, StandardCharsets.UTF_8.name());
+            serializer.setFeature(
+                    "http://xmlpull.org/v1/doc/features.html#indent-output", true);
+            serializer.startDocument(null, true);
+
+            serializeRoles(serializer, version, roles);
+
+            serializer.endDocument();
+            destination.finishWrite(out);
+        } catch (Throwable t) {
+            // Any error while writing is fatal.
+            Slog.wtf(LOG_TAG, "Failed to write roles file, restoring backup", t);
+            destination.failWrite(out);
+        } finally {
+            IoUtils.closeQuietly(out);
+        }
+    }
+
+    @WorkerThread
+    private void serializeRoles(@NonNull XmlSerializer serializer, int version,
+            @NonNull ArrayMap<String, ArraySet<String>> roles) throws IOException {
+        serializer.startTag(null, TAG_ROLES);
+        serializer.attribute(null, ATTRIBUTE_VERSION, Integer.toString(version));
+        for (int i = 0, size = roles.size(); i < size; ++i) {
+            String roleName = roles.keyAt(i);
+            ArraySet<String> roleHolders = roles.valueAt(i);
+            serializer.startTag(null, TAG_ROLE);
+            serializer.attribute(null, ATTRIBUTE_NAME, roleName);
+            serializeRoleHolders(serializer, roleHolders);
+            serializer.endTag(null, TAG_ROLE);
+        }
+        serializer.endTag(null, TAG_ROLES);
+    }
+
+    @WorkerThread
+    private void serializeRoleHolders(@NonNull XmlSerializer serializer,
+            @NonNull ArraySet<String> roleHolders) throws IOException {
+        for (int i = 0, size = roleHolders.size(); i < size; ++i) {
+            String roleHolder = roleHolders.valueAt(i);
+            serializer.startTag(null, TAG_HOLDER);
+            serializer.attribute(null, ATTRIBUTE_NAME, roleHolder);
+            serializer.endTag(null, TAG_HOLDER);
+        }
+    }
+
+    /**
+     * Read the state from file.
+     */
+    @GuardedBy("RoleManagerService.mLock")
+    public void readSyncLocked() {
+        if (mRoles != null) {
+            throw new IllegalStateException("This RoleUserState has already read the XML file");
+        }
+        File file = getFile(mUserId);
+        FileInputStream in;
+        try {
+            in = new AtomicFile(file).openRead();
+        } catch (FileNotFoundException e) {
+            Slog.i(LOG_TAG, "No roles file found");
+            return;
+        }
+
+        try {
+            XmlPullParser parser = Xml.newPullParser();
+            parser.setInput(in, null);
+            parseXmlLocked(parser);
+        } catch (XmlPullParserException | IOException e) {
+            throw new IllegalStateException("Failed to parse roles file: " + file , e);
+        } finally {
+            IoUtils.closeQuietly(in);
+        }
+    }
+
+    private void parseXmlLocked(@NonNull XmlPullParser parser) throws IOException,
+            XmlPullParserException {
+        int outerDepth = parser.getDepth();
+        int type;
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+                continue;
+            }
+            if (parser.getName().equals(TAG_ROLES)) {
+                parseRolesLocked(parser);
+                return;
+            }
+        }
+    }
+
+    private void parseRolesLocked(@NonNull XmlPullParser parser) throws IOException,
+            XmlPullParserException {
+        mVersion = Integer.parseInt(parser.getAttributeValue(null, ATTRIBUTE_VERSION));
+        mRoles = new ArrayMap<>();
+        int outerDepth = parser.getDepth();
+        int type;
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+                continue;
+            }
+            if (parser.getName().equals(TAG_ROLE)) {
+                String roleName = parser.getAttributeValue(null, ATTRIBUTE_NAME);
+                ArraySet<String> roleHolders = parseRoleHoldersLocked(parser);
+                mRoles.put(roleName, roleHolders);
+            }
+        }
+    }
+
+    @NonNull
+    private ArraySet<String> parseRoleHoldersLocked(@NonNull XmlPullParser parser)
+            throws IOException, XmlPullParserException {
+        ArraySet<String> roleHolders = new ArraySet<>();
+        int outerDepth = parser.getDepth();
+        int type;
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+                continue;
+            }
+            if (parser.getName().equals(TAG_HOLDER)) {
+                String roleHolder = parser.getAttributeValue(null, ATTRIBUTE_NAME);
+                roleHolders.add(roleHolder);
+            }
+        }
+        return roleHolders;
+    }
+
+    /**
+     * Destroy this state and delete the corresponding file. Any pending writes to the file will be
+     * cancelled and any future interaction with this state will throw an exception.
+     */
+    @GuardedBy("RoleManagerService.mLock")
+    public void destroySyncLocked() {
+        throwIfDestroyedLocked();
+        mWriteHandler.removeCallbacksAndMessages(null);
+        getFile(mUserId).delete();
+        mDestroyed = true;
+    }
+
+    @GuardedBy("RoleManagerService.mLock")
+    private void throwIfDestroyedLocked() {
+        if (mDestroyed) {
+            throw new IllegalStateException("This RoleUserState has already been destroyed");
+        }
+    }
+
+    private static @NonNull File getFile(@UserIdInt int userId) {
+        return new File(Environment.getUserSystemDirectory(userId), ROLES_FILE_NAME);
+    }
+}
diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java
index f10fe58..7b35b91 100644
--- a/services/core/java/com/android/server/stats/StatsCompanionService.java
+++ b/services/core/java/com/android/server/stats/StatsCompanionService.java
@@ -80,6 +80,7 @@
 import com.android.internal.net.NetworkStatsFactory;
 import com.android.internal.os.BinderCallsStats.ExportedCallStat;
 import com.android.internal.os.KernelCpuSpeedReader;
+import com.android.internal.os.KernelCpuThreadReader;
 import com.android.internal.os.KernelUidCpuActiveTimeReader;
 import com.android.internal.os.KernelUidCpuClusterTimeReader;
 import com.android.internal.os.KernelUidCpuFreqTimeReader;
@@ -191,6 +192,8 @@
             new KernelUidCpuClusterTimeReader();
     private StoragedUidIoStatsReader mStoragedUidIoStatsReader =
             new StoragedUidIoStatsReader();
+    @Nullable
+    private final KernelCpuThreadReader mKernelCpuThreadReader;
 
     private static IThermalService sThermalService;
     private File mBaseDir =
@@ -265,6 +268,7 @@
         handlerThread.start();
         mHandler = new CompanionHandler(handlerThread.getLooper());
 
+        mKernelCpuThreadReader = KernelCpuThreadReader.create();
     }
 
     @Override
@@ -1017,6 +1021,7 @@
             e.writeLong(processMemoryState.pgmajfault);
             e.writeLong(processMemoryState.rssInBytes);
             e.writeLong(processMemoryState.rssHighWatermarkInBytes);
+            e.writeLong(processMemoryState.startTimeNanos);
             pulledData.add(e);
         }
     }
@@ -1034,7 +1039,7 @@
         binderStats.reset();
         for (ExportedCallStat callStat : callStats) {
             StatsLogEventWrapper e = new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
-            e.writeInt(callStat.uid);
+            e.writeInt(callStat.workSourceUid);
             e.writeString(callStat.className);
             e.writeString(callStat.methodName);
             e.writeLong(callStat.callCount);
@@ -1444,6 +1449,46 @@
         }
     }
 
+    private void pullCpuTimePerThreadFreq(int tagId, long elapsedNanos, long wallClockNanos,
+            List<StatsLogEventWrapper> pulledData) {
+        if (this.mKernelCpuThreadReader == null) {
+            return;
+        }
+        KernelCpuThreadReader.ProcessCpuUsage processCpuUsage = this.mKernelCpuThreadReader
+                .getCurrentProcessCpuUsage();
+        if (processCpuUsage == null) {
+            return;
+        }
+        int[] cpuFrequencies = mKernelCpuThreadReader.getCpuFrequenciesKhz();
+        for (KernelCpuThreadReader.ThreadCpuUsage threadCpuUsage
+                : processCpuUsage.threadCpuUsages) {
+            if (threadCpuUsage.usageTimesMillis.length != cpuFrequencies.length) {
+                Slog.w(TAG, "Unexpected number of usage times,"
+                        + " expected " + cpuFrequencies.length
+                        + " but got " + threadCpuUsage.usageTimesMillis.length);
+                continue;
+            }
+
+            for (int i = 0; i < threadCpuUsage.usageTimesMillis.length; i++) {
+                // Do not report CPU usage at a frequency when it's zero
+                if (threadCpuUsage.usageTimesMillis[i] == 0) {
+                    continue;
+                }
+
+                StatsLogEventWrapper e =
+                        new StatsLogEventWrapper(tagId, elapsedNanos, wallClockNanos);
+                e.writeInt(processCpuUsage.uid);
+                e.writeInt(processCpuUsage.processId);
+                e.writeInt(threadCpuUsage.threadId);
+                e.writeString(processCpuUsage.processName);
+                e.writeString(threadCpuUsage.threadName);
+                e.writeInt(cpuFrequencies[i]);
+                e.writeInt(threadCpuUsage.usageTimesMillis[i]);
+                pulledData.add(e);
+            }
+        }
+    }
+
     /**
      * Pulls various data.
      */
@@ -1582,6 +1627,10 @@
                 pullProcessCpuTime(tagId, elapsedNanos, wallClockNanos, ret);
                 break;
             }
+            case StatsLog.CPU_TIME_PER_THREAD_FREQ: {
+                pullCpuTimePerThreadFreq(tagId, elapsedNanos, wallClockNanos, ret);
+                break;
+            }
             default:
                 Slog.w(TAG, "No such tagId data as " + tagId);
                 return null;
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
index 443d6fe..b011da6 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
@@ -410,6 +410,9 @@
             String[] args, int opti, boolean dumpAll, boolean dumpVisibleStacksOnly,
             boolean dumpFocusedStackOnly);
 
+    /** Dump the current state for inclusion in oom dump. */
+    public abstract void dumpForOom(PrintWriter pw);
+
     /** @return true if it the activity management system is okay with GC running now. */
     public abstract boolean canGcNow();
 
@@ -447,4 +450,24 @@
 
     public abstract void onUidAddedToPendingTempWhitelist(int uid, String tag);
     public abstract void onUidRemovedFromPendingTempWhitelist(int uid);
+
+    /** Handle app crash event in {@link android.app.IActivityController} if there is one. */
+    public abstract boolean handleAppCrashInActivityController(String processName, int pid,
+            String shortMsg, String longMsg, long timeMillis, String stackTrace,
+            Runnable killCrashingAppCallback);
+
+    public abstract void removeRecentTasksByPackageName(String packageName, int userId);
+    public abstract void cleanupRecentTasksForUser(int userId);
+    public abstract void loadRecentTasksForUser(int userId);
+    public abstract void onPackagesSuspendedChanged(String[] packages, boolean suspended,
+            int userId);
+    /** Flush recent tasks to disk. */
+    public abstract void flushRecentTasks();
+
+    public abstract WindowProcessController getHomeProcess();
+    public abstract WindowProcessController getPreviousProcess();
+
+    public abstract void clearLockedTasks(String reason);
+    public abstract void updateUserConfiguration();
+    public abstract boolean canShowErrorDialogs();
 }
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index ca23360..fa9ae52 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -120,6 +120,7 @@
 import static com.android.server.wm.WindowStateAnimator.READY_TO_SHOW;
 
 import android.annotation.CallSuper;
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.content.pm.PackageManager;
 import android.content.res.CompatibilityInfo;
@@ -137,6 +138,7 @@
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.os.Trace;
+import android.os.UserHandle;
 import android.util.ArraySet;
 import android.util.DisplayMetrics;
 import android.util.Slog;
@@ -162,6 +164,8 @@
 import com.android.server.wm.utils.WmDisplayCutout;
 
 import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.Comparator;
 import java.util.HashMap;
@@ -183,6 +187,18 @@
         implements WindowManagerPolicy.DisplayContentInfo {
     private static final String TAG = TAG_WITH_CLASS_NAME ? "DisplayContent" : TAG_WM;
 
+    /** The default scaling mode that scales content automatically. */
+    static final int FORCE_SCALING_MODE_AUTO = 0;
+    /** For {@link #setForcedScalingMode} to apply flag {@link Display#FLAG_SCALING_DISABLED}. */
+    static final int FORCE_SCALING_MODE_DISABLED = 1;
+
+    @IntDef(prefix = { "FORCE_SCALING_MODE_" }, value = {
+            FORCE_SCALING_MODE_AUTO,
+            FORCE_SCALING_MODE_DISABLED
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    @interface ForceScalingMode {}
+
     /** Unique identifier of this stack. */
     private final int mDisplayId;
 
@@ -237,6 +253,11 @@
      * @see WindowManagerService#setForcedDisplayDensityForUser(int, int, int)
      */
     int mBaseDisplayDensity = 0;
+
+    /**
+     * Whether to disable display scaling. This can be set via shell command "adb shell wm scaling".
+     * @see WindowManagerService#setForcedDisplayScalingMode(int, int)
+     */
     boolean mDisplayScalingDisabled;
     private final DisplayInfo mDisplayInfo = new DisplayInfo();
     private final Display mDisplay;
@@ -836,6 +857,7 @@
         // {@link DisplayContent} ready for use.
         mDisplayReady = true;
 
+        mService.mAnimator.addDisplayLocked(mDisplayId);
         mInputMonitor = new InputMonitor(service, mDisplayId);
 
         if (mService.mInputManager != null) {
@@ -1790,7 +1812,7 @@
 
         // The display size information is heavily dependent on the resources in the current
         // configuration, so we need to reconfigure it every time the configuration changes.
-        // See {@link PhoneWindowManager#setInitialDisplaySize}...sigh...
+        // See {@link #configureDisplayPolicy}...sigh...
         mService.reconfigureDisplayLocked(this);
 
         final DockedStackDividerController dividerController = getDockedDividerController();
@@ -2027,6 +2049,68 @@
         updateBounds();
     }
 
+    /**
+     * Forces this display to use the specified density.
+     *
+     * @param density The density in DPI to use. If the value equals to initial density, the setting
+     *                will be cleared.
+     * @param userId The target user to apply. Only meaningful when this is default display. If the
+     *               user id is {@link UserHandle#USER_CURRENT}, it means to apply current settings
+     *               so only need to configure display.
+     */
+    void setForcedDensity(int density, int userId) {
+        final boolean clear = density == mInitialDisplayDensity;
+        final boolean updateCurrent = userId == UserHandle.USER_CURRENT;
+        if (mService.mCurrentUserId == userId || updateCurrent) {
+            mBaseDisplayDensity = density;
+            mService.reconfigureDisplayLocked(this);
+        }
+        if (updateCurrent) {
+            // We are applying existing settings so no need to save it again.
+            return;
+        }
+
+        if (density == mInitialDisplayDensity) {
+            density = 0;
+        }
+        mService.mDisplaySettings.setForcedDensity(this, density, userId);
+    }
+
+    /** @param mode {@link #FORCE_SCALING_MODE_AUTO} or {@link #FORCE_SCALING_MODE_DISABLED}. */
+    void setForcedScalingMode(@ForceScalingMode int mode) {
+        if (mode != FORCE_SCALING_MODE_DISABLED) {
+            mode = FORCE_SCALING_MODE_AUTO;
+        }
+
+        mDisplayScalingDisabled = (mode != FORCE_SCALING_MODE_AUTO);
+        Slog.i(TAG_WM, "Using display scaling mode: " + (mDisplayScalingDisabled ? "off" : "auto"));
+        mService.reconfigureDisplayLocked(this);
+
+        mService.mDisplaySettings.setForcedScalingMode(this, mode);
+    }
+
+    /** If the given width and height equal to initial size, the setting will be cleared. */
+    void setForcedSize(int width, int height) {
+        final boolean clear = mInitialDisplayWidth == width && mInitialDisplayHeight == height;
+        if (!clear) {
+            // Set some sort of reasonable bounds on the size of the display that we will try
+            // to emulate.
+            final int minSize = 200;
+            final int maxScale = 2;
+            width = Math.min(Math.max(width, minSize), mInitialDisplayWidth * maxScale);
+            height = Math.min(Math.max(height, minSize), mInitialDisplayHeight * maxScale);
+        }
+
+        Slog.i(TAG_WM, "Using new display size: " + width + "x" + height);
+        updateBaseDisplayMetrics(width, height, mBaseDisplayDensity);
+        mService.reconfigureDisplayLocked(this);
+
+        if (clear) {
+            width = height = 0;
+        }
+        mService.mDisplaySettings.setForcedSize(this, width, height);
+    }
+
     void getStableRect(Rect out) {
         out.set(mDisplayFrames.mStable);
     }
@@ -2225,7 +2309,7 @@
         }
 
         mInputMonitor.onRemoved();
-        mService.onDisplayRemoved(mDisplayId);
+        mService.mWindowPlacerLocked.requestTraversal();
     }
 
     /** Returns true if a removal action is still being deferred. */
diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java
index 847cff9..9f98dc5 100644
--- a/services/core/java/com/android/server/wm/DisplayRotation.java
+++ b/services/core/java/com/android/server/wm/DisplayRotation.java
@@ -269,7 +269,6 @@
         if (changed) {
             mService.updateRotation(true /* alwaysSendConfiguration */,
                     false /* forceRelayout */);
-            mService.mDisplaySettings.writeSettingsLocked();
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/DisplaySettings.java b/services/core/java/com/android/server/wm/DisplaySettings.java
index 28dc008..44956ab 100644
--- a/services/core/java/com/android/server/wm/DisplaySettings.java
+++ b/services/core/java/com/android/server/wm/DisplaySettings.java
@@ -16,12 +16,14 @@
 
 package com.android.server.wm;
 
+import static com.android.server.wm.DisplayContent.FORCE_SCALING_MODE_AUTO;
+import static com.android.server.wm.DisplayContent.FORCE_SCALING_MODE_DISABLED;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 
 import android.app.WindowConfiguration;
-import android.graphics.Rect;
 import android.os.Environment;
+import android.provider.Settings;
 import android.util.AtomicFile;
 import android.util.Slog;
 import android.util.Xml;
@@ -33,6 +35,7 @@
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.XmlUtils;
 import com.android.server.policy.WindowManagerPolicy;
+import com.android.server.wm.DisplayContent.ForceScalingMode;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -65,17 +68,24 @@
         private int mWindowingMode = WindowConfiguration.WINDOWING_MODE_UNDEFINED;
         private int mUserRotationMode = WindowManagerPolicy.USER_ROTATION_FREE;
         private int mUserRotation = Surface.ROTATION_0;
+        private int mForcedWidth;
+        private int mForcedHeight;
+        private int mForcedDensity;
+        private int mForcedScalingMode = FORCE_SCALING_MODE_AUTO;
 
         private Entry(String _name) {
             mName = _name;
         }
 
+        /** @return {@code true} if all values are default. */
         private boolean isEmpty() {
             return mOverscanLeft == 0 && mOverscanTop == 0 && mOverscanRight == 0
                     && mOverscanBottom == 0
                     && mWindowingMode == WindowConfiguration.WINDOWING_MODE_UNDEFINED
                     && mUserRotationMode == WindowManagerPolicy.USER_ROTATION_FREE
-                    && mUserRotation == Surface.ROTATION_0;
+                    && mUserRotation == Surface.ROTATION_0
+                    && mForcedWidth == 0 && mForcedHeight == 0 && mForcedDensity == 0
+                    && mForcedScalingMode == FORCE_SCALING_MODE_AUTO;
         }
     }
 
@@ -87,64 +97,84 @@
     DisplaySettings(WindowManagerService service, File folder) {
         mService = service;
         mFile = new AtomicFile(new File(folder, "display_settings.xml"), "wm-displays");
+        readSettings();
     }
 
-    private Entry getEntry(String name, String uniqueId) {
+    private Entry getEntry(DisplayInfo displayInfo) {
         // Try to get the entry with the unique if possible.
         // Else, fall back on the display name.
         Entry entry;
-        if (uniqueId == null || (entry = mEntries.get(uniqueId)) == null) {
-            entry = mEntries.get(name);
+        if (displayInfo.uniqueId == null || (entry = mEntries.get(displayInfo.uniqueId)) == null) {
+            entry = mEntries.get(displayInfo.name);
         }
         return entry;
     }
 
-    private Entry getOrCreateEntry(String uniqueId, String name) {
-        Entry entry = getEntry(uniqueId, name);
-        if (entry == null) {
-            entry = new Entry(uniqueId);
-            mEntries.put(uniqueId, entry);
-        }
-        return entry;
+    private Entry getOrCreateEntry(DisplayInfo displayInfo) {
+        final Entry entry = getEntry(displayInfo);
+        return entry != null ? entry : new Entry(displayInfo.uniqueId);
     }
 
-    private void removeEntryIfEmpty(String uniqueId, String name) {
-        final Entry entry = getEntry(uniqueId, name);
-        if (entry.isEmpty()) {
-            mEntries.remove(uniqueId);
-            mEntries.remove(name);
-        }
-    }
-
-    private void getOverscanLocked(String name, String uniqueId, Rect outRect) {
-        final Entry entry = getEntry(name, uniqueId);
-        if (entry != null) {
-            outRect.left = entry.mOverscanLeft;
-            outRect.top = entry.mOverscanTop;
-            outRect.right = entry.mOverscanRight;
-            outRect.bottom = entry.mOverscanBottom;
-        } else {
-            outRect.set(0, 0, 0, 0);
-        }
-    }
-
-    void setOverscanLocked(String uniqueId, String name, int left, int top, int right,
-            int bottom) {
-        Entry entry = mEntries.get(uniqueId);
-        if (left == 0 && top == 0 && right == 0 && bottom == 0 && entry == null) {
-            // All default value, no action needed.
-            return;
-        }
-        entry = getOrCreateEntry(uniqueId, name);
+    void setOverscanLocked(DisplayInfo displayInfo, int left, int top, int right, int bottom) {
+        final Entry entry = getOrCreateEntry(displayInfo);
         entry.mOverscanLeft = left;
         entry.mOverscanTop = top;
         entry.mOverscanRight = right;
         entry.mOverscanBottom = bottom;
-        removeEntryIfEmpty(uniqueId, name);
+        writeSettingsIfNeeded(entry, displayInfo);
     }
 
-    private int getWindowingModeLocked(String name, String uniqueId, int displayId) {
-        final Entry entry = getEntry(name, uniqueId);
+    void setUserRotation(DisplayContent displayContent, int rotationMode, int rotation) {
+        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
+        final Entry entry = getOrCreateEntry(displayInfo);
+        entry.mUserRotationMode = rotationMode;
+        entry.mUserRotation = rotation;
+        writeSettingsIfNeeded(entry, displayInfo);
+    }
+
+    void setForcedSize(DisplayContent displayContent, int width, int height) {
+        if (displayContent.isDefaultDisplay) {
+            final String sizeString = (width == 0 || height == 0) ? "" : (width + "," + height);
+            Settings.Global.putString(mService.mContext.getContentResolver(),
+                    Settings.Global.DISPLAY_SIZE_FORCED, sizeString);
+            return;
+        }
+
+        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
+        final Entry entry = getOrCreateEntry(displayInfo);
+        entry.mForcedWidth = width;
+        entry.mForcedHeight = height;
+        writeSettingsIfNeeded(entry, displayInfo);
+    }
+
+    void setForcedDensity(DisplayContent displayContent, int density, int userId) {
+        if (displayContent.isDefaultDisplay) {
+            final String densityString = density == 0 ? "" : Integer.toString(density);
+            Settings.Secure.putStringForUser(mService.mContext.getContentResolver(),
+                    Settings.Secure.DISPLAY_DENSITY_FORCED, densityString, userId);
+            return;
+        }
+
+        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
+        final Entry entry = getOrCreateEntry(displayInfo);
+        entry.mForcedDensity = density;
+        writeSettingsIfNeeded(entry, displayInfo);
+    }
+
+    void setForcedScalingMode(DisplayContent displayContent, @ForceScalingMode int mode) {
+        if (displayContent.isDefaultDisplay) {
+            Settings.Global.putInt(mService.mContext.getContentResolver(),
+                    Settings.Global.DISPLAY_SCALING_FORCE, mode);
+            return;
+        }
+
+        final DisplayInfo displayInfo = displayContent.getDisplayInfo();
+        final Entry entry = getOrCreateEntry(displayInfo);
+        entry.mForcedScalingMode = mode;
+        writeSettingsIfNeeded(entry, displayInfo);
+    }
+
+    private int getWindowingModeLocked(Entry entry, int displayId) {
         int windowingMode = entry != null ? entry.mWindowingMode
                 : WindowConfiguration.WINDOWING_MODE_UNDEFINED;
         // This display used to be in freeform, but we don't support freeform anymore, so fall
@@ -168,54 +198,35 @@
         return windowingMode;
     }
 
-    void setUserRotation(DisplayContent dc, int rotationMode, int rotation) {
+    void applySettingsToDisplayLocked(DisplayContent dc) {
         final DisplayInfo displayInfo = dc.getDisplayInfo();
+        final Entry entry = getEntry(displayInfo);
 
-        final String uniqueId = displayInfo.uniqueId;
-        final String name = displayInfo.name;
-        Entry entry = getEntry(displayInfo.name, uniqueId);
-        if (rotationMode == WindowManagerPolicy.USER_ROTATION_FREE
-                && rotation == Surface.ROTATION_0 && entry == null) {
-            // All default values. No action needed.
+        // Setting windowing mode first, because it may override overscan values later.
+        dc.setWindowingMode(getWindowingModeLocked(entry, dc.getDisplayId()));
+
+        if (entry == null) {
             return;
         }
 
-        entry = getOrCreateEntry(uniqueId, name);
-        entry.mUserRotationMode = rotationMode;
-        entry.mUserRotation = rotation;
-        removeEntryIfEmpty(uniqueId, name);
+        displayInfo.overscanLeft = entry.mOverscanLeft;
+        displayInfo.overscanTop = entry.mOverscanTop;
+        displayInfo.overscanRight = entry.mOverscanRight;
+        displayInfo.overscanBottom = entry.mOverscanBottom;
+
+        dc.getDisplayRotation().restoreUserRotation(entry.mUserRotationMode, entry.mUserRotation);
+
+        if (entry.mForcedDensity != 0) {
+            dc.mBaseDisplayDensity = entry.mForcedDensity;
+        }
+        if (entry.mForcedWidth != 0 && entry.mForcedHeight != 0) {
+            dc.updateBaseDisplayMetrics(entry.mForcedWidth, entry.mForcedHeight,
+                    dc.mBaseDisplayDensity);
+        }
+        dc.mDisplayScalingDisabled = entry.mForcedScalingMode == FORCE_SCALING_MODE_DISABLED;
     }
 
-    private void restoreUserRotation(DisplayContent dc) {
-        final DisplayInfo info = dc.getDisplayInfo();
-
-        final Entry entry = getEntry(info.name, info.uniqueId);
-        final int userRotationMode = entry != null ? entry.mUserRotationMode
-                : WindowManagerPolicy.USER_ROTATION_FREE;
-        final int userRotation = entry != null ? entry.mUserRotation
-                : Surface.ROTATION_0;
-
-        dc.getDisplayRotation().restoreUserRotation(userRotationMode, userRotation);
-    }
-
-    void applySettingsToDisplayLocked(DisplayContent dc) {
-        final DisplayInfo displayInfo = dc.getDisplayInfo();
-
-        // Setting windowing mode first, because it may override overscan values later.
-        dc.setWindowingMode(getWindowingModeLocked(displayInfo.name, displayInfo.uniqueId,
-                dc.getDisplayId()));
-
-        final Rect rect = new Rect();
-        getOverscanLocked(displayInfo.name, displayInfo.uniqueId, rect);
-        displayInfo.overscanLeft = rect.left;
-        displayInfo.overscanTop = rect.top;
-        displayInfo.overscanRight = rect.right;
-        displayInfo.overscanBottom = rect.bottom;
-
-        restoreUserRotation(dc);
-    }
-
-    void readSettingsLocked() {
+    private void readSettings() {
         FileInputStream stream;
         try {
             stream = mFile.openRead();
@@ -306,12 +317,29 @@
                     WindowManagerPolicy.USER_ROTATION_FREE);
             entry.mUserRotation = getIntAttribute(parser, "userRotation",
                     Surface.ROTATION_0);
+            entry.mForcedWidth = getIntAttribute(parser, "forcedWidth");
+            entry.mForcedHeight = getIntAttribute(parser, "forcedHeight");
+            entry.mForcedDensity = getIntAttribute(parser, "forcedDensity");
+            entry.mForcedScalingMode = getIntAttribute(parser, "forcedScalingMode",
+                    FORCE_SCALING_MODE_AUTO);
             mEntries.put(name, entry);
         }
         XmlUtils.skipCurrentTag(parser);
     }
 
-    void writeSettingsLocked() {
+    private void writeSettingsIfNeeded(Entry changedEntry, DisplayInfo displayInfo) {
+        if (changedEntry.isEmpty()) {
+            boolean removed = mEntries.remove(displayInfo.uniqueId) != null;
+            // Legacy name might have been in used, so we need to clear it.
+            removed |= mEntries.remove(displayInfo.name) != null;
+            if (!removed) {
+                // The entry didn't exist so nothing is changed and no need to update the file.
+                return;
+            }
+        } else {
+            mEntries.put(displayInfo.uniqueId, changedEntry);
+        }
+
         FileOutputStream stream;
         try {
             stream = mFile.startWrite();
@@ -351,6 +379,17 @@
                 if (entry.mUserRotation != Surface.ROTATION_0) {
                     out.attribute(null, "userRotation", Integer.toString(entry.mUserRotation));
                 }
+                if (entry.mForcedWidth != 0 && entry.mForcedHeight != 0) {
+                    out.attribute(null, "forcedWidth", Integer.toString(entry.mForcedWidth));
+                    out.attribute(null, "forcedHeight", Integer.toString(entry.mForcedHeight));
+                }
+                if (entry.mForcedDensity != 0) {
+                    out.attribute(null, "forcedDensity", Integer.toString(entry.mForcedDensity));
+                }
+                if (entry.mForcedScalingMode != FORCE_SCALING_MODE_AUTO) {
+                    out.attribute(null, "forcedScalingMode",
+                            Integer.toString(entry.mForcedScalingMode));
+                }
                 out.endTag(null, "display");
             }
 
diff --git a/services/core/java/com/android/server/wm/DisplayWindowController.java b/services/core/java/com/android/server/wm/DisplayWindowController.java
index ab87759..3282b1c 100644
--- a/services/core/java/com/android/server/wm/DisplayWindowController.java
+++ b/services/core/java/com/android/server/wm/DisplayWindowController.java
@@ -81,6 +81,22 @@
     }
 
     /**
+     * Called when the corresponding display receives
+     * {@link android.hardware.display.DisplayManager.DisplayListener#onDisplayChanged(int)}.
+     */
+    public void onDisplayChanged() {
+        synchronized (mWindowMap) {
+            if (mContainer == null) {
+                if (DEBUG_DISPLAY) Slog.i(TAG_WM, "onDisplayChanged: could not find display="
+                        + mDisplayId);
+                return;
+            }
+            mContainer.updateDisplayInfo();
+            mService.mWindowPlacerLocked.requestTraversal();
+        }
+    }
+
+    /**
      * Positions the task stack at the given position in the task stack container.
      */
     public void positionChildAt(StackWindowController child, int position,
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index ad0b8ec..bc0f19a 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -105,9 +105,6 @@
         // Create the DisplayContentsAnimator object by retrieving it if the associated
         // {@link DisplayContent} exists.
         getDisplayContentsAnimatorLocked(displayId);
-        if (displayId == DEFAULT_DISPLAY) {
-            mInitialized = true;
-        }
     }
 
     void removeDisplayLocked(final int displayId) {
@@ -122,6 +119,10 @@
         mDisplayContentsAnimators.delete(displayId);
     }
 
+    void ready() {
+        mInitialized = true;
+    }
+
     /**
      * DO NOT HOLD THE WINDOW MANAGER LOCK WHILE CALLING THIS METHOD. Reason: the method closes
      * an animation transaction, that might be blocking until the next sf-vsync, so we want to make
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 5642b1f..3aad73c 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -930,7 +930,6 @@
         mInputManager = inputManager; // Must be before createDisplayContentLocked.
         mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
         mDisplaySettings = new DisplaySettings(this);
-        mDisplaySettings.readSettingsLocked();
 
         mPolicy = policy;
         mAnimator = new WindowAnimator(this);
@@ -3241,7 +3240,7 @@
                 final int forcedDensity = getForcedDisplayDensityForUserLocked(newUserId);
                 final int targetDensity = forcedDensity != 0 ? forcedDensity
                         : displayContent.mInitialDisplayDensity;
-                setForcedDisplayDensityLocked(displayContent, targetDensity);
+                displayContent.setForcedDensity(targetDensity, UserHandle.USER_CURRENT);
             }
         }
     }
@@ -4415,31 +4414,15 @@
     }
 
     public void displayReady() {
-        final int displayCount = mRoot.mChildren.size();
-        for (int i = 0; i < displayCount; ++i) {
-            final DisplayContent display = mRoot.mChildren.get(i);
-            displayReady(display.getDisplayId());
-        }
-
-
-        synchronized(mWindowMap) {
-            final DisplayContent displayContent = getDefaultDisplayContentLocked();
+        synchronized (mWindowMap) {
             if (mMaxUiWidth > 0) {
-                displayContent.setMaxUiWidth(mMaxUiWidth);
+                mRoot.forAllDisplays(displayContent -> displayContent.setMaxUiWidth(mMaxUiWidth));
             }
-            readForcedDisplayPropertiesLocked(displayContent);
+            applyForcedPropertiesForDefaultDisplay();
+            mAnimator.ready();
             mDisplayReady = true;
-        }
-
-        try {
-            mActivityTaskManager.updateConfiguration(null);
-        } catch (RemoteException e) {
-        }
-
-        synchronized(mWindowMap) {
             mIsTouchDevice = mContext.getPackageManager().hasSystemFeature(
                     PackageManager.FEATURE_TOUCHSCREEN);
-            getDefaultDisplayContentLocked().configureDisplayPolicy();
         }
 
         try {
@@ -4450,17 +4433,6 @@
         updateCircularDisplayMaskIfNeeded();
     }
 
-    private void displayReady(int displayId) {
-        synchronized(mWindowMap) {
-            final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
-            if (displayContent != null) {
-                mAnimator.addDisplayLocked(displayId);
-                displayContent.initializeDisplayBaseInfo();
-                reconfigureDisplayLocked(displayContent);
-            }
-        }
-    }
-
     public void systemReady() {
         mPolicy.systemReady();
         mTaskSnapshotController.systemReady();
@@ -5017,20 +4989,9 @@
         final long ident = Binder.clearCallingIdentity();
         try {
             synchronized(mWindowMap) {
-                // Set some sort of reasonable bounds on the size of the display that we
-                // will try to emulate.
-                final int MIN_WIDTH = 200;
-                final int MIN_HEIGHT = 200;
-                final int MAX_SCALE = 2;
                 final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
                 if (displayContent != null) {
-                    width = Math.min(Math.max(width, MIN_WIDTH),
-                            displayContent.mInitialDisplayWidth * MAX_SCALE);
-                    height = Math.min(Math.max(height, MIN_HEIGHT),
-                            displayContent.mInitialDisplayHeight * MAX_SCALE);
-                    setForcedDisplaySizeLocked(displayContent, width, height);
-                    Settings.Global.putString(mContext.getContentResolver(),
-                            Settings.Global.DISPLAY_SIZE_FORCED, width + "," + height);
+                    displayContent.setForcedSize(width, height);
                 }
             }
         } finally {
@@ -5052,12 +5013,7 @@
             synchronized(mWindowMap) {
                 final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
                 if (displayContent != null) {
-                    if (mode < 0 || mode > 1) {
-                        mode = 0;
-                    }
-                    setForcedDisplayScalingModeLocked(displayContent, mode);
-                    Settings.Global.putInt(mContext.getContentResolver(),
-                            Settings.Global.DISPLAY_SCALING_FORCE, mode);
+                    displayContent.setForcedScalingMode(mode);
                 }
             }
         } finally {
@@ -5065,13 +5021,10 @@
         }
     }
 
-    private void setForcedDisplayScalingModeLocked(DisplayContent displayContent, int mode) {
-        Slog.i(TAG_WM, "Using display scaling mode: " + (mode == 0 ? "auto" : "off"));
-        displayContent.mDisplayScalingDisabled = (mode != 0);
-        reconfigureDisplayLocked(displayContent);
-    }
-
-    private void readForcedDisplayPropertiesLocked(final DisplayContent displayContent) {
+    /** The global settings only apply to default display. */
+    private void applyForcedPropertiesForDefaultDisplay() {
+        final DisplayContent displayContent = getDefaultDisplayContentLocked();
+        boolean changed = false;
         // Display size.
         String sizeStr = Settings.Global.getString(mContext.getContentResolver(),
                 Settings.Global.DISPLAY_SIZE_FORCED);
@@ -5090,6 +5043,7 @@
                         Slog.i(TAG_WM, "FORCED DISPLAY SIZE: " + width + "x" + height);
                         displayContent.updateBaseDisplayMetrics(width, height,
                                 displayContent.mBaseDisplayDensity);
+                        changed = true;
                     }
                 } catch (NumberFormatException ex) {
                 }
@@ -5100,6 +5054,7 @@
         final int density = getForcedDisplayDensityForUserLocked(mCurrentUserId);
         if (density != 0) {
             displayContent.mBaseDisplayDensity = density;
+            changed = true;
         }
 
         // Display scaling mode.
@@ -5108,14 +5063,12 @@
         if (mode != 0) {
             Slog.i(TAG_WM, "FORCED DISPLAY SCALING DISABLED");
             displayContent.mDisplayScalingDisabled = true;
+            changed = true;
         }
-    }
 
-    // displayContent must not be null
-    private void setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height) {
-        Slog.i(TAG_WM, "Using new display size: " + width + "x" + height);
-        displayContent.updateBaseDisplayMetrics(width, height, displayContent.mBaseDisplayDensity);
-        reconfigureDisplayLocked(displayContent);
+        if (changed) {
+            reconfigureDisplayLocked(displayContent);
+        }
     }
 
     @Override
@@ -5132,10 +5085,8 @@
             synchronized(mWindowMap) {
                 final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
                 if (displayContent != null) {
-                    setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth,
+                    displayContent.setForcedSize(displayContent.mInitialDisplayWidth,
                             displayContent.mInitialDisplayHeight);
-                    Settings.Global.putString(mContext.getContentResolver(),
-                            Settings.Global.DISPLAY_SIZE_FORCED, "");
                 }
             }
         } finally {
@@ -5181,12 +5132,9 @@
         try {
             synchronized(mWindowMap) {
                 final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
-                if (displayContent != null && mCurrentUserId == targetUserId) {
-                    setForcedDisplayDensityLocked(displayContent, density);
+                if (displayContent != null) {
+                    displayContent.setForcedDensity(density, targetUserId);
                 }
-                Settings.Secure.putStringForUser(mContext.getContentResolver(),
-                        Settings.Secure.DISPLAY_DENSITY_FORCED,
-                        Integer.toString(density), targetUserId);
             }
         } finally {
             Binder.restoreCallingIdentity(ident);
@@ -5209,12 +5157,10 @@
         try {
             synchronized(mWindowMap) {
                 final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
-                if (displayContent != null && mCurrentUserId == callingUserId) {
-                    setForcedDisplayDensityLocked(displayContent,
-                            displayContent.mInitialDisplayDensity);
+                if (displayContent != null) {
+                    displayContent.setForcedDensity(displayContent.mInitialDisplayDensity,
+                            callingUserId);
                 }
-                Settings.Secure.putStringForUser(mContext.getContentResolver(),
-                        Settings.Secure.DISPLAY_DENSITY_FORCED, "", callingUserId);
             }
         } finally {
             Binder.restoreCallingIdentity(ident);
@@ -5241,18 +5187,6 @@
         return 0;
     }
 
-    /**
-     * Forces the given display to the use the specified density.
-     *
-     * @param displayContent the display to modify
-     * @param density the density in DPI to use
-     */
-    private void setForcedDisplayDensityLocked(@NonNull DisplayContent displayContent,
-            int density) {
-        displayContent.mBaseDisplayDensity = density;
-        reconfigureDisplayLocked(displayContent);
-    }
-
     void reconfigureDisplayLocked(@NonNull DisplayContent displayContent) {
         if (!displayContent.isReady()) {
             return;
@@ -5306,9 +5240,7 @@
         displayInfo.overscanRight = right;
         displayInfo.overscanBottom = bottom;
 
-        mDisplaySettings.setOverscanLocked(displayInfo.uniqueId, displayInfo.name, left, top,
-                right, bottom);
-        mDisplaySettings.writeSettingsLocked();
+        mDisplaySettings.setOverscanLocked(displayInfo, left, top, right, bottom);
 
         reconfigureDisplayLocked(displayContent);
     }
@@ -6507,23 +6439,6 @@
         return mRoot.getDisplayContent(DEFAULT_DISPLAY);
     }
 
-    public void onDisplayAdded(int displayId) {
-        synchronized (mWindowMap) {
-            final Display display = mDisplayManager.getDisplay(displayId);
-            if (display != null) {
-                displayReady(displayId);
-            }
-            mWindowPlacerLocked.requestTraversal();
-        }
-    }
-
-    public void onDisplayRemoved(int displayId) {
-        synchronized (mWindowMap) {
-            mAnimator.removeDisplayLocked(displayId);
-            mWindowPlacerLocked.requestTraversal();
-        }
-    }
-
     public void onOverlayChanged() {
         synchronized (mWindowMap) {
             mRoot.forAllDisplays(displayContent -> {
diff --git a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
index bf2d0df..bf77ba8 100644
--- a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
+++ b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
@@ -233,9 +233,11 @@
     private int runDisplayScaling(PrintWriter pw) throws RemoteException {
         String scalingStr = getNextArgRequired();
         if ("auto".equals(scalingStr)) {
-            mInterface.setForcedDisplayScalingMode(getDisplayId(scalingStr), 0);
+            mInterface.setForcedDisplayScalingMode(getDisplayId(scalingStr),
+                    DisplayContent.FORCE_SCALING_MODE_AUTO);
         } else if ("off".equals(scalingStr)) {
-            mInterface.setForcedDisplayScalingMode(getDisplayId(scalingStr), 1);
+            mInterface.setForcedDisplayScalingMode(getDisplayId(scalingStr),
+                    DisplayContent.FORCE_SCALING_MODE_DISABLED);
         } else {
             getErrPrintWriter().println("Error: scaling must be 'auto' or 'off'");
             return -1;
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index f16008d..2f89d5c 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -2949,7 +2949,12 @@
         // isDragResizing() or isDragResizeChanged() is true.
         boolean resizing = isDragResizing() || isDragResizeChanged();
         if (getWindowConfiguration().useWindowFrameForBackdrop() || !resizing) {
-            return frame;
+            // Surface position is now inherited from parent, and BackdropFrameRenderer uses
+            // backdrop frame to position content. Thus we just keep the size of backdrop frame, and
+            // remove the offset to avoid double offset from display origin.
+            mTmpRect.set(frame);
+            mTmpRect.offsetTo(0, 0);
+            return mTmpRect;
         }
         final DisplayInfo displayInfo = getDisplayInfo();
         mTmpRect.set(0, 0, displayInfo.logicalWidth, displayInfo.logicalHeight);
diff --git a/services/robotests/src/com/android/server/backup/encryption/chunking/ChunkEncryptorTest.java b/services/robotests/src/com/android/server/backup/encryption/chunking/ChunkEncryptorTest.java
new file mode 100644
index 0000000..2cc3ef8
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/encryption/chunking/ChunkEncryptorTest.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.backup.encryption.chunking;
+
+import static com.android.server.backup.testing.CryptoTestUtils.generateAesKey;
+import static com.google.common.truth.Truth.assertThat;
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+
+import android.platform.test.annotations.Presubmit;
+import com.android.server.backup.encryption.chunk.ChunkHash;
+import com.android.server.testing.FrameworkRobolectricTestRunner;
+import com.android.server.testing.SystemLoaderPackages;
+import java.security.SecureRandom;
+import javax.crypto.Cipher;
+import javax.crypto.Mac;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.GCMParameterSpec;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.robolectric.annotation.Config;
+
+@RunWith(FrameworkRobolectricTestRunner.class)
+@Config(manifest = Config.NONE, sdk = 26)
+@SystemLoaderPackages({"com.android.server.backup"})
+@Presubmit
+public class ChunkEncryptorTest {
+    private static final String MAC_ALGORITHM = "HmacSHA256";
+    private static final String CIPHER_ALGORITHM = "AES/GCM/NoPadding";
+    private static final int GCM_NONCE_LENGTH_BYTES = 12;
+    private static final int GCM_TAG_LENGTH_BYTES = 16;
+    private static final String CHUNK_PLAINTEXT =
+            "A little Learning is a dang'rous Thing;\n"
+                    + "Drink deep, or taste not the Pierian Spring:\n"
+                    + "There shallow Draughts intoxicate the Brain,\n"
+                    + "And drinking largely sobers us again.";
+    private static final byte[] PLAINTEXT_BYTES = CHUNK_PLAINTEXT.getBytes(UTF_8);
+    private static final byte[] NONCE_1 = "0123456789abc".getBytes(UTF_8);
+    private static final byte[] NONCE_2 = "123456789abcd".getBytes(UTF_8);
+
+    private static final byte[][] NONCES = new byte[][] {NONCE_1, NONCE_2};
+
+    @Mock private SecureRandom mSecureRandomMock;
+    private SecretKey mSecretKey;
+    private ChunkHash mPlaintextHash;
+    private ChunkEncryptor mChunkEncryptor;
+
+    @Before
+    public void setUp() throws Exception {
+        mSecretKey = generateAesKey();
+        ChunkHasher chunkHasher = new ChunkHasher(mSecretKey);
+        mPlaintextHash = chunkHasher.computeHash(PLAINTEXT_BYTES);
+        mSecureRandomMock = mock(SecureRandom.class);
+        mChunkEncryptor = new ChunkEncryptor(mSecretKey, mSecureRandomMock);
+
+        // Return NONCE_1, then NONCE_2 for invocations of mSecureRandomMock.nextBytes().
+        doAnswer(
+                        new Answer<Void>() {
+                            private int mInvocation = 0;
+
+                            @Override
+                            public Void answer(InvocationOnMock invocation) {
+                                byte[] nonceDestination = invocation.getArgument(0);
+                                System.arraycopy(
+                                        NONCES[this.mInvocation],
+                                        0,
+                                        nonceDestination,
+                                        0,
+                                        GCM_NONCE_LENGTH_BYTES);
+                                this.mInvocation++;
+                                return null;
+                            }
+                        })
+                .when(mSecureRandomMock)
+                .nextBytes(any(byte[].class));
+    }
+
+    @Test
+    public void encrypt_withHash_resultContainsHashAsKey() throws Exception {
+        EncryptedChunk chunk = mChunkEncryptor.encrypt(mPlaintextHash, PLAINTEXT_BYTES);
+
+        assertThat(chunk.key()).isEqualTo(mPlaintextHash);
+    }
+
+    @Test
+    public void encrypt_generatesHmacOfPlaintext() throws Exception {
+        EncryptedChunk chunk = mChunkEncryptor.encrypt(mPlaintextHash, PLAINTEXT_BYTES);
+
+        byte[] generatedHash = chunk.key().getHash();
+        Mac mac = Mac.getInstance(MAC_ALGORITHM);
+        mac.init(mSecretKey);
+        byte[] plaintextHmac = mac.doFinal(PLAINTEXT_BYTES);
+        assertThat(generatedHash).isEqualTo(plaintextHmac);
+    }
+
+    @Test
+    public void encrypt_whenInvokedAgain_generatesNewNonce() throws Exception {
+        EncryptedChunk chunk1 = mChunkEncryptor.encrypt(mPlaintextHash, PLAINTEXT_BYTES);
+
+        EncryptedChunk chunk2 = mChunkEncryptor.encrypt(mPlaintextHash, PLAINTEXT_BYTES);
+
+        assertThat(chunk1.nonce()).isNotEqualTo(chunk2.nonce());
+    }
+
+    @Test
+    public void encrypt_whenInvokedAgain_generatesNewCiphertext() throws Exception {
+        EncryptedChunk chunk1 = mChunkEncryptor.encrypt(mPlaintextHash, PLAINTEXT_BYTES);
+
+        EncryptedChunk chunk2 = mChunkEncryptor.encrypt(mPlaintextHash, PLAINTEXT_BYTES);
+
+        assertThat(chunk1.encryptedBytes()).isNotEqualTo(chunk2.encryptedBytes());
+    }
+
+    @Test
+    public void encrypt_generates12ByteNonce() throws Exception {
+        EncryptedChunk encryptedChunk = mChunkEncryptor.encrypt(mPlaintextHash, PLAINTEXT_BYTES);
+
+        byte[] nonce = encryptedChunk.nonce();
+        assertThat(nonce).hasLength(GCM_NONCE_LENGTH_BYTES);
+    }
+
+    @Test
+    public void encrypt_decryptedResultCorrespondsToPlaintext() throws Exception {
+        EncryptedChunk chunk = mChunkEncryptor.encrypt(mPlaintextHash, PLAINTEXT_BYTES);
+
+        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
+        cipher.init(
+                Cipher.DECRYPT_MODE,
+                mSecretKey,
+                new GCMParameterSpec(GCM_TAG_LENGTH_BYTES * 8, chunk.nonce()));
+        byte[] decrypted = cipher.doFinal(chunk.encryptedBytes());
+        assertThat(decrypted).isEqualTo(PLAINTEXT_BYTES);
+    }
+}
diff --git a/services/robotests/src/com/android/server/backup/encryption/chunking/ChunkHasherTest.java b/services/robotests/src/com/android/server/backup/encryption/chunking/ChunkHasherTest.java
new file mode 100644
index 0000000..11796c0
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/encryption/chunking/ChunkHasherTest.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.backup.encryption.chunking;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.platform.test.annotations.Presubmit;
+import com.android.server.backup.encryption.chunk.ChunkHash;
+import com.android.server.testing.FrameworkRobolectricTestRunner;
+import com.android.server.testing.SystemLoaderPackages;
+import javax.crypto.Mac;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
+
+@RunWith(FrameworkRobolectricTestRunner.class)
+@Config(manifest = Config.NONE, sdk = 26)
+@SystemLoaderPackages({"com.android.server.backup"})
+@Presubmit
+public class ChunkHasherTest {
+    private static final String KEY_ALGORITHM = "AES";
+    private static final String MAC_ALGORITHM = "HmacSHA256";
+
+    private static final byte[] TEST_KEY = {100, 120};
+    private static final byte[] TEST_DATA = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};
+
+    private SecretKey mSecretKey;
+    private ChunkHasher mChunkHasher;
+
+    @Before
+    public void setUp() throws Exception {
+        mSecretKey = new SecretKeySpec(TEST_KEY, KEY_ALGORITHM);
+        mChunkHasher = new ChunkHasher(mSecretKey);
+    }
+
+    @Test
+    public void computeHash_returnsHmacForData() throws Exception {
+        ChunkHash chunkHash = mChunkHasher.computeHash(TEST_DATA);
+
+        byte[] hash = chunkHash.getHash();
+        Mac mac = Mac.getInstance(MAC_ALGORITHM);
+        mac.init(mSecretKey);
+        byte[] expectedHash = mac.doFinal(TEST_DATA);
+        assertThat(hash).isEqualTo(expectedHash);
+    }
+
+    @Test
+    public void computeHash_generates256BitHmac() throws Exception {
+        int expectedLength = 256 / Byte.SIZE;
+
+        byte[] hash = mChunkHasher.computeHash(TEST_DATA).getHash();
+
+        assertThat(hash).hasLength(expectedLength);
+    }
+}
diff --git a/services/robotests/src/com/android/server/backup/encryption/chunking/RawBackupWriterTest.java b/services/robotests/src/com/android/server/backup/encryption/chunking/RawBackupWriterTest.java
new file mode 100644
index 0000000..8b54e1e
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/encryption/chunking/RawBackupWriterTest.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.backup.encryption.chunking;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.testng.Assert.assertThrows;
+
+import android.platform.test.annotations.Presubmit;
+import com.android.server.testing.FrameworkRobolectricTestRunner;
+import com.android.server.testing.SystemLoaderPackages;
+import com.google.common.primitives.Bytes;
+import java.io.ByteArrayOutputStream;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
+
+@RunWith(FrameworkRobolectricTestRunner.class)
+@Config(manifest = Config.NONE, sdk = 26)
+@SystemLoaderPackages({"com.android.server.backup"})
+@Presubmit
+public class RawBackupWriterTest {
+    private static final byte[] TEST_BYTES = {1, 2, 3, 4, 5, 6};
+
+    private BackupWriter mWriter;
+    private ByteArrayOutputStream mOutput;
+
+    @Before
+    public void setUp() {
+        mOutput = new ByteArrayOutputStream();
+        mWriter = new RawBackupWriter(mOutput);
+    }
+
+    @Test
+    public void writeBytes_writesToOutputStream() throws Exception {
+        mWriter.writeBytes(TEST_BYTES);
+
+        assertThat(mOutput.toByteArray())
+                .asList()
+                .containsExactlyElementsIn(Bytes.asList(TEST_BYTES))
+                .inOrder();
+    }
+
+    @Test
+    public void writeChunk_throwsUnsupportedOperationException() throws Exception {
+        assertThrows(UnsupportedOperationException.class, () -> mWriter.writeChunk(0, 0));
+    }
+
+    @Test
+    public void getBytesWritten_returnsTotalSum() throws Exception {
+        mWriter.writeBytes(TEST_BYTES);
+        mWriter.writeBytes(TEST_BYTES);
+
+        long bytesWritten = mWriter.getBytesWritten();
+
+        assertThat(bytesWritten).isEqualTo(2 * TEST_BYTES.length);
+    }
+
+    @Test
+    public void flush_flushesOutputStream() throws Exception {
+        mOutput = mock(ByteArrayOutputStream.class);
+        mWriter = new RawBackupWriter(mOutput);
+
+        mWriter.flush();
+
+        verify(mOutput).flush();
+    }
+}
diff --git a/services/robotests/src/com/android/server/backup/testing/CryptoTestUtils.java b/services/robotests/src/com/android/server/backup/testing/CryptoTestUtils.java
new file mode 100644
index 0000000..83e8461
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/testing/CryptoTestUtils.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.backup.testing;
+
+import java.security.NoSuchAlgorithmException;
+import javax.crypto.KeyGenerator;
+import javax.crypto.SecretKey;
+
+/** Helpers for crypto code tests. */
+public class CryptoTestUtils {
+    private static final String KEY_ALGORITHM = "AES";
+    private static final int KEY_SIZE_BITS = 256;
+
+    private CryptoTestUtils() {}
+
+    public static SecretKey generateAesKey() throws NoSuchAlgorithmException {
+        KeyGenerator keyGenerator = KeyGenerator.getInstance(KEY_ALGORITHM);
+        keyGenerator.init(KEY_SIZE_BITS);
+        return keyGenerator.generateKey();
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/StorageManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/StorageManagerServiceTest.java
index 8022532..e53518c 100644
--- a/services/tests/servicestests/src/com/android/server/StorageManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/StorageManagerServiceTest.java
@@ -30,7 +30,6 @@
 import android.os.storage.StorageManagerInternal;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
-import android.util.SparseArray;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -38,9 +37,6 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
-import java.util.ArrayList;
-import java.util.List;
-
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class StorageManagerServiceTest {
@@ -83,29 +79,14 @@
 
         when(mUmi.getUserIds()).thenReturn(new int[] { 0 });
 
-        {
-            final SparseArray<String> res = new SparseArray<>();
-            res.put(UID_COLORS, NAME_COLORS);
-            when(mPmi.getAppsWithSharedUserIds()).thenReturn(res);
-        }
+        when(mPmi.getSharedUserIdForPackage(eq(PKG_GREY))).thenReturn(null);
+        when(mPmi.getSharedUserIdForPackage(eq(PKG_RED))).thenReturn(NAME_COLORS);
+        when(mPmi.getSharedUserIdForPackage(eq(PKG_BLUE))).thenReturn(NAME_COLORS);
 
-        {
-            final List<ApplicationInfo> res = new ArrayList<>();
-            res.add(buildApplicationInfo(PKG_GREY, UID_GREY));
-            res.add(buildApplicationInfo(PKG_RED, UID_COLORS));
-            res.add(buildApplicationInfo(PKG_BLUE, UID_COLORS));
-            when(mPm.getInstalledApplicationsAsUser(anyInt(), anyInt())).thenReturn(res);
-        }
-
-        when(mPmi.getPackageUid(eq(PKG_GREY), anyInt(), anyInt())).thenReturn(UID_GREY);
-        when(mPmi.getPackageUid(eq(PKG_RED), anyInt(), anyInt())).thenReturn(UID_COLORS);
-        when(mPmi.getPackageUid(eq(PKG_BLUE), anyInt(), anyInt())).thenReturn(UID_COLORS);
-
-        when(mPm.getPackagesForUid(eq(UID_GREY))).thenReturn(new String[] { PKG_GREY });
-        when(mPm.getPackagesForUid(eq(UID_COLORS))).thenReturn(new String[] { PKG_RED, PKG_BLUE });
+        when(mPmi.getPackagesForSharedUserId(eq(NAME_COLORS), anyInt()))
+                .thenReturn(new String[] { PKG_RED, PKG_BLUE });
 
         mService = new StorageManagerService(mContext);
-        mService.collectPackagesInfo();
     }
 
     @Test
diff --git a/services/tests/servicestests/src/com/android/server/accounts/AccountsDbTest.java b/services/tests/servicestests/src/com/android/server/accounts/AccountsDbTest.java
index 72c22fd..29a920a 100644
--- a/services/tests/servicestests/src/com/android/server/accounts/AccountsDbTest.java
+++ b/services/tests/servicestests/src/com/android/server/accounts/AccountsDbTest.java
@@ -22,9 +22,14 @@
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
 import android.accounts.Account;
 import android.content.Context;
 import android.database.Cursor;
+import android.database.sqlite.SQLiteStatement;
 import android.os.Build;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.util.Pair;
@@ -37,7 +42,11 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
 import java.io.File;
+import java.io.PrintWriter;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
@@ -64,8 +73,11 @@
     private File deDb;
     private File ceDb;
 
+    @Mock private PrintWriter mockWriter;
+
     @Before
     public void setUp() {
+        MockitoAnnotations.initMocks(this);
         Context context = InstrumentationRegistry.getContext();
         preNDb = new File(context.getCacheDir(), PREN_DB);
         ceDb = new File(context.getCacheDir(), CE_DB);
@@ -444,4 +456,33 @@
         assertTrue(mAccountsDb.deleteDeAccount(accId)); // Trigger should remove visibility.
         assertNull(mAccountsDb.findAccountVisibility(account, packageName1));
     }
+
+    @Test
+    public void testDumpDebugTable() {
+        long accId = 10;
+        long insertionPoint = mAccountsDb.reserveDebugDbInsertionPoint();
+
+        SQLiteStatement logStatement = mAccountsDb.getStatementForLogging();
+
+        logStatement.bindLong(1, accId);
+        logStatement.bindString(2, "action");
+        logStatement.bindString(3, "date");
+        logStatement.bindLong(4, 10);
+        logStatement.bindString(5, "table");
+        logStatement.bindLong(6, insertionPoint);
+        logStatement.execute();
+
+        mAccountsDb.dumpDebugTable(mockWriter);
+
+        verify(mockWriter, times(3)).println(anyString());
+    }
+
+    @Test
+    public void testReserveDebugDbInsertionPoint() {
+        long insertionPoint = mAccountsDb.reserveDebugDbInsertionPoint();
+        long insertionPoint2 = mAccountsDb.reserveDebugDbInsertionPoint();
+
+        assertEquals(0, insertionPoint);
+        assertEquals(1, insertionPoint2);
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityDisplayTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityDisplayTests.java
index 0da5742..59c4067 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityDisplayTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityDisplayTests.java
@@ -60,8 +60,7 @@
     public void testLastFocusedStackIsUpdatedWhenMovingStack() {
         // Create a stack at bottom.
         final ActivityDisplay display = mSupervisor.getDefaultDisplay();
-        final ActivityStack stack = display.createStack(
-                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, !ON_TOP);
+        final ActivityStack stack = new StackBuilder(mSupervisor).setOnTop(!ON_TOP).build();
         final ActivityStack prevFocusedStack = display.getFocusedStack();
 
         stack.moveToFront("moveStackToFront");
@@ -140,16 +139,14 @@
      */
     @Test
     public void testTopRunningActivity() {
-        // Create stack to hold focus.
         final ActivityDisplay display = mSupervisor.getDefaultDisplay();
-        final ActivityStack emptyStack = display.createStack(WINDOWING_MODE_FULLSCREEN,
-                ACTIVITY_TYPE_STANDARD, true /* onTop */);
-
         final KeyguardController keyguard = mSupervisor.getKeyguardController();
-        final ActivityStack stack = mSupervisor.getDefaultDisplay().createStack(
-                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
-        final ActivityRecord activity = new ActivityBuilder(mService).setCreateTask(true)
-                .setStack(stack).build();
+        final ActivityStack stack = new StackBuilder(mSupervisor).build();
+        final ActivityRecord activity = stack.getTopActivity();
+
+        // Create empty stack on top.
+        final ActivityStack emptyStack =
+                new StackBuilder(mSupervisor).setCreateActivity(false).build();
 
         // Make sure the top running activity is not affected when keyguard is not locked.
         assertTopRunningActivity(activity, display);
@@ -159,8 +156,8 @@
         assertEquals(activity, display.topRunningActivity());
         assertNull(display.topRunningActivity(true /* considerKeyguardState */));
 
-        // Change focus to stack with activity.
-        stack.moveToFront("focusChangeToTestStack");
+        // Move stack with activity to top.
+        stack.moveToFront("testStackToFront");
         assertEquals(stack, display.getFocusedStack());
         assertEquals(activity, display.topRunningActivity());
         assertNull(display.topRunningActivity(true /* considerKeyguardState */));
@@ -175,11 +172,10 @@
         // Ensure the show when locked activity is returned.
         assertTopRunningActivity(showWhenLockedActivity, display);
 
-        // Change focus back to empty stack.
-        emptyStack.moveToFront("focusChangeToEmptyStack");
-        assertEquals(emptyStack, display.getFocusedStack());
-        // If there is no running activity in focused stack, the running activity in next focusable
-        // stack should be returned.
+        // Move empty stack to front. The running activity in focusable stack which below the
+        // empty stack should be returned.
+        emptyStack.moveToFront("emptyStackToFront");
+        assertEquals(stack, display.getFocusedStack());
         assertTopRunningActivity(showWhenLockedActivity, display);
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
index 349c0a37..060c55d 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
@@ -260,7 +260,7 @@
         uidRec.hasInternetPermission = true;
         mAms.mActiveUids.put(uid, uidRec);
 
-        final ProcessRecord appRec = new ProcessRecord(mAms, new ApplicationInfo(), TAG, uid, null);
+        final ProcessRecord appRec = new ProcessRecord(mAms, new ApplicationInfo(), TAG, uid);
         appRec.thread = Mockito.mock(IApplicationThread.class);
         mAms.mProcessList.mLruProcesses.add(appRec);
 
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
index ffc7fa2..1015008 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
@@ -79,10 +79,9 @@
         super.setUp();
 
         setupActivityTaskManagerService();
-        mStack = mSupervisor.getDefaultDisplay().createStack(
-                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
-        mTask = new TaskBuilder(mSupervisor).setStack(mStack).build();
-        mActivity = new ActivityBuilder(mService).setTask(mTask).build();
+        mStack = new StackBuilder(mSupervisor).build();
+        mTask = mStack.getChildAt(0);
+        mActivity = mTask.getTopActivity();
     }
 
     @Test
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
index 2c993d3..bdceec7 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
@@ -359,15 +359,12 @@
     public void testFindTaskToMoveToFrontWhenRecentsOnTop() throws Exception {
         // Create stack/task on default display.
         final ActivityDisplay display = mSupervisor.getDefaultDisplay();
-        final ActivityStack targetStack = display.createStack(WINDOWING_MODE_FULLSCREEN,
-                ACTIVITY_TYPE_STANDARD, false /* onTop */);
-        final TaskRecord targetTask = new TaskBuilder(mSupervisor).setStack(targetStack).build();
+        final TestActivityStack targetStack = new StackBuilder(mSupervisor).setOnTop(false).build();
+        final TaskRecord targetTask = targetStack.getChildAt(0);
 
         // Create Recents on top of the display.
-        final ActivityStack stack = display.createStack(WINDOWING_MODE_FULLSCREEN,
-                ACTIVITY_TYPE_RECENTS, true /* onTop */);
-        final TaskRecord task = new TaskBuilder(mSupervisor).setStack(stack).build();
-        new ActivityBuilder(mService).setTask(task).build();
+        final ActivityStack stack =
+                new StackBuilder(mSupervisor).setActivityType(ACTIVITY_TYPE_RECENTS).build();
 
         final String reason = "findTaskToMoveToFront";
         mSupervisor.findTaskToMoveToFront(targetTask, 0, ActivityOptions.makeBasic(), reason,
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
index 53f67af..ea33de74 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
@@ -26,8 +26,8 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
 
+import static com.android.server.am.ActivityStack.ActivityState.STOPPING;
 import static com.android.server.am.ActivityStack.ActivityState.DESTROYING;
-import static com.android.server.am.ActivityStack.ActivityState.FINISHING;
 import static com.android.server.am.ActivityStack.ActivityState.PAUSED;
 import static com.android.server.am.ActivityStack.ActivityState.PAUSING;
 import static com.android.server.am.ActivityStack.ActivityState.RESUMED;
@@ -361,14 +361,12 @@
                 translucentStack.topRunningActivityLocked();
         topRunningTranslucentActivity.finishing = true;
 
-        // Home shouldn't be visible since its activity is marked as finishing and it isn't the top
-        // of the stack list.
-        assertFalse(homeStack.shouldBeVisible(null /* starting */));
+        // Home stack should be visible even there are no running activities.
+        assertTrue(homeStack.shouldBeVisible(null /* starting */));
         // Home should be visible if we are starting an activity within it.
         assertTrue(homeStack.shouldBeVisible(topRunningHomeActivity /* starting */));
-        // The translucent stack should be visible since it is the top of the stack list even though
-        // it has its activity marked as finishing.
-        assertTrue(translucentStack.shouldBeVisible(null /* starting */));
+        // The translucent stack shouldn't be visible since its activity marked as finishing.
+        assertFalse(translucentStack.shouldBeVisible(null /* starting */));
     }
 
     @Test
@@ -672,9 +670,10 @@
 
         // There is still an activity1 in stack1 so the activity2 should be added to finishing list
         // that will be destroyed until idle.
+        stack2.getTopActivity().visible = true;
         final ActivityRecord activity2 = finishCurrentActivity(stack2);
-        assertEquals(FINISHING, activity2.getState());
-        assertTrue(mSupervisor.mFinishingActivities.contains(activity2));
+        assertEquals(STOPPING, activity2.getState());
+        assertTrue(mSupervisor.mStoppingActivities.contains(activity2));
 
         // The display becomes empty. Since there is no next activity to be idle, the activity
         // should be destroyed immediately with updating configuration to restore original state.
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStartControllerTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStartControllerTests.java
index 9192d6b..e1ebbcf 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStartControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStartControllerTests.java
@@ -83,7 +83,7 @@
         final WindowProcessController wpc = new WindowProcessController(mService,
                 mService.mContext.getApplicationInfo(), "name", 12345,
                 UserHandle.getUserId(12345), mock(Object.class),
-                mock(WindowProcessListener.class), null);
+                mock(WindowProcessListener.class));
         wpc.setThread(mock(IApplicationThread.class));
 
         mController.addPendingActivityLaunch(
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java
index ba64b51..fb11a04 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java
@@ -211,7 +211,7 @@
         final WindowProcessController wpc =
                 containsConditions(preconditions, PRECONDITION_NO_CALLER_APP)
                 ? null : new WindowProcessController(
-                        service, mock(ApplicationInfo.class),null, 0, -1, null, null, null);
+                        service, mock(ApplicationInfo.class),null, 0, -1, null, null);
         doReturn(wpc).when(service).getProcessController(anyObject());
 
         final Intent intent = new Intent();
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
index 01d51e4..adf861b 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
@@ -39,14 +39,6 @@
 
 import android.app.ActivityManagerInternal;
 import android.app.ActivityOptions;
-import android.content.pm.PackageManagerInternal;
-import com.android.server.uri.UriGrantsManagerInternal;
-import com.android.server.wm.ActivityTaskManagerInternal;
-import com.android.server.wm.DisplayWindowController;
-
-import org.junit.Rule;
-import org.mockito.invocation.InvocationOnMock;
-
 import android.app.IApplicationThread;
 import android.content.ComponentName;
 import android.content.Context;
@@ -54,6 +46,7 @@
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageManager;
+import android.content.pm.PackageManagerInternal;
 import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.hardware.display.DisplayManager;
@@ -73,7 +66,10 @@
 import com.android.server.AppOpsService;
 import com.android.server.AttributeCache;
 import com.android.server.ServiceThread;
+import com.android.server.uri.UriGrantsManagerInternal;
+import com.android.server.wm.ActivityTaskManagerInternal;
 import com.android.server.wm.AppWindowContainerController;
+import com.android.server.wm.DisplayWindowController;
 import com.android.server.wm.PinnedStackWindowController;
 import com.android.server.wm.RootWindowContainerController;
 import com.android.server.wm.StackWindowController;
@@ -83,7 +79,9 @@
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Rule;
 import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
 
 import java.io.File;
 import java.util.List;
@@ -286,7 +284,7 @@
             final WindowProcessController wpc = new WindowProcessController(mService,
                     mService.mContext.getApplicationInfo(), "name", 12345,
                     UserHandle.getUserId(12345), mock(Object.class),
-                    mock(WindowProcessListener.class), null);
+                    mock(WindowProcessListener.class));
             wpc.setThread(mock(IApplicationThread.class));
             activity.setProcess(wpc);
             return activity;
@@ -536,11 +534,6 @@
             mUgmInternal = mock(UriGrantsManagerInternal.class);
         }
 
-        @Override
-        Configuration getGlobalConfiguration() {
-            return mContext.getResources().getConfiguration();
-        }
-
         ActivityManagerInternal getLocalService() {
             if (mInternal == null) {
                 mInternal = new LocalService();
@@ -613,23 +606,9 @@
         @Override
         <T extends ActivityStack> T createStackUnchecked(int windowingMode, int activityType,
                 int stackId, boolean onTop) {
-            if (windowingMode == WINDOWING_MODE_PINNED) {
-                return (T) new PinnedActivityStack(this, stackId, mSupervisor, onTop) {
-                    @Override
-                    Rect getDefaultPictureInPictureBounds(float aspectRatio) {
-                        return new Rect(50, 50, 100, 100);
-                    }
-
-                    @Override
-                    PinnedStackWindowController createStackWindowController(int displayId,
-                            boolean onTop, Rect outBounds) {
-                        return mock(PinnedStackWindowController.class);
-                    }
-                };
-            } else {
-                return (T) new TestActivityStack(
-                        this, stackId, mSupervisor, windowingMode, activityType, onTop);
-            }
+            return new StackBuilder(mSupervisor).setDisplay(this)
+                    .setWindowingMode(windowingMode).setActivityType(activityType)
+                    .setStackId(stackId).setOnTop(onTop).setCreateActivity(false).build();
         }
 
         @Override
@@ -682,8 +661,19 @@
         private int mSupportsSplitScreen = SUPPORTS_SPLIT_SCREEN_UNSET;
 
         TestActivityStack(ActivityDisplay display, int stackId, ActivityStackSupervisor supervisor,
-                int windowingMode, int activityType, boolean onTop) {
+                int windowingMode, int activityType, boolean onTop, boolean createActivity) {
             super(display, stackId, supervisor, windowingMode, activityType, onTop);
+            if (createActivity) {
+                new ActivityBuilder(mService).setCreateTask(true).setStack(this).build();
+                if (onTop) {
+                    // We move the task to front again in order to regain focus after activity
+                    // added to the stack. Or {@link ActivityDisplay#mPreferredTopFocusableStack}
+                    // could be other stacks (e.g. home stack).
+                    moveToFront("createActivityStack");
+                } else {
+                    moveToBack("createActivityStack", null);
+                }
+            }
         }
 
         @Override
@@ -755,4 +745,71 @@
                                  ActivityOptions options) {
         }
     }
+
+    protected static class StackBuilder {
+        private final ActivityStackSupervisor mSupervisor;
+        private ActivityDisplay mDisplay;
+        private int mStackId = -1;
+        private int mWindowingMode = WINDOWING_MODE_FULLSCREEN;
+        private int mActivityType = ACTIVITY_TYPE_STANDARD;
+        private boolean mOnTop = true;
+        private boolean mCreateActivity = true;
+
+        StackBuilder(ActivityStackSupervisor supervisor) {
+            mSupervisor = supervisor;
+            mDisplay = mSupervisor.getDefaultDisplay();
+        }
+
+        StackBuilder setWindowingMode(int windowingMode) {
+            mWindowingMode = windowingMode;
+            return this;
+        }
+
+        StackBuilder setActivityType(int activityType) {
+            mActivityType = activityType;
+            return this;
+        }
+
+        StackBuilder setStackId(int stackId) {
+            mStackId = stackId;
+            return this;
+        }
+
+        StackBuilder setDisplay(ActivityDisplay display) {
+            mDisplay = display;
+            return this;
+        }
+
+        StackBuilder setOnTop(boolean onTop) {
+            mOnTop = onTop;
+            return this;
+        }
+
+        StackBuilder setCreateActivity(boolean createActivity) {
+            mCreateActivity = createActivity;
+            return this;
+        }
+
+        <T extends ActivityStack> T build() {
+            final int stackId = mStackId >= 0 ? mStackId : mDisplay.getNextStackId();
+            if (mWindowingMode == WINDOWING_MODE_PINNED) {
+                return (T) new PinnedActivityStack(mDisplay, stackId, mSupervisor, mOnTop) {
+                    @Override
+                    Rect getDefaultPictureInPictureBounds(float aspectRatio) {
+                        return new Rect(50, 50, 100, 100);
+                    }
+
+                    @Override
+                    PinnedStackWindowController createStackWindowController(int displayId,
+                            boolean onTop, Rect outBounds) {
+                        return mock(PinnedStackWindowController.class);
+                    }
+                };
+            } else {
+                return (T) new TestActivityStack(mDisplay, stackId, mSupervisor, mWindowingMode,
+                        mActivityType, mOnTop, mCreateActivity);
+            }
+        }
+
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/am/AppErrorDialogTest.java b/services/tests/servicestests/src/com/android/server/am/AppErrorDialogTest.java
index 06d41f1..3a7a24d 100644
--- a/services/tests/servicestests/src/com/android/server/am/AppErrorDialogTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/AppErrorDialogTest.java
@@ -69,7 +69,7 @@
     @UiThreadTest
     public void testCreateWorks() throws Exception {
         AppErrorDialog.Data data = new AppErrorDialog.Data();
-        data.proc = new ProcessRecord(null, mContext.getApplicationInfo(), "name", 12345, null);
+        data.proc = new ProcessRecord(null, mContext.getApplicationInfo(), "name", 12345);
         data.result = new AppErrorResult();
 
         AppErrorDialog dialog = new AppErrorDialog(mContext, mService, data);
diff --git a/services/tests/servicestests/src/com/android/server/am/MemoryStatUtilTest.java b/services/tests/servicestests/src/com/android/server/am/MemoryStatUtilTest.java
index 9a283fe..72c5b10 100644
--- a/services/tests/servicestests/src/com/android/server/am/MemoryStatUtilTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/MemoryStatUtilTest.java
@@ -17,6 +17,7 @@
 package com.android.server.am;
 
 import static com.android.server.am.MemoryStatUtil.BYTES_IN_KILOBYTE;
+import static com.android.server.am.MemoryStatUtil.JIFFY_NANOS;
 import static com.android.server.am.MemoryStatUtil.MemoryStat;
 import static com.android.server.am.MemoryStatUtil.PAGE_SIZE;
 import static com.android.server.am.MemoryStatUtil.parseMemoryMaxUsageFromMemCg;
@@ -96,7 +97,7 @@
             "-2",
             "117",
             "0",
-            "2206",
+            "2222", // this in start time (in ticks per second)
             "1257177088",
             "3", // this is RSS (number of pages)
             "4294967295",
@@ -219,6 +220,7 @@
         assertEquals(3 * PAGE_SIZE, stat.rssInBytes);
         assertEquals(0, stat.cacheInBytes);
         assertEquals(0, stat.swapInBytes);
+        assertEquals(2222 * JIFFY_NANOS, stat.startTimeNanos);
     }
 
     @Test
diff --git a/services/tests/servicestests/src/com/android/server/am/PendingRemoteAnimationRegistryTest.java b/services/tests/servicestests/src/com/android/server/am/PendingRemoteAnimationRegistryTest.java
index 1c4e0f6..4beebc4 100644
--- a/services/tests/servicestests/src/com/android/server/am/PendingRemoteAnimationRegistryTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/PendingRemoteAnimationRegistryTest.java
@@ -50,17 +50,17 @@
     private PendingRemoteAnimationRegistry mRegistry;
     private final OffsettableClock mClock = new OffsettableClock.Stopped();
     private TestHandler mHandler;
-    private ActivityManagerService mService;
+    private ActivityTaskManagerService mService;
 
     @Before
     public void setUp() throws Exception {
         super.setUp();
         MockitoAnnotations.initMocks(this);
-        mService = createActivityManagerService();
-        mService.mHandlerThread.getThreadHandler().runWithScissors(() -> {
+        mService = createActivityTaskManagerService();
+        mService.mH.runWithScissors(() -> {
             mHandler = new TestHandler(null, mClock);
         }, 0);
-        mRegistry = new PendingRemoteAnimationRegistry(mService.mActivityTaskManager, mHandler);
+        mRegistry = new PendingRemoteAnimationRegistry(mService, mHandler);
     }
 
     @Test
diff --git a/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java b/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
index 27e8c63..129b835 100644
--- a/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
@@ -883,7 +883,7 @@
 
         MyTestActivityStack(ActivityDisplay display, ActivityStackSupervisor supervisor) {
             super(display, LAST_STACK_ID++, supervisor, WINDOWING_MODE_FULLSCREEN,
-                    ACTIVITY_TYPE_STANDARD, true);
+                    ACTIVITY_TYPE_STANDARD, true /* onTop */, false /* createActivity */);
             mDisplay = display;
         }
 
diff --git a/services/tests/servicestests/src/com/android/server/am/RunningTasksTest.java b/services/tests/servicestests/src/com/android/server/am/RunningTasksTest.java
index aa3046f..849a411 100644
--- a/services/tests/servicestests/src/com/android/server/am/RunningTasksTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/RunningTasksTest.java
@@ -16,9 +16,7 @@
 
 package com.android.server.am;
 
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
 import static android.view.Display.DEFAULT_DISPLAY;
 
@@ -30,7 +28,6 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.platform.test.annotations.Presubmit;
-import android.util.SparseArray;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.MediumTest;
@@ -72,8 +69,8 @@
 
         final int numStacks = 2;
         for (int stackIndex = 0; stackIndex < numStacks; stackIndex++) {
-            final ActivityStack stack = new TestActivityStack(display, stackIndex, mSupervisor,
-                    WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true);
+            final ActivityStack stack =
+                    new StackBuilder(mSupervisor).setCreateActivity(false).build();
             display.addChild(stack, POSITION_BOTTOM);
         }
 
diff --git a/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java b/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java
index 543f51cba..78751a1 100644
--- a/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java
+++ b/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java
@@ -27,6 +27,7 @@
 import android.util.Pair;
 
 import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.internal.util.HexDump;
@@ -53,6 +54,7 @@
  * atest $ANDROID_BUILD_TOP/frameworks/base/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java
  */
 @RunWith(AndroidJUnit4.class)
+@SmallTest
 public class JobStoreTest {
     private static final String TAG = "TaskStoreTest";
     private static final String TEST_PREFIX = "_test_";
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
index 9af7b1c..b0b7def 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
@@ -26,6 +26,7 @@
 import android.content.pm.PackageParser;
 import android.content.pm.ProviderInfo;
 import android.content.pm.ServiceInfo;
+import android.content.pm.SharedLibraryInfo;
 import android.content.pm.Signature;
 import android.os.Bundle;
 import android.os.Parcel;
@@ -488,6 +489,9 @@
 
         pkg.usesLibraryFiles = new String[] { "foo13"};
 
+        pkg.usesLibraryInfos = new ArrayList<>();
+        pkg.usesLibraryInfos.add(new SharedLibraryInfo(null, null, null, 0L, 0, null, null));
+
         pkg.mOriginalPackages = new ArrayList<>();
         pkg.mOriginalPackages.add("foo14");
 
diff --git a/services/tests/servicestests/src/com/android/server/usage/AppTimeLimitControllerTests.java b/services/tests/servicestests/src/com/android/server/usage/AppTimeLimitControllerTests.java
index 047addd..793d6b0 100644
--- a/services/tests/servicestests/src/com/android/server/usage/AppTimeLimitControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/usage/AppTimeLimitControllerTests.java
@@ -61,6 +61,7 @@
 
     private static final long TIME_30_MIN = 30 * 60_000L;
     private static final long TIME_10_MIN = 10 * 60_000L;
+    private static final long TIME_1_MIN = 10 * 60_000L;
 
     private static final long MAX_OBSERVER_PER_UID = 10;
     private static final long MIN_TIME_LIMIT = 4_000L;
@@ -77,7 +78,8 @@
             PKG_GAME1, PKG_GAME2
     };
 
-    private final CountDownLatch mCountDownLatch = new CountDownLatch(1);
+    private CountDownLatch mLimitReachedLatch = new CountDownLatch(1);
+    private CountDownLatch mSessionEndLatch = new CountDownLatch(1);
 
     private AppTimeLimitController mController;
 
@@ -85,18 +87,24 @@
 
     private long mUptimeMillis;
 
-    AppTimeLimitController.OnLimitReachedListener mListener
-            = new AppTimeLimitController.OnLimitReachedListener() {
+    AppTimeLimitController.TimeLimitCallbackListener mListener =
+            new AppTimeLimitController.TimeLimitCallbackListener() {
+                @Override
+                public void onLimitReached(int observerId, int userId, long timeLimit,
+                        long timeElapsed,
+                        PendingIntent callbackIntent) {
+                    mLimitReachedLatch.countDown();
+                }
 
-        @Override
-        public void onLimitReached(int observerId, int userId, long timeLimit, long timeElapsed,
-                PendingIntent callbackIntent) {
-            mCountDownLatch.countDown();
-        }
-    };
+                @Override
+                public void onSessionEnd(int observerId, int userId, long timeElapsed,
+                        PendingIntent callbackIntent) {
+                    mSessionEndLatch.countDown();
+                }
+            };
 
     class MyAppTimeLimitController extends AppTimeLimitController {
-        MyAppTimeLimitController(AppTimeLimitController.OnLimitReachedListener listener,
+        MyAppTimeLimitController(AppTimeLimitController.TimeLimitCallbackListener listener,
                 Looper looper) {
             super(listener, looper);
         }
@@ -107,7 +115,12 @@
         }
 
         @Override
-        protected long getObserverPerUidLimit() {
+        protected long getAppUsageObserverPerUidLimit() {
+            return MAX_OBSERVER_PER_UID;
+        }
+
+        @Override
+        protected long getUsageSessionObserverPerUidLimit() {
             return MAX_OBSERVER_PER_UID;
         }
 
@@ -129,188 +142,551 @@
         mThread.quit();
     }
 
-    /** Verify observer is added */
+    /** Verify app usage observer is added */
     @Test
-    public void testAddObserver() {
-        addObserver(OBS_ID1, GROUP1, TIME_30_MIN);
-        assertTrue("Observer wasn't added", hasObserver(OBS_ID1));
-        addObserver(OBS_ID2, GROUP_GAME, TIME_30_MIN);
-        assertTrue("Observer wasn't added", hasObserver(OBS_ID2));
-        assertTrue("Observer wasn't added", hasObserver(OBS_ID1));
+    public void testAppUsageObserver_AddObserver() {
+        addAppUsageObserver(OBS_ID1, GROUP1, TIME_30_MIN);
+        assertTrue("Observer wasn't added", hasAppUsageObserver(UID, OBS_ID1));
+        addAppUsageObserver(OBS_ID2, GROUP_GAME, TIME_30_MIN);
+        assertTrue("Observer wasn't added", hasAppUsageObserver(UID, OBS_ID2));
+        assertTrue("Observer wasn't added", hasAppUsageObserver(UID, OBS_ID1));
     }
 
-    /** Verify observer is removed */
+    /** Verify usage session observer is added */
     @Test
-    public void testRemoveObserver() {
-        addObserver(OBS_ID1, GROUP1, TIME_30_MIN);
-        assertTrue("Observer wasn't added", hasObserver(OBS_ID1));
-        mController.removeObserver(UID, OBS_ID1, USER_ID);
-        assertFalse("Observer wasn't removed", hasObserver(OBS_ID1));
+    public void testUsageSessionObserver_AddObserver() {
+        addUsageSessionObserver(OBS_ID1, GROUP1, TIME_30_MIN, TIME_1_MIN);
+        assertTrue("Observer wasn't added", hasUsageSessionObserver(UID, OBS_ID1));
+        addUsageSessionObserver(OBS_ID2, GROUP_GAME, TIME_30_MIN, TIME_1_MIN);
+        assertTrue("Observer wasn't added", hasUsageSessionObserver(UID, OBS_ID2));
+        assertTrue("Observer wasn't added", hasUsageSessionObserver(UID, OBS_ID1));
+    }
+
+    /** Verify app usage observer is removed */
+    @Test
+    public void testAppUsageObserver_RemoveObserver() {
+        addAppUsageObserver(OBS_ID1, GROUP1, TIME_30_MIN);
+        assertTrue("Observer wasn't added", hasAppUsageObserver(UID, OBS_ID1));
+        mController.removeAppUsageObserver(UID, OBS_ID1, USER_ID);
+        assertFalse("Observer wasn't removed", hasAppUsageObserver(UID, OBS_ID1));
+    }
+
+    /** Verify usage session observer is removed */
+    @Test
+    public void testUsageSessionObserver_RemoveObserver() {
+        addUsageSessionObserver(OBS_ID1, GROUP1, TIME_30_MIN, TIME_1_MIN);
+        assertTrue("Observer wasn't added", hasUsageSessionObserver(UID, OBS_ID1));
+        mController.removeUsageSessionObserver(UID, OBS_ID1, USER_ID);
+        assertFalse("Observer wasn't removed", hasUsageSessionObserver(UID, OBS_ID1));
     }
 
     /** Re-adding an observer should result in only one copy */
     @Test
-    public void testObserverReAdd() {
-        addObserver(OBS_ID1, GROUP1, TIME_30_MIN);
-        assertTrue("Observer wasn't added", hasObserver(OBS_ID1));
-        addObserver(OBS_ID1, GROUP1, TIME_10_MIN);
+    public void testAppUsageObserver_ObserverReAdd() {
+        addAppUsageObserver(OBS_ID1, GROUP1, TIME_30_MIN);
+        assertTrue("Observer wasn't added", hasAppUsageObserver(UID, OBS_ID1));
+        addAppUsageObserver(OBS_ID1, GROUP1, TIME_10_MIN);
         assertTrue("Observer wasn't added",
-                mController.getObserverGroup(OBS_ID1, USER_ID).timeLimit == TIME_10_MIN);
-        mController.removeObserver(UID, OBS_ID1, USER_ID);
-        assertFalse("Observer wasn't removed", hasObserver(OBS_ID1));
+                mController.getAppUsageGroup(UID, OBS_ID1).getTimeLimitMs() == TIME_10_MIN);
+        mController.removeAppUsageObserver(UID, OBS_ID1, USER_ID);
+        assertFalse("Observer wasn't removed", hasAppUsageObserver(UID, OBS_ID1));
+    }
+
+    /** Re-adding an observer should result in only one copy */
+    @Test
+    public void testUsageSessionObserver_ObserverReAdd() {
+        addUsageSessionObserver(OBS_ID1, GROUP1, TIME_30_MIN, TIME_1_MIN);
+        assertTrue("Observer wasn't added", hasUsageSessionObserver(UID, OBS_ID1));
+        addUsageSessionObserver(OBS_ID1, GROUP1, TIME_10_MIN, TIME_1_MIN);
+        assertTrue("Observer wasn't added",
+                mController.getSessionUsageGroup(UID, OBS_ID1).getTimeLimitMs() == TIME_10_MIN);
+        mController.removeUsageSessionObserver(UID, OBS_ID1, USER_ID);
+        assertFalse("Observer wasn't removed", hasUsageSessionObserver(UID, OBS_ID1));
+    }
+
+    /** Different type observers can be registered to the same observerId value */
+    @Test
+    public void testAllObservers_ExclusiveObserverIds() {
+        addAppUsageObserver(OBS_ID1, GROUP1, TIME_10_MIN);
+        addUsageSessionObserver(OBS_ID1, GROUP1, TIME_30_MIN, TIME_1_MIN);
+        assertTrue("Observer wasn't added", hasAppUsageObserver(UID, OBS_ID1));
+        assertTrue("Observer wasn't added", hasUsageSessionObserver(UID, OBS_ID1));
+
+        AppTimeLimitController.UsageGroup appUsageGroup = mController.getAppUsageGroup(UID,
+                OBS_ID1);
+        AppTimeLimitController.UsageGroup sessionUsageGroup = mController.getSessionUsageGroup(UID,
+                OBS_ID1);
+
+        // Verify data still intact
+        assertEquals(TIME_10_MIN, appUsageGroup.getTimeLimitMs());
+        assertEquals(TIME_30_MIN, sessionUsageGroup.getTimeLimitMs());
     }
 
     /** Verify that usage across different apps within a group are added up */
     @Test
-    public void testAccumulation() throws Exception {
+    public void testAppUsageObserver_Accumulation() throws Exception {
         setTime(0L);
-        addObserver(OBS_ID1, GROUP1, TIME_30_MIN);
-        moveToForeground(PKG_SOC1);
+        addAppUsageObserver(OBS_ID1, GROUP1, TIME_30_MIN);
+        startUsage(PKG_SOC1);
         // Add 10 mins
         setTime(TIME_10_MIN);
-        moveToBackground(PKG_SOC1);
+        stopUsage(PKG_SOC1);
 
-        long timeRemaining = mController.getObserverGroup(OBS_ID1, USER_ID).timeRemaining;
+        AppTimeLimitController.UsageGroup group = mController.getAppUsageGroup(UID, OBS_ID1);
+
+        long timeRemaining = group.getTimeLimitMs() - group.getUsageTimeMs();
         assertEquals(TIME_10_MIN * 2, timeRemaining);
 
-        moveToForeground(PKG_SOC1);
+        startUsage(PKG_SOC1);
         setTime(TIME_10_MIN * 2);
-        moveToBackground(PKG_SOC1);
+        stopUsage(PKG_SOC1);
 
-        timeRemaining = mController.getObserverGroup(OBS_ID1, USER_ID).timeRemaining;
+        timeRemaining = group.getTimeLimitMs() - group.getUsageTimeMs();
         assertEquals(TIME_10_MIN, timeRemaining);
 
         setTime(TIME_30_MIN);
 
-        assertFalse(mCountDownLatch.await(100L, TimeUnit.MILLISECONDS));
+        assertFalse(mLimitReachedLatch.await(100L, TimeUnit.MILLISECONDS));
 
         // Add a different package in the group
-        moveToForeground(PKG_GAME1);
+        startUsage(PKG_GAME1);
         setTime(TIME_30_MIN + TIME_10_MIN);
-        moveToBackground(PKG_GAME1);
+        stopUsage(PKG_GAME1);
 
-        assertEquals(0, mController.getObserverGroup(OBS_ID1, USER_ID).timeRemaining);
-        assertTrue(mCountDownLatch.await(100L, TimeUnit.MILLISECONDS));
+        assertEquals(0, group.getTimeLimitMs() - group.getUsageTimeMs());
+        assertTrue(mLimitReachedLatch.await(100L, TimeUnit.MILLISECONDS));
+    }
+
+    /** Verify that usage across different apps within a group are added up */
+    @Test
+    public void testUsageSessionObserver_Accumulation() throws Exception {
+        setTime(0L);
+        addUsageSessionObserver(OBS_ID1, GROUP1, TIME_30_MIN, TIME_1_MIN);
+        startUsage(PKG_SOC1);
+        // Add 10 mins
+        setTime(TIME_10_MIN);
+        stopUsage(PKG_SOC1);
+
+        AppTimeLimitController.UsageGroup group = mController.getSessionUsageGroup(UID, OBS_ID1);
+
+        long timeRemaining = group.getTimeLimitMs() - group.getUsageTimeMs();
+        assertEquals(TIME_10_MIN * 2, timeRemaining);
+
+        startUsage(PKG_SOC1);
+        setTime(TIME_10_MIN * 2);
+        stopUsage(PKG_SOC1);
+
+        timeRemaining = group.getTimeLimitMs() - group.getUsageTimeMs();
+        assertEquals(TIME_10_MIN, timeRemaining);
+
+        setTime(TIME_30_MIN);
+
+        assertFalse(mLimitReachedLatch.await(100L, TimeUnit.MILLISECONDS));
+
+        // Add a different package in the group
+        startUsage(PKG_GAME1);
+        setTime(TIME_30_MIN + TIME_10_MIN);
+        stopUsage(PKG_GAME1);
+
+        assertEquals(0, group.getTimeLimitMs() - group.getUsageTimeMs());
+        assertTrue(mLimitReachedLatch.await(100L, TimeUnit.MILLISECONDS));
     }
 
     /** Verify that time limit does not get triggered due to a different app */
     @Test
-    public void testTimeoutOtherApp() throws Exception {
+    public void testAppUsageObserver_TimeoutOtherApp() throws Exception {
         setTime(0L);
-        addObserver(OBS_ID1, GROUP1, 4_000L);
-        moveToForeground(PKG_SOC2);
-        assertFalse(mCountDownLatch.await(6_000L, TimeUnit.MILLISECONDS));
+        addAppUsageObserver(OBS_ID1, GROUP1, 4_000L);
+        startUsage(PKG_SOC2);
+        assertFalse(mLimitReachedLatch.await(6_000L, TimeUnit.MILLISECONDS));
         setTime(6_000L);
-        moveToBackground(PKG_SOC2);
-        assertFalse(mCountDownLatch.await(100L, TimeUnit.MILLISECONDS));
+        stopUsage(PKG_SOC2);
+        assertFalse(mLimitReachedLatch.await(100L, TimeUnit.MILLISECONDS));
+    }
+
+    /** Verify that time limit does not get triggered due to a different app */
+    @Test
+    public void testUsageSessionObserver_TimeoutOtherApp() throws Exception {
+        setTime(0L);
+        addUsageSessionObserver(OBS_ID1, GROUP1, 4_000L, 1_000L);
+        startUsage(PKG_SOC2);
+        assertFalse(mLimitReachedLatch.await(6_000L, TimeUnit.MILLISECONDS));
+        setTime(6_000L);
+        stopUsage(PKG_SOC2);
+        assertFalse(mLimitReachedLatch.await(100L, TimeUnit.MILLISECONDS));
+
     }
 
     /** Verify the timeout message is delivered at the right time */
     @Test
-    public void testTimeout() throws Exception {
+    public void testAppUsageObserver_Timeout() throws Exception {
         setTime(0L);
-        addObserver(OBS_ID1, GROUP1, 4_000L);
-        moveToForeground(PKG_SOC1);
+        addAppUsageObserver(OBS_ID1, GROUP1, 4_000L);
+        startUsage(PKG_SOC1);
         setTime(6_000L);
-        assertTrue(mCountDownLatch.await(6_000L, TimeUnit.MILLISECONDS));
-        moveToBackground(PKG_SOC1);
+        assertTrue(mLimitReachedLatch.await(6_000L, TimeUnit.MILLISECONDS));
+        stopUsage(PKG_SOC1);
         // Verify that the observer was removed
-        assertFalse(hasObserver(OBS_ID1));
+        assertFalse(hasAppUsageObserver(UID, OBS_ID1));
+    }
+
+    /** Verify the timeout message is delivered at the right time */
+    @Test
+    public void testUsageSessionObserver_Timeout() throws Exception {
+        setTime(0L);
+        addUsageSessionObserver(OBS_ID1, GROUP1, 4_000L, 1_000L);
+        startUsage(PKG_SOC1);
+        setTime(6_000L);
+        assertTrue(mLimitReachedLatch.await(6_000L, TimeUnit.MILLISECONDS));
+        stopUsage(PKG_SOC1);
+        // Usage has stopped, Session should end in a second. Verify session end occurs in a second
+        // (+/- 100ms, which is hopefully not too slim a margin)
+        assertFalse(mSessionEndLatch.await(900L, TimeUnit.MILLISECONDS));
+        assertTrue(mSessionEndLatch.await(200L, TimeUnit.MILLISECONDS));
+        // Verify that the observer was not removed
+        assertTrue(hasUsageSessionObserver(UID, OBS_ID1));
     }
 
     /** If an app was already running, make sure it is partially counted towards the time limit */
     @Test
-    public void testAlreadyRunning() throws Exception {
+    public void testAppUsageObserver_AlreadyRunning() throws Exception {
         setTime(TIME_10_MIN);
-        moveToForeground(PKG_GAME1);
+        startUsage(PKG_GAME1);
         setTime(TIME_30_MIN);
-        addObserver(OBS_ID2, GROUP_GAME, TIME_30_MIN);
+        addAppUsageObserver(OBS_ID2, GROUP_GAME, TIME_30_MIN);
         setTime(TIME_30_MIN + TIME_10_MIN);
-        moveToBackground(PKG_GAME1);
-        assertFalse(mCountDownLatch.await(1000L, TimeUnit.MILLISECONDS));
+        stopUsage(PKG_GAME1);
+        assertFalse(mLimitReachedLatch.await(1_000L, TimeUnit.MILLISECONDS));
 
-        moveToForeground(PKG_GAME2);
+        startUsage(PKG_GAME2);
         setTime(TIME_30_MIN + TIME_30_MIN);
-        moveToBackground(PKG_GAME2);
-        assertTrue(mCountDownLatch.await(1000L, TimeUnit.MILLISECONDS));
+        stopUsage(PKG_GAME2);
+        assertTrue(mLimitReachedLatch.await(1_000L, TimeUnit.MILLISECONDS));
         // Verify that the observer was removed
-        assertFalse(hasObserver(OBS_ID2));
+        assertFalse(hasAppUsageObserver(UID, OBS_ID2));
+    }
+
+    /** If an app was already running, make sure it is partially counted towards the time limit */
+    @Test
+    public void testUsageSessionObserver_AlreadyRunning() throws Exception {
+        setTime(TIME_10_MIN);
+        startUsage(PKG_GAME1);
+        setTime(TIME_30_MIN);
+        addUsageSessionObserver(OBS_ID2, GROUP_GAME, TIME_30_MIN, TIME_1_MIN);
+        setTime(TIME_30_MIN + TIME_10_MIN);
+        stopUsage(PKG_GAME1);
+        assertFalse(mLimitReachedLatch.await(1_000L, TimeUnit.MILLISECONDS));
+
+        startUsage(PKG_GAME2);
+        setTime(TIME_30_MIN + TIME_30_MIN);
+        stopUsage(PKG_GAME2);
+        assertTrue(mLimitReachedLatch.await(1_000L, TimeUnit.MILLISECONDS));
+        // Verify that the observer was removed
+        assertTrue(hasUsageSessionObserver(UID, OBS_ID2));
     }
 
     /** If watched app is already running, verify the timeout callback happens at the right time */
     @Test
-    public void testAlreadyRunningTimeout() throws Exception {
+    public void testAppUsageObserver_AlreadyRunningTimeout() throws Exception {
         setTime(0);
-        moveToForeground(PKG_SOC1);
+        startUsage(PKG_SOC1);
         setTime(TIME_10_MIN);
         // 10 second time limit
-        addObserver(OBS_ID1, GROUP_SOC, 10_000L);
+        addAppUsageObserver(OBS_ID1, GROUP_SOC, 10_000L);
         setTime(TIME_10_MIN + 5_000L);
         // Shouldn't call back in 6 seconds
-        assertFalse(mCountDownLatch.await(6_000L, TimeUnit.MILLISECONDS));
+        assertFalse(mLimitReachedLatch.await(6_000L, TimeUnit.MILLISECONDS));
         setTime(TIME_10_MIN + 10_000L);
         // Should call back by 11 seconds (6 earlier + 5 now)
-        assertTrue(mCountDownLatch.await(5_000L, TimeUnit.MILLISECONDS));
+        assertTrue(mLimitReachedLatch.await(5_000L, TimeUnit.MILLISECONDS));
         // Verify that the observer was removed
-        assertFalse(hasObserver(OBS_ID1));
+        assertFalse(hasAppUsageObserver(UID, OBS_ID1));
     }
 
-    /** Verify that App Time Limit Controller will limit the number of observerIds */
+    /** If watched app is already running, verify the timeout callback happens at the right time */
     @Test
-    public void testMaxObserverLimit() throws Exception {
+    public void testUsageSessionObserver_AlreadyRunningTimeout() throws Exception {
+        setTime(0);
+        startUsage(PKG_SOC1);
+        setTime(TIME_10_MIN);
+        // 10 second time limit
+        addUsageSessionObserver(OBS_ID1, GROUP_SOC, 10_000L, 1_000L);
+        setTime(TIME_10_MIN + 5_000L);
+        // Shouldn't call back in 6 seconds
+        assertFalse(mLimitReachedLatch.await(6_000L, TimeUnit.MILLISECONDS));
+        setTime(TIME_10_MIN + 10_000L);
+        // Should call back by 11 seconds (6 earlier + 5 now)
+        assertTrue(mLimitReachedLatch.await(5_000L, TimeUnit.MILLISECONDS));
+        stopUsage(PKG_SOC1);
+        // Usage has stopped, Session should end in a second. Verify session end occurs in a second
+        // (+/- 100ms, which is hopefully not too slim a margin)
+        assertFalse(mSessionEndLatch.await(900L, TimeUnit.MILLISECONDS));
+        assertTrue(mSessionEndLatch.await(200L, TimeUnit.MILLISECONDS));
+        // Verify that the observer was removed
+        assertTrue(hasUsageSessionObserver(UID, OBS_ID1));
+    }
+
+    /**
+     * Verify that App Time Limit Controller will limit the number of observerIds for app usage
+     * observers
+     */
+    @Test
+    public void testAppUsageObserver_MaxObserverLimit() throws Exception {
         boolean receivedException = false;
         int ANOTHER_UID = UID + 1;
-        addObserver(OBS_ID1, GROUP1, TIME_30_MIN);
-        addObserver(OBS_ID2, GROUP1, TIME_30_MIN);
-        addObserver(OBS_ID3, GROUP1, TIME_30_MIN);
-        addObserver(OBS_ID4, GROUP1, TIME_30_MIN);
-        addObserver(OBS_ID5, GROUP1, TIME_30_MIN);
-        addObserver(OBS_ID6, GROUP1, TIME_30_MIN);
-        addObserver(OBS_ID7, GROUP1, TIME_30_MIN);
-        addObserver(OBS_ID8, GROUP1, TIME_30_MIN);
-        addObserver(OBS_ID9, GROUP1, TIME_30_MIN);
-        addObserver(OBS_ID10, GROUP1, TIME_30_MIN);
+        addAppUsageObserver(OBS_ID1, GROUP1, TIME_30_MIN);
+        addAppUsageObserver(OBS_ID2, GROUP1, TIME_30_MIN);
+        addAppUsageObserver(OBS_ID3, GROUP1, TIME_30_MIN);
+        addAppUsageObserver(OBS_ID4, GROUP1, TIME_30_MIN);
+        addAppUsageObserver(OBS_ID5, GROUP1, TIME_30_MIN);
+        addAppUsageObserver(OBS_ID6, GROUP1, TIME_30_MIN);
+        addAppUsageObserver(OBS_ID7, GROUP1, TIME_30_MIN);
+        addAppUsageObserver(OBS_ID8, GROUP1, TIME_30_MIN);
+        addAppUsageObserver(OBS_ID9, GROUP1, TIME_30_MIN);
+        addAppUsageObserver(OBS_ID10, GROUP1, TIME_30_MIN);
         // Readding an observer should not cause an IllegalStateException
-        addObserver(OBS_ID5, GROUP1, TIME_30_MIN);
+        addAppUsageObserver(OBS_ID5, GROUP1, TIME_30_MIN);
         // Adding an observer for a different uid shouldn't cause an IllegalStateException
-        mController.addObserver(ANOTHER_UID, OBS_ID11, GROUP1, TIME_30_MIN, null, USER_ID);
+        mController.addAppUsageObserver(ANOTHER_UID, OBS_ID11, GROUP1, TIME_30_MIN, null, USER_ID);
         try {
-            addObserver(OBS_ID11, GROUP1, TIME_30_MIN);
+            addAppUsageObserver(OBS_ID11, GROUP1, TIME_30_MIN);
         } catch (IllegalStateException ise) {
             receivedException = true;
         }
         assertTrue("Should have caused an IllegalStateException", receivedException);
     }
 
-    /** Verify that addObserver minimum time limit is one minute */
+    /**
+     * Verify that App Time Limit Controller will limit the number of observerIds for usage session
+     * observers
+     */
     @Test
-    public void testMinimumTimeLimit() throws Exception {
+    public void testUsageSessionObserver_MaxObserverLimit() throws Exception {
+        addUsageSessionObserver(OBS_ID1, GROUP1, TIME_30_MIN, TIME_1_MIN);
+        boolean receivedException = false;
+        int ANOTHER_UID = UID + 1;
+        addUsageSessionObserver(OBS_ID2, GROUP1, TIME_30_MIN, TIME_1_MIN);
+        addUsageSessionObserver(OBS_ID3, GROUP1, TIME_30_MIN, TIME_1_MIN);
+        addUsageSessionObserver(OBS_ID4, GROUP1, TIME_30_MIN, TIME_1_MIN);
+        addUsageSessionObserver(OBS_ID5, GROUP1, TIME_30_MIN, TIME_1_MIN);
+        addUsageSessionObserver(OBS_ID6, GROUP1, TIME_30_MIN, TIME_1_MIN);
+        addUsageSessionObserver(OBS_ID7, GROUP1, TIME_30_MIN, TIME_1_MIN);
+        addUsageSessionObserver(OBS_ID8, GROUP1, TIME_30_MIN, TIME_1_MIN);
+        addUsageSessionObserver(OBS_ID9, GROUP1, TIME_30_MIN, TIME_1_MIN);
+        addUsageSessionObserver(OBS_ID10, GROUP1, TIME_30_MIN, TIME_1_MIN);
+        // Readding an observer should not cause an IllegalStateException
+        addUsageSessionObserver(OBS_ID5, GROUP1, TIME_30_MIN, TIME_1_MIN);
+        // Adding an observer for a different uid shouldn't cause an IllegalStateException
+        mController.addUsageSessionObserver(ANOTHER_UID, OBS_ID11, GROUP1, TIME_30_MIN, TIME_1_MIN,
+                null, null, USER_ID);
+        try {
+            addUsageSessionObserver(OBS_ID11, GROUP1, TIME_30_MIN, TIME_1_MIN);
+        } catch (IllegalStateException ise) {
+            receivedException = true;
+        }
+        assertTrue("Should have caused an IllegalStateException", receivedException);
+    }
+
+    /** Verify that addAppUsageObserver minimum time limit is one minute */
+    @Test
+    public void testAppUsageObserver_MinimumTimeLimit() throws Exception {
         boolean receivedException = false;
         // adding an observer with a one minute time limit should not cause an exception
-        addObserver(OBS_ID1, GROUP1, MIN_TIME_LIMIT);
+        addAppUsageObserver(OBS_ID1, GROUP1, MIN_TIME_LIMIT);
         try {
-            addObserver(OBS_ID1, GROUP1, MIN_TIME_LIMIT - 1);
+            addAppUsageObserver(OBS_ID1, GROUP1, MIN_TIME_LIMIT - 1);
         } catch (IllegalArgumentException iae) {
             receivedException = true;
         }
         assertTrue("Should have caused an IllegalArgumentException", receivedException);
     }
 
-    private void moveToForeground(String packageName) {
-        mController.moveToForeground(packageName, "class", USER_ID);
+    /** Verify that addUsageSessionObserver minimum time limit is one minute */
+    @Test
+    public void testUsageSessionObserver_MinimumTimeLimit() throws Exception {
+        boolean receivedException = false;
+        // test also for session observers
+        addUsageSessionObserver(OBS_ID10, GROUP1, MIN_TIME_LIMIT, TIME_1_MIN);
+        try {
+            addUsageSessionObserver(OBS_ID10, GROUP1, MIN_TIME_LIMIT - 1, TIME_1_MIN);
+        } catch (IllegalArgumentException iae) {
+            receivedException = true;
+        }
+        assertTrue("Should have caused an IllegalArgumentException", receivedException);
     }
 
-    private void moveToBackground(String packageName) {
-        mController.moveToBackground(packageName, "class", USER_ID);
+    /** Verify that concurrent usage from multiple apps in the same group will counted correctly */
+    @Test
+    public void testAppUsageObserver_ConcurrentUsage() throws Exception {
+        setTime(0L);
+        addAppUsageObserver(OBS_ID1, GROUP1, TIME_30_MIN);
+        AppTimeLimitController.UsageGroup group = mController.getAppUsageGroup(UID, OBS_ID1);
+        startUsage(PKG_SOC1);
+        // Add 10 mins
+        setTime(TIME_10_MIN);
+
+        // Add a different package in the group will first package is still in use
+        startUsage(PKG_GAME1);
+        setTime(TIME_10_MIN * 2);
+        // Stop first package usage
+        stopUsage(PKG_SOC1);
+
+        setTime(TIME_30_MIN);
+        stopUsage(PKG_GAME1);
+
+        assertEquals(TIME_30_MIN, group.getUsageTimeMs());
+        assertTrue(mLimitReachedLatch.await(100L, TimeUnit.MILLISECONDS));
     }
 
-    private void addObserver(int observerId, String[] packages, long timeLimit) {
-        mController.addObserver(UID, observerId, packages, timeLimit, null, USER_ID);
+    /** Verify that concurrent usage from multiple apps in the same group will counted correctly */
+    @Test
+    public void testUsageSessionObserver_ConcurrentUsage() throws Exception {
+        setTime(0L);
+        addUsageSessionObserver(OBS_ID1, GROUP1, TIME_30_MIN, TIME_1_MIN);
+        AppTimeLimitController.UsageGroup group = mController.getSessionUsageGroup(UID, OBS_ID1);
+        startUsage(PKG_SOC1);
+        // Add 10 mins
+        setTime(TIME_10_MIN);
+
+        // Add a different package in the group will first package is still in use
+        startUsage(PKG_GAME1);
+        setTime(TIME_10_MIN * 2);
+        // Stop first package usage
+        stopUsage(PKG_SOC1);
+
+        setTime(TIME_30_MIN);
+        stopUsage(PKG_GAME1);
+
+        assertEquals(TIME_30_MIN, group.getUsageTimeMs());
+        assertTrue(mLimitReachedLatch.await(100L, TimeUnit.MILLISECONDS));
     }
 
-    /** Is there still an observer by that id */
-    private boolean hasObserver(int observerId) {
-        return mController.getObserverGroup(observerId, USER_ID) != null;
+    /** Verify that a session will continue if usage starts again within the session threshold */
+    @Test
+    public void testUsageSessionObserver_ContinueSession() throws Exception {
+        setTime(0L);
+        addUsageSessionObserver(OBS_ID1, GROUP1, 10_000L, 2_000L);
+        startUsage(PKG_SOC1);
+        setTime(6_000L);
+        stopUsage(PKG_SOC1);
+        // Wait momentarily, Session should not end
+        assertFalse(mSessionEndLatch.await(1_000L, TimeUnit.MILLISECONDS));
+
+        setTime(7_000L);
+        startUsage(PKG_SOC1);
+        setTime(10_500L);
+        stopUsage(PKG_SOC1);
+        // Total usage time has not reached the limit. Time limit callback should not fire yet
+        assertFalse(mLimitReachedLatch.await(100L, TimeUnit.MILLISECONDS));
+
+        setTime(10_600L);
+        startUsage(PKG_SOC1);
+        setTime(12_000L);
+        assertTrue(mLimitReachedLatch.await(1_000L, TimeUnit.MILLISECONDS));
+        stopUsage(PKG_SOC1);
+        // Usage has stopped, Session should end in 2 seconds. Verify session end occurs
+        // (+/- 100ms, which is hopefully not too slim a margin)
+        assertFalse(mSessionEndLatch.await(1_900L, TimeUnit.MILLISECONDS));
+        assertTrue(mSessionEndLatch.await(200L, TimeUnit.MILLISECONDS));
+        // Verify that the observer was not removed
+        assertTrue(hasUsageSessionObserver(UID, OBS_ID1));
+    }
+
+    /** Verify that a new session will start if next usage starts after the session threshold */
+    @Test
+    public void testUsageSessionObserver_NewSession() throws Exception {
+        setTime(0L);
+        addUsageSessionObserver(OBS_ID1, GROUP1, 10_000L, 1_000L);
+        startUsage(PKG_SOC1);
+        setTime(6_000L);
+        stopUsage(PKG_SOC1);
+        // Wait for longer than the session threshold. Session end callback should not be triggered
+        // because the usage timelimit hasn't been triggered.
+        assertFalse(mSessionEndLatch.await(1_500L, TimeUnit.MILLISECONDS));
+
+        setTime(7_500L);
+        // This should be the start of a new session
+        startUsage(PKG_SOC1);
+        setTime(16_000L);
+        stopUsage(PKG_SOC1);
+        // Total usage has exceed the timelimit, but current session time has not
+        assertFalse(mLimitReachedLatch.await(100L, TimeUnit.MILLISECONDS));
+
+        setTime(16_100L);
+        startUsage(PKG_SOC1);
+        setTime(18_000L);
+        assertTrue(mLimitReachedLatch.await(2000L, TimeUnit.MILLISECONDS));
+        stopUsage(PKG_SOC1);
+        // Usage has stopped, Session should end in 2 seconds. Verify session end occurs
+        // (+/- 100ms, which is hopefully not too slim a margin)
+        assertFalse(mSessionEndLatch.await(900L, TimeUnit.MILLISECONDS));
+        assertTrue(mSessionEndLatch.await(200L, TimeUnit.MILLISECONDS));
+        // Verify that the observer was not removed
+        assertTrue(hasUsageSessionObserver(UID, OBS_ID1));
+    }
+
+    /** Verify that the callbacks will be triggered for multiple sessions */
+    @Test
+    public void testUsageSessionObserver_RepeatSessions() throws Exception {
+        setTime(0L);
+        addUsageSessionObserver(OBS_ID1, GROUP1, 10_000L, 1_000L);
+        startUsage(PKG_SOC1);
+        setTime(9_000L);
+        stopUsage(PKG_SOC1);
+        // Stutter usage here, to reduce real world time needed trigger limit reached callback
+        startUsage(PKG_SOC1);
+        setTime(11_000L);
+        assertTrue(mLimitReachedLatch.await(2_000L, TimeUnit.MILLISECONDS));
+        stopUsage(PKG_SOC1);
+        // Usage has stopped, Session should end in 1 seconds. Verify session end occurs
+        // (+/- 100ms, which is hopefully not too slim a margin)
+        assertFalse(mSessionEndLatch.await(900L, TimeUnit.MILLISECONDS));
+        assertTrue(mSessionEndLatch.await(200L, TimeUnit.MILLISECONDS));
+
+        // Rearm the countdown latches
+        mLimitReachedLatch = new CountDownLatch(1);
+        mSessionEndLatch = new CountDownLatch(1);
+
+        // New session start
+        setTime(20_000L);
+        startUsage(PKG_SOC1);
+        setTime(29_000L);
+        stopUsage(PKG_SOC1);
+        startUsage(PKG_SOC1);
+        setTime(31_000L);
+        assertTrue(mLimitReachedLatch.await(2_000L, TimeUnit.MILLISECONDS));
+        stopUsage(PKG_SOC1);
+        assertFalse(mSessionEndLatch.await(900L, TimeUnit.MILLISECONDS));
+        assertTrue(mSessionEndLatch.await(200L, TimeUnit.MILLISECONDS));
+        assertTrue(hasUsageSessionObserver(UID, OBS_ID1));
+    }
+
+    private void startUsage(String packageName) {
+        mController.noteUsageStart(packageName, USER_ID);
+    }
+
+    private void stopUsage(String packageName) {
+        mController.noteUsageStop(packageName, USER_ID);
+    }
+
+    private void addAppUsageObserver(int observerId, String[] packages, long timeLimit) {
+        mController.addAppUsageObserver(UID, observerId, packages, timeLimit, null, USER_ID);
+    }
+
+    private void addUsageSessionObserver(int observerId, String[] packages, long timeLimit,
+            long sessionThreshold) {
+        mController.addUsageSessionObserver(UID, observerId, packages, timeLimit, sessionThreshold,
+                null, null, USER_ID);
+    }
+
+    /** Is there still an app usage observer by that id */
+    private boolean hasAppUsageObserver(int uid, int observerId) {
+        return mController.getAppUsageGroup(uid, observerId) != null;
+    }
+
+    /** Is there still an usage session observer by that id */
+    private boolean hasUsageSessionObserver(int uid, int observerId) {
+        return mController.getSessionUsageGroup(uid, observerId) != null;
     }
 
     private void setTime(long time) {
diff --git a/services/tests/servicestests/src/com/android/server/wm/DisplaySettingsTests.java b/services/tests/servicestests/src/com/android/server/wm/DisplaySettingsTests.java
index a028d5ee..3be1258 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DisplaySettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DisplaySettingsTests.java
@@ -21,6 +21,9 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.doAnswer;
 
 import android.app.WindowConfiguration;
 import android.platform.test.annotations.Presubmit;
@@ -68,10 +71,9 @@
         sWm.setIsPc(false);
 
         mTarget = new DisplaySettings(sWm, mTestFolder);
-        mTarget.readSettingsLocked();
 
         mPrimaryDisplay = sWm.getDefaultDisplayContentLocked();
-        mSecondaryDisplay = createNewDisplay();
+        mSecondaryDisplay = mDisplayContent;
         assertNotEquals(Display.DEFAULT_DISPLAY, mSecondaryDisplay.getDisplayId());
     }
 
@@ -134,6 +136,65 @@
     }
 
     @Test
+    public void testDefaultToOriginalMetrics() {
+        final int originalWidth = mSecondaryDisplay.mBaseDisplayWidth;
+        final int originalHeight = mSecondaryDisplay.mBaseDisplayHeight;
+        final int originalDensity = mSecondaryDisplay.mBaseDisplayDensity;
+        final boolean originalScalingDisabled = mSecondaryDisplay.mDisplayScalingDisabled;
+
+        mTarget.applySettingsToDisplayLocked(mSecondaryDisplay);
+
+        assertEquals(originalWidth, mSecondaryDisplay.mBaseDisplayWidth);
+        assertEquals(originalHeight, mSecondaryDisplay.mBaseDisplayHeight);
+        assertEquals(originalDensity, mSecondaryDisplay.mBaseDisplayDensity);
+        assertEquals(originalScalingDisabled, mSecondaryDisplay.mDisplayScalingDisabled);
+    }
+
+    @Test
+    public void testSetForcedSize() {
+        final DisplayInfo originalInfo = new DisplayInfo(mSecondaryDisplay.getDisplayInfo());
+        // Provides the orginal display info to avoid changing initial display size.
+        doAnswer(invocation -> {
+            ((DisplayInfo) invocation.getArguments()[1]).copyFrom(originalInfo);
+            return null;
+        }).when(sWm.mDisplayManagerInternal).getNonOverrideDisplayInfo(anyInt(), any());
+
+        mTarget.setForcedSize(mSecondaryDisplay, 1000 /* width */, 2000 /* height */);
+        applySettingsToDisplayByNewInstance(mSecondaryDisplay);
+
+        assertEquals(1000 /* width */, mSecondaryDisplay.mBaseDisplayWidth);
+        assertEquals(2000 /* height */, mSecondaryDisplay.mBaseDisplayHeight);
+
+        sWm.clearForcedDisplaySize(mSecondaryDisplay.getDisplayId());
+        assertEquals(mSecondaryDisplay.mInitialDisplayWidth, mSecondaryDisplay.mBaseDisplayWidth);
+        assertEquals(mSecondaryDisplay.mInitialDisplayHeight, mSecondaryDisplay.mBaseDisplayHeight);
+    }
+
+    @Test
+    public void testSetForcedDensity() {
+        mTarget.setForcedDensity(mSecondaryDisplay, 600 /* density */, 0 /* userId */);
+        applySettingsToDisplayByNewInstance(mSecondaryDisplay);
+
+        assertEquals(600 /* density */, mSecondaryDisplay.mBaseDisplayDensity);
+
+        sWm.clearForcedDisplayDensityForUser(mSecondaryDisplay.getDisplayId(), 0 /* userId */);
+        assertEquals(mSecondaryDisplay.mInitialDisplayDensity,
+                mSecondaryDisplay.mBaseDisplayDensity);
+    }
+
+    @Test
+    public void testSetForcedScalingMode() {
+        mTarget.setForcedScalingMode(mSecondaryDisplay, DisplayContent.FORCE_SCALING_MODE_DISABLED);
+        applySettingsToDisplayByNewInstance(mSecondaryDisplay);
+
+        assertTrue(mSecondaryDisplay.mDisplayScalingDisabled);
+
+        sWm.setForcedDisplayScalingMode(mSecondaryDisplay.getDisplayId(),
+                DisplayContent.FORCE_SCALING_MODE_AUTO);
+        assertFalse(mSecondaryDisplay.mDisplayScalingDisabled);
+    }
+
+    @Test
     public void testDefaultToZeroOverscan() {
         mTarget.applySettingsToDisplayLocked(mPrimaryDisplay);
 
@@ -143,8 +204,7 @@
     @Test
     public void testPersistOverscanInSameInstance() {
         final DisplayInfo info = mPrimaryDisplay.getDisplayInfo();
-        mTarget.setOverscanLocked(info.uniqueId, info.name, 1 /* left */, 2 /* top */,
-                3 /* right */, 4 /* bottom */);
+        mTarget.setOverscanLocked(info, 1 /* left */, 2 /* top */, 3 /* right */, 4 /* bottom */);
 
         mTarget.applySettingsToDisplayLocked(mPrimaryDisplay);
 
@@ -154,14 +214,9 @@
     @Test
     public void testPersistOverscanAcrossInstances() {
         final DisplayInfo info = mPrimaryDisplay.getDisplayInfo();
-        mTarget.setOverscanLocked(info.uniqueId, info.name, 1 /* left */, 2 /* top */,
-                3 /* right */, 4 /* bottom */);
-        mTarget.writeSettingsLocked();
+        mTarget.setOverscanLocked(info, 1 /* left */, 2 /* top */, 3 /* right */, 4 /* bottom */);
 
-        DisplaySettings target = new DisplaySettings(sWm, mTestFolder);
-        target.readSettingsLocked();
-
-        target.applySettingsToDisplayLocked(mPrimaryDisplay);
+        applySettingsToDisplayByNewInstance(mPrimaryDisplay);
 
         assertOverscan(mPrimaryDisplay, 1 /* left */, 2 /* top */, 3 /* right */, 4 /* bottom */);
     }
@@ -208,12 +263,8 @@
     public void testPersistUserRotationModeAcrossInstances() {
         mTarget.setUserRotation(mSecondaryDisplay, WindowManagerPolicy.USER_ROTATION_LOCKED,
                 Surface.ROTATION_270);
-        mTarget.writeSettingsLocked();
 
-        DisplaySettings target = new DisplaySettings(sWm, mTestFolder);
-        target.readSettingsLocked();
-
-        target.applySettingsToDisplayLocked(mSecondaryDisplay);
+        applySettingsToDisplayByNewInstance(mSecondaryDisplay);
 
         final DisplayRotation rotation = mSecondaryDisplay.getDisplayRotation();
         assertEquals(WindowManagerPolicy.USER_ROTATION_LOCKED, rotation.getUserRotationMode());
@@ -225,7 +276,7 @@
         mTarget.setUserRotation(mSecondaryDisplay, WindowManagerPolicy.USER_ROTATION_LOCKED,
                 Surface.ROTATION_270);
 
-        mTarget.applySettingsToDisplayLocked(mSecondaryDisplay);
+        applySettingsToDisplayByNewInstance(mSecondaryDisplay);
 
         assertEquals(Surface.ROTATION_270,
                 mSecondaryDisplay.getDisplayRotation().getUserRotation());
@@ -241,6 +292,15 @@
         assertEquals(bottom, info.overscanBottom);
     }
 
+    /**
+     * This method helps to ensure read and write persistent settings successfully because the
+     * constructor of {@link DisplaySettings} should read the persistent file from the given path
+     * that also means the previous state must be written correctly.
+     */
+    private void applySettingsToDisplayByNewInstance(DisplayContent display) {
+        new DisplaySettings(sWm, mTestFolder).applySettingsToDisplayLocked(display);
+    }
+
     private static boolean deleteRecursively(File file) {
         if (file.isFile()) {
             return file.delete();
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
index cf67d78..d0a81b2 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
@@ -75,6 +75,7 @@
     private static int sNextDisplayId = DEFAULT_DISPLAY + 1;
     static int sNextStackId = 1000;
 
+    /** Non-default display. */
     DisplayContent mDisplayContent;
     DisplayInfo mDisplayInfo = new DisplayInfo();
     WindowState mWallpaperWindow;
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 3266b8b..f5c0603 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -288,6 +288,7 @@
         when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
         when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
         when(mUgmInternal.newUriPermissionOwner(anyString())).thenReturn(mPermOwner);
+        when(mPackageManager.getNameForUid(mUid)).thenReturn(PKG);
 
         // write to a test file; the system file isn't readable from tests
         mFile = new File(mContext.getCacheDir(), "test.xml");
@@ -1735,7 +1736,8 @@
     }
 
     @Test
-    public void testGetNotificationChannelFromPrivilegedListener_assistant_noAccess() throws Exception {
+    public void testGetNotificationChannelFromPrivilegedListener_assistant_noAccess()
+            throws Exception {
         mService.setPreferencesHelper(mPreferencesHelper);
         when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(new ArrayList<>());
         when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(false);
@@ -3459,11 +3461,12 @@
         ApplicationInfo info = new ApplicationInfo();
         info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT;
         when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(info);
+        when(mPackageManager.getNameForUid(anyInt())).thenReturn("any");
 
-        assertTrue(mService.isCallerInstantApp("any", 45770, 0));
+        assertTrue(mService.isCallerInstantApp(45770, 0));
 
         info.privateFlags = 0;
-        assertFalse(mService.isCallerInstantApp("any", 575370, 0));
+        assertFalse(mService.isCallerInstantApp(575370, 0));
     }
 
     @Test
@@ -3472,8 +3475,9 @@
         info.privateFlags = ApplicationInfo.PRIVATE_FLAG_INSTANT;
         when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(10))).thenReturn(info);
         when(mPackageManager.getApplicationInfo(anyString(), anyInt(), eq(0))).thenReturn(null);
+        when(mPackageManager.getNameForUid(anyInt())).thenReturn("any");
 
-        assertTrue(mService.isCallerInstantApp("any", 68638450, 10));
+        assertTrue(mService.isCallerInstantApp(68638450, 10));
     }
 
     @Test
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
index 79998a5..3fe381b 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
@@ -280,7 +280,8 @@
 
         assertTrue(mHelper.canShowBadge(PKG_N_MR1, UID_N_MR1));
         assertTrue(mHelper.getIsAppImportanceLocked(PKG_N_MR1, UID_N_MR1));
-        assertEquals(channel1, mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1.getId(), false));
+        assertEquals(channel1,
+                mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1.getId(), false));
         compareChannels(channel2,
                 mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2.getId(), false));
 
@@ -348,7 +349,8 @@
 
         assertEquals(IMPORTANCE_NONE, mHelper.getImportance(PKG_O, UID_O));
         assertTrue(mHelper.canShowBadge(PKG_N_MR1, UID_N_MR1));
-        assertEquals(channel1, mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1.getId(), false));
+        assertEquals(channel1,
+                mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1.getId(), false));
         compareChannels(channel2,
                 mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2.getId(), false));
         compareChannels(channel3,
@@ -487,7 +489,7 @@
         NotificationChannel channel1 =
                 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH);
         NotificationChannel channel2 =
-                new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
+                new NotificationChannel("id2", "name2", IMPORTANCE_HIGH);
         NotificationChannel channel3 =
                 new NotificationChannel("id3", "name3", IMPORTANCE_LOW);
         channel3.setGroup(ncg.getId());
@@ -500,7 +502,8 @@
 
         mHelper.deleteNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1.getId());
         mHelper.deleteNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg.getId());
-        assertEquals(channel2, mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2.getId(), false));
+        assertEquals(channel2,
+                mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2.getId(), false));
 
         ByteArrayOutputStream baos = writeXmlAndPurge(PKG_N_MR1, UID_N_MR1, true, channel1.getId(),
                 channel2.getId(), channel3.getId(), NotificationChannel.DEFAULT_CHANNEL_ID);
@@ -516,8 +519,8 @@
         assertNull(mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1.getId(), false));
         assertNull(mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel3.getId(), false));
         assertNull(mHelper.getNotificationChannelGroup(ncg.getId(), PKG_N_MR1, UID_N_MR1));
-        //assertEquals(ncg2, mHelper.getNotificationChannelGroup(ncg2.getId(), PKG_N_MR1, UID_N_MR1));
-        assertEquals(channel2, mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2.getId(), false));
+        assertEquals(channel2,
+                mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2.getId(), false));
     }
 
     @Test
@@ -799,14 +802,15 @@
     }
 
     @Test
-    public void testCreateChannel_CannotChangeHiddenFields() throws Exception {
+    public void testCreateChannel_CannotChangeHiddenFields() {
         final NotificationChannel channel =
-                new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
+                new NotificationChannel("id2", "name2", IMPORTANCE_HIGH);
         channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes);
         channel.enableLights(true);
         channel.setBypassDnd(true);
         channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
         channel.setShowBadge(true);
+        channel.setAllowAppOverlay(false);
         int lockMask = 0;
         for (int i = 0; i < NotificationChannel.LOCKABLE_FIELDS.length; i++) {
             lockMask |= NotificationChannel.LOCKABLE_FIELDS[i];
@@ -823,19 +827,21 @@
         assertFalse(savedChannel.canBypassDnd());
         assertFalse(Notification.VISIBILITY_SECRET == savedChannel.getLockscreenVisibility());
         assertEquals(channel.canShowBadge(), savedChannel.canShowBadge());
+        assertEquals(channel.canOverlayApps(), savedChannel.canOverlayApps());
 
         verify(mHandler, never()).requestSort();
     }
 
     @Test
-    public void testCreateChannel_CannotChangeHiddenFieldsAssistant() throws Exception {
+    public void testCreateChannel_CannotChangeHiddenFieldsAssistant() {
         final NotificationChannel channel =
-                new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
+                new NotificationChannel("id2", "name2", IMPORTANCE_HIGH);
         channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes);
         channel.enableLights(true);
         channel.setBypassDnd(true);
         channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
         channel.setShowBadge(true);
+        channel.setAllowAppOverlay(false);
         int lockMask = 0;
         for (int i = 0; i < NotificationChannel.LOCKABLE_FIELDS.length; i++) {
             lockMask |= NotificationChannel.LOCKABLE_FIELDS[i];
@@ -852,10 +858,11 @@
         assertFalse(savedChannel.canBypassDnd());
         assertFalse(Notification.VISIBILITY_SECRET == savedChannel.getLockscreenVisibility());
         assertEquals(channel.canShowBadge(), savedChannel.canShowBadge());
+        assertEquals(channel.canOverlayApps(), savedChannel.canOverlayApps());
     }
 
     @Test
-    public void testClearLockedFields() throws Exception {
+    public void testClearLockedFields() {
         final NotificationChannel channel = getChannel();
         mHelper.clearLockedFields(channel);
         assertEquals(0, channel.getUserLockedFields());
@@ -867,7 +874,7 @@
     }
 
     @Test
-    public void testLockFields_soundAndVibration() throws Exception {
+    public void testLockFields_soundAndVibration() {
         mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, getChannel(), true, false);
 
         final NotificationChannel update1 = getChannel();
@@ -891,7 +898,7 @@
     }
 
     @Test
-    public void testLockFields_vibrationAndLights() throws Exception {
+    public void testLockFields_vibrationAndLights() {
         mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, getChannel(), true, false);
 
         final NotificationChannel update1 = getChannel();
@@ -911,7 +918,7 @@
     }
 
     @Test
-    public void testLockFields_lightsAndImportance() throws Exception {
+    public void testLockFields_lightsAndImportance() {
         mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, getChannel(), true, false);
 
         final NotificationChannel update1 = getChannel();
@@ -931,7 +938,7 @@
     }
 
     @Test
-    public void testLockFields_visibilityAndDndAndBadge() throws Exception {
+    public void testLockFields_visibilityAndDndAndBadge() {
         mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, getChannel(), true, false);
         assertEquals(0,
                 mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, getChannel().getId(), false)
@@ -963,6 +970,21 @@
     }
 
     @Test
+    public void testLockFields_appOverlay() {
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, getChannel(), true, false);
+        assertEquals(0,
+                mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, getChannel().getId(), false)
+                        .getUserLockedFields());
+
+        final NotificationChannel update = getChannel();
+        update.setAllowAppOverlay(false);
+        mHelper.updateNotificationChannel(PKG_N_MR1, UID_N_MR1, update, true);
+        assertEquals(NotificationChannel.USER_LOCKED_ALLOW_APP_OVERLAY,
+                mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, update.getId(), false)
+                        .getUserLockedFields());
+    }
+
+    @Test
     public void testDeleteNonExistentChannel() throws Exception {
         mHelper.deleteNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, "does not exist");
     }
@@ -1255,21 +1277,24 @@
 
         mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, notDeleted, true);
         mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, deleted, true);
-        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, nonGroupedNonDeletedChannel, true, false);
+        mHelper.createNotificationChannel(
+                PKG_N_MR1, UID_N_MR1, nonGroupedNonDeletedChannel, true, false);
         mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, groupedAndDeleted, true, false);
         mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, groupedButNotDeleted, true, false);
 
         mHelper.deleteNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, deleted.getId());
 
         assertNull(mHelper.getNotificationChannelGroup(deleted.getId(), PKG_N_MR1, UID_N_MR1));
-        assertNotNull(mHelper.getNotificationChannelGroup(notDeleted.getId(), PKG_N_MR1, UID_N_MR1));
+        assertNotNull(
+                mHelper.getNotificationChannelGroup(notDeleted.getId(), PKG_N_MR1, UID_N_MR1));
 
-        assertNull(mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, groupedAndDeleted.getId(), false));
-        compareChannels(groupedAndDeleted,
-                mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, groupedAndDeleted.getId(), true));
+        assertNull(mHelper.getNotificationChannel(
+                PKG_N_MR1, UID_N_MR1, groupedAndDeleted.getId(), false));
+        compareChannels(groupedAndDeleted, mHelper.getNotificationChannel(
+                PKG_N_MR1, UID_N_MR1, groupedAndDeleted.getId(), true));
 
-        compareChannels(groupedButNotDeleted,
-                mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, groupedButNotDeleted.getId(), false));
+        compareChannels(groupedButNotDeleted, mHelper.getNotificationChannel(
+                PKG_N_MR1, UID_N_MR1, groupedButNotDeleted.getId(), false));
         compareChannels(nonGroupedNonDeletedChannel, mHelper.getNotificationChannel(
                 PKG_N_MR1, UID_N_MR1, nonGroupedNonDeletedChannel.getId(), false));
 
@@ -1381,15 +1406,49 @@
     }
 
     @Test
-    public void testCreateGroup() throws Exception {
+    public void testCreateGroup() {
         NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1");
         mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg, true);
-        assertEquals(ncg, mHelper.getNotificationChannelGroups(PKG_N_MR1, UID_N_MR1).iterator().next());
+        assertEquals(ncg,
+                mHelper.getNotificationChannelGroups(PKG_N_MR1, UID_N_MR1).iterator().next());
         verify(mHandler, never()).requestSort();
     }
 
     @Test
-    public void testCannotCreateChannel_badGroup() throws Exception {
+    public void testUpdateGroup_fromSystem_appOverlay() {
+        NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1");
+        mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg, true);
+
+        // from system, allowed
+        NotificationChannelGroup update = ncg.clone();
+        update.setAllowAppOverlay(false);
+
+        mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, update, false);
+        NotificationChannelGroup updated =
+                mHelper.getNotificationChannelGroup("group1", PKG_N_MR1, UID_N_MR1);
+        assertFalse(updated.canOverlayApps());
+        assertEquals(NotificationChannelGroup.USER_LOCKED_ALLOW_APP_OVERLAY,
+                updated.getUserLockedFields());
+    }
+
+    @Test
+    public void testUpdateGroup_fromApp_appOverlay() {
+        NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1");
+        mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg, true);
+
+        // from app, not allowed
+        NotificationChannelGroup update = new NotificationChannelGroup("group1", "name1");
+        update.setAllowAppOverlay(false);
+
+        mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg, true);
+        NotificationChannelGroup updated =
+                mHelper.getNotificationChannelGroup("group1", PKG_N_MR1, UID_N_MR1);
+        assertTrue(updated.canOverlayApps());
+        assertEquals(0, updated.getUserLockedFields());
+    }
+
+    @Test
+    public void testCannotCreateChannel_badGroup() {
         NotificationChannel channel1 =
                 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH);
         channel1.setGroup("garbage");
@@ -1401,7 +1460,7 @@
     }
 
     @Test
-    public void testCannotCreateChannel_goodGroup() throws Exception {
+    public void testCannotCreateChannel_goodGroup() {
         NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1");
         mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg, true);
         NotificationChannel channel1 =
@@ -1409,12 +1468,12 @@
         channel1.setGroup(ncg.getId());
         mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1, true, false);
 
-        assertEquals(ncg.getId(),
-                mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1.getId(), false).getGroup());
+        assertEquals(ncg.getId(), mHelper.getNotificationChannel(
+                PKG_N_MR1, UID_N_MR1, channel1.getId(), false).getGroup());
     }
 
     @Test
-    public void testGetChannelGroups() throws Exception {
+    public void testGetChannelGroups() {
         NotificationChannelGroup unused = new NotificationChannelGroup("unused", "s");
         mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, unused, true);
         NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1");
@@ -1465,7 +1524,7 @@
     }
 
     @Test
-    public void testGetChannelGroups_noSideEffects() throws Exception {
+    public void testGetChannelGroups_noSideEffects() {
         NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1");
         mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg, true);
 
@@ -1516,10 +1575,11 @@
     }
 
     @Test
-    public void testCreateChannel_updateName() throws Exception {
+    public void testCreateChannel_updateName() {
         NotificationChannel nc = new NotificationChannel("id", "hello", IMPORTANCE_DEFAULT);
         mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, nc, true, false);
-        NotificationChannel actual = mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, "id", false);
+        NotificationChannel actual =
+                mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, "id", false);
         assertEquals("hello", actual.getName());
 
         nc = new NotificationChannel("id", "goodbye", IMPORTANCE_HIGH);
@@ -1533,12 +1593,13 @@
     }
 
     @Test
-    public void testCreateChannel_addToGroup() throws Exception {
+    public void testCreateChannel_addToGroup() {
         NotificationChannelGroup group = new NotificationChannelGroup("group", "");
         mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, group, true);
         NotificationChannel nc = new NotificationChannel("id", "hello", IMPORTANCE_DEFAULT);
         mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, nc, true, false);
-        NotificationChannel actual = mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, "id", false);
+        NotificationChannel actual =
+                mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, "id", false);
         assertNull(actual.getGroup());
 
         nc = new NotificationChannel("id", "hello", IMPORTANCE_HIGH);
diff --git a/services/usage/java/com/android/server/usage/AppTimeLimitController.java b/services/usage/java/com/android/server/usage/AppTimeLimitController.java
index 5916b04c..eaaf9b2 100644
--- a/services/usage/java/com/android/server/usage/AppTimeLimitController.java
+++ b/services/usage/java/com/android/server/usage/AppTimeLimitController.java
@@ -22,17 +22,16 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.SystemClock;
-import android.text.TextUtils;
 import android.util.ArrayMap;
+import android.util.ArraySet;
 import android.util.Slog;
 import android.util.SparseArray;
-import android.util.SparseIntArray;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.ArrayUtils;
 
 import java.io.PrintWriter;
+import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.Arrays;
 
@@ -57,72 +56,432 @@
 
     private final MyHandler mHandler;
 
-    private OnLimitReachedListener mListener;
+    private TimeLimitCallbackListener mListener;
 
     private static final long MAX_OBSERVER_PER_UID = 1000;
 
     private static final long ONE_MINUTE = 60_000L;
 
+    /** Collection of data for each user that has reported usage */
     @GuardedBy("mLock")
     private final SparseArray<UserData> mUsers = new SparseArray<>();
 
-    private static class UserData {
+    /**
+     * Collection of data for each app that is registering observers
+     * WARNING: Entries are currently not removed, based on the assumption there are a small
+     *          fixed number of apps on device that can register observers.
+     */
+    @GuardedBy("mLock")
+    private final SparseArray<ObserverAppData> mObserverApps = new SparseArray<>();
+
+    private class UserData {
         /** userId of the user */
-        private @UserIdInt int userId;
+        private @UserIdInt
+        int userId;
 
-        /** The app that is currently in the foreground */
-        private String currentForegroundedPackage;
+        /** Set of the currently active entities */
+        private final ArraySet<String> currentlyActive = new ArraySet<>();
 
-        /** The time when the current app came to the foreground */
-        private long currentForegroundedTime;
-
-        /** Map from package name for quick lookup */
-        private ArrayMap<String, ArrayList<TimeLimitGroup>> packageMap = new ArrayMap<>();
-
-        /** Map of observerId to details of the time limit group */
-        private SparseArray<TimeLimitGroup> groups = new SparseArray<>();
-
-        /** Map of the number of observerIds registered by uid */
-        private SparseIntArray observerIdCounts = new SparseIntArray();
+        /** Map from entity name for quick lookup */
+        private final ArrayMap<String, ArrayList<UsageGroup>> observedMap = new ArrayMap<>();
 
         private UserData(@UserIdInt int userId) {
             this.userId = userId;
         }
+
+        @GuardedBy("mLock")
+        boolean isActive(String[] entities) {
+            // TODO: Consider using a bloom filter here if number of actives becomes large
+            final int size = entities.length;
+            for (int i = 0; i < size; i++) {
+                if (currentlyActive.contains(entities[i])) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        @GuardedBy("mLock")
+        void addUsageGroup(UsageGroup group) {
+            final int size = group.mObserved.length;
+            for (int i = 0; i < size; i++) {
+                ArrayList<UsageGroup> list = observedMap.get(group.mObserved[i]);
+                if (list == null) {
+                    list = new ArrayList<>();
+                    observedMap.put(group.mObserved[i], list);
+                }
+                list.add(group);
+            }
+        }
+
+        @GuardedBy("mLock")
+        void removeUsageGroup(UsageGroup group) {
+            final int size = group.mObserved.length;
+            for (int i = 0; i < size; i++) {
+                final ArrayList<UsageGroup> list = observedMap.get(group.mObserved[i]);
+                if (list != null) {
+                    list.remove(group);
+                }
+            }
+        }
+
+        @GuardedBy("mLock")
+        void dump(PrintWriter pw) {
+            pw.print(" userId=");
+            pw.println(userId);
+            pw.print(" Currently Active:");
+            final int nActive = currentlyActive.size();
+            for (int i = 0; i < nActive; i++) {
+                pw.print(currentlyActive.valueAt(i));
+                pw.print(", ");
+            }
+            pw.println();
+            pw.print(" Observed Entities:");
+            final int nEntities = currentlyActive.size();
+            for (int i = 0; i < nEntities; i++) {
+                pw.print(observedMap.keyAt(i));
+                pw.print(", ");
+            }
+            pw.println();
+        }
+    }
+
+
+    private class ObserverAppData {
+        /** uid of the observing app */
+        private int uid;
+
+        /** Map of observerId to details of the time limit group */
+        SparseArray<AppUsageGroup> appUsageGroups = new SparseArray<>();
+
+        /** Map of observerId to details of the time limit group */
+        SparseArray<SessionUsageGroup> sessionUsageGroups = new SparseArray<>();
+
+        private ObserverAppData(int uid) {
+            this.uid = uid;
+        }
+
+        @GuardedBy("mLock")
+        void removeAppUsageGroup(int observerId) {
+            appUsageGroups.remove(observerId);
+        }
+
+        @GuardedBy("mLock")
+        void removeSessionUsageGroup(int observerId) {
+            sessionUsageGroups.remove(observerId);
+        }
+
+
+        @GuardedBy("mLock")
+        void dump(PrintWriter pw) {
+            pw.print(" uid=");
+            pw.println(uid);
+            pw.println("    App Usage Groups:");
+            final int nAppUsageGroups = appUsageGroups.size();
+            for (int i = 0; i < nAppUsageGroups; i++) {
+                appUsageGroups.valueAt(i).dump(pw);
+                pw.println();
+            }
+            pw.println("    Session Usage Groups:");
+            final int nSessionUsageGroups = appUsageGroups.size();
+            for (int i = 0; i < nSessionUsageGroups; i++) {
+                sessionUsageGroups.valueAt(i).dump(pw);
+                pw.println();
+            }
+        }
     }
 
     /**
      * Listener interface for being informed when an app group's time limit is reached.
      */
-    public interface OnLimitReachedListener {
+    public interface TimeLimitCallbackListener {
         /**
          * Time limit for a group, keyed by the observerId, has been reached.
-         * @param observerId The observerId of the group whose limit was reached
-         * @param userId The userId
-         * @param timeLimit The original time limit in milliseconds
-         * @param timeElapsed How much time was actually spent on apps in the group, in milliseconds
+         *
+         * @param observerId     The observerId of the group whose limit was reached
+         * @param userId         The userId
+         * @param timeLimit      The original time limit in milliseconds
+         * @param timeElapsed    How much time was actually spent on apps in the group, in
+         *                       milliseconds
          * @param callbackIntent The PendingIntent to send when the limit is reached
          */
         public void onLimitReached(int observerId, @UserIdInt int userId, long timeLimit,
                 long timeElapsed, PendingIntent callbackIntent);
+
+        /**
+         * Session ended for a group, keyed by the observerId, after limit was reached.
+         *
+         * @param observerId     The observerId of the group whose limit was reached
+         * @param userId         The userId
+         * @param timeElapsed    How much time was actually spent on apps in the group, in
+         *                       milliseconds
+         * @param callbackIntent The PendingIntent to send when the limit is reached
+         */
+        public void onSessionEnd(int observerId, @UserIdInt int userId, long timeElapsed,
+                PendingIntent callbackIntent);
     }
 
-    static class TimeLimitGroup {
-        int requestingUid;
-        int observerId;
-        String[] packages;
-        long timeLimit;
-        long timeRequested;
-        long timeRemaining;
-        PendingIntent callbackIntent;
-        String currentPackage;
-        long timeCurrentPackageStarted;
-        int userId;
+    abstract class UsageGroup {
+        protected int mObserverId;
+        protected String[] mObserved;
+        protected long mTimeLimitMs;
+        protected long mUsageTimeMs;
+        protected int mActives;
+        protected long mLastKnownUsageTimeMs;
+        protected WeakReference<UserData> mUserRef;
+        protected WeakReference<ObserverAppData> mObserverAppRef;
+        protected PendingIntent mLimitReachedCallback;
+
+        UsageGroup(UserData user, ObserverAppData observerApp, int observerId, String[] observed,
+                long timeLimitMs, PendingIntent limitReachedCallback) {
+            mUserRef = new WeakReference<>(user);
+            mObserverAppRef = new WeakReference<>(observerApp);
+            mObserverId = observerId;
+            mObserved = observed;
+            mTimeLimitMs = timeLimitMs;
+            mLimitReachedCallback = limitReachedCallback;
+        }
+
+        @GuardedBy("mLock")
+        public long getTimeLimitMs() { return mTimeLimitMs; }
+
+        @GuardedBy("mLock")
+        public long getUsageTimeMs() { return mUsageTimeMs; }
+
+        @GuardedBy("mLock")
+        public void remove() {
+            UserData user = mUserRef.get();
+            if (user != null) {
+                user.removeUsageGroup(this);
+            }
+            // Clear the callback, so any racy inflight message will do nothing
+            mLimitReachedCallback = null;
+        }
+
+        @GuardedBy("mLock")
+        void noteUsageStart(long startTimeMs) {
+            noteUsageStart(startTimeMs, startTimeMs);
+        }
+
+        @GuardedBy("mLock")
+        void noteUsageStart(long startTimeMs, long currentTimeMs) {
+            if (mActives++ == 0) {
+                mLastKnownUsageTimeMs = startTimeMs;
+                final long timeRemaining =
+                        mTimeLimitMs - mUsageTimeMs + currentTimeMs - startTimeMs;
+                if (timeRemaining > 0) {
+                    if (DEBUG) {
+                        Slog.d(TAG, "Posting timeout for " + mObserverId + " for "
+                                + timeRemaining + "ms");
+                    }
+                    postCheckTimeoutLocked(this, timeRemaining);
+                }
+            } else {
+                if (mActives > mObserved.length) {
+                    // Try to get to a sane state and log the issue
+                    mActives = mObserved.length;
+                    final UserData user = mUserRef.get();
+                    if (user == null) return;
+                    final Object[] array = user.currentlyActive.toArray();
+                    Slog.e(TAG,
+                            "Too many noted usage starts! Observed entities: " + Arrays.toString(
+                                    mObserved) + "   Active Entities: " + Arrays.toString(array));
+                }
+            }
+        }
+
+        @GuardedBy("mLock")
+        void noteUsageStop(long stopTimeMs) {
+            if (--mActives == 0) {
+                final boolean limitNotCrossed = mUsageTimeMs < mTimeLimitMs;
+                mUsageTimeMs += stopTimeMs - mLastKnownUsageTimeMs;
+                if (limitNotCrossed && mUsageTimeMs >= mTimeLimitMs) {
+                    // Crossed the limit
+                    if (DEBUG) Slog.d(TAG, "MTB informing group obs=" + mObserverId);
+                    postInformLimitReachedListenerLocked(this);
+                }
+                cancelCheckTimeoutLocked(this);
+            } else {
+                if (mActives < 0) {
+                    // Try to get to a sane state and log the issue
+                    mActives = 0;
+                    final UserData user = mUserRef.get();
+                    if (user == null) return;
+                    final Object[] array = user.currentlyActive.toArray();
+                    Slog.e(TAG,
+                            "Too many noted usage stops! Observed entities: " + Arrays.toString(
+                                    mObserved) + "   Active Entities: " + Arrays.toString(array));
+                }
+            }
+        }
+
+        @GuardedBy("mLock")
+        void checkTimeout(long currentTimeMs) {
+            final UserData user = mUserRef.get();
+            if (user == null) return;
+
+            long timeRemainingMs = mTimeLimitMs - mUsageTimeMs;
+
+            if (DEBUG) Slog.d(TAG, "checkTimeout timeRemaining=" + timeRemainingMs);
+
+            // Already reached the limit, no need to report again
+            if (timeRemainingMs <= 0) return;
+
+            if (DEBUG) {
+                Slog.d(TAG, "checkTimeout");
+            }
+
+            // Double check that at least one entity in this group is currently active
+            if (user.isActive(mObserved)) {
+                if (DEBUG) {
+                    Slog.d(TAG, "checkTimeout group is active");
+                }
+                final long timeUsedMs = currentTimeMs - mLastKnownUsageTimeMs;
+                if (timeRemainingMs <= timeUsedMs) {
+                    if (DEBUG) Slog.d(TAG, "checkTimeout : Time limit reached");
+                    // Hit the limit, set timeRemaining to zero to avoid checking again
+                    mUsageTimeMs += timeUsedMs;
+                    mLastKnownUsageTimeMs = currentTimeMs;
+                    AppTimeLimitController.this.postInformLimitReachedListenerLocked(this);
+                } else {
+                    if (DEBUG) Slog.d(TAG, "checkTimeout : Some more time remaining");
+                    AppTimeLimitController.this.postCheckTimeoutLocked(this,
+                            timeRemainingMs - timeUsedMs);
+                }
+            }
+        }
+
+        @GuardedBy("mLock")
+        public void onLimitReached() {
+            UserData user = mUserRef.get();
+            if (user == null) return;
+            if (mListener != null) {
+                mListener.onLimitReached(mObserverId, user.userId, mTimeLimitMs, mUsageTimeMs,
+                        mLimitReachedCallback);
+            }
+        }
+
+        @GuardedBy("mLock")
+        void dump(PrintWriter pw) {
+            pw.print("        Group id=");
+            pw.print(mObserverId);
+            pw.print(" timeLimit=");
+            pw.print(mTimeLimitMs);
+            pw.print(" used=");
+            pw.print(mUsageTimeMs);
+            pw.print(" lastKnownUsage=");
+            pw.print(mLastKnownUsageTimeMs);
+            pw.print(" mActives=");
+            pw.print(mActives);
+            pw.print(" observed=");
+            pw.print(Arrays.toString(mObserved));
+        }
     }
 
+    class AppUsageGroup extends UsageGroup {
+        public AppUsageGroup(UserData user, ObserverAppData observerApp, int observerId,
+                String[] observed, long timeLimitMs, PendingIntent limitReachedCallback) {
+            super(user, observerApp, observerId, observed, timeLimitMs, limitReachedCallback);
+        }
+
+        @Override
+        @GuardedBy("mLock")
+        public void remove() {
+            super.remove();
+            ObserverAppData observerApp = mObserverAppRef.get();
+            if (observerApp != null) {
+                observerApp.removeAppUsageGroup(mObserverId);
+            }
+        }
+
+        @Override
+        @GuardedBy("mLock")
+        public void onLimitReached() {
+            super.onLimitReached();
+            // Unregister since the limit has been met and observer was informed.
+            remove();
+        }
+    }
+
+    class SessionUsageGroup extends UsageGroup {
+        private long mLastUsageEndTimeMs;
+        private long mNewSessionThresholdMs;
+        private PendingIntent mSessionEndCallback;
+
+        public SessionUsageGroup(UserData user, ObserverAppData observerApp, int observerId,
+                String[] observed, long timeLimitMs, PendingIntent limitReachedCallback,
+                long newSessionThresholdMs, PendingIntent sessionEndCallback) {
+            super(user, observerApp, observerId, observed, timeLimitMs, limitReachedCallback);
+            this.mNewSessionThresholdMs = newSessionThresholdMs;
+            this.mSessionEndCallback = sessionEndCallback;
+        }
+
+        @Override
+        @GuardedBy("mLock")
+        public void remove() {
+            super.remove();
+            ObserverAppData observerApp = mObserverAppRef.get();
+            if (observerApp != null) {
+                observerApp.removeSessionUsageGroup(mObserverId);
+            }
+            // Clear the callback, so any racy inflight messages will do nothing
+            mSessionEndCallback = null;
+        }
+
+        @Override
+        @GuardedBy("mLock")
+        public void noteUsageStart(long startTimeMs, long currentTimeMs) {
+            if (mActives == 0) {
+                if (startTimeMs - mLastUsageEndTimeMs > mNewSessionThresholdMs) {
+                    // New session has started, clear usage time.
+                    mUsageTimeMs = 0;
+                }
+                AppTimeLimitController.this.cancelInformSessionEndListener(this);
+            }
+            super.noteUsageStart(startTimeMs, currentTimeMs);
+        }
+
+        @Override
+        @GuardedBy("mLock")
+        public void noteUsageStop(long stopTimeMs) {
+            super.noteUsageStop(stopTimeMs);
+            if (mActives == 0) {
+                mLastUsageEndTimeMs = stopTimeMs;
+                if (mUsageTimeMs >= mTimeLimitMs) {
+                    // Usage has ended. Schedule the session end callback to be triggered once
+                    // the new session threshold has been reached
+                    AppTimeLimitController.this.postInformSessionEndListenerLocked(this,
+                            mNewSessionThresholdMs);
+                }
+
+            }
+        }
+
+        @GuardedBy("mLock")
+        public void onSessionEnd() {
+            UserData user = mUserRef.get();
+            if (user == null) return;
+            if (mListener != null) {
+                mListener.onSessionEnd(mObserverId, user.userId, mUsageTimeMs, mSessionEndCallback);
+            }
+        }
+
+        @Override
+        @GuardedBy("mLock")
+        void dump(PrintWriter pw) {
+            super.dump(pw);
+            pw.print(" lastUsageEndTime=");
+            pw.print(mLastUsageEndTimeMs);
+            pw.print(" newSessionThreshold=");
+            pw.print(mNewSessionThresholdMs);
+        }
+    }
+
+
     private class MyHandler extends Handler {
-
         static final int MSG_CHECK_TIMEOUT = 1;
-        static final int MSG_INFORM_LISTENER = 2;
+        static final int MSG_INFORM_LIMIT_REACHED_LISTENER = 2;
+        static final int MSG_INFORM_SESSION_END = 3;
 
         MyHandler(Looper looper) {
             super(looper);
@@ -132,10 +491,19 @@
         public void handleMessage(Message msg) {
             switch (msg.what) {
                 case MSG_CHECK_TIMEOUT:
-                    checkTimeout((TimeLimitGroup) msg.obj);
+                    synchronized (mLock) {
+                        ((UsageGroup) msg.obj).checkTimeout(getUptimeMillis());
+                    }
                     break;
-                case MSG_INFORM_LISTENER:
-                    informListener((TimeLimitGroup) msg.obj);
+                case MSG_INFORM_LIMIT_REACHED_LISTENER:
+                    synchronized (mLock) {
+                        ((UsageGroup) msg.obj).onLimitReached();
+                    }
+                    break;
+                case MSG_INFORM_SESSION_END:
+                    synchronized (mLock) {
+                        ((SessionUsageGroup) msg.obj).onSessionEnd();
+                    }
                     break;
                 default:
                     super.handleMessage(msg);
@@ -144,7 +512,7 @@
         }
     }
 
-    public AppTimeLimitController(OnLimitReachedListener listener, Looper looper) {
+    public AppTimeLimitController(TimeLimitCallbackListener listener, Looper looper) {
         mHandler = new MyHandler(looper);
         mListener = listener;
     }
@@ -157,7 +525,13 @@
 
     /** Overrideable for testing purposes */
     @VisibleForTesting
-    protected long getObserverPerUidLimit() {
+    protected long getAppUsageObserverPerUidLimit() {
+        return MAX_OBSERVER_PER_UID;
+    }
+
+    /** Overrideable for testing purposes */
+    @VisibleForTesting
+    protected long getUsageSessionObserverPerUidLimit() {
         return MAX_OBSERVER_PER_UID;
     }
 
@@ -167,6 +541,21 @@
         return ONE_MINUTE;
     }
 
+    @VisibleForTesting
+    AppUsageGroup getAppUsageGroup(int observerAppUid, int observerId) {
+        synchronized (mLock) {
+            return getOrCreateObserverAppDataLocked(observerAppUid).appUsageGroups.get(observerId);
+        }
+    }
+
+    @VisibleForTesting
+    SessionUsageGroup getSessionUsageGroup(int observerAppUid, int observerId) {
+        synchronized (mLock) {
+            return getOrCreateObserverAppDataLocked(observerAppUid).sessionUsageGroups.get(
+                    observerId);
+        }
+    }
+
     /** Returns an existing UserData object for the given userId, or creates one */
     @GuardedBy("mLock")
     private UserData getOrCreateUserDataLocked(int userId) {
@@ -178,6 +567,17 @@
         return userData;
     }
 
+    /** Returns an existing ObserverAppData object for the given uid, or creates one */
+    @GuardedBy("mLock")
+    private ObserverAppData getOrCreateObserverAppDataLocked(int uid) {
+        ObserverAppData appData = mObserverApps.get(uid);
+        if (appData == null) {
+            appData = new ObserverAppData(uid);
+            mObserverApps.put(uid, appData);
+        }
+        return appData;
+    }
+
     /** Clean up data if user is removed */
     public void onUserRemoved(int userId) {
         synchronized (mLock) {
@@ -187,300 +587,219 @@
     }
 
     /**
-     * Registers an observer with the given details. Existing observer with the same observerId
-     * is removed.
+     * Check if group has any currently active entities.
      */
-    public void addObserver(int requestingUid, int observerId, String[] packages, long timeLimit,
-            PendingIntent callbackIntent, @UserIdInt int userId) {
+    @GuardedBy("mLock")
+    private void noteActiveLocked(UserData user, UsageGroup group, long currentTimeMs) {
+        // TODO: Consider using a bloom filter here if number of actives becomes large
+        final int size = group.mObserved.length;
+        for (int i = 0; i < size; i++) {
+            if (user.currentlyActive.contains(group.mObserved[i])) {
+                // Entity is currently active. Start group's usage.
+                group.noteUsageStart(currentTimeMs);
+            }
+        }
+    }
 
+    /**
+     * Registers an app usage observer with the given details.
+     * Existing app usage observer with the same observerId will be removed.
+     */
+    public void addAppUsageObserver(int requestingUid, int observerId, String[] observed,
+            long timeLimit, PendingIntent callbackIntent, @UserIdInt int userId) {
         if (timeLimit < getMinTimeLimit()) {
             throw new IllegalArgumentException("Time limit must be >= " + getMinTimeLimit());
         }
         synchronized (mLock) {
             UserData user = getOrCreateUserDataLocked(userId);
-            removeObserverLocked(user, requestingUid, observerId, /*readding =*/ true);
-
-            final int observerIdCount = user.observerIdCounts.get(requestingUid, 0);
-            if (observerIdCount >= getObserverPerUidLimit()) {
-                throw new IllegalStateException(
-                        "Too many observers added by uid " + requestingUid);
+            ObserverAppData observerApp = getOrCreateObserverAppDataLocked(requestingUid);
+            AppUsageGroup group = observerApp.appUsageGroups.get(observerId);
+            if (group != null) {
+                // Remove previous app usage group associated with observerId
+                observerApp.appUsageGroups.get(observerId).remove();
             }
-            user.observerIdCounts.put(requestingUid, observerIdCount + 1);
 
-            TimeLimitGroup group = new TimeLimitGroup();
-            group.observerId = observerId;
-            group.callbackIntent = callbackIntent;
-            group.packages = packages;
-            group.timeLimit = timeLimit;
-            group.timeRemaining = group.timeLimit;
-            group.timeRequested = getUptimeMillis();
-            group.requestingUid = requestingUid;
-            group.timeCurrentPackageStarted = -1L;
-            group.userId = userId;
-
-            user.groups.append(observerId, group);
-
-            addGroupToPackageMapLocked(user, packages, group);
+            final int observerIdCount = observerApp.appUsageGroups.size();
+            if (observerIdCount >= getAppUsageObserverPerUidLimit()) {
+                throw new IllegalStateException(
+                        "Too many app usage observers added by uid " + requestingUid);
+            }
+            group = new AppUsageGroup(user, observerApp, observerId, observed, timeLimit,
+                    callbackIntent);
+            observerApp.appUsageGroups.append(observerId, group);
 
             if (DEBUG) {
-                Slog.d(TAG, "addObserver " + packages + " for " + timeLimit);
+                Slog.d(TAG, "addObserver " + observed + " for " + timeLimit);
             }
-            // Handle the case where a target package is already in the foreground when observer
-            // is added.
-            if (user.currentForegroundedPackage != null && inPackageList(group.packages,
-                    user.currentForegroundedPackage)) {
-                group.timeCurrentPackageStarted = group.timeRequested;
-                group.currentPackage = user.currentForegroundedPackage;
-                if (group.timeRemaining > 0) {
-                    postCheckTimeoutLocked(group, group.timeRemaining);
-                }
-            }
+
+            user.addUsageGroup(group);
+            noteActiveLocked(user, group, getUptimeMillis());
         }
     }
 
     /**
      * Remove a registered observer by observerId and calling uid.
+     *
      * @param requestingUid The calling uid
-     * @param observerId The unique observer id for this user
-     * @param userId The user id of the observer
+     * @param observerId    The unique observer id for this user
+     * @param userId        The user id of the observer
      */
-    public void removeObserver(int requestingUid, int observerId, @UserIdInt int userId) {
+    public void removeAppUsageObserver(int requestingUid, int observerId, @UserIdInt int userId) {
+        synchronized (mLock) {
+            ObserverAppData observerApp = getOrCreateObserverAppDataLocked(requestingUid);
+            observerApp.appUsageGroups.get(observerId).remove();
+        }
+    }
+
+
+    /**
+     * Registers a usage session observer with the given details.
+     * Existing usage session observer with the same observerId will be removed.
+     */
+    public void addUsageSessionObserver(int requestingUid, int observerId, String[] observed,
+            long timeLimit, long sessionThresholdTime,
+            PendingIntent limitReachedCallbackIntent, PendingIntent sessionEndCallbackIntent,
+            @UserIdInt int userId) {
+        if (timeLimit < getMinTimeLimit()) {
+            throw new IllegalArgumentException("Time limit must be >= " + getMinTimeLimit());
+        }
         synchronized (mLock) {
             UserData user = getOrCreateUserDataLocked(userId);
-            removeObserverLocked(user, requestingUid, observerId, /*readding =*/ false);
+            ObserverAppData observerApp = getOrCreateObserverAppDataLocked(requestingUid);
+            SessionUsageGroup group = observerApp.sessionUsageGroups.get(observerId);
+            if (group != null) {
+                // Remove previous app usage group associated with observerId
+                observerApp.sessionUsageGroups.get(observerId).remove();
+            }
+
+            final int observerIdCount = observerApp.sessionUsageGroups.size();
+            if (observerIdCount >= getUsageSessionObserverPerUidLimit()) {
+                throw new IllegalStateException(
+                        "Too many app usage observers added by uid " + requestingUid);
+            }
+            group = new SessionUsageGroup(user, observerApp, observerId, observed, timeLimit,
+                    limitReachedCallbackIntent, sessionThresholdTime, sessionEndCallbackIntent);
+            observerApp.sessionUsageGroups.append(observerId, group);
+
+            user.addUsageGroup(group);
+            noteActiveLocked(user, group, getUptimeMillis());
         }
     }
 
-    @VisibleForTesting
-    TimeLimitGroup getObserverGroup(int observerId, int userId) {
+    /**
+     * Remove a registered observer by observerId and calling uid.
+     *
+     * @param requestingUid The calling uid
+     * @param observerId    The unique observer id for this user
+     * @param userId        The user id of the observer
+     */
+    public void removeUsageSessionObserver(int requestingUid, int observerId,
+            @UserIdInt int userId) {
         synchronized (mLock) {
-            return getOrCreateUserDataLocked(userId).groups.get(observerId);
+            ObserverAppData observerApp = getOrCreateObserverAppDataLocked(requestingUid);
+            observerApp.sessionUsageGroups.get(observerId).remove();
         }
     }
 
-    private static boolean inPackageList(String[] packages, String packageName) {
-        return ArrayUtils.contains(packages, packageName);
+    /**
+     * Called when an entity becomes active.
+     *
+     * @param name   The entity that became active
+     * @param userId The user
+     */
+    public void noteUsageStart(String name, int userId) throws IllegalArgumentException {
+        synchronized (mLock) {
+            UserData user = getOrCreateUserDataLocked(userId);
+            if (DEBUG) Slog.d(TAG, "Usage entity " + name + " became active");
+            if (user.currentlyActive.contains(name)) {
+                throw new IllegalArgumentException(
+                        "Unable to start usage for " + name + ", already in use");
+            }
+            final long currentTime = getUptimeMillis();
+
+            // Add to the list of active entities
+            user.currentlyActive.add(name);
+
+            ArrayList<UsageGroup> groups = user.observedMap.get(name);
+            if (groups == null) return;
+
+            final int size = groups.size();
+            for (int i = 0; i < size; i++) {
+                UsageGroup group = groups.get(i);
+                group.noteUsageStart(currentTime);
+            }
+        }
+    }
+
+    /**
+     * Called when an entity becomes inactive.
+     *
+     * @param name   The entity that became inactive
+     * @param userId The user
+     */
+    public void noteUsageStop(String name, int userId) throws IllegalArgumentException {
+        synchronized (mLock) {
+            UserData user = getOrCreateUserDataLocked(userId);
+            if (DEBUG) Slog.d(TAG, "Usage entity " + name + " became inactive");
+            if (!user.currentlyActive.remove(name)) {
+                throw new IllegalArgumentException(
+                        "Unable to stop usage for " + name + ", not in use");
+            }
+            final long currentTime = getUptimeMillis();
+
+            // Check if any of the groups need to watch for this entity
+            ArrayList<UsageGroup> groups = user.observedMap.get(name);
+            if (groups == null) return;
+
+            final int size = groups.size();
+            for (int i = 0; i < size; i++) {
+                UsageGroup group = groups.get(i);
+                group.noteUsageStop(currentTime);
+            }
+        }
     }
 
     @GuardedBy("mLock")
-    private void removeObserverLocked(UserData user, int requestingUid, int observerId,
-            boolean readding) {
-        TimeLimitGroup group = user.groups.get(observerId);
-        if (group != null && group.requestingUid == requestingUid) {
-            removeGroupFromPackageMapLocked(user, group);
-            user.groups.remove(observerId);
-            mHandler.removeMessages(MyHandler.MSG_CHECK_TIMEOUT, group);
-            final int observerIdCount = user.observerIdCounts.get(requestingUid);
-            if (observerIdCount <= 1 && !readding) {
-                user.observerIdCounts.delete(requestingUid);
-            } else {
-                user.observerIdCounts.put(requestingUid, observerIdCount - 1);
-            }
-        }
-    }
-
-    /**
-     * Called when an app has moved to the foreground.
-     * @param packageName The app that is foregrounded
-     * @param className The className of the activity
-     * @param userId The user
-     */
-    public void moveToForeground(String packageName, String className, int userId) {
-        synchronized (mLock) {
-            UserData user = getOrCreateUserDataLocked(userId);
-            if (DEBUG) Slog.d(TAG, "Setting mCurrentForegroundedPackage to " + packageName);
-            // Note the current foreground package
-            user.currentForegroundedPackage = packageName;
-            user.currentForegroundedTime = getUptimeMillis();
-
-            // Check if any of the groups need to watch for this package
-            maybeWatchForPackageLocked(user, packageName, user.currentForegroundedTime);
-        }
-    }
-
-    /**
-     * Called when an app is sent to the background.
-     *
-     * @param packageName
-     * @param className
-     * @param userId
-     */
-    public void moveToBackground(String packageName, String className, int userId) {
-        synchronized (mLock) {
-            UserData user = getOrCreateUserDataLocked(userId);
-            if (!TextUtils.equals(user.currentForegroundedPackage, packageName)) {
-                Slog.w(TAG, "Eh? Last foregrounded package = " + user.currentForegroundedPackage
-                        + " and now backgrounded = " + packageName);
-                return;
-            }
-            final long stopTime = getUptimeMillis();
-
-            // Add up the usage time to all groups that contain the package
-            ArrayList<TimeLimitGroup> groups = user.packageMap.get(packageName);
-            if (groups != null) {
-                final int size = groups.size();
-                for (int i = 0; i < size; i++) {
-                    final TimeLimitGroup group = groups.get(i);
-                    // Don't continue to send
-                    if (group.timeRemaining <= 0) continue;
-
-                    final long startTime = Math.max(user.currentForegroundedTime,
-                            group.timeRequested);
-                    long diff = stopTime - startTime;
-                    group.timeRemaining -= diff;
-                    if (group.timeRemaining <= 0) {
-                        if (DEBUG) Slog.d(TAG, "MTB informing group obs=" + group.observerId);
-                        postInformListenerLocked(group);
-                    }
-                    // Reset indicators that observer was added when package was already fg
-                    group.currentPackage = null;
-                    group.timeCurrentPackageStarted = -1L;
-                    mHandler.removeMessages(MyHandler.MSG_CHECK_TIMEOUT, group);
-                }
-            }
-            user.currentForegroundedPackage = null;
-        }
-    }
-
-    private void postInformListenerLocked(TimeLimitGroup group) {
-        mHandler.sendMessage(mHandler.obtainMessage(MyHandler.MSG_INFORM_LISTENER,
+    private void postInformLimitReachedListenerLocked(UsageGroup group) {
+        mHandler.sendMessage(mHandler.obtainMessage(MyHandler.MSG_INFORM_LIMIT_REACHED_LISTENER,
                 group));
     }
 
-    /**
-     * Inform the observer and unregister it, as the limit has been reached.
-     * @param group the observed group
-     */
-    private void informListener(TimeLimitGroup group) {
-        if (mListener != null) {
-            mListener.onLimitReached(group.observerId, group.userId, group.timeLimit,
-                    group.timeLimit - group.timeRemaining, group.callbackIntent);
-        }
-        // Unregister since the limit has been met and observer was informed.
-        synchronized (mLock) {
-            UserData user = getOrCreateUserDataLocked(group.userId);
-            removeObserverLocked(user, group.requestingUid, group.observerId, false);
-        }
-    }
-
-    /** Check if any of the groups care about this package and set up delayed messages */
     @GuardedBy("mLock")
-    private void maybeWatchForPackageLocked(UserData user, String packageName, long uptimeMillis) {
-        ArrayList<TimeLimitGroup> groups = user.packageMap.get(packageName);
-        if (groups == null) return;
-
-        final int size = groups.size();
-        for (int i = 0; i < size; i++) {
-            TimeLimitGroup group = groups.get(i);
-            if (group.timeRemaining > 0) {
-                group.timeCurrentPackageStarted = uptimeMillis;
-                group.currentPackage = packageName;
-                if (DEBUG) {
-                    Slog.d(TAG, "Posting timeout for " + packageName + " for "
-                            + group.timeRemaining + "ms");
-                }
-                postCheckTimeoutLocked(group, group.timeRemaining);
-            }
-        }
+    private void postInformSessionEndListenerLocked(SessionUsageGroup group, long timeout) {
+        mHandler.sendMessageDelayed(mHandler.obtainMessage(MyHandler.MSG_INFORM_SESSION_END, group),
+                timeout);
     }
 
-    private void addGroupToPackageMapLocked(UserData user, String[] packages,
-            TimeLimitGroup group) {
-        for (int i = 0; i < packages.length; i++) {
-            ArrayList<TimeLimitGroup> list = user.packageMap.get(packages[i]);
-            if (list == null) {
-                list = new ArrayList<>();
-                user.packageMap.put(packages[i], list);
-            }
-            list.add(group);
-        }
+    @GuardedBy("mLock")
+    private void cancelInformSessionEndListener(SessionUsageGroup group) {
+        mHandler.removeMessages(MyHandler.MSG_INFORM_SESSION_END, group);
     }
 
-    /**
-     * Remove the group reference from the package to group mapping, which is 1 to many.
-     * @param group The group to remove from the package map.
-     */
-    private void removeGroupFromPackageMapLocked(UserData user, TimeLimitGroup group) {
-        final int mapSize = user.packageMap.size();
-        for (int i = 0; i < mapSize; i++) {
-            ArrayList<TimeLimitGroup> list = user.packageMap.valueAt(i);
-            list.remove(group);
-        }
-    }
-
-    private void postCheckTimeoutLocked(TimeLimitGroup group, long timeout) {
+    @GuardedBy("mLock")
+    private void postCheckTimeoutLocked(UsageGroup group, long timeout) {
         mHandler.sendMessageDelayed(mHandler.obtainMessage(MyHandler.MSG_CHECK_TIMEOUT, group),
                 timeout);
     }
 
-    /**
-     * See if the given group has reached the timeout if the current foreground app is included
-     * and it exceeds the time remaining.
-     * @param group the group of packages to check
-     */
-    void checkTimeout(TimeLimitGroup group) {
-        // For each package in the group, check if any of the currently foregrounded apps are adding
-        // up to hit the limit and inform the observer
-        synchronized (mLock) {
-            UserData user = getOrCreateUserDataLocked(group.userId);
-            // This group doesn't exist anymore, nothing to see here.
-            if (user.groups.get(group.observerId) != group) return;
-
-            if (DEBUG) Slog.d(TAG, "checkTimeout timeRemaining=" + group.timeRemaining);
-
-            // Already reached the limit, no need to report again
-            if (group.timeRemaining <= 0) return;
-
-            if (DEBUG) {
-                Slog.d(TAG, "checkTimeout foregroundedPackage="
-                        + user.currentForegroundedPackage);
-            }
-
-            if (inPackageList(group.packages, user.currentForegroundedPackage)) {
-                if (DEBUG) {
-                    Slog.d(TAG, "checkTimeout package in foreground="
-                            + user.currentForegroundedPackage);
-                }
-                if (group.timeCurrentPackageStarted < 0) {
-                    Slog.w(TAG, "startTime was not set correctly for " + group);
-                }
-                final long timeInForeground = getUptimeMillis() - group.timeCurrentPackageStarted;
-                if (group.timeRemaining <= timeInForeground) {
-                    if (DEBUG) Slog.d(TAG, "checkTimeout : Time limit reached");
-                    // Hit the limit, set timeRemaining to zero to avoid checking again
-                    group.timeRemaining -= timeInForeground;
-                    postInformListenerLocked(group);
-                    // Reset
-                    group.timeCurrentPackageStarted = -1L;
-                    group.currentPackage = null;
-                } else {
-                    if (DEBUG) Slog.d(TAG, "checkTimeout : Some more time remaining");
-                    postCheckTimeoutLocked(group, group.timeRemaining - timeInForeground);
-                }
-            }
-        }
+    @GuardedBy("mLock")
+    private void cancelCheckTimeoutLocked(UsageGroup group) {
+        mHandler.removeMessages(MyHandler.MSG_CHECK_TIMEOUT, group);
     }
 
     void dump(PrintWriter pw) {
         synchronized (mLock) {
             pw.println("\n  App Time Limits");
-            int nUsers = mUsers.size();
+            final int nUsers = mUsers.size();
             for (int i = 0; i < nUsers; i++) {
-                UserData user = mUsers.valueAt(i);
-                pw.print("   User "); pw.println(user.userId);
-                int nGroups = user.groups.size();
-                for (int j = 0; j < nGroups; j++) {
-                    TimeLimitGroup group = user.groups.valueAt(j);
-                    pw.print("    Group id="); pw.print(group.observerId);
-                    pw.print(" timeLimit="); pw.print(group.timeLimit);
-                    pw.print(" remaining="); pw.print(group.timeRemaining);
-                    pw.print(" currentPackage="); pw.print(group.currentPackage);
-                    pw.print(" timeCurrentPkgStarted="); pw.print(group.timeCurrentPackageStarted);
-                    pw.print(" packages="); pw.println(Arrays.toString(group.packages));
-                }
-                pw.println();
-                pw.print("    currentForegroundedPackage=");
-                pw.println(user.currentForegroundedPackage);
+                pw.print("   User ");
+                mUsers.valueAt(i).dump(pw);
+            }
+            pw.println();
+            final int nObserverApps = mObserverApps.size();
+            for (int i = 0; i < nObserverApps; i++) {
+                pw.print("   Observer App ");
+                mObserverApps.valueAt(i).dump(pw);
             }
         }
     }
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index dd1ddfa..2621252 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -165,16 +165,36 @@
         mAppStandby = new AppStandbyController(getContext(), BackgroundThread.get().getLooper());
 
         mAppTimeLimit = new AppTimeLimitController(
-                (observerId, userId, timeLimit, timeElapsed, callbackIntent) -> {
-                    Intent intent = new Intent();
-                    intent.putExtra(UsageStatsManager.EXTRA_OBSERVER_ID, observerId);
-                    intent.putExtra(UsageStatsManager.EXTRA_TIME_LIMIT, timeLimit);
-                    intent.putExtra(UsageStatsManager.EXTRA_TIME_USED, timeElapsed);
-                    try {
-                        callbackIntent.send(getContext(), 0, intent);
-                    } catch (PendingIntent.CanceledException e) {
-                        Slog.w(TAG, "Couldn't deliver callback: "
-                                + callbackIntent);
+                new AppTimeLimitController.TimeLimitCallbackListener() {
+                    @Override
+                    public void onLimitReached(int observerId, int userId, long timeLimit,
+                            long timeElapsed, PendingIntent callbackIntent) {
+                        if (callbackIntent == null) return;
+                        Intent intent = new Intent();
+                        intent.putExtra(UsageStatsManager.EXTRA_OBSERVER_ID, observerId);
+                        intent.putExtra(UsageStatsManager.EXTRA_TIME_LIMIT, timeLimit);
+                        intent.putExtra(UsageStatsManager.EXTRA_TIME_USED, timeElapsed);
+                        try {
+                            callbackIntent.send(getContext(), 0, intent);
+                        } catch (PendingIntent.CanceledException e) {
+                            Slog.w(TAG, "Couldn't deliver callback: "
+                                    + callbackIntent);
+                        }
+                    }
+
+                    @Override
+                    public void onSessionEnd(int observerId, int userId, long timeElapsed,
+                            PendingIntent callbackIntent) {
+                        if (callbackIntent == null) return;
+                        Intent intent = new Intent();
+                        intent.putExtra(UsageStatsManager.EXTRA_OBSERVER_ID, observerId);
+                        intent.putExtra(UsageStatsManager.EXTRA_TIME_USED, timeElapsed);
+                        try {
+                            callbackIntent.send(getContext(), 0, intent);
+                        } catch (PendingIntent.CanceledException e) {
+                            Slog.w(TAG, "Couldn't deliver callback: "
+                                    + callbackIntent);
+                        }
                     }
                 }, mHandler.getLooper());
 
@@ -412,12 +432,18 @@
             mAppStandby.reportEvent(event, elapsedRealtime, userId);
             switch (event.mEventType) {
                 case Event.MOVE_TO_FOREGROUND:
-                    mAppTimeLimit.moveToForeground(event.getPackageName(), event.getClassName(),
-                            userId);
+                    try {
+                        mAppTimeLimit.noteUsageStart(event.getPackageName(), userId);
+                    } catch (IllegalArgumentException iae) {
+                        Slog.e(TAG, "Failed to note usage start", iae);
+                    }
                     break;
                 case Event.MOVE_TO_BACKGROUND:
-                    mAppTimeLimit.moveToBackground(event.getPackageName(), event.getClassName(),
-                            userId);
+                    try {
+                        mAppTimeLimit.noteUsageStop(event.getPackageName(), userId);
+                    } catch (IllegalArgumentException iae) {
+                        Slog.e(TAG, "Failed to note usage stop", iae);
+                    }
                     break;
             }
         }
@@ -1151,16 +1177,70 @@
                 Binder.restoreCallingIdentity(token);
             }
         }
+
+        @Override
+        public void registerUsageSessionObserver(int sessionObserverId, String[] observed,
+                long timeLimitMs, long sessionThresholdTimeMs,
+                PendingIntent limitReachedCallbackIntent, PendingIntent sessionEndCallbackIntent,
+                String callingPackage) {
+            if (!hasObserverPermission(callingPackage)) {
+                throw new SecurityException("Caller doesn't have OBSERVE_APP_USAGE permission");
+            }
+
+            if (observed == null || observed.length == 0) {
+                throw new IllegalArgumentException("Must specify at least one observed entity");
+            }
+            if (limitReachedCallbackIntent == null) {
+                throw new NullPointerException("limitReachedCallbackIntent can't be null");
+            }
+            final int callingUid = Binder.getCallingUid();
+            final int userId = UserHandle.getUserId(callingUid);
+            final long token = Binder.clearCallingIdentity();
+            try {
+                UsageStatsService.this.registerUsageSessionObserver(callingUid, sessionObserverId,
+                        observed, timeLimitMs, sessionThresholdTimeMs, limitReachedCallbackIntent,
+                        sessionEndCallbackIntent, userId);
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        @Override
+        public void unregisterUsageSessionObserver(int sessionObserverId, String callingPackage) {
+            if (!hasObserverPermission(callingPackage)) {
+                throw new SecurityException("Caller doesn't have OBSERVE_APP_USAGE permission");
+            }
+
+            final int callingUid = Binder.getCallingUid();
+            final int userId = UserHandle.getUserId(callingUid);
+            final long token = Binder.clearCallingIdentity();
+            try {
+                UsageStatsService.this.unregisterUsageSessionObserver(callingUid, sessionObserverId, userId);
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
     }
 
     void registerAppUsageObserver(int callingUid, int observerId, String[] packages,
             long timeLimitMs, PendingIntent callbackIntent, int userId) {
-        mAppTimeLimit.addObserver(callingUid, observerId, packages, timeLimitMs, callbackIntent,
+        mAppTimeLimit.addAppUsageObserver(callingUid, observerId, packages, timeLimitMs, callbackIntent,
                 userId);
     }
 
     void unregisterAppUsageObserver(int callingUid, int observerId, int userId) {
-        mAppTimeLimit.removeObserver(callingUid, observerId, userId);
+        mAppTimeLimit.removeAppUsageObserver(callingUid, observerId, userId);
+    }
+
+    void registerUsageSessionObserver(int callingUid, int observerId, String[] observed,
+            long timeLimitMs, long sessionThresholdTime, PendingIntent limitReachedCallbackIntent,
+            PendingIntent sessionEndCallbackIntent, int userId) {
+        mAppTimeLimit.addUsageSessionObserver(callingUid, observerId, observed, timeLimitMs,
+                sessionThresholdTime, limitReachedCallbackIntent, sessionEndCallbackIntent, userId);
+    }
+
+    void unregisterUsageSessionObserver(int callingUid, int sessionObserverId, int userId) {
+        mAppTimeLimit.removeUsageSessionObserver(callingUid, sessionObserverId, userId);
     }
 
     /**
diff --git a/startop/tools/view_compiler/Android.bp b/startop/view_compiler/Android.bp
similarity index 100%
rename from startop/tools/view_compiler/Android.bp
rename to startop/view_compiler/Android.bp
diff --git a/startop/tools/view_compiler/README.md b/startop/view_compiler/README.md
similarity index 100%
rename from startop/tools/view_compiler/README.md
rename to startop/view_compiler/README.md
diff --git a/startop/tools/view_compiler/TEST_MAPPING b/startop/view_compiler/TEST_MAPPING
similarity index 100%
rename from startop/tools/view_compiler/TEST_MAPPING
rename to startop/view_compiler/TEST_MAPPING
diff --git a/startop/tools/view_compiler/dex_builder.cc b/startop/view_compiler/dex_builder.cc
similarity index 100%
rename from startop/tools/view_compiler/dex_builder.cc
rename to startop/view_compiler/dex_builder.cc
diff --git a/startop/tools/view_compiler/dex_builder.h b/startop/view_compiler/dex_builder.h
similarity index 100%
rename from startop/tools/view_compiler/dex_builder.h
rename to startop/view_compiler/dex_builder.h
diff --git a/startop/tools/view_compiler/dex_builder_test.cc b/startop/view_compiler/dex_builder_test.cc
similarity index 100%
rename from startop/tools/view_compiler/dex_builder_test.cc
rename to startop/view_compiler/dex_builder_test.cc
diff --git a/startop/tools/view_compiler/java_lang_builder.cc b/startop/view_compiler/java_lang_builder.cc
similarity index 100%
rename from startop/tools/view_compiler/java_lang_builder.cc
rename to startop/view_compiler/java_lang_builder.cc
diff --git a/startop/tools/view_compiler/java_lang_builder.h b/startop/view_compiler/java_lang_builder.h
similarity index 100%
rename from startop/tools/view_compiler/java_lang_builder.h
rename to startop/view_compiler/java_lang_builder.h
diff --git a/startop/tools/view_compiler/main.cc b/startop/view_compiler/main.cc
similarity index 100%
rename from startop/tools/view_compiler/main.cc
rename to startop/view_compiler/main.cc
diff --git a/startop/tools/view_compiler/util.cc b/startop/view_compiler/util.cc
similarity index 100%
rename from startop/tools/view_compiler/util.cc
rename to startop/view_compiler/util.cc
diff --git a/startop/tools/view_compiler/util.h b/startop/view_compiler/util.h
similarity index 100%
rename from startop/tools/view_compiler/util.h
rename to startop/view_compiler/util.h
diff --git a/startop/tools/view_compiler/util_test.cc b/startop/view_compiler/util_test.cc
similarity index 100%
rename from startop/tools/view_compiler/util_test.cc
rename to startop/view_compiler/util_test.cc
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index d33a537..3127b35 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -676,7 +676,7 @@
     /**
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     public static TelecomManager from(Context context) {
         return (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE);
     }
diff --git a/telephony/java/android/provider/Telephony.java b/telephony/java/android/provider/Telephony.java
index d9e7167..52ac32d 100644
--- a/telephony/java/android/provider/Telephony.java
+++ b/telephony/java/android/provider/Telephony.java
@@ -1245,6 +1245,33 @@
                     "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
+             * this is the initial create of the db. Requires
+             * {@link android.Manifest.permission#READ_SMS} to receive.
+             *
+             * @see #EXTRA_IS_INITIAL_CREATE
+             *
+             * @hide
+             */
+            @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+            public static final String ACTION_SMS_MMS_DB_CREATED =
+                    "android.provider.action.SMS_MMS_DB_CREATED";
+
+            /**
+             * Boolean flag passed as an extra with {@link #ACTION_SMS_MMS_DB_CREATED} to indicate
+             * whether the DB creation is the initial creation on the device, that is it is after a
+             * factory-data reset or a new device. Any subsequent creations of the DB (which
+             * happens only in error scenarios) will have this flag set to false.
+             *
+             * @see #ACTION_SMS_MMS_DB_CREATED
+             *
+             * @hide
+             */
+            public static final String EXTRA_IS_INITIAL_CREATE =
+                    "android.provider.extra.IS_INITIAL_CREATE";
+            /**
              * Read the PDUs out of an {@link #SMS_RECEIVED_ACTION} or a
              * {@link #DATA_SMS_RECEIVED_ACTION} intent.
              *
@@ -3059,6 +3086,13 @@
         @SystemApi
         public static final int NO_SET_SET = 0;
 
+        /**
+         * A unique carrier id associated with this APN
+         * {@see TelephonyManager#getSimCarrierId()}
+         * <p>Type: STRING</p>
+         */
+        public static final String CARRIER_ID = "carrier_id";
+
     }
 
     /**
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index b0997f1..f4b5f86 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -16,12 +16,14 @@
 
 package android.telephony;
 
+import android.Manifest;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
+import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.os.PersistableBundle;
@@ -1132,6 +1134,13 @@
     public static final String KEY_CARRIER_NAME_STRING = "carrier_name_string";
 
     /**
+     * The Component Name of a carrier-provided CallScreeningService implementation. Telecom will
+     * bind to this CallScreeningService for ALL incoming calls and provide the carrier
+     * CallScreeningService with the opportunity to allow or block calls.
+     */
+    public static final String KEY_CARRIER_CALL_SCREENING_APP_STRING = "call_screening_app";
+
+    /**
      * Override the registered PLMN name using #KEY_CDMA_HOME_REGISTERED_PLMN_NAME_STRING.
      *
      * If true, then the registered PLMN name (only for CDMA/CDMA-LTE and only when not roaming)
@@ -1222,8 +1231,8 @@
     public static final String KEY_SHOW_PRECISE_FAILED_CAUSE_BOOL =
             "show_precise_failed_cause_bool";
 
-    // These variables are used by the MMS service and exposed through another API, {@link
-    // SmsManager}. The variable names and string values are copied from there.
+    // These variables are used by the MMS service and exposed through another API,
+    // SmsManager. The variable names and string values are copied from there.
     public static final String KEY_MMS_ALIAS_ENABLED_BOOL = "aliasEnabled";
     public static final String KEY_MMS_ALLOW_ATTACH_AUDIO_BOOL = "allowAttachAudio";
     public static final String KEY_MMS_APPEND_TRANSACTION_ID_BOOL = "enabledTransID";
@@ -1271,7 +1280,7 @@
      * network as part of the Setup Wizard flow.
      * @hide
      */
-     public static final String KEY_CARRIER_SETUP_APP_STRING = "carrier_setup_app_string";
+    public static final String KEY_CARRIER_SETUP_APP_STRING = "carrier_setup_app_string";
 
     /**
      * Defines carrier-specific actions which act upon
@@ -2222,6 +2231,13 @@
     public static final String KEY_CALL_WAITING_OVER_UT_WARNING_BOOL =
             "call_waiting_over_ut_warning_bool";
 
+    /**
+     * Flag indicating whether to support "Network default" option in Caller ID settings for Calling
+     * Line Identification Restriction (CLIR).
+     */
+    public static final String KEY_SUPPORT_CLIR_NETWORK_DEFAULT_BOOL =
+            "support_clir_network_default_bool";
+
     /** The default value for every variable. */
     private final static PersistableBundle sDefaults;
 
@@ -2406,6 +2422,7 @@
         sDefaults.putBoolean(KEY_CONFIG_WIFI_DISABLE_IN_ECBM, false);
         sDefaults.putBoolean(KEY_CARRIER_NAME_OVERRIDE_BOOL, false);
         sDefaults.putString(KEY_CARRIER_NAME_STRING, "");
+        sDefaults.putString(KEY_CARRIER_CALL_SCREENING_APP_STRING, "");
         sDefaults.putBoolean(KEY_CDMA_HOME_REGISTERED_PLMN_NAME_OVERRIDE_BOOL, false);
         sDefaults.putString(KEY_CDMA_HOME_REGISTERED_PLMN_NAME_STRING, "");
         sDefaults.putBoolean(KEY_SUPPORT_DIRECT_FDN_DIALING_BOOL, false);
@@ -2544,7 +2561,7 @@
         sDefaults.putBoolean(KEY_SHOW_PRECISE_FAILED_CAUSE_BOOL, false);
         sDefaults.putBoolean(KEY_SPN_DISPLAY_RULE_USE_ROAMING_FROM_SERVICE_STATE_BOOL, false);
         sDefaults.putBoolean(KEY_ALWAYS_SHOW_DATA_RAT_ICON_BOOL, false);
-        sDefaults.putBoolean(KEY_SHOW_4G_FOR_LTE_DATA_ICON_BOOL, true);
+        sDefaults.putBoolean(KEY_SHOW_4G_FOR_LTE_DATA_ICON_BOOL, false);
         sDefaults.putBoolean(KEY_HIDE_LTE_PLUS_DATA_ICON_BOOL, false);
         sDefaults.putBoolean(KEY_CARRIER_CONFIG_APPLIED_BOOL, false);
         sDefaults.putBoolean(KEY_CHECK_PRICING_WITH_CARRIER_FOR_DATA_ROAMING_BOOL, false);
@@ -2569,6 +2586,7 @@
         sDefaults.putBoolean(KEY_CALL_BARRING_OVER_UT_WARNING_BOOL, false);
         sDefaults.putBoolean(KEY_CALLER_ID_OVER_UT_WARNING_BOOL, false);
         sDefaults.putBoolean(KEY_CALL_WAITING_OVER_UT_WARNING_BOOL, false);
+        sDefaults.putBoolean(KEY_SUPPORT_CLIR_NETWORK_DEFAULT_BOOL, true);
     }
 
     /**
@@ -2603,6 +2621,40 @@
     }
 
     /**
+     * Overrides the carrier config of the provided subscription ID with the provided values.
+     *
+     * Any further queries to carrier config from any process will return
+     * the overriden values after this method returns. The overrides are effective for the lifetime
+     * of the phone process.
+     *
+     * May throw an {@link IllegalArgumentException} if {@code overrideValues} contains invalid
+     * values for the specified config keys.
+     *
+     * @param subscriptionId The subscription ID for which the override should be done.
+     * @param overrideValues Key-value pairs of the values that are to be overriden. If null,
+     *                       all previous overrides will be disabled and the config reset back to
+     *                       its initial state.
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
+    @SystemApi
+    @TestApi
+    public void overrideConfig(int subscriptionId, @Nullable PersistableBundle overrideValues) {
+        try {
+            ICarrierConfigLoader loader = getICarrierConfigLoader();
+            if (loader == null) {
+                Rlog.w(TAG, "Error setting config for subId " + subscriptionId
+                        + " ICarrierConfigLoader is null");
+                return;
+            }
+            loader.overrideConfig(subscriptionId, overrideValues);
+        } catch (RemoteException ex) {
+            Rlog.e(TAG, "Error setting config for subId " + subscriptionId + ": "
+                    + ex.toString());
+        }
+    }
+
+    /**
      * Gets the configuration values for the default subscription. After using this method to get
      * the configuration bundle, {@link #isConfigForIdentifiedCarrier(PersistableBundle)} should be
      * called to confirm whether any carrier specific configuration has been applied.
diff --git a/telephony/java/android/telephony/CellIdentityCdma.java b/telephony/java/android/telephony/CellIdentityCdma.java
index 9218bdc..598f567 100644
--- a/telephony/java/android/telephony/CellIdentityCdma.java
+++ b/telephony/java/android/telephony/CellIdentityCdma.java
@@ -16,7 +16,6 @@
 
 package android.telephony;
 
-import android.annotation.Nullable;
 import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.telephony.cdma.CdmaCellLocation;
@@ -56,11 +55,11 @@
      */
     public CellIdentityCdma() {
         super(TAG, CellInfo.TYPE_CDMA, null, null, null, null);
-        mNetworkId = Integer.MAX_VALUE;
-        mSystemId = Integer.MAX_VALUE;
-        mBasestationId = Integer.MAX_VALUE;
-        mLongitude = Integer.MAX_VALUE;
-        mLatitude = Integer.MAX_VALUE;
+        mNetworkId = CellInfo.UNAVAILABLE;
+        mSystemId = CellInfo.UNAVAILABLE;
+        mBasestationId = CellInfo.UNAVAILABLE;
+        mLongitude = CellInfo.UNAVAILABLE;
+        mLatitude = CellInfo.UNAVAILABLE;
     }
 
     /**
@@ -104,7 +103,7 @@
             mLongitude = lon;
             mLatitude = lat;
         } else {
-            mLongitude = mLatitude = Integer.MAX_VALUE;
+            mLongitude = mLatitude = CellInfo.UNAVAILABLE;
         }
     }
 
@@ -130,21 +129,24 @@
     }
 
     /**
-     * @return Network Id 0..65535, Integer.MAX_VALUE if unknown
+     * @return Network Id 0..65535, {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE}
+     *         if unavailable.
      */
     public int getNetworkId() {
         return mNetworkId;
     }
 
     /**
-     * @return System Id 0..32767, Integer.MAX_VALUE if unknown
+     * @return System Id 0..32767, {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE}
+     *         if unavailable.
      */
     public int getSystemId() {
         return mSystemId;
     }
 
     /**
-     * @return Base Station Id 0..65535, Integer.MAX_VALUE if unknown
+     * @return Base Station Id 0..65535, {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE}
+     *         if unavailable.
      */
     public int getBasestationId() {
         return mBasestationId;
@@ -155,7 +157,7 @@
      * specified in 3GPP2 C.S0005-A v6.0. It is represented in units
      * of 0.25 seconds and ranges from -2592000 to 2592000, both
      * values inclusive (corresponding to a range of -180
-     * to +180 degrees). Integer.MAX_VALUE if unknown.
+     * to +180 degrees). {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable.
      */
     public int getLongitude() {
         return mLongitude;
@@ -166,7 +168,7 @@
      * specified in 3GPP2 C.S0005-A v6.0. It is represented in units
      * of 0.25 seconds and ranges from -1296000 to 1296000, both
      * values inclusive (corresponding to a range of -90
-     * to +90 degrees). Integer.MAX_VALUE if unknown.
+     * to +90 degrees). {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable.
      */
     public int getLatitude() {
         return mLatitude;
@@ -182,10 +184,10 @@
     @Override
     public CdmaCellLocation asCellLocation() {
         CdmaCellLocation cl = new CdmaCellLocation();
-        int bsid = mBasestationId != Integer.MAX_VALUE ? mBasestationId : -1;
-        int sid = mSystemId != Integer.MAX_VALUE ? mSystemId : -1;
-        int nid = mNetworkId != Integer.MAX_VALUE ? mNetworkId : -1;
-        // lat and long already use Integer.MAX_VALUE for invalid/unknown
+        int bsid = mBasestationId != CellInfo.UNAVAILABLE ? mBasestationId : -1;
+        int sid = mSystemId != CellInfo.UNAVAILABLE ? mSystemId : -1;
+        int nid = mNetworkId != CellInfo.UNAVAILABLE ? mNetworkId : -1;
+        // lat and long already use CellInfo.UNAVAILABLE for invalid/unknown
         cl.setCellLocationData(bsid, mLatitude, mLongitude, sid, nid);
         return cl;
     }
diff --git a/telephony/java/android/telephony/CellIdentityGsm.java b/telephony/java/android/telephony/CellIdentityGsm.java
index cb9dbf3..04c28e5 100644
--- a/telephony/java/android/telephony/CellIdentityGsm.java
+++ b/telephony/java/android/telephony/CellIdentityGsm.java
@@ -16,7 +16,6 @@
 
 package android.telephony;
 
-import android.annotation.Nullable;
 import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.telephony.gsm.GsmCellLocation;
@@ -48,10 +47,10 @@
     @UnsupportedAppUsage
     public CellIdentityGsm() {
         super(TAG, CellInfo.TYPE_GSM, null, null, null, null);
-        mLac = Integer.MAX_VALUE;
-        mCid = Integer.MAX_VALUE;
-        mArfcn = Integer.MAX_VALUE;
-        mBsic = Integer.MAX_VALUE;
+        mLac = CellInfo.UNAVAILABLE;
+        mCid = CellInfo.UNAVAILABLE;
+        mArfcn = CellInfo.UNAVAILABLE;
+        mBsic = CellInfo.UNAVAILABLE;
     }
     /**
      * public constructor
@@ -63,7 +62,7 @@
      * @hide
      */
     public CellIdentityGsm(int mcc, int mnc, int lac, int cid) {
-        this(lac, cid, Integer.MAX_VALUE, Integer.MAX_VALUE,
+        this(lac, cid, CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE,
                 String.valueOf(mcc), String.valueOf(mnc), null, null);
     }
 
@@ -103,7 +102,7 @@
         mArfcn = arfcn;
         // In RIL BSIC is a UINT8, so 0xFF is the 'INVALID' designator
         // for inbound parcels
-        mBsic = (bsic == 0xFF) ? Integer.MAX_VALUE : bsic;
+        mBsic = (bsic == 0xFF) ? CellInfo.UNAVAILABLE : bsic;
     }
 
     private CellIdentityGsm(CellIdentityGsm cid) {
@@ -116,69 +115,73 @@
     }
 
     /**
-     * @return 3-digit Mobile Country Code, 0..999, Integer.MAX_VALUE if unknown
+     * @return 3-digit Mobile Country Code, 0..999,
+     *         {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable.
      * @deprecated Use {@link #getMccString} instead.
      */
     @Deprecated
     public int getMcc() {
-        return (mMccStr != null) ? Integer.valueOf(mMccStr) : Integer.MAX_VALUE;
+        return (mMccStr != null) ? Integer.valueOf(mMccStr) : CellInfo.UNAVAILABLE;
     }
 
     /**
-     * @return 2 or 3-digit Mobile Network Code, 0..999, Integer.MAX_VALUE if unknown
+     * @return 2 or 3-digit Mobile Network Code, 0..999,
+     *         {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable.
      * @deprecated Use {@link #getMncString} instead.
      */
     @Deprecated
     public int getMnc() {
-        return (mMncStr != null) ? Integer.valueOf(mMncStr) : Integer.MAX_VALUE;
+        return (mMncStr != null) ? Integer.valueOf(mMncStr) : CellInfo.UNAVAILABLE;
     }
 
     /**
-     * @return 16-bit Location Area Code, 0..65535, Integer.MAX_VALUE if unknown
+     * @return 16-bit Location Area Code, 0..65535,
+     *         {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable.
      */
     public int getLac() {
         return mLac;
     }
 
     /**
-     * @return CID
-     * Either 16-bit GSM Cell Identity described
-     * in TS 27.007, 0..65535, Integer.MAX_VALUE if unknown
+     * @return 16-bit GSM Cell Identity described in TS 27.007, 0..65535,
+     *         {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable.
      */
     public int getCid() {
         return mCid;
     }
 
     /**
-     * @return 16-bit GSM Absolute RF Channel Number, Integer.MAX_VALUE if unknown
+     * @return 16-bit GSM Absolute RF Channel Number,
+     *         {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable.
      */
     public int getArfcn() {
         return mArfcn;
     }
 
     /**
-     * @return 6-bit Base Station Identity Code, Integer.MAX_VALUE if unknown
+     * @return 6-bit Base Station Identity Code,
+     *         {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable.
      */
     public int getBsic() {
         return mBsic;
     }
 
     /**
-     * @return a 5 or 6 character string (MCC+MNC), null if any field is unknown
+     * @return a 5 or 6 character string (MCC+MNC), null if any field is unknown.
      */
     public String getMobileNetworkOperator() {
         return (mMccStr == null || mMncStr == null) ? null : mMccStr + mMncStr;
     }
 
     /**
-     * @return Mobile Country Code in string format, null if unknown
+     * @return Mobile Country Code in string format, null if unavailable.
      */
     public String getMccString() {
         return mMccStr;
     }
 
     /**
-     * @return Mobile Network Code in string format, null if unknown
+     * @return Mobile Network Code in string format, null if unavailable.
      */
     public String getMncString() {
         return mMncStr;
@@ -192,19 +195,19 @@
 
     /**
      * @deprecated Primary Scrambling Code is not applicable to GSM.
-     * @return Integer.MAX_VALUE, undefined for GSM
+     * @return {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} - undefined for GSM
      */
     @Deprecated
     public int getPsc() {
-        return Integer.MAX_VALUE;
+        return CellInfo.UNAVAILABLE;
     }
 
     /** @hide */
     @Override
     public GsmCellLocation asCellLocation() {
         GsmCellLocation cl = new GsmCellLocation();
-        int lac = mLac != Integer.MAX_VALUE ? mLac : -1;
-        int cid = mCid != Integer.MAX_VALUE ? mCid : -1;
+        int lac = mLac != CellInfo.UNAVAILABLE ? mLac : -1;
+        int cid = mCid != CellInfo.UNAVAILABLE ? mCid : -1;
         cl.setLacAndCid(lac, cid);
         cl.setPsc(-1);
         return cl;
diff --git a/telephony/java/android/telephony/CellIdentityLte.java b/telephony/java/android/telephony/CellIdentityLte.java
index b44e891..04b6a6c 100644
--- a/telephony/java/android/telephony/CellIdentityLte.java
+++ b/telephony/java/android/telephony/CellIdentityLte.java
@@ -16,7 +16,6 @@
 
 package android.telephony;
 
-import android.annotation.Nullable;
 import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.telephony.gsm.GsmCellLocation;
@@ -49,11 +48,11 @@
     @UnsupportedAppUsage
     public CellIdentityLte() {
         super(TAG, CellInfo.TYPE_LTE, null, null, null, null);
-        mCi = Integer.MAX_VALUE;
-        mPci = Integer.MAX_VALUE;
-        mTac = Integer.MAX_VALUE;
-        mEarfcn = Integer.MAX_VALUE;
-        mBandwidth = Integer.MAX_VALUE;
+        mCi = CellInfo.UNAVAILABLE;
+        mPci = CellInfo.UNAVAILABLE;
+        mTac = CellInfo.UNAVAILABLE;
+        mEarfcn = CellInfo.UNAVAILABLE;
+        mBandwidth = CellInfo.UNAVAILABLE;
     }
 
     /**
@@ -68,7 +67,7 @@
      */
     @UnsupportedAppUsage
     public CellIdentityLte(int mcc, int mnc, int ci, int pci, int tac) {
-        this(ci, pci, tac, Integer.MAX_VALUE, Integer.MAX_VALUE, String.valueOf(mcc),
+        this(ci, pci, tac, CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE, String.valueOf(mcc),
                 String.valueOf(mnc), null, null);
     }
 
@@ -84,7 +83,7 @@
      * @hide
      */
     public CellIdentityLte(int mcc, int mnc, int ci, int pci, int tac, int earfcn) {
-        this(ci, pci, tac, earfcn, Integer.MAX_VALUE, String.valueOf(mcc), String.valueOf(mnc),
+        this(ci, pci, tac, earfcn, CellInfo.UNAVAILABLE, String.valueOf(mcc), String.valueOf(mnc),
                 null, null);
     }
 
@@ -122,74 +121,81 @@
     }
 
     /**
-     * @return 3-digit Mobile Country Code, 0..999, Integer.MAX_VALUE if unknown
+     * @return 3-digit Mobile Country Code, 0..999,
+     *         {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable.
      * @deprecated Use {@link #getMccString} instead.
      */
     @Deprecated
     public int getMcc() {
-        return (mMccStr != null) ? Integer.valueOf(mMccStr) : Integer.MAX_VALUE;
+        return (mMccStr != null) ? Integer.valueOf(mMccStr) : CellInfo.UNAVAILABLE;
     }
 
     /**
-     * @return 2 or 3-digit Mobile Network Code, 0..999, Integer.MAX_VALUE if unknown
+     * @return 2 or 3-digit Mobile Network Code, 0..999,
+     *         {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable.
      * @deprecated Use {@link #getMncString} instead.
      */
     @Deprecated
     public int getMnc() {
-        return (mMncStr != null) ? Integer.valueOf(mMncStr) : Integer.MAX_VALUE;
+        return (mMncStr != null) ? Integer.valueOf(mMncStr) : CellInfo.UNAVAILABLE;
     }
 
     /**
-     * @return 28-bit Cell Identity, Integer.MAX_VALUE if unknown
+     * @return 28-bit Cell Identity,
+     *         {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable.
      */
     public int getCi() {
         return mCi;
     }
 
     /**
-     * @return Physical Cell Id 0..503, Integer.MAX_VALUE if unknown
+     * @return Physical Cell Id 0..503,
+     *         {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable.
      */
     public int getPci() {
         return mPci;
     }
 
     /**
-     * @return 16-bit Tracking Area Code, Integer.MAX_VALUE if unknown
+     * @return 16-bit Tracking Area Code,
+     *         {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable.
      */
     public int getTac() {
         return mTac;
     }
 
     /**
-     * @return 18-bit Absolute RF Channel Number, Integer.MAX_VALUE if unknown
+     * @return 18-bit Absolute RF Channel Number,
+     *         {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable.
      */
     public int getEarfcn() {
         return mEarfcn;
     }
 
     /**
-     * @return Cell bandwidth in kHz, Integer.MAX_VALUE if unknown
+     * @return Cell bandwidth in kHz,
+     *         {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable.
      */
     public int getBandwidth() {
         return mBandwidth;
     }
 
     /**
-     * @return Mobile Country Code in string format, null if unknown
+     * @return Mobile Country Code in string format, null if unavailable.
      */
     public String getMccString() {
         return mMccStr;
     }
 
     /**
-     * @return Mobile Network Code in string format, null if unknown
+     * @return Mobile Network Code in string format, null if unavailable.
      */
     public String getMncString() {
         return mMncStr;
     }
 
     /**
-     * @return a 5 or 6 character string (MCC+MNC), null if any field is unknown
+     * @return a 5 or 6 character string (MCC+MNC), null if any field is unknown.
      */
     public String getMobileNetworkOperator() {
         return (mMccStr == null || mMncStr == null) ? null : mMccStr + mMncStr;
@@ -216,8 +222,8 @@
     @Override
     public GsmCellLocation asCellLocation() {
         GsmCellLocation cl = new GsmCellLocation();
-        int tac = mTac != Integer.MAX_VALUE ? mTac : -1;
-        int cid = mCi != Integer.MAX_VALUE ? mCi : -1;
+        int tac = mTac != CellInfo.UNAVAILABLE ? mTac : -1;
+        int cid = mCi != CellInfo.UNAVAILABLE ? mCi : -1;
         cl.setLacAndCid(tac, cid);
         cl.setPsc(0);
         return cl;
diff --git a/telephony/java/android/telephony/CellIdentityTdscdma.java b/telephony/java/android/telephony/CellIdentityTdscdma.java
index 5a9e474..8b1c1b9 100644
--- a/telephony/java/android/telephony/CellIdentityTdscdma.java
+++ b/telephony/java/android/telephony/CellIdentityTdscdma.java
@@ -28,11 +28,12 @@
     private static final String TAG = CellIdentityTdscdma.class.getSimpleName();
     private static final boolean DBG = false;
 
-    // 16-bit Location Area Code, 0..65535, INT_MAX if unknown.
+    // 16-bit Location Area Code, 0..65535, CellInfo.UNAVAILABLE if unknown.
     private final int mLac;
-    // 28-bit UMTS Cell Identity described in TS 25.331, 0..268435455, INT_MAX if unknown.
+    // 28-bit UMTS Cell Identity described in TS 25.331, 0..268435455, CellInfo.UNAVAILABLE
+    // if unknown.
     private final int mCid;
-    // 8-bit Cell Parameters ID described in TS 25.331, 0..127, INT_MAX if unknown.
+    // 8-bit Cell Parameters ID described in TS 25.331, 0..127, CellInfo.UNAVAILABLE if unknown.
     private final int mCpid;
     // 16-bit UMTS Absolute RF Channel Number described in TS 25.101 sec. 5.4.3
     private final int mUarfcn;
@@ -42,18 +43,20 @@
      */
     public CellIdentityTdscdma() {
         super(TAG, CellInfo.TYPE_TDSCDMA, null, null, null, null);
-        mLac = Integer.MAX_VALUE;
-        mCid = Integer.MAX_VALUE;
-        mCpid = Integer.MAX_VALUE;
-        mUarfcn = Integer.MAX_VALUE;
+        mLac = CellInfo.UNAVAILABLE;
+        mCid = CellInfo.UNAVAILABLE;
+        mCpid = CellInfo.UNAVAILABLE;
+        mUarfcn = CellInfo.UNAVAILABLE;
     }
 
     /**
      * @param mcc 3-digit Mobile Country Code, 0..999
      * @param mnc 2 or 3-digit Mobile Network Code, 0..999
-     * @param lac 16-bit Location Area Code, 0..65535, INT_MAX if unknown
-     * @param cid 28-bit UMTS Cell Identity described in TS 25.331, 0..268435455, INT_MAX if unknown
-     * @param cpid 8-bit Cell Parameters ID described in TS 25.331, 0..127, INT_MAX if unknown
+     * @param lac 16-bit Location Area Code, 0..65535, CellInfo.UNAVAILABLE if unknown
+     * @param cid 28-bit UMTS Cell Identity described in TS 25.331, 0..268435455, CellInfo.
+     *        UNAVAILABLE if unknown
+     * @param cpid 8-bit Cell Parameters ID described in TS 25.331, 0..127, CellInfo.UNAVAILABLE
+     *        if unknown
      * @param uarfcn 16-bit UMTS Absolute RF Channel Number described in TS 25.101 sec. 5.4.3
      *
      * @hide
@@ -65,9 +68,11 @@
     /**
      * @param mcc 3-digit Mobile Country Code in string format
      * @param mnc 2 or 3-digit Mobile Network Code in string format
-     * @param lac 16-bit Location Area Code, 0..65535, INT_MAX if unknown
-     * @param cid 28-bit UMTS Cell Identity described in TS 25.331, 0..268435455, INT_MAX if unknown
-     * @param cpid 8-bit Cell Parameters ID described in TS 25.331, 0..127, INT_MAX if unknown
+     * @param lac 16-bit Location Area Code, 0..65535, CellInfo.UNAVAILABLE if unknown
+     * @param cid 28-bit UMTS Cell Identity described in TS 25.331, 0..268435455,
+     *        CellInfo.UNAVAILABLE if unknown
+     * @param cpid 8-bit Cell Parameters ID described in TS 25.331, 0..127,
+     *        CellInfo.UNAVAILABLE if unknown
      * @param uarfcn 16-bit UMTS Absolute RF Channel Number described in TS 25.101 sec. 5.4.3
      * @param alphal long alpha Operator Name String or Enhanced Operator Name String
      * @param alphas short alpha Operator Name String or Enhanced Operator Name String
@@ -109,21 +114,31 @@
     }
 
     /**
-     * @return 16-bit Location Area Code, 0..65535, INT_MAX if unknown
+     * @return a 5 or 6 character string (MCC+MNC), null if any field is unknown
+     */
+    public String getMobileNetworkOperator() {
+        return (mMccStr == null || mMncStr == null) ? null : mMccStr + mMncStr;
+    }
+
+    /**
+     * @return 16-bit Location Area Code, 0..65535,
+     *         {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable.
      */
     public int getLac() {
         return mLac;
     }
 
     /**
-     * @return 28-bit UMTS Cell Identity described in TS 25.331, 0..268435455, INT_MAX if unknown
+     * @return 28-bit UMTS Cell Identity described in TS 25.331, 0..268435455,
+     *         {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable.
      */
     public int getCid() {
         return mCid;
     }
 
     /**
-     * @return 8-bit Cell Parameters ID described in TS 25.331, 0..127, INT_MAX if unknown
+     * @return 8-bit Cell Parameters ID described in TS 25.331, 0..127,
+     *         {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable.
      */
     public int getCpid() {
         return mCpid;
@@ -139,8 +154,8 @@
     @Override
     public GsmCellLocation asCellLocation() {
         GsmCellLocation cl = new GsmCellLocation();
-        int lac = mLac != Integer.MAX_VALUE ? mLac : -1;
-        int cid = mCid != Integer.MAX_VALUE ? mCid : -1;
+        int lac = mLac != CellInfo.UNAVAILABLE ? mLac : -1;
+        int cid = mCid != CellInfo.UNAVAILABLE ? mCid : -1;
         cl.setLacAndCid(lac, cid);
         cl.setPsc(-1); // There is no PSC for TD-SCDMA; not using this for CPI to stem shenanigans
         return cl;
diff --git a/telephony/java/android/telephony/CellIdentityWcdma.java b/telephony/java/android/telephony/CellIdentityWcdma.java
index 727d990..3416ffe 100644
--- a/telephony/java/android/telephony/CellIdentityWcdma.java
+++ b/telephony/java/android/telephony/CellIdentityWcdma.java
@@ -16,7 +16,6 @@
 
 package android.telephony;
 
-import android.annotation.Nullable;
 import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.telephony.gsm.GsmCellLocation;
@@ -46,10 +45,10 @@
      */
     public CellIdentityWcdma() {
         super(TAG, CellInfo.TYPE_WCDMA, null, null, null, null);
-        mLac = Integer.MAX_VALUE;
-        mCid = Integer.MAX_VALUE;
-        mPsc = Integer.MAX_VALUE;
-        mUarfcn = Integer.MAX_VALUE;
+        mLac = CellInfo.UNAVAILABLE;
+        mCid = CellInfo.UNAVAILABLE;
+        mPsc = CellInfo.UNAVAILABLE;
+        mUarfcn = CellInfo.UNAVAILABLE;
     }
     /**
      * public constructor
@@ -62,7 +61,7 @@
      * @hide
      */
     public CellIdentityWcdma (int mcc, int mnc, int lac, int cid, int psc) {
-        this(lac, cid, psc, Integer.MAX_VALUE, String.valueOf(mcc), String.valueOf(mnc),
+        this(lac, cid, psc, CellInfo.UNAVAILABLE, String.valueOf(mcc), String.valueOf(mnc),
                 null, null);
     }
 
@@ -113,25 +112,28 @@
     }
 
     /**
-     * @return 3-digit Mobile Country Code, 0..999, Integer.MAX_VALUE if unknown
+     * @return 3-digit Mobile Country Code, 0..999,
+     *         {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable.
      * @deprecated Use {@link #getMccString} instead.
      */
     @Deprecated
     public int getMcc() {
-        return (mMccStr != null) ? Integer.valueOf(mMccStr) : Integer.MAX_VALUE;
+        return (mMccStr != null) ? Integer.valueOf(mMccStr) : CellInfo.UNAVAILABLE;
     }
 
     /**
-     * @return 2 or 3-digit Mobile Network Code, 0..999, Integer.MAX_VALUE if unknown
+     * @return 2 or 3-digit Mobile Network Code, 0..999,
+     *         {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable.
      * @deprecated Use {@link #getMncString} instead.
      */
     @Deprecated
     public int getMnc() {
-        return (mMncStr != null) ? Integer.valueOf(mMncStr) : Integer.MAX_VALUE;
+        return (mMncStr != null) ? Integer.valueOf(mMncStr) : CellInfo.UNAVAILABLE;
     }
 
     /**
-     * @return 16-bit Location Area Code, 0..65535, Integer.MAX_VALUE if unknown
+     * @return 16-bit Location Area Code, 0..65535,
+     *         {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable.
      */
     public int getLac() {
         return mLac;
@@ -139,29 +141,30 @@
 
     /**
      * @return CID
-     * 28-bit UMTS Cell Identity described in TS 25.331, 0..268435455, Integer.MAX_VALUE if unknown
+     * 28-bit UMTS Cell Identity described in TS 25.331, 0..268435455,
+     *         {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable.
      */
     public int getCid() {
         return mCid;
     }
 
     /**
-     * @return 9-bit UMTS Primary Scrambling Code described in TS 25.331, 0..511, Integer.MAX_VALUE
-     * if unknown
+     * @return 9-bit UMTS Primary Scrambling Code described in TS 25.331, 0..511,
+     *         {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable.
      */
     public int getPsc() {
         return mPsc;
     }
 
     /**
-     * @return Mobile Country Code in string version, null if unknown
+     * @return Mobile Country Code in string version, null if unavailable.
      */
     public String getMccString() {
         return mMccStr;
     }
 
     /**
-     * @return Mobile Network Code in string version, null if unknown
+     * @return Mobile Network Code in string version, null if unavailable.
      */
     public String getMncString() {
         return mMncStr;
@@ -180,7 +183,8 @@
     }
 
     /**
-     * @return 16-bit UMTS Absolute RF Channel Number, Integer.MAX_VALUE if unknown
+     * @return 16-bit UMTS Absolute RF Channel Number,
+     *         {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable.
      */
     public int getUarfcn() {
         return mUarfcn;
@@ -196,9 +200,9 @@
     @Override
     public GsmCellLocation asCellLocation() {
         GsmCellLocation cl = new GsmCellLocation();
-        int lac = mLac != Integer.MAX_VALUE ? mLac : -1;
-        int cid = mCid != Integer.MAX_VALUE ? mCid : -1;
-        int psc = mPsc != Integer.MAX_VALUE ? mPsc : -1;
+        int lac = mLac != CellInfo.UNAVAILABLE ? mLac : -1;
+        int cid = mCid != CellInfo.UNAVAILABLE ? mCid : -1;
+        int psc = mPsc != CellInfo.UNAVAILABLE ? mPsc : -1;
         cl.setLacAndCid(lac, cid);
         cl.setPsc(psc);
 
@@ -280,4 +284,4 @@
     protected static CellIdentityWcdma createFromParcelBody(Parcel in) {
         return new CellIdentityWcdma(in);
     }
-}
\ No newline at end of file
+}
diff --git a/telephony/java/android/telephony/CellInfo.java b/telephony/java/android/telephony/CellInfo.java
index 4fe1b01..1c63e82 100644
--- a/telephony/java/android/telephony/CellInfo.java
+++ b/telephony/java/android/telephony/CellInfo.java
@@ -22,6 +22,8 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import com.android.internal.annotations.VisibleForTesting;
+
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
@@ -31,6 +33,11 @@
 public abstract class CellInfo implements Parcelable {
 
     /**
+     * This value indicates that the integer field is unreported.
+     */
+    public static final int UNAVAILABLE = Integer.MAX_VALUE;
+
+    /**
      * Cell identity type
      * @hide
      */
@@ -120,41 +127,45 @@
     // Observation time stamped as type in nanoseconds since boot
     private long mTimeStamp;
 
-    // Where time stamp gets recorded.
-    // Value of TIMESTAMP_TYPE_XXXX
-    private int mTimeStampType;
-
     /** @hide */
     protected CellInfo() {
         this.mRegistered = false;
-        this.mTimeStampType = TIMESTAMP_TYPE_UNKNOWN;
         this.mTimeStamp = Long.MAX_VALUE;
     }
 
     /** @hide */
     protected CellInfo(CellInfo ci) {
         this.mRegistered = ci.mRegistered;
-        this.mTimeStampType = ci.mTimeStampType;
         this.mTimeStamp = ci.mTimeStamp;
         this.mCellConnectionStatus = ci.mCellConnectionStatus;
     }
 
-    /** True if this cell is registered to the mobile network */
+    /**
+     * True if the phone is registered to a mobile network that provides service on this cell
+     * and this cell is being used or would be used for network signaling.
+     */
     public boolean isRegistered() {
         return mRegistered;
     }
+
     /** @hide */
     public void setRegistered(boolean registered) {
         mRegistered = registered;
     }
 
-    /** Approximate time of this cell information in nanos since boot */
+    /**
+     * Approximate time this cell information was received from the modem.
+     *
+     * @return a time stamp in nanos since boot.
+     */
     public long getTimeStamp() {
         return mTimeStamp;
     }
+
     /** @hide */
-    public void setTimeStamp(long timeStamp) {
-        mTimeStamp = timeStamp;
+    @VisibleForTesting
+    public void setTimeStamp(long ts) {
+        mTimeStamp = ts;
     }
 
     /** @hide */
@@ -184,31 +195,11 @@
         mCellConnectionStatus = cellConnectionStatus;
     }
 
-    /**
-     * Where time stamp gets recorded.
-     * @return one of TIMESTAMP_TYPE_XXXX
-     *
-     * @hide
-     */
-    @UnsupportedAppUsage
-    public int getTimeStampType() {
-        return mTimeStampType;
-    }
-
-    /** @hide */
-    public void setTimeStampType(int timeStampType) {
-        if (timeStampType < TIMESTAMP_TYPE_UNKNOWN || timeStampType > TIMESTAMP_TYPE_JAVA_RIL) {
-            mTimeStampType = TIMESTAMP_TYPE_UNKNOWN;
-        } else {
-            mTimeStampType = timeStampType;
-        }
-    }
-
     @Override
     public int hashCode() {
         int primeNum = 31;
         return ((mRegistered ? 0 : 1) * primeNum) + ((int)(mTimeStamp / 1000) * primeNum)
-                + (mTimeStampType * primeNum) + (mCellConnectionStatus * primeNum);
+                + (mCellConnectionStatus * primeNum);
     }
 
     @Override
@@ -223,37 +214,17 @@
             CellInfo o = (CellInfo) other;
             return mRegistered == o.mRegistered
                     && mTimeStamp == o.mTimeStamp
-                    && mTimeStampType == o.mTimeStampType
                     && mCellConnectionStatus == o.mCellConnectionStatus;
         } catch (ClassCastException e) {
             return false;
         }
     }
 
-    @UnsupportedAppUsage
-    private static String timeStampTypeToString(int type) {
-        switch (type) {
-            case 1:
-                return "antenna";
-            case 2:
-                return "modem";
-            case 3:
-                return "oem_ril";
-            case 4:
-                return "java_ril";
-            default:
-                return "unknown";
-        }
-    }
-
     @Override
     public String toString() {
         StringBuffer sb = new StringBuffer();
-        String timeStampType;
 
         sb.append("mRegistered=").append(mRegistered ? "YES" : "NO");
-        timeStampType = timeStampTypeToString(mTimeStampType);
-        sb.append(" mTimeStampType=").append(timeStampType);
         sb.append(" mTimeStamp=").append(mTimeStamp).append("ns");
         sb.append(" mCellConnectionStatus=").append(mCellConnectionStatus);
 
@@ -280,7 +251,6 @@
     protected void writeToParcel(Parcel dest, int flags, int type) {
         dest.writeInt(type);
         dest.writeInt(mRegistered ? 1 : 0);
-        dest.writeInt(mTimeStampType);
         dest.writeLong(mTimeStamp);
         dest.writeInt(mCellConnectionStatus);
     }
@@ -292,7 +262,6 @@
      */
     protected CellInfo(Parcel in) {
         mRegistered = (in.readInt() == 1) ? true : false;
-        mTimeStampType = in.readInt();
         mTimeStamp = in.readLong();
         mCellConnectionStatus = in.readInt();
     }
diff --git a/telephony/java/android/telephony/CellSignalStrengthCdma.java b/telephony/java/android/telephony/CellSignalStrengthCdma.java
index aa6b207..5123052 100644
--- a/telephony/java/android/telephony/CellSignalStrengthCdma.java
+++ b/telephony/java/android/telephony/CellSignalStrengthCdma.java
@@ -51,8 +51,9 @@
      * <p>Note that this HAL is inconsistent with UMTS-based radio techs as the value indicating
      * that a field is unreported is negative, rather than a large(r) positive number.
      * <p>Also note that to keep the public-facing methods of this class consistent with others,
-     * unreported values are coerced to Integer.MAX_VALUE rather than left as -1, which is
-     * a departure from SignalStrength, which is stuck with the values it currently reports.
+     * unreported values are coerced to {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE}
+     * rather than left as -1, which is a departure from SignalStrength, which is stuck with the
+     * values it currently reports.
      *
      * @param cdmaDbm negative of the CDMA signal strength value or -1 if invalid.
      * @param cdmaEcio negative of the CDMA pilot/noise ratio or -1 if invalid.
@@ -65,12 +66,12 @@
             int evdoSnr) {
         // The values here were lifted from SignalStrength.validateInput()
         // FIXME: Combine all checking and setting logic between this and SignalStrength.
-        mCdmaDbm = ((cdmaDbm > 0) && (cdmaDbm < 120))  ? -cdmaDbm : Integer.MAX_VALUE;
-        mCdmaEcio = ((cdmaEcio > 0) && (cdmaEcio < 160)) ? -cdmaEcio : Integer.MAX_VALUE;
+        mCdmaDbm = ((cdmaDbm > 0) && (cdmaDbm < 120))  ? -cdmaDbm : CellInfo.UNAVAILABLE;
+        mCdmaEcio = ((cdmaEcio > 0) && (cdmaEcio < 160)) ? -cdmaEcio : CellInfo.UNAVAILABLE;
 
-        mEvdoDbm = ((evdoDbm > 0) && (evdoDbm < 120)) ? -evdoDbm : Integer.MAX_VALUE;
-        mEvdoEcio = ((evdoEcio > 0) && (evdoEcio < 160)) ? -evdoEcio : Integer.MAX_VALUE;
-        mEvdoSnr = ((evdoSnr > 0) && (evdoSnr <= 8)) ? evdoSnr : Integer.MAX_VALUE;
+        mEvdoDbm = ((evdoDbm > 0) && (evdoDbm < 120)) ? -evdoDbm : CellInfo.UNAVAILABLE;
+        mEvdoEcio = ((evdoEcio > 0) && (evdoEcio < 160)) ? -evdoEcio : CellInfo.UNAVAILABLE;
+        mEvdoSnr = ((evdoSnr > 0) && (evdoSnr <= 8)) ? evdoSnr : CellInfo.UNAVAILABLE;
     }
 
     /** @hide */
@@ -96,11 +97,11 @@
     /** @hide */
     @Override
     public void setDefaultValues() {
-        mCdmaDbm = Integer.MAX_VALUE;
-        mCdmaEcio = Integer.MAX_VALUE;
-        mEvdoDbm = Integer.MAX_VALUE;
-        mEvdoEcio = Integer.MAX_VALUE;
-        mEvdoSnr = Integer.MAX_VALUE;
+        mCdmaDbm = CellInfo.UNAVAILABLE;
+        mCdmaEcio = CellInfo.UNAVAILABLE;
+        mEvdoDbm = CellInfo.UNAVAILABLE;
+        mEvdoEcio = CellInfo.UNAVAILABLE;
+        mEvdoSnr = CellInfo.UNAVAILABLE;
     }
 
     /**
@@ -139,7 +140,7 @@
         int cdmaAsuLevel;
         int ecioAsuLevel;
 
-        if (cdmaDbm == Integer.MAX_VALUE) cdmaAsuLevel = 99;
+        if (cdmaDbm == CellInfo.UNAVAILABLE) cdmaAsuLevel = 99;
         else if (cdmaDbm >= -75) cdmaAsuLevel = 16;
         else if (cdmaDbm >= -82) cdmaAsuLevel = 8;
         else if (cdmaDbm >= -90) cdmaAsuLevel = 4;
@@ -148,7 +149,7 @@
         else cdmaAsuLevel = 99;
 
         // Ec/Io are in dB*10
-        if (cdmaEcio == Integer.MAX_VALUE) ecioAsuLevel = 99;
+        if (cdmaEcio == CellInfo.UNAVAILABLE) ecioAsuLevel = 99;
         else if (cdmaEcio >= -90) ecioAsuLevel = 16;
         else if (cdmaEcio >= -100) ecioAsuLevel = 8;
         else if (cdmaEcio >= -115) ecioAsuLevel = 4;
@@ -170,7 +171,7 @@
         int levelDbm;
         int levelEcio;
 
-        if (cdmaDbm == Integer.MAX_VALUE) levelDbm = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+        if (cdmaDbm == CellInfo.UNAVAILABLE) levelDbm = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
         else if (cdmaDbm >= -75) levelDbm = SIGNAL_STRENGTH_GREAT;
         else if (cdmaDbm >= -85) levelDbm = SIGNAL_STRENGTH_GOOD;
         else if (cdmaDbm >= -95) levelDbm = SIGNAL_STRENGTH_MODERATE;
@@ -178,7 +179,7 @@
         else levelDbm = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
 
         // Ec/Io are in dB*10
-        if (cdmaEcio == Integer.MAX_VALUE) levelEcio = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+        if (cdmaEcio == CellInfo.UNAVAILABLE) levelEcio = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
         else if (cdmaEcio >= -90) levelEcio = SIGNAL_STRENGTH_GREAT;
         else if (cdmaEcio >= -110) levelEcio = SIGNAL_STRENGTH_GOOD;
         else if (cdmaEcio >= -130) levelEcio = SIGNAL_STRENGTH_MODERATE;
@@ -199,14 +200,14 @@
         int levelEvdoDbm;
         int levelEvdoSnr;
 
-        if (evdoDbm == Integer.MAX_VALUE) levelEvdoDbm = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+        if (evdoDbm == CellInfo.UNAVAILABLE) levelEvdoDbm = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
         else if (evdoDbm >= -65) levelEvdoDbm = SIGNAL_STRENGTH_GREAT;
         else if (evdoDbm >= -75) levelEvdoDbm = SIGNAL_STRENGTH_GOOD;
         else if (evdoDbm >= -90) levelEvdoDbm = SIGNAL_STRENGTH_MODERATE;
         else if (evdoDbm >= -105) levelEvdoDbm = SIGNAL_STRENGTH_POOR;
         else levelEvdoDbm = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
 
-        if (evdoSnr == Integer.MAX_VALUE) levelEvdoSnr = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+        if (evdoSnr == CellInfo.UNAVAILABLE) levelEvdoSnr = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
         else if (evdoSnr >= 7) levelEvdoSnr = SIGNAL_STRENGTH_GREAT;
         else if (evdoSnr >= 5) levelEvdoSnr = SIGNAL_STRENGTH_GOOD;
         else if (evdoSnr >= 3) levelEvdoSnr = SIGNAL_STRENGTH_MODERATE;
diff --git a/telephony/java/android/telephony/CellSignalStrengthGsm.java b/telephony/java/android/telephony/CellSignalStrengthGsm.java
index 1e8d119..e906f46 100644
--- a/telephony/java/android/telephony/CellSignalStrengthGsm.java
+++ b/telephony/java/android/telephony/CellSignalStrengthGsm.java
@@ -40,7 +40,7 @@
     @UnsupportedAppUsage
     private int mBitErrorRate;   // bit error rate (0-7, 99) as defined in TS 27.007 8.5
     @UnsupportedAppUsage
-    private int mTimingAdvance; // range from 0-219 or Integer.MAX_VALUE if unknown
+    private int mTimingAdvance; // range from 0-219 or CellInfo.UNAVAILABLE if unknown
 
     /** @hide */
     @UnsupportedAppUsage
@@ -50,7 +50,7 @@
 
     /** @hide */
     public CellSignalStrengthGsm(int ss, int ber) {
-        this(ss, ber, Integer.MAX_VALUE);
+        this(ss, ber, CellInfo.UNAVAILABLE);
     }
 
     /** @hide */
@@ -81,9 +81,9 @@
     /** @hide */
     @Override
     public void setDefaultValues() {
-        mSignalStrength = Integer.MAX_VALUE;
-        mBitErrorRate = Integer.MAX_VALUE;
-        mTimingAdvance = Integer.MAX_VALUE;
+        mSignalStrength = CellInfo.UNAVAILABLE;
+        mBitErrorRate = CellInfo.UNAVAILABLE;
+        mTimingAdvance = CellInfo.UNAVAILABLE;
     }
 
     /**
@@ -112,8 +112,9 @@
 
     /**
      * Get the GSM timing advance between 0..219 symbols (normally 0..63).
-     * Integer.MAX_VALUE is reported when there is no RR connection.
-     * Refer to 3GPP 45.010 Sec 5.8
+     * <p>{@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} is reported when there is no RR
+     * connection. Refer to 3GPP 45.010 Sec 5.8.
+     *
      * @return the current GSM timing advance, if available.
      */
     public int getTimingAdvance() {
@@ -128,11 +129,11 @@
         int dBm;
 
         int level = mSignalStrength;
-        int asu = (level == 99 ? Integer.MAX_VALUE : level);
-        if (asu != Integer.MAX_VALUE) {
+        int asu = (level == 99 ? CellInfo.UNAVAILABLE : level);
+        if (asu != CellInfo.UNAVAILABLE) {
             dBm = -113 + (2 * asu);
         } else {
-            dBm = Integer.MAX_VALUE;
+            dBm = CellInfo.UNAVAILABLE;
         }
         if (DBG) log("getDbm=" + dBm);
         return dBm;
diff --git a/telephony/java/android/telephony/CellSignalStrengthLte.java b/telephony/java/android/telephony/CellSignalStrengthLte.java
index ed7d4b2..d6856b3 100644
--- a/telephony/java/android/telephony/CellSignalStrengthLte.java
+++ b/telephony/java/android/telephony/CellSignalStrengthLte.java
@@ -85,12 +85,12 @@
     /** @hide */
     @Override
     public void setDefaultValues() {
-        mSignalStrength = Integer.MAX_VALUE;
-        mRsrp = Integer.MAX_VALUE;
-        mRsrq = Integer.MAX_VALUE;
-        mRssnr = Integer.MAX_VALUE;
-        mCqi = Integer.MAX_VALUE;
-        mTimingAdvance = Integer.MAX_VALUE;
+        mSignalStrength = CellInfo.UNAVAILABLE;
+        mRsrp = CellInfo.UNAVAILABLE;
+        mRsrq = CellInfo.UNAVAILABLE;
+        mRssnr = CellInfo.UNAVAILABLE;
+        mCqi = CellInfo.UNAVAILABLE;
+        mTimingAdvance = CellInfo.UNAVAILABLE;
     }
 
     /**
@@ -104,26 +104,27 @@
         int levelRsrp = 0;
         int levelRssnr = 0;
 
-        if (mRsrp == Integer.MAX_VALUE) levelRsrp = 0;
+        if (mRsrp == CellInfo.UNAVAILABLE) levelRsrp = 0;
         else if (mRsrp >= -95) levelRsrp = SIGNAL_STRENGTH_GREAT;
         else if (mRsrp >= -105) levelRsrp = SIGNAL_STRENGTH_GOOD;
         else if (mRsrp >= -115) levelRsrp = SIGNAL_STRENGTH_MODERATE;
         else levelRsrp = SIGNAL_STRENGTH_POOR;
 
         // See RIL_LTE_SignalStrength in ril.h
-        if (mRssnr == Integer.MAX_VALUE) levelRssnr = 0;
+        if (mRssnr == CellInfo.UNAVAILABLE) levelRssnr = 0;
         else if (mRssnr >= 45) levelRssnr = SIGNAL_STRENGTH_GREAT;
         else if (mRssnr >= 10) levelRssnr = SIGNAL_STRENGTH_GOOD;
         else if (mRssnr >= -30) levelRssnr = SIGNAL_STRENGTH_MODERATE;
         else levelRssnr = SIGNAL_STRENGTH_POOR;
 
         int level;
-        if (mRsrp == Integer.MAX_VALUE)
+        if (mRsrp == CellInfo.UNAVAILABLE) {
             level = levelRssnr;
-        else if (mRssnr == Integer.MAX_VALUE)
+        } else if (mRssnr == CellInfo.UNAVAILABLE) {
             level = levelRsrp;
-        else
+        } else {
             level = (levelRssnr < levelRsrp) ? levelRssnr : levelRsrp;
+        }
 
         if (DBG) log("Lte rsrp level: " + levelRsrp
                 + " snr level: " + levelRssnr + " level: " + level);
@@ -133,7 +134,8 @@
     /**
      * Get reference signal received quality
      *
-     * @return the RSRQ if available or Integer.MAX_VALUE if unavailable.
+     * @return the RSRQ if available or
+     *         {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable.
      */
     public int getRsrq() {
         return mRsrq;
@@ -142,7 +144,8 @@
     /**
      * Get reference signal signal-to-noise ratio
      *
-     * @return the RSSNR if available or Integer.MAX_VALUE if unavailable.
+     * @return the RSSNR if available or
+     *         {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable.
      */
     public int getRssnr() {
         return mRssnr;
@@ -160,7 +163,8 @@
     /**
      * Get channel quality indicator
      *
-     * @return the CQI if available or Integer.MAX_VALUE if unavailable.
+     * @return the CQI if available or
+     *         {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable.
      */
     public int getCqi() {
         return mCqi;
@@ -184,7 +188,7 @@
     public int getAsuLevel() {
         int lteAsuLevel = 99;
         int lteDbm = getDbm();
-        if (lteDbm == Integer.MAX_VALUE) lteAsuLevel = 99;
+        if (lteDbm == CellInfo.UNAVAILABLE) lteAsuLevel = 99;
         else if (lteDbm <= -140) lteAsuLevel = 0;
         else if (lteDbm >= -43) lteAsuLevel = 97;
         else lteAsuLevel = lteDbm + 140;
@@ -194,10 +198,11 @@
 
     /**
      * Get the timing advance value for LTE, as a value in range of 0..1282.
-     * Integer.MAX_VALUE is reported when there is no active RRC
-     * connection. Refer to 3GPP 36.213 Sec 4.2.3
+     * {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} is reported when there is no
+     * active RRC connection. Refer to 3GPP 36.213 Sec 4.2.3
      *
-     * @return the LTE timing advance if available or Integer.MAX_VALUE if unavailable.
+     * @return the LTE timing advance if available or
+     *         {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable.
      */
     public int getTimingAdvance() {
         return mTimingAdvance;
@@ -252,8 +257,8 @@
         // Need to multiply rsrp and rsrq by -1
         // to ensure consistency when reading values written here
         // unless the values are invalid
-        dest.writeInt(mRsrp * (mRsrp != Integer.MAX_VALUE ? -1 : 1));
-        dest.writeInt(mRsrq * (mRsrq != Integer.MAX_VALUE ? -1 : 1));
+        dest.writeInt(mRsrp * (mRsrp != CellInfo.UNAVAILABLE ? -1 : 1));
+        dest.writeInt(mRsrq * (mRsrq != CellInfo.UNAVAILABLE ? -1 : 1));
         dest.writeInt(mRssnr);
         dest.writeInt(mCqi);
         dest.writeInt(mTimingAdvance);
@@ -268,9 +273,9 @@
         // rsrp and rsrq are written into the parcel as positive values.
         // Need to convert into negative values unless the values are invalid
         mRsrp = in.readInt();
-        if (mRsrp != Integer.MAX_VALUE) mRsrp *= -1;
+        if (mRsrp != CellInfo.UNAVAILABLE) mRsrp *= -1;
         mRsrq = in.readInt();
-        if (mRsrq != Integer.MAX_VALUE) mRsrq *= -1;
+        if (mRsrq != CellInfo.UNAVAILABLE) mRsrq *= -1;
         mRssnr = in.readInt();
         mCqi = in.readInt();
         mTimingAdvance = in.readInt();
diff --git a/telephony/java/android/telephony/CellSignalStrengthTdscdma.java b/telephony/java/android/telephony/CellSignalStrengthTdscdma.java
index 41859a3..4d040cc 100644
--- a/telephony/java/android/telephony/CellSignalStrengthTdscdma.java
+++ b/telephony/java/android/telephony/CellSignalStrengthTdscdma.java
@@ -36,11 +36,11 @@
     private static final int TDSCDMA_SIGNAL_STRENGTH_MODERATE = 5;
 
     private int mSignalStrength; // in ASU; Valid values are (0-31, 99) as defined in TS 27.007 8.5
-                                 // or Integer.MAX_VALUE if unknown
+                                 // or CellInfo.UNAVAILABLE if unknown
     private int mBitErrorRate; // bit error rate (0-7, 99) as defined in TS 27.007 8.5 or
-                               // Integer.MAX_VALUE if unknown
-    private int mRscp; // Pilot power (0-96, 255) as defined in TS 27.007 8.69 or Integer.MAX_VALUE
-                       // if unknown
+                               // CellInfo.UNAVAILABLE if unknown
+    private int mRscp; // Pilot power (0-96, 255) as defined in TS 27.007 8.69 or
+                       // CellInfo.UNAVAILABLE if unknown
 
     /** @hide */
     public CellSignalStrengthTdscdma() {
@@ -75,9 +75,9 @@
     /** @hide */
     @Override
     public void setDefaultValues() {
-        mSignalStrength = Integer.MAX_VALUE;
-        mBitErrorRate = Integer.MAX_VALUE;
-        mRscp = Integer.MAX_VALUE;
+        mSignalStrength = CellInfo.UNAVAILABLE;
+        mBitErrorRate = CellInfo.UNAVAILABLE;
+        mRscp = CellInfo.UNAVAILABLE;
     }
 
     /**
@@ -118,11 +118,11 @@
         int dBm;
 
         int level = mSignalStrength;
-        int asu = (level == 99 ? Integer.MAX_VALUE : level);
-        if (asu != Integer.MAX_VALUE) {
+        int asu = (level == 99 ? CellInfo.UNAVAILABLE : level);
+        if (asu != CellInfo.UNAVAILABLE) {
             dBm = -113 + (2 * asu);
         } else {
-            dBm = Integer.MAX_VALUE;
+            dBm = CellInfo.UNAVAILABLE;
         }
         if (DBG) log("getDbm=" + dBm);
         return dBm;
diff --git a/telephony/java/android/telephony/CellSignalStrengthWcdma.java b/telephony/java/android/telephony/CellSignalStrengthWcdma.java
index 66e0882..0048cbd 100644
--- a/telephony/java/android/telephony/CellSignalStrengthWcdma.java
+++ b/telephony/java/android/telephony/CellSignalStrengthWcdma.java
@@ -37,14 +37,14 @@
 
     @UnsupportedAppUsage
     private int mSignalStrength; // in ASU; Valid values are (0-31, 99) as defined in TS 27.007 8.5
-                                 // or Integer.MAX_VALUE if unknown
+                                 // or CellInfo.UNAVAILABLE if unknown
     @UnsupportedAppUsage
     private int mBitErrorRate; // bit error rate (0-7, 99) as defined in TS 27.007 8.5 or
-                               // Integer.MAX_VALUE if unknown
+                               // CellInfo.UNAVAILABLE if unknown
     private int mRscp; // bit error rate (0-96, 255) as defined in TS 27.007 8.69 or
-                       // Integer.MAX_VALUE if unknown
+                       // CellInfo.UNAVAILABLE if unknown
     private int mEcNo; // signal to noise radio (0-49, 255) as defined in TS 27.007 8.69 or
-                       // Integer.MAX_VALUE if unknown
+                       // CellInfo.UNAVAILABLE if unknown
 
     /** @hide */
     public CellSignalStrengthWcdma() {
@@ -81,10 +81,10 @@
     /** @hide */
     @Override
     public void setDefaultValues() {
-        mSignalStrength = Integer.MAX_VALUE;
-        mBitErrorRate = Integer.MAX_VALUE;
-        mRscp = Integer.MAX_VALUE;
-        mEcNo = Integer.MAX_VALUE;
+        mSignalStrength = CellInfo.UNAVAILABLE;
+        mBitErrorRate = CellInfo.UNAVAILABLE;
+        mRscp = CellInfo.UNAVAILABLE;
+        mEcNo = CellInfo.UNAVAILABLE;
     }
 
     /**
@@ -119,11 +119,11 @@
         int dBm;
 
         int level = mSignalStrength;
-        int asu = (level == 99 ? Integer.MAX_VALUE : level);
-        if (asu != Integer.MAX_VALUE) {
+        int asu = (level == 99 ? CellInfo.UNAVAILABLE : level);
+        if (asu != CellInfo.UNAVAILABLE) {
             dBm = -113 + (2 * asu);
         } else {
-            dBm = Integer.MAX_VALUE;
+            dBm = CellInfo.UNAVAILABLE;
         }
         if (DBG) log("getDbm=" + dBm);
         return dBm;
diff --git a/telephony/java/android/telephony/NetworkRegistrationState.java b/telephony/java/android/telephony/NetworkRegistrationState.java
index b312f84..c3d8898 100644
--- a/telephony/java/android/telephony/NetworkRegistrationState.java
+++ b/telephony/java/android/telephony/NetworkRegistrationState.java
@@ -102,7 +102,7 @@
     @ServiceState.RoamingType
     private int mRoamingType;
 
-    private final int mAccessNetworkTechnology;
+    private int mAccessNetworkTechnology;
 
     private final int mRejectCause;
 
@@ -256,13 +256,21 @@
     public int[] getAvailableServices() { return mAvailableServices; }
 
     /**
-     * @return The access network technology. Must be one of TelephonyManager.NETWORK_TYPE_XXXX.
+     * @return The access network technology {@link TelephonyManager.NetworkType}.
      */
-    public int getAccessNetworkTechnology() {
+    public @TelephonyManager.NetworkType int getAccessNetworkTechnology() {
         return mAccessNetworkTechnology;
     }
 
     /**
+     * override the access network technology {@link TelephonyManager.NetworkType} e.g, rat ratchet.
+     * @hide
+     */
+    public void setAccessNetworkTechnology(@TelephonyManager.NetworkType int tech) {
+        mAccessNetworkTechnology = tech;
+    }
+
+    /**
      * @return Network reject cause
      */
     public int getRejectCause() {
diff --git a/telephony/java/android/telephony/RadioAccessFamily.java b/telephony/java/android/telephony/RadioAccessFamily.java
index 1d79988..da3acc2 100644
--- a/telephony/java/android/telephony/RadioAccessFamily.java
+++ b/telephony/java/android/telephony/RadioAccessFamily.java
@@ -29,29 +29,32 @@
  */
 public class RadioAccessFamily implements Parcelable {
 
-    // Radio Access Family
+    /**
+     * TODO: get rid of RAF definition in RadioAccessFamily and
+     * use {@link TelephonyManager.NetworkTypeBitMask}
+     */
     // 2G
-    public static final int RAF_UNKNOWN = (1 <<  ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN);
-    public static final int RAF_GSM = (1 << ServiceState.RIL_RADIO_TECHNOLOGY_GSM);
-    public static final int RAF_GPRS = (1 << ServiceState.RIL_RADIO_TECHNOLOGY_GPRS);
-    public static final int RAF_EDGE = (1 << ServiceState.RIL_RADIO_TECHNOLOGY_EDGE);
-    public static final int RAF_IS95A = (1 << ServiceState.RIL_RADIO_TECHNOLOGY_IS95A);
-    public static final int RAF_IS95B = (1 << ServiceState.RIL_RADIO_TECHNOLOGY_IS95B);
-    public static final int RAF_1xRTT = (1 << ServiceState.RIL_RADIO_TECHNOLOGY_1xRTT);
+    public static final int RAF_UNKNOWN = TelephonyManager.NETWORK_TYPE_BITMASK_UNKNOWN;
+    public static final int RAF_GSM = TelephonyManager.NETWORK_TYPE_BITMASK_GSM;
+    public static final int RAF_GPRS = TelephonyManager.NETWORK_TYPE_BITMASK_GPRS;
+    public static final int RAF_EDGE = TelephonyManager.NETWORK_TYPE_BITMASK_EDGE;
+    public static final int RAF_IS95A = TelephonyManager.NETWORK_TYPE_BITMASK_CDMA;
+    public static final int RAF_IS95B = TelephonyManager.NETWORK_TYPE_BITMASK_CDMA;
+    public static final int RAF_1xRTT = TelephonyManager.NETWORK_TYPE_BITMASK_1xRTT;
     // 3G
-    public static final int RAF_EVDO_0 = (1 << ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_0);
-    public static final int RAF_EVDO_A = (1 << ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_A);
-    public static final int RAF_EVDO_B = (1 << ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_B);
-    public static final int RAF_EHRPD = (1 << ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD);
-    public static final int RAF_HSUPA = (1 << ServiceState.RIL_RADIO_TECHNOLOGY_HSUPA);
-    public static final int RAF_HSDPA = (1 << ServiceState.RIL_RADIO_TECHNOLOGY_HSDPA);
-    public static final int RAF_HSPA = (1 << ServiceState.RIL_RADIO_TECHNOLOGY_HSPA);
-    public static final int RAF_HSPAP = (1 << ServiceState.RIL_RADIO_TECHNOLOGY_HSPAP);
-    public static final int RAF_UMTS = (1 << ServiceState.RIL_RADIO_TECHNOLOGY_UMTS);
-    public static final int RAF_TD_SCDMA = (1 << ServiceState.RIL_RADIO_TECHNOLOGY_TD_SCDMA);
+    public static final int RAF_EVDO_0 = TelephonyManager.NETWORK_TYPE_BITMASK_EVDO_0;
+    public static final int RAF_EVDO_A = TelephonyManager.NETWORK_TYPE_BITMASK_EVDO_A;
+    public static final int RAF_EVDO_B = TelephonyManager.NETWORK_TYPE_BITMASK_EVDO_B;
+    public static final int RAF_EHRPD = TelephonyManager.NETWORK_TYPE_BITMASK_EHRPD;
+    public static final int RAF_HSUPA = TelephonyManager.NETWORK_TYPE_BITMASK_HSUPA;
+    public static final int RAF_HSDPA = TelephonyManager.NETWORK_TYPE_BITMASK_HSDPA;
+    public static final int RAF_HSPA = TelephonyManager.NETWORK_TYPE_BITMASK_HSPA;
+    public static final int RAF_HSPAP = TelephonyManager.NETWORK_TYPE_BITMASK_HSPAP;
+    public static final int RAF_UMTS = TelephonyManager.NETWORK_TYPE_BITMASK_UMTS;
+    public static final int RAF_TD_SCDMA = TelephonyManager.NETWORK_TYPE_BITMASK_TD_SCDMA;
     // 4G
-    public static final int RAF_LTE = (1 << ServiceState.RIL_RADIO_TECHNOLOGY_LTE);
-    public static final int RAF_LTE_CA = (1 << ServiceState.RIL_RADIO_TECHNOLOGY_LTE_CA);
+    public static final int RAF_LTE = TelephonyManager.NETWORK_TYPE_BITMASK_LTE;
+    public static final int RAF_LTE_CA = TelephonyManager.NETWORK_TYPE_BITMASK_LTE_CA;
 
     // Grouping of RAFs
     // 2G
@@ -74,9 +77,9 @@
      * Constructor.
      *
      * @param phoneId the phone ID
-     * @param radioAccessFamily the phone radio access family defined
-     *        in RadioAccessFamily. It's a bit mask value to represent
-     *        the support type.
+     * @param radioAccessFamily the phone radio access family bitmask based on
+     * {@link TelephonyManager.NetworkTypeBitMask}. It's a bit mask value to represent the support
+     *                          type.
      */
     @UnsupportedAppUsage
     public RadioAccessFamily(int phoneId, int radioAccessFamily) {
@@ -100,7 +103,7 @@
      * @return radio access family
      */
     @UnsupportedAppUsage
-    public int getRadioAccessFamily() {
+    public @TelephonyManager.NetworkTypeBitMask int getRadioAccessFamily() {
         return mRadioAccessFamily;
     }
 
@@ -388,4 +391,76 @@
         }
         return result;
     }
+
+    /**
+     * convert RAF from {@link ServiceState.RilRadioTechnology} bitmask to
+     * {@link TelephonyManager.NetworkTypeBitMask}, the bitmask represented by
+     * {@link TelephonyManager.NetworkType}. Reasons are {@link TelephonyManager.NetworkType} are
+     * public while {@link ServiceState.RilRadioTechnology} are hidden. We
+     * don't want to expose two sets of definition to public.
+     *
+     * @param raf bitmask represented by {@link ServiceState.RilRadioTechnology}
+     * @return {@link TelephonyManager.NetworkTypeBitMask}
+     */
+    public static int convertToNetworkTypeBitMask(int raf) {
+        int networkTypeRaf = 0;
+
+        if ((raf & (1 << ServiceState.RIL_RADIO_TECHNOLOGY_GSM)) != 0) {
+            networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_GSM;
+        }
+        if ((raf & (1 << ServiceState.RIL_RADIO_TECHNOLOGY_GPRS)) != 0) {
+            networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_GPRS;
+        }
+        if ((raf & (1 << ServiceState.RIL_RADIO_TECHNOLOGY_EDGE)) != 0) {
+            networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_EDGE;
+        }
+        // convert both IS95A/IS95B to CDMA as network mode doesn't support CDMA
+        if ((raf & (1 << ServiceState.RIL_RADIO_TECHNOLOGY_IS95A)) != 0) {
+            networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_CDMA;
+        }
+        if ((raf & (1 << ServiceState.RIL_RADIO_TECHNOLOGY_IS95B)) != 0) {
+            networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_CDMA;
+        }
+        if ((raf & (1 << ServiceState.RIL_RADIO_TECHNOLOGY_1xRTT)) != 0) {
+            networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_1xRTT;
+        }
+        if ((raf & (1 << ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_0)) != 0) {
+            networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_EVDO_0;
+        }
+        if ((raf & (1 << ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_A)) != 0) {
+            networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_EVDO_A;
+        }
+        if ((raf & (1 << ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_B)) != 0) {
+            networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_EVDO_B;
+        }
+        if ((raf & (1 << ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD)) != 0) {
+            networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_EHRPD;
+        }
+        if ((raf & (1 << ServiceState.RIL_RADIO_TECHNOLOGY_HSUPA)) != 0) {
+            networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_HSUPA;
+        }
+        if ((raf & (1 << ServiceState.RIL_RADIO_TECHNOLOGY_HSDPA)) != 0) {
+            networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_HSDPA;
+        }
+        if ((raf & (1 << ServiceState.RIL_RADIO_TECHNOLOGY_HSPA)) != 0) {
+            networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_HSPA;
+        }
+        if ((raf & (1 << ServiceState.RIL_RADIO_TECHNOLOGY_HSPAP)) != 0) {
+            networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_HSPAP;
+        }
+        if ((raf & (1 << ServiceState.RIL_RADIO_TECHNOLOGY_UMTS)) != 0) {
+            networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_UMTS;
+        }
+        if ((raf & (1 << ServiceState.RIL_RADIO_TECHNOLOGY_TD_SCDMA)) != 0) {
+            networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_TD_SCDMA;
+        }
+        if ((raf & (1 << ServiceState.RIL_RADIO_TECHNOLOGY_LTE)) != 0) {
+            networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_LTE;
+        }
+        if ((raf & (1 << ServiceState.RIL_RADIO_TECHNOLOGY_LTE_CA)) != 0) {
+            networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_LTE_CA;
+        }
+
+        return (networkTypeRaf == 0) ? TelephonyManager.NETWORK_TYPE_UNKNOWN : networkTypeRaf;
+    }
 }
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index e0ec2c5..c407681 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -21,6 +21,7 @@
 import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
 import android.content.Intent;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -246,19 +247,28 @@
     private String mDataOperatorAlphaLong;
     private String mDataOperatorAlphaShort;
     private String mDataOperatorNumeric;
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     private boolean mIsManualNetworkSelection;
 
     private boolean mIsEmergencyOnly;
-
+    /**
+     * TODO: remove mRilVoiceRadioTechnology after completely migrate to
+     * {@link TelephonyManager.NetworkType}
+     */
+    @RilRadioTechnology
     private int mRilVoiceRadioTechnology;
+    /**
+     * TODO: remove mRilDataRadioTechnology after completely migrate to
+     * {@link TelephonyManager.NetworkType}
+     */
+    @RilRadioTechnology
     private int mRilDataRadioTechnology;
 
     @UnsupportedAppUsage
     private boolean mCssIndicator;
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     private int mNetworkId;
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     private int mSystemId;
     @UnsupportedAppUsage
     private int mCdmaRoamingIndicator;
@@ -456,7 +466,7 @@
      *
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     public int getVoiceRegState() {
         return mVoiceRegState;
     }
@@ -471,7 +481,7 @@
      *
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     public int getDataRegState() {
         return mDataRegState;
     }
@@ -532,7 +542,7 @@
      * @return roaming status
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     public boolean getVoiceRoaming() {
         return getVoiceRoamingType() != ROAMING_TYPE_NOT_ROAMING;
     }
@@ -556,7 +566,7 @@
      * @return roaming type
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     public boolean getDataRoaming() {
         return getDataRoamingType() != ROAMING_TYPE_NOT_ROAMING;
     }
@@ -1218,17 +1228,30 @@
 
     /** @hide */
     @TestApi
-    public void setRilVoiceRadioTechnology(int rt) {
+    public void setRilVoiceRadioTechnology(@RilRadioTechnology int rt) {
         if (rt == RIL_RADIO_TECHNOLOGY_LTE_CA) {
             rt = RIL_RADIO_TECHNOLOGY_LTE;
         }
 
         this.mRilVoiceRadioTechnology = rt;
+
+        // sync to network registration state
+        NetworkRegistrationState regState = getNetworkRegistrationState(
+                NetworkRegistrationState.DOMAIN_CS, AccessNetworkConstants.TransportType.WWAN);
+        if (regState == null) {
+            regState = new NetworkRegistrationState(
+                    NetworkRegistrationState.DOMAIN_CS, AccessNetworkConstants.TransportType.WWAN,
+                    ServiceState.ROAMING_TYPE_NOT_ROAMING, TelephonyManager.NETWORK_TYPE_UNKNOWN,
+                    0, false, null, null);
+            addNetworkRegistrationState(regState);
+        }
+        regState.setAccessNetworkTechnology(
+                rilRadioTechnologyToNetworkType(mRilVoiceRadioTechnology));
     }
 
     /** @hide */
     @TestApi
-    public void setRilDataRadioTechnology(int rt) {
+    public void setRilDataRadioTechnology(@RilRadioTechnology int rt) {
         if (rt == RIL_RADIO_TECHNOLOGY_LTE_CA) {
             rt = RIL_RADIO_TECHNOLOGY_LTE;
             this.mIsUsingCarrierAggregation = true;
@@ -1238,6 +1261,20 @@
         this.mRilDataRadioTechnology = rt;
         if (VDBG) Rlog.d(LOG_TAG, "[ServiceState] setRilDataRadioTechnology=" +
                 mRilDataRadioTechnology);
+
+        // sync to network registration state
+        NetworkRegistrationState regState = getNetworkRegistrationState(
+                NetworkRegistrationState.DOMAIN_PS, AccessNetworkConstants.TransportType.WWAN);
+
+        if (regState == null) {
+            regState = new NetworkRegistrationState(
+                    NetworkRegistrationState.DOMAIN_PS, AccessNetworkConstants.TransportType.WWAN,
+                    ServiceState.ROAMING_TYPE_NOT_ROAMING, TelephonyManager.NETWORK_TYPE_UNKNOWN,
+                    0, false, null, null);
+            addNetworkRegistrationState(regState);
+        }
+        regState.setAccessNetworkTechnology(
+                rilRadioTechnologyToNetworkType(mRilDataRadioTechnology));
     }
 
     /** @hide */
@@ -1418,15 +1455,25 @@
 
 
     /** @hide */
-    @UnsupportedAppUsage
-    public int getDataNetworkType() {
-        return rilRadioTechnologyToNetworkType(mRilDataRadioTechnology);
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+    public @TelephonyManager.NetworkType int getDataNetworkType() {
+        final NetworkRegistrationState regState = getNetworkRegistrationState(
+                NetworkRegistrationState.DOMAIN_PS, AccessNetworkConstants.TransportType.WWAN);
+        if (regState != null) {
+            return regState.getAccessNetworkTechnology();
+        }
+        return TelephonyManager.NETWORK_TYPE_UNKNOWN;
     }
 
     /** @hide */
-    @UnsupportedAppUsage
-    public int getVoiceNetworkType() {
-        return rilRadioTechnologyToNetworkType(mRilVoiceRadioTechnology);
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+    public @TelephonyManager.NetworkType int getVoiceNetworkType() {
+        final NetworkRegistrationState regState = getNetworkRegistrationState(
+                NetworkRegistrationState.DOMAIN_CS, AccessNetworkConstants.TransportType.WWAN);
+        if (regState != null) {
+            return regState.getAccessNetworkTechnology();
+        }
+        return TelephonyManager.NETWORK_TYPE_UNKNOWN;
     }
 
     /** @hide */
diff --git a/telephony/java/android/telephony/SignalStrength.java b/telephony/java/android/telephony/SignalStrength.java
index ed758a9..fb801b2 100644
--- a/telephony/java/android/telephony/SignalStrength.java
+++ b/telephony/java/android/telephony/SignalStrength.java
@@ -21,8 +21,8 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.telephony.CarrierConfigManager;
+import android.text.TextUtils;
 import android.util.Log;
-import android.content.res.Resources;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -1116,7 +1116,7 @@
     public int getWcdmaLevel() {
         int level = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
 
-        if (mWcdmaDefaultSignalMeasurement == null) {
+        if (TextUtils.isEmpty(mWcdmaDefaultSignalMeasurement)) {
             Log.wtf(LOG_TAG, "getWcdmaLevel - WCDMA default signal measurement is invalid.");
             return level;
         }
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 7f87c4d..0ba18ee 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -43,6 +43,7 @@
 import android.net.INetworkPolicyManager;
 import android.net.NetworkCapabilities;
 import android.net.Uri;
+import android.os.Binder;
 import android.os.Build;
 import android.os.Handler;
 import android.os.Looper;
@@ -781,8 +782,13 @@
         IOnSubscriptionsChangedListener callback = new IOnSubscriptionsChangedListener.Stub() {
             @Override
             public void onSubscriptionsChanged() {
-                if (DBG) log("onOpportunisticSubscriptionsChanged callback received.");
-                mExecutor.execute(() -> onOpportunisticSubscriptionsChanged());
+                final long identity = Binder.clearCallingIdentity();
+                try {
+                    if (DBG) log("onOpportunisticSubscriptionsChanged callback received.");
+                    mExecutor.execute(() -> onOpportunisticSubscriptionsChanged());
+                } finally {
+                    Binder.restoreCallingIdentity(identity);
+                }
             }
         };
 
@@ -1341,6 +1347,7 @@
      * @param slotIndex the slot Index.
      * @return subscription Ids or null if the given slot Index is not valid.
      */
+    @Nullable
     public static int[] getSubscriptionIds(int slotIndex) {
         return getSubId(slotIndex);
     }
@@ -1368,7 +1375,7 @@
     }
 
     /** @hide */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     public static int getPhoneId(int subId) {
         if (!isValidSubscriptionId(subId)) {
             if (DBG) {
@@ -1664,7 +1671,7 @@
      * usable subId means its neither a INVALID_SUBSCRIPTION_ID nor a DEFAULT_SUB_ID.
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     public static boolean isUsableSubIdValue(int subId) {
         return subId >= MIN_SUBSCRIPTION_ID_VALUE && subId <= MAX_SUBSCRIPTION_ID_VALUE;
     }
@@ -1682,7 +1689,7 @@
     }
 
     /** @hide */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     public static void putPhoneIdAndSubIdExtra(Intent intent, int phoneId) {
         int[] subIds = SubscriptionManager.getSubId(phoneId);
         if (subIds != null && subIds.length > 0) {
@@ -2228,22 +2235,27 @@
     }
 
     /**
-     * Get opportunistic data Profiles.
+     * Return opportunistic subscriptions that can be visible to the caller.
+     * Opportunistic subscriptions are for opportunistic networks, which are cellular
+     * networks with limited capabilities and coverage, for example, CBRS.
      *
-     *  Provide all available user downloaded profiles on phone which are used only for
-     *  opportunistic data.
-     *  @param slotIndex slot on which the profiles are queried from.
-     *  @return the list of opportunistic subscription info. If none exists, an empty list. 
+     * <p>Requires Permission:
+     * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+     * or that the calling app has carrier privileges (see
+     * {@link TelephonyManager#hasCarrierPrivileges}).
+     *
+     * @return the list of opportunistic subscription info. If none exists, an empty list.
      */
+    @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
-    public @NonNull List<SubscriptionInfo> getOpportunisticSubscriptions(int slotIndex) {
+    public @NonNull List<SubscriptionInfo> getOpportunisticSubscriptions() {
         String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
         List<SubscriptionInfo> subInfoList = null;
 
         try {
             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
             if (iSub != null) {
-                subInfoList = iSub.getOpportunisticSubscriptions(slotIndex, pkgForDebug);
+                subInfoList = iSub.getOpportunisticSubscriptions(pkgForDebug);
             }
         } catch (RemoteException ex) {
             // ignore it
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 69901d2..f484d1f 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -232,7 +232,8 @@
 
     /** @hide
     /* @deprecated - use getSystemService as described above */
-    @UnsupportedAppUsage
+    @Deprecated
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     public static TelephonyManager getDefault() {
         return sInstance;
     }
@@ -321,7 +322,7 @@
     }
 
     /** {@hide} */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     public static TelephonyManager from(Context context) {
         return (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
     }
@@ -1949,7 +1950,7 @@
      * @param subId
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     public String getNetworkOperatorName(int subId) {
         int phoneId = SubscriptionManager.getPhoneId(subId);
         return getTelephonyProperty(phoneId, TelephonyProperties.PROPERTY_OPERATOR_ALPHA, "");
@@ -1977,7 +1978,7 @@
      * @param subId
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     public String getNetworkOperator(int subId) {
         int phoneId = SubscriptionManager.getPhoneId(subId);
         return getNetworkOperatorForPhone(phoneId);
@@ -2301,7 +2302,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     public int getDataNetworkType(int subId) {
         try{
             ITelephony telephony = getITelephony();
@@ -2337,7 +2338,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     public int getVoiceNetworkType(int subId) {
         try{
             ITelephony telephony = getITelephony();
@@ -2820,7 +2821,7 @@
      * @param subId for which SimOperator is returned
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     public String getSimOperator(int subId) {
         return getSimOperatorNumeric(subId);
     }
@@ -2834,7 +2835,7 @@
      * @see #getSimState
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     public String getSimOperatorNumeric() {
         int subId = mSubId;
         if (!SubscriptionManager.isUsableSubIdValue(subId)) {
@@ -2863,7 +2864,7 @@
      * @param subId for which SimOperator is returned
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     public String getSimOperatorNumeric(int subId) {
         int phoneId = SubscriptionManager.getPhoneId(subId);
         return getSimOperatorNumericForPhone(phoneId);
@@ -2877,7 +2878,7 @@
      * @param phoneId for which SimOperator is returned
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     public String getSimOperatorNumericForPhone(int phoneId) {
         return getTelephonyProperty(phoneId,
                 TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC, "");
@@ -2904,7 +2905,7 @@
      * @param subId for which SimOperatorName is returned
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     public String getSimOperatorName(int subId) {
         int phoneId = SubscriptionManager.getPhoneId(subId);
         return getSimOperatorNameForPhone(phoneId);
@@ -2934,7 +2935,7 @@
      * @param subId for which SimCountryIso is returned
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     public String getSimCountryIso(int subId) {
         int phoneId = SubscriptionManager.getPhoneId(subId);
         return getSimCountryIsoForPhone(phoneId);
@@ -3146,7 +3147,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     public String getSubscriberId(int subId) {
         try {
             IPhoneSubInfo info = getSubscriberInfo();
@@ -3531,7 +3532,7 @@
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     public String getMsisdn(int subId) {
         try {
             IPhoneSubInfo info = getSubscriberInfo();
@@ -4464,7 +4465,7 @@
    /**
     * @hide
     */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     private ITelephony getITelephony() {
         return ITelephony.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_SERVICE));
     }
@@ -6619,7 +6620,7 @@
     }
 
     /**
-     * @removed Use {@link android.telecom.TelecomManager#isInCall} instead
+     * @deprecated Use {@link android.telecom.TelecomManager#isInCall} instead
      * @hide
      */
     @Deprecated
@@ -6629,11 +6630,12 @@
             android.Manifest.permission.READ_PHONE_STATE
     })
     public boolean isOffhook() {
-        return false;
+        TelecomManager tm = (TelecomManager) mContext.getSystemService(TELECOM_SERVICE);
+        return tm.isInCall();
     }
 
     /**
-     * @removed Use {@link android.telecom.TelecomManager#isRinging} instead
+     * @deprecated Use {@link android.telecom.TelecomManager#isRinging} instead
      * @hide
      */
     @Deprecated
@@ -6643,11 +6645,12 @@
             android.Manifest.permission.READ_PHONE_STATE
     })
     public boolean isRinging() {
-        return false;
+        TelecomManager tm = (TelecomManager) mContext.getSystemService(TELECOM_SERVICE);
+        return tm.isRinging();
     }
 
     /**
-     * @removed Use {@link android.telecom.TelecomManager#isInCall} instead
+     * @deprecated Use {@link android.telecom.TelecomManager#isInCall} instead
      * @hide
      */
     @Deprecated
@@ -6657,7 +6660,8 @@
             android.Manifest.permission.READ_PHONE_STATE
     })
     public boolean isIdle() {
-        return true;
+        TelecomManager tm = (TelecomManager) mContext.getSystemService(TELECOM_SERVICE);
+        return !tm.isInCall();
     }
 
     /**
@@ -8044,7 +8048,7 @@
      * either READ_PRIVILEGED_PHONE_STATE or READ_PHONE_STATE to retrieve the information.
      * @hide
      */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     public ServiceState getServiceStateForSubscriber(int subId) {
         try {
             ITelephony service = getITelephony();
@@ -8816,4 +8820,168 @@
 
         return isEnabled;
     }
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(flag = true, prefix = {"NETWORK_TYPE_BITMASK_"},
+            value = {NETWORK_TYPE_BITMASK_UNKNOWN,
+                    NETWORK_TYPE_BITMASK_GSM,
+                    NETWORK_TYPE_BITMASK_GPRS,
+                    NETWORK_TYPE_BITMASK_EDGE,
+                    NETWORK_TYPE_BITMASK_CDMA,
+                    NETWORK_TYPE_BITMASK_1xRTT,
+                    NETWORK_TYPE_BITMASK_EVDO_0,
+                    NETWORK_TYPE_BITMASK_EVDO_A,
+                    NETWORK_TYPE_BITMASK_EVDO_B,
+                    NETWORK_TYPE_BITMASK_EHRPD,
+                    NETWORK_TYPE_BITMASK_HSUPA,
+                    NETWORK_TYPE_BITMASK_HSDPA,
+                    NETWORK_TYPE_BITMASK_HSPA,
+                    NETWORK_TYPE_BITMASK_HSPAP,
+                    NETWORK_TYPE_BITMASK_UMTS,
+                    NETWORK_TYPE_BITMASK_TD_SCDMA,
+                    NETWORK_TYPE_BITMASK_LTE,
+                    NETWORK_TYPE_BITMASK_LTE_CA,
+            })
+    public @interface NetworkTypeBitMask {}
+
+    // 2G
+    /**
+     * network type bitmask unknown.
+     * @hide
+     */
+    @SystemApi
+    public static final int NETWORK_TYPE_BITMASK_UNKNOWN = (1 << NETWORK_TYPE_UNKNOWN);
+    /**
+     * network type bitmask indicating the support of radio tech GSM.
+     * @hide
+     */
+    @SystemApi
+    public static final int NETWORK_TYPE_BITMASK_GSM = (1 << NETWORK_TYPE_GSM);
+    /**
+     * network type bitmask indicating the support of radio tech GPRS.
+     * @hide
+     */
+    @SystemApi
+    public static final int NETWORK_TYPE_BITMASK_GPRS = (1 << NETWORK_TYPE_GPRS);
+    /**
+     * network type bitmask indicating the support of radio tech EDGE.
+     * @hide
+     */
+    @SystemApi
+    public static final int NETWORK_TYPE_BITMASK_EDGE = (1 << NETWORK_TYPE_EDGE);
+    /**
+     * network type bitmask indicating the support of radio tech CDMA(IS95A/IS95B).
+     * @hide
+     */
+    @SystemApi
+    public static final int NETWORK_TYPE_BITMASK_CDMA = (1 << NETWORK_TYPE_CDMA);
+    /**
+     * network type bitmask indicating the support of radio tech 1xRTT.
+     * @hide
+     */
+    @SystemApi
+    public static final int NETWORK_TYPE_BITMASK_1xRTT = (1 << NETWORK_TYPE_1xRTT);
+    // 3G
+    /**
+     * network type bitmask indicating the support of radio tech EVDO 0.
+     * @hide
+     */
+    @SystemApi
+    public static final int NETWORK_TYPE_BITMASK_EVDO_0 = (1 << NETWORK_TYPE_EVDO_0);
+    /**
+     * network type bitmask indicating the support of radio tech EVDO A.
+     * @hide
+     */
+    @SystemApi
+    public static final int NETWORK_TYPE_BITMASK_EVDO_A = (1 << NETWORK_TYPE_EVDO_A);
+    /**
+     * network type bitmask indicating the support of radio tech EVDO B.
+     * @hide
+     */
+    @SystemApi
+    public static final int NETWORK_TYPE_BITMASK_EVDO_B = (1 << NETWORK_TYPE_EVDO_B);
+    /**
+     * network type bitmask indicating the support of radio tech EHRPD.
+     * @hide
+     */
+    @SystemApi
+    public static final int NETWORK_TYPE_BITMASK_EHRPD = (1 << NETWORK_TYPE_EHRPD);
+    /**
+     * network type bitmask indicating the support of radio tech HSUPA.
+     * @hide
+     */
+    @SystemApi
+    public static final int NETWORK_TYPE_BITMASK_HSUPA = (1 << NETWORK_TYPE_HSUPA);
+    /**
+     * network type bitmask indicating the support of radio tech HSDPA.
+     * @hide
+     */
+    @SystemApi
+    public static final int NETWORK_TYPE_BITMASK_HSDPA = (1 << NETWORK_TYPE_HSDPA);
+    /**
+     * network type bitmask indicating the support of radio tech HSPA.
+     * @hide
+     */
+    @SystemApi
+    public static final int NETWORK_TYPE_BITMASK_HSPA = (1 << NETWORK_TYPE_HSPA);
+    /**
+     * network type bitmask indicating the support of radio tech HSPAP.
+     * @hide
+     */
+    @SystemApi
+    public static final int NETWORK_TYPE_BITMASK_HSPAP = (1 << NETWORK_TYPE_HSPAP);
+    /**
+     * network type bitmask indicating the support of radio tech UMTS.
+     * @hide
+     */
+    @SystemApi
+    public static final int NETWORK_TYPE_BITMASK_UMTS = (1 << NETWORK_TYPE_UMTS);
+    /**
+     * network type bitmask indicating the support of radio tech TD_SCDMA.
+     * @hide
+     */
+    @SystemApi
+    public static final int NETWORK_TYPE_BITMASK_TD_SCDMA = (1 << NETWORK_TYPE_TD_SCDMA);
+    // 4G
+    /**
+     * network type bitmask indicating the support of radio tech LTE.
+     * @hide
+     */
+    @SystemApi
+    public static final int NETWORK_TYPE_BITMASK_LTE = (1 << NETWORK_TYPE_LTE);
+    /**
+     * network type bitmask indicating the support of radio tech LTE CA (carrier aggregation).
+     * @hide
+     */
+    @SystemApi
+    public static final int NETWORK_TYPE_BITMASK_LTE_CA = (1 << NETWORK_TYPE_LTE_CA);
+
+    /**
+     * @return Modem supported radio access family bitmask {@link NetworkTypeBitMask}
+     *
+     * <p>Requires permission: {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE} or
+     * that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    public @NetworkTypeBitMask int getSupportedRadioAccessFamily() {
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                return telephony.getRadioAccessFamily(getSlotIndex(), getOpPackageName());
+            } else {
+                // This can happen when the ITelephony interface is not up yet.
+                return NETWORK_TYPE_BITMASK_UNKNOWN;
+            }
+        } catch (RemoteException ex) {
+            // This shouldn't happen in the normal case
+            return NETWORK_TYPE_BITMASK_UNKNOWN;
+        } catch (NullPointerException ex) {
+            // This could happen before phone restarts due to crashing
+            return NETWORK_TYPE_BITMASK_UNKNOWN;
+        }
+    }
+
 }
diff --git a/telephony/java/android/telephony/ims/ImsCallForwardInfo.java b/telephony/java/android/telephony/ims/ImsCallForwardInfo.java
index 34b8884..70daa8b 100644
--- a/telephony/java/android/telephony/ims/ImsCallForwardInfo.java
+++ b/telephony/java/android/telephony/ims/ImsCallForwardInfo.java
@@ -16,11 +16,16 @@
 
 package android.telephony.ims;
 
+import android.annotation.IntDef;
+import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
 /**
  * Provides the call forward information for the supplementary service configuration.
  *
@@ -28,39 +33,120 @@
  */
 @SystemApi
 public final class ImsCallForwardInfo implements Parcelable {
-    // Refer to ImsUtInterface#CDIV_CF_XXX
-    /** @hide */
-    // TODO: Make private, do not modify this field directly, use getter.
+
+    /**
+     * CDIV (Communication Diversion, 3GPP TS 24.604) call forwarding reason for unconditional call
+     * forwarding. See TC 27.007
+     */
+    public static final int CDIV_CF_REASON_UNCONDITIONAL = 0;
+
+    /**
+     * CDIV (Communication Diversion, 3GPP TS 24.604) call forwarding reason for call forwarding
+     * when the user is busy.
+     */
+    public static final int CDIV_CF_REASON_BUSY = 1;
+
+    /**
+     * CDIV (Communication Diversion, 3GPP TS 24.604) call forwarding reason for call forwarding
+     * when there is no reply from the user.
+     */
+    public static final int CDIV_CF_REASON_NO_REPLY = 2;
+
+    /**
+     * CDIV (Communication Diversion, 3GPP TS 24.604) call forwarding reason for call forwarding
+     * when the user is not reachable.
+     */
+    public static final int CDIV_CF_REASON_NOT_REACHABLE = 3;
+
+    /**
+     * CDIV (Communication Diversion, 3GPP TS 24.604) call forwarding reason for setting all call
+     * forwarding reasons simultaneously (i.e. unconditional, busy, no reply, and not reachable).
+     */
+    public static final int CDIV_CF_REASON_ALL = 4;
+
+    /**
+     * CDIV (Communication Diversion, 3GPP TS 24.604) call forwarding reason for setting all
+     * conditional call forwarding reasons simultaneously (i.e. if busy, if no reply, and if not
+     * reachable).
+     */
+    public static final int CDIV_CF_REASON_ALL_CONDITIONAL = 5;
+
+    /**
+     * CDIV (Communication Diversion) IMS only call forwarding reason for call forwarding when the
+     * user is not logged in.
+     */
+    public static final int CDIV_CF_REASON_NOT_LOGGED_IN = 6;
+
+    /**@hide*/
+    @IntDef(prefix = {"CDIV_CF_REASON_"}, value = {
+            CDIV_CF_REASON_UNCONDITIONAL,
+            CDIV_CF_REASON_BUSY,
+            CDIV_CF_REASON_NO_REPLY,
+            CDIV_CF_REASON_NOT_REACHABLE,
+            CDIV_CF_REASON_ALL,
+            CDIV_CF_REASON_ALL_CONDITIONAL,
+            CDIV_CF_REASON_NOT_LOGGED_IN})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface CallForwardReasons{}
+
+    /**
+     * Call forwarding is not active for any service class.
+     */
+    public static final int STATUS_NOT_ACTIVE = 0;
+
+    /**
+     * Call forwarding is active for one or more service classes.
+     */
+    public static final int STATUS_ACTIVE = 1;
+
+    /**@hide*/
+    @IntDef(prefix = {"STATUS_"}, value = {
+            STATUS_NOT_ACTIVE,
+            STATUS_ACTIVE})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface CallForwardStatus{}
+
+    /**
+     * The address defined in {@link #getNumber()} is in an unknown format.
+     *
+     * See TS 27.007, section 7.11 for more information.
+     */
+    public static final int TYPE_OF_ADDRESS_UNKNOWN = 0x81;
+    /**
+     * The address defined in {@link #getNumber()} is in E.164 international format, which includes
+     * international access code "+".
+     *
+     * See TS 27.007, section 7.11 for more information.
+     */
+    public static final int TYPE_OF_ADDRESS_INTERNATIONAL = 0x91;
+
+    /**@hide*/
+    @IntDef(prefix = {"TYPE_OF_ADDRESS_"}, value = {
+            TYPE_OF_ADDRESS_INTERNATIONAL,
+            TYPE_OF_ADDRESS_UNKNOWN})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface TypeOfAddress{}
+
+    /**@hide*/
     @UnsupportedAppUsage
-    public int mCondition;
-    // 0: disabled, 1: enabled
+    public @CallForwardReasons int mCondition;
     /** @hide */
-    // TODO: Make private, do not modify this field directly, use getter.
     @UnsupportedAppUsage
-    public int mStatus;
-    // 0x91: International, 0x81: Unknown
+    public @CallForwardStatus int mStatus;
     /** @hide */
-    // TODO: Make private, do not modify this field directly, use getter.
     @UnsupportedAppUsage
-    public int mToA;
-    // Service class
+    public @TypeOfAddress int mToA;
     /** @hide */
-    // TODO: Make private, do not modify this field directly, use getter.
     @UnsupportedAppUsage
-    public int mServiceClass;
-    // Number (it will not include the "sip" or "tel" URI scheme)
+    public @ImsSsData.ServiceClassFlags int mServiceClass;
     /** @hide */
-    // TODO: Make private, do not modify this field directly, use getter.
     @UnsupportedAppUsage
     public String mNumber;
-    // No reply timer for CF
     /** @hide */
-    // TODO: Make private, do not modify this field directly, use getter.
     @UnsupportedAppUsage
     public int mTimeSeconds;
 
     /** @hide */
-    // TODO: Will be removed in the future, use public constructor instead.
     @UnsupportedAppUsage
     public ImsCallForwardInfo() {
     }
@@ -68,9 +154,10 @@
     /**
      * IMS Call Forward Information.
      */
-    public ImsCallForwardInfo(int condition, int status, int toA, int serviceClass, String number,
-            int replyTimerSec) {
-        mCondition = condition;
+    public ImsCallForwardInfo(@CallForwardReasons int reason, @CallForwardStatus int status,
+            @TypeOfAddress int toA, @ImsSsData.ServiceClassFlags int serviceClass,
+            @NonNull String number, int replyTimerSec) {
+        mCondition = reason;
         mStatus = status;
         mToA = toA;
         mServiceClass = serviceClass;
@@ -130,26 +217,47 @@
         }
     };
 
-    public int getCondition() {
+    /**
+     * @return the condition of call forwarding for the service classes specified.
+     */
+    public @CallForwardReasons int getCondition() {
         return mCondition;
     }
 
-    public int getStatus() {
+    /**
+     * @return The call forwarding status.
+     */
+    public @CallForwardStatus int getStatus() {
         return mStatus;
     }
 
-    public int getToA() {
+    /**
+     * @return the type of address (ToA) for the number.
+     * @see #getNumber()
+     */
+    public @TypeOfAddress int getToA() {
         return mToA;
     }
 
-    public int getServiceClass() {
+    /**
+     * @return a bitfield containing the service classes that are enabled for call forwarding.
+     */
+    public @ImsSsData.ServiceClassFlags int getServiceClass() {
         return mServiceClass;
     }
 
+    /**
+     * @return the call forwarding number associated with call forwarding, with a number type
+     * defined by {@link #getToA()}.
+     */
     public String getNumber() {
         return mNumber;
     }
 
+    /**
+     * @return the number in seconds to wait before the call is forwarded for call forwarding
+     * condition {@link #CDIV_CF_REASON_NO_REPLY}
+     */
     public int getTimeSeconds() {
         return mTimeSeconds;
     }
diff --git a/telephony/java/android/telephony/ims/ImsSsData.java b/telephony/java/android/telephony/ims/ImsSsData.java
index b68055e..db5ba47 100644
--- a/telephony/java/android/telephony/ims/ImsSsData.java
+++ b/telephony/java/android/telephony/ims/ImsSsData.java
@@ -16,9 +16,11 @@
 package android.telephony.ims;
 
 import android.annotation.IntDef;
+import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.telephony.Rlog;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -31,6 +33,8 @@
 @SystemApi
 public final class ImsSsData implements Parcelable {
 
+    private static final String TAG = ImsSsData.class.getCanonicalName();
+
     // Supplementary Service Type
     // Call Forwarding
     public static final int SS_CFU = 0;
@@ -76,30 +80,85 @@
     public static final int SS_SMS_SERVICES = 4;
     public static final int SS_ALL_TELESERVICES_EXCEPT_SMS = 5;
 
-    // Service Class of Supplementary Service
-    // See 27.007 +CCFC or +CLCK
-    /** @hide */
-    public static final int SERVICE_CLASS_NONE = 0; // no user input
-    /** @hide */
-    public static final int SERVICE_CLASS_VOICE = 1;
-    /** @hide */
-    public static final int SERVICE_CLASS_DATA = (1 << 1);
-    /** @hide */
-    public static final int SERVICE_CLASS_FAX = (1 << 2);
-    /** @hide */
-    public static final int SERVICE_CLASS_SMS = (1 << 3);
-    /** @hide */
-    public static final int SERVICE_CLASS_DATA_SYNC = (1 << 4);
-    /** @hide */
-    public static final int SERVICE_CLASS_DATA_ASYNC = (1 << 5);
-    /** @hide */
-    public static final int SERVICE_CLASS_PACKET = (1 << 6);
-    /** @hide */
-    public static final int SERVICE_CLASS_PAD = (1 << 7);
+    /**
+     * No call forwarding service class defined.
+     *
+     * See TS 27.007 7.11 (+CCFC) and 7.4 (CLCK)
+     */
+    public static final int SERVICE_CLASS_NONE = 0;
 
     /**
-     * Result code used if the operation was successful. See {@link #result}.
-     * @hide
+     * Service class flag for voice telephony.
+     *
+     * See TS 27.007 7.11 (+CCFC) and 7.4 (CLCK)
+     */
+    public static final int SERVICE_CLASS_VOICE = 1;
+
+    /**
+     * Service class flag for all data bearers (including
+     * {@link #SERVICE_CLASS_DATA_CIRCUIT_SYNC,
+     * {@link #SERVICE_CLASS_DATA_CIRCUIT_ASYNC}, {@link #SERVICE_CLASS_PACKET_ACCESS},
+     * {@link #SERVICE_CLASS_PAD}}) if supported by the carrier.
+     *
+     * See TS 27.007 7.11 (+CCFC) and 7.4 (CLCK)
+     */
+    public static final int SERVICE_CLASS_DATA = (1 << 1);
+    /**
+     * Service class flag for fax services.
+     *
+     * See TS 27.007 7.11 (+CCFC) and 7.4 (CLCK)
+     */
+    public static final int SERVICE_CLASS_FAX = (1 << 2);
+    /**
+     * Service class flag for SMS services.
+     *
+     * See TS 27.007 7.11 (+CCFC) and 7.4 (CLCK)
+     */
+    public static final int SERVICE_CLASS_SMS = (1 << 3);
+    /**
+     * Service class flag for the synchronous bearer service.
+     *
+     * See TS 27.007 7.11 (+CCFC) and 7.4 (CLCK)
+     */
+    public static final int SERVICE_CLASS_DATA_CIRCUIT_SYNC = (1 << 4);
+
+    /**
+     * Service class flag for the asynchronous bearer service.
+     *
+     * See TS 27.007 7.11 (+CCFC) and 7.4 (CLCK)
+     */
+    public static final int SERVICE_CLASS_DATA_CIRCUIT_ASYNC = (1 << 5);
+
+    /**
+     * Service class flag for the packet access bearer service.
+     *
+     * See TS 27.007 7.11 (+CCFC) and 7.4 (CLCK)
+     */
+    public static final int SERVICE_CLASS_DATA_PACKET_ACCESS = (1 << 6);
+
+    /**
+     * Service class flag for the Packet Assembly/Disassembly bearer service.
+     *
+     * See TS 27.007 7.11 (+CCFC) and 7.4 (CLCK)
+     */
+    public static final int SERVICE_CLASS_DATA_PAD = (1 << 7);
+
+    /**@hide*/
+    @IntDef(flag = true, prefix = {"SERVICE_CLASS_"}, value = {
+            SERVICE_CLASS_NONE,
+            SERVICE_CLASS_VOICE,
+            SERVICE_CLASS_DATA,
+            SERVICE_CLASS_FAX,
+            SERVICE_CLASS_SMS,
+            SERVICE_CLASS_DATA_CIRCUIT_SYNC,
+            SERVICE_CLASS_DATA_CIRCUIT_ASYNC,
+            SERVICE_CLASS_DATA_PACKET_ACCESS,
+            SERVICE_CLASS_DATA_PAD})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ServiceClassFlags{}
+
+    /**
+     * Result code used if the operation was successful. See {@link #getResult()}.
      */
     public static final int RESULT_SUCCESS = 0;
 
@@ -139,97 +198,58 @@
             SERVICE_CLASS_DATA,
             SERVICE_CLASS_FAX,
             SERVICE_CLASS_SMS,
-            SERVICE_CLASS_DATA_SYNC,
-            SERVICE_CLASS_DATA_ASYNC,
-            SERVICE_CLASS_PACKET,
-            SERVICE_CLASS_PAD
+            SERVICE_CLASS_DATA_CIRCUIT_SYNC,
+            SERVICE_CLASS_DATA_CIRCUIT_ASYNC,
+            SERVICE_CLASS_DATA_PACKET_ACCESS,
+            SERVICE_CLASS_DATA_PAD
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface ServiceClass{}
 
     /**
-     * The Service type of this Supplementary service. Valid values include:
-     *     SS_CFU,
-     *     SS_CF_BUSY,
-     *     SS_CF_NO_REPLY,
-     *     SS_CF_NOT_REACHABLE,
-     *     SS_CF_ALL,
-     *     SS_CF_ALL_CONDITIONAL,
-     *     SS_CFUT,
-     *     SS_CLIP,
-     *     SS_CLIR,
-     *     SS_COLP,
-     *     SS_COLR,
-     *     SS_CNAP,
-     *     SS_WAIT,
-     *     SS_BAOC,
-     *     SS_BAOIC,
-     *     SS_BAOIC_EXC_HOME,
-     *     SS_BAIC,
-     *     SS_BAIC_ROAMING,
-     *     SS_ALL_BARRING,
-     *     SS_OUTGOING_BARRING,
-     *     SS_INCOMING_BARRING,
-     *     SS_INCOMING_BARRING_DN,
-     *     SS_INCOMING_BARRING_ANONYMOUS
-     *
+     * The Service type of this Supplementary service.
      * @hide
      */
-    // TODO: Make final, do not modify this field directly!
-    public int serviceType;
+    public final @ServiceType int serviceType;
 
     /**
-     * Supplementary Service request Type. Valid values are:
-     *     SS_ACTIVATION,
-     *     SS_DEACTIVATION,
-     *     SS_INTERROGATION,
-     *     SS_REGISTRATION,
-     *     SS_ERASURE
-     *
+     * Supplementary Service request Type:
+     *     {@link #SS_ACTIVATION),
+     *     {@link #SS_DEACTIVATION},
+     *     {@link #SS_INTERROGATION},
+     *     {@link #SS_REGISTRATION},
+     *     {@link #SS_ERASURE}
      * @hide
      */
-    // TODO: Make final, do not modify this field directly!
-    public int requestType;
+    public final int requestType;
 
     /**
      * Supplementary Service teleservice type:
-     *     SS_TELESERVICE_ALL_TELE_AND_BEARER,
-     *     SS_TELESERVICE_ALL_TELESEVICES,
-     *     SS_TELESERVICE_TELEPHONY,
-     *     SS_TELESERVICE_ALL_DATA,
-     *     SS_TELESERVICE_SMS,
-     *     SS_TELESERVICE_ALL_TELESERVICES_EXCEPT_SMS
+     *     {@link #SS_ALL_TELE_AND_BEARER_SERVICES},
+     *     {@link #SS_ALL_TELESEVICES},
+     *     {@link #SS_TELEPHONY},
+     *     {@link #SS_ALL_DATA_TELESERVICES},
+     *     {@link #SS_SMS_SERVICES},
+     *     {@link #SS_ALL_TELESERVICES_EXCEPT_SMS}
      *
      * @hide
      */
-    // TODO: Make this param final! Do not try to modify this param directly.
-    public int teleserviceType;
+    public final int teleserviceType;
 
     /**
-     * Supplementary Service service class. Valid values are:
-     *     SERVICE_CLASS_NONE,
-     *     SERVICE_CLASS_VOICE,
-     *     SERVICE_CLASS_DATA,
-     *     SERVICE_CLASS_FAX,
-     *     SERVICE_CLASS_SMS,
-     *     SERVICE_CLASS_DATA_SYNC,
-     *     SERVICE_CLASS_DATA_ASYNC,
-     *     SERVICE_CLASS_PACKET,
-     *     SERVICE_CLASS_PAD
+     * Supplementary Service service class.
      *
      * @hide
      */
-    // TODO: Make this param final! Do not try to modify this param directly.
-    public int serviceClass;
+    public final @ServiceClass int serviceClass;
 
     /**
      * Result of Supplementary Service operation. Valid values are:
-     *     RESULT_SUCCESS if the result is success, or
+     *     {@link #RESULT_SUCCESS} if the result is success, or
      *     ImsReasonInfo code if the result is a failure.
      *
      * @hide
      */
-    // TODO: Make this param final! Do not try to modify this param directly.
     public final int result;
 
     private int[] mSsInfo;
@@ -237,44 +257,81 @@
     private ImsSsInfo[] mImsSsInfo;
 
     /**
+     * Builder for optional ImsSsData parameters.
+     */
+    public static class Builder {
+        private ImsSsData mImsSsData;
+
+        /**
+         * Generate IMS Supplementary Service information.
+         * @param serviceType The Supplementary Service type.
+         * @param requestType Supplementary Service request Type:
+         *     {@link #SS_ACTIVATION},
+         *     {@link #SS_DEACTIVATION},
+         *     {@link #SS_INTERROGATION},
+         *     {@link #SS_REGISTRATION},
+         *     {@link #SS_ERASURE}
+         * @param teleserviceType Supplementary Service teleservice type:
+         *     {@link #SS_ALL_TELE_AND_BEARER_SERVICES},
+         *     {@link #SS_ALL_TELESEVICES},
+         *     {@link #SS_TELEPHONY},
+         *     {@link #SS_ALL_DATA_TELESERVICES},
+         *     {@link #SS_SMS_SERVICES},
+         *     {@link #SS_ALL_TELESERVICES_EXCEPT_SMS}
+         * @param serviceClass Supplementary Service service class. See See 27.007 +CCFC or +CLCK.
+         * @param result Result of Supplementary Service operation. Valid values are 0 if the result
+         *               is success, or {@link ImsReasonInfo} code if the result is a failure.
+         * @return this Builder instance for further constructing.
+         * @see #build()
+         */
+        public Builder(@ServiceType int serviceType, int requestType, int teleserviceType,
+                @ServiceClass int serviceClass, int result) {
+            mImsSsData = new ImsSsData(serviceType, requestType, teleserviceType, serviceClass,
+                    result);
+        }
+
+        /**
+         * Set the array of {@link ImsSsInfo}s that are associated with this supplementary service
+         * data.
+         */
+        public Builder setSuppServiceInfo(@NonNull ImsSsInfo[] imsSsInfos) {
+            mImsSsData.mImsSsInfo = imsSsInfos;
+            return this;
+        }
+
+        /**
+         * Set the array of {@link ImsCallForwardInfo}s that are associated with this supplementary
+         * service data.
+         */
+        public Builder setCallForwardingInfo(@NonNull ImsCallForwardInfo[] imsCallForwardInfos) {
+            mImsSsData.mCfInfo = imsCallForwardInfos;
+            return this;
+        }
+
+        /**
+         * @return an {@link ImsSsData} containing optional parameters.
+         */
+        public ImsSsData build() {
+            return mImsSsData;
+        }
+    }
+
+    /**
      * Generate IMS Supplementary Service information.
-     * @param serviceType The Supplementary Service type. Valid entries:
-     *     SS_CFU,
-     *     SS_CF_BUSY,
-     *     SS_CF_NO_REPLY,
-     *     SS_CF_NOT_REACHABLE,
-     *     SS_CF_ALL,
-     *     SS_CF_ALL_CONDITIONAL,
-     *     SS_CFUT,
-     *     SS_CLIP,
-     *     SS_CLIR,
-     *     SS_COLP,
-     *     SS_COLR,
-     *     SS_CNAP,
-     *     SS_WAIT,
-     *     SS_BAOC,
-     *     SS_BAOIC,
-     *     SS_BAOIC_EXC_HOME,
-     *     SS_BAIC,
-     *     SS_BAIC_ROAMING,
-     *     SS_ALL_BARRING,
-     *     SS_OUTGOING_BARRING,
-     *     SS_INCOMING_BARRING,
-     *     SS_INCOMING_BARRING_DN,
-     *     SS_INCOMING_BARRING_ANONYMOUS
+     * @param serviceType The Supplementary Service type.
      * @param requestType Supplementary Service request Type. Valid values are:
-     *     SS_ACTIVATION,
-     *     SS_DEACTIVATION,
-     *     SS_INTERROGATION,
-     *     SS_REGISTRATION,
-     *     SS_ERASURE
+     *     {@link #SS_ACTIVATION},
+     *     {@link #SS_DEACTIVATION},
+     *     {@link #SS_INTERROGATION},
+     *     {@link #SS_REGISTRATION},
+     *     {@link #SS_ERASURE}
      * @param teleserviceType Supplementary Service teleservice type:
-     *     SS_TELESERVICE_ALL_TELE_AND_BEARER,
-     *     SS_TELESERVICE_ALL_TELESEVICES,
-     *     SS_TELESERVICE_TELEPHONY,
-     *     SS_TELESERVICE_ALL_DATA,
-     *     SS_TELESERVICE_SMS,
-     *     SS_TELESERVICE_ALL_TELESERVICES_EXCEPT_SMS
+     *     {@link #SS_ALL_TELE_AND_BEARER_SERVICES},
+     *     {@link #SS_ALL_TELESEVICES},
+     *     {@link #SS_TELEPHONY},
+     *     {@link #SS_ALL_DATA_TELESERVICES},
+     *     {@link #SS_SMS_SERVICES},
+     *     {@link #SS_ALL_TELESERVICES_EXCEPT_SMS}
      * @param serviceClass Supplementary Service service class. See See 27.007 +CCFC or +CLCK.
      * @param result Result of Supplementary Service operation. Valid values are 0 if the result is
      *               success, or ImsReasonInfo code if the result is a failure.
@@ -313,11 +370,11 @@
 
     @Override
     public void writeToParcel(Parcel out, int flags) {
-        out.writeInt(serviceType);
-        out.writeInt(requestType);
-        out.writeInt(teleserviceType);
-        out.writeInt(serviceClass);
-        out.writeInt(result);
+        out.writeInt(getServiceType());
+        out.writeInt(getRequestType());
+        out.writeInt(getTeleserviceType());
+        out.writeInt(getServiceClass());
+        out.writeInt(getResult());
         out.writeIntArray(mSsInfo);
         out.writeParcelableArray(mCfInfo, 0);
         out.writeParcelableArray(mImsSsInfo, 0);
@@ -333,9 +390,9 @@
      * @hide
      */
     public boolean isTypeCF() {
-        return (serviceType == SS_CFU || serviceType == SS_CF_BUSY ||
-              serviceType == SS_CF_NO_REPLY || serviceType == SS_CF_NOT_REACHABLE ||
-              serviceType == SS_CF_ALL || serviceType == SS_CF_ALL_CONDITIONAL);
+        return (getServiceType() == SS_CFU || getServiceType() == SS_CF_BUSY
+                || getServiceType() == SS_CF_NO_REPLY || getServiceType() == SS_CF_NOT_REACHABLE
+                || getServiceType() == SS_CF_ALL || getServiceType() == SS_CF_ALL_CONDITIONAL);
     }
 
     public boolean isTypeCf() {
@@ -343,7 +400,7 @@
     }
 
     public boolean isTypeUnConditional() {
-        return (serviceType == SS_CFU || serviceType == SS_CF_ALL);
+        return (getServiceType() == SS_CFU || getServiceType() == SS_CF_ALL);
     }
 
     /**
@@ -351,7 +408,7 @@
      * @hide
      */
     public boolean isTypeCW() {
-        return (serviceType == SS_WAIT);
+        return (getServiceType() == SS_WAIT);
     }
 
     public boolean isTypeCw() {
@@ -359,35 +416,84 @@
     }
 
     public boolean isTypeClip() {
-        return (serviceType == SS_CLIP);
+        return (getServiceType() == SS_CLIP);
     }
 
     public boolean isTypeColr() {
-        return (serviceType == SS_COLR);
+        return (getServiceType() == SS_COLR);
     }
 
     public boolean isTypeColp() {
-        return (serviceType == SS_COLP);
+        return (getServiceType() == SS_COLP);
     }
 
     public boolean isTypeClir() {
-        return (serviceType == SS_CLIR);
+        return (getServiceType() == SS_CLIR);
     }
 
     public boolean isTypeIcb() {
-        return (serviceType == SS_INCOMING_BARRING_DN ||
-                serviceType == SS_INCOMING_BARRING_ANONYMOUS);
+        return (getServiceType() == SS_INCOMING_BARRING_DN
+                || getServiceType() == SS_INCOMING_BARRING_ANONYMOUS);
     }
 
     public boolean isTypeBarring() {
-        return (serviceType == SS_BAOC || serviceType == SS_BAOIC ||
-              serviceType == SS_BAOIC_EXC_HOME || serviceType == SS_BAIC ||
-              serviceType == SS_BAIC_ROAMING || serviceType == SS_ALL_BARRING ||
-              serviceType == SS_OUTGOING_BARRING || serviceType == SS_INCOMING_BARRING);
+        return (getServiceType() == SS_BAOC || getServiceType() == SS_BAOIC
+                || getServiceType() == SS_BAOIC_EXC_HOME || getServiceType() == SS_BAIC
+                || getServiceType() == SS_BAIC_ROAMING || getServiceType() == SS_ALL_BARRING
+                || getServiceType() == SS_OUTGOING_BARRING
+                || getServiceType() == SS_INCOMING_BARRING);
     }
 
     public boolean isTypeInterrogation() {
-        return (serviceType == SS_INTERROGATION);
+        return (getServiceType() == SS_INTERROGATION);
+    }
+
+    /**
+     * Supplementary Service request Type:
+     *     {@link #SS_ACTIVATION),
+     *     {@link #SS_DEACTIVATION},
+     *     {@link #SS_INTERROGATION},
+     *     {@link #SS_REGISTRATION},
+     *     {@link #SS_ERASURE}
+     */
+    public int getRequestType() {
+        return requestType;
+    }
+
+    /**
+     * The Service type of this Supplementary service.
+     */
+    public @ServiceType int getServiceType() {
+        return serviceType;
+    }
+
+    /**
+     * Supplementary Service teleservice type:
+     *     {@link #SS_ALL_TELE_AND_BEARER_SERVICES},
+     *     {@link #SS_ALL_TELESEVICES},
+     *     {@link #SS_TELEPHONY},
+     *     {@link #SS_ALL_DATA_TELESERVICES},
+     *     {@link #SS_SMS_SERVICES},
+     *     {@link #SS_ALL_TELESERVICES_EXCEPT_SMS}
+     */
+    public int getTeleserviceType() {
+        return teleserviceType;
+    }
+
+    /**
+     * Supplementary Service service class.
+     */
+    public @ServiceClass int getServiceClass() {
+        return serviceClass;
+    }
+
+    /**
+     * Result of Supplementary Service operation. Valid values are:
+     *     {@link #RESULT_SUCCESS} if the result is success, or
+     *     {@link ImsReasonInfo} CODE_* code if the result is a failure.
+     */
+    public int getResult() {
+        return result;
     }
 
     /** @hide */
@@ -406,43 +512,68 @@
     }
 
     /**
-     * This field will be null for RequestType SS_INTERROGATION
-     * and ServiceType SS_CF_*, SS_INCOMING_BARRING_DN,
-     * SS_INCOMING_BARRING_ANONYMOUS.
+     * This is a compatibility function to transform the public API to a form that can be processed
+     * by telephony.
      *
      * @hide
      */
-    public int[] getSuppServiceInfo() {
-        return mSsInfo;
+    //TODO: Refactor Telephony to use well defined classes instead of an int[] to process SS.
+    public int[] getSuppServiceInfoCompat() {
+        if (mSsInfo != null) {
+            // Something has set the ssInfo using hidden APIs, so for compatibility just return that
+            // structure directly.
+            return mSsInfo;
+        }
+
+
+        int[] result = new int[2];
+        if (mImsSsInfo == null || mImsSsInfo.length == 0) {
+            Rlog.e(TAG, "getSuppServiceInfoCompat: Could not parse mImsSsInfo, returning empty "
+                    + "int[]");
+            return result;
+        }
+
+        // Convert ImsSsInfo into a form that telephony can read (as per 3GPP 27.007)
+        // CLIR (section 7.7)
+        if (isTypeClir()) {
+            // Assume there will only be one ImsSsInfo.
+            // contains {"n","m"} parameters
+            result[0] = mImsSsInfo[0].getClirOutgoingState();
+            result[1] = mImsSsInfo[0].getClirInterrogationStatus();
+            return result;
+        }
+        // COLR 7.31
+        if (isTypeColr()) {
+            result[0] = mImsSsInfo[0].getProvisionStatus();
+        }
+        // Facility Lock CLCK 7.4 (for call barring), CLIP 7.6, COLP 7.8, as well as any
+        // other result, just return the status for the "n" parameter and provisioning status for
+        // "m" as the default.
+        result[0] = mImsSsInfo[0].getStatus();
+        result[1] = mImsSsInfo[0].getProvisionStatus();
+        return result;
     }
 
     /**
-     * Valid only for ServiceTypes
-     *  - SS_INCOMING_BARRING_DN and
-     *  - ServiceType SS_INCOMING_BARRING_ANONYMOUS.
-     *  Will be null otherwise.
-     * @hide
+     * @return an array of {@link ImsSsInfo}s associated with this supplementary service data.
      */
-    public ImsSsInfo[] getImsSpecificSuppServiceInfo() {
+    public @NonNull ImsSsInfo[] getSuppServiceInfo() {
         return mImsSsInfo;
     }
 
     /**
-     * Valid only for supplementary services
-     * - ServiceType SS_CF_* and
-     * - RequestType SS_INTERROGATION.
-     * Will be null otherwise.
-     * @hide
+     * @return an array of {@link ImsCallForwardInfo}s associated with this supplementary service
+     * data.
      **/
     public ImsCallForwardInfo[] getCallForwardInfo() {
         return mCfInfo;
     }
 
     public String toString() {
-        return "[ImsSsData] " + "ServiceType: " + serviceType
-            + " RequestType: " + requestType
-            + " TeleserviceType: " + teleserviceType
-            + " ServiceClass: " + serviceClass
-            + " Result: " + result;
+        return "[ImsSsData] " + "ServiceType: " + getServiceType()
+            + " RequestType: " + getRequestType()
+            + " TeleserviceType: " + getTeleserviceType()
+            + " ServiceClass: " + getServiceClass()
+            + " Result: " + getResult();
     }
 }
diff --git a/telephony/java/android/telephony/ims/ImsSsInfo.java b/telephony/java/android/telephony/ims/ImsSsInfo.java
index 3a784c1..0af6e62 100644
--- a/telephony/java/android/telephony/ims/ImsSsInfo.java
+++ b/telephony/java/android/telephony/ims/ImsSsInfo.java
@@ -17,6 +17,8 @@
 package android.telephony.ims;
 
 import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.annotation.UnsupportedAppUsage;
 import android.os.Parcel;
@@ -28,10 +30,24 @@
 /**
  * Provides the result to the update operation for the supplementary service configuration.
  *
+ * Also supports IMS specific Incoming Communication Barring (ICB) as well as Anonymous
+ * Communication Rejection (ACR), as per 3GPP 24.611.
+ *
+ * @see Builder
  * @hide
  */
 @SystemApi
 public final class ImsSsInfo implements Parcelable {
+
+    /**@hide*/
+    @IntDef(value = {
+            NOT_REGISTERED,
+            DISABLED,
+            ENABLED
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ServiceStatus {}
+
     /**
      * For the status of service registration or activation/deactivation.
      */
@@ -40,57 +56,180 @@
     public static final int ENABLED = 1;
 
     /**
-     * Provision status of service
+     * Provision status of service.
+     * @hide
      */
-    /** @hide */
-    @IntDef({
+    @IntDef(value = {
             SERVICE_PROVISIONING_UNKNOWN,
             SERVICE_NOT_PROVISIONED,
             SERVICE_PROVISIONED
-    })
+    }, prefix = "SERVICE_")
     @Retention(RetentionPolicy.SOURCE)
     public @interface ServiceProvisionStatus {}
+
     /**
      * Unknown provision status for the service.
      */
     public static final int SERVICE_PROVISIONING_UNKNOWN = (-1);
+
     /**
      * Service is not provisioned.
      */
     public static final int SERVICE_NOT_PROVISIONED = 0;
+
     /**
      * Service is provisioned.
      */
     public static final int SERVICE_PROVISIONED = 1;
 
+    @IntDef(value = {
+            CLIR_OUTGOING_DEFAULT,
+            CLIR_OUTGOING_INVOCATION,
+            CLIR_OUTGOING_SUPPRESSION
+    }, prefix = "CLIR_OUTGOING_")
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ClirOutgoingState {}
+
+    /**
+     * Calling line identification restriction (CLIR) is set to the default according to the
+     * subscription of the CLIR service.
+     *
+     * See TS 27.007, section 7.7 for more information.
+     */
+    public static final int CLIR_OUTGOING_DEFAULT = 0;
+    /**
+     * Activate Calling line identification restriction for outgoing calls.
+     *
+     * See TS 27.007, section 7.7 for more information.
+     */
+    public static final int CLIR_OUTGOING_INVOCATION = 1;
+    /**
+     * Deactivate Calling line identification restriction for outgoing calls.
+     *
+     * See TS 27.007, section 7.7 for more information.
+     */
+    public static final int CLIR_OUTGOING_SUPPRESSION = 2;
+
+    /**
+     * Calling line identification restriction is currently not provisioned.
+     *
+     * See TS 27.007, section 7.7 for more information.
+     */
+    public static final int CLIR_STATUS_NOT_PROVISIONED = 0;
+    /**
+     * Calling line identification restriction is currently provisioned in permanent mode.
+     *
+     * See TS 27.007, section 7.7 for more information.
+     */
+    public static final int CLIR_STATUS_PROVISIONED_PERMANENT = 1;
+    /**
+     * Calling line identification restriction is currently unknown, e.g. no network, etc.
+     *
+     * See TS 27.007, section 7.7 for more information.
+     */
+    public static final int CLIR_STATUS_UNKNOWN = 2;
+    /**
+     * Calling line identification restriction temporary mode, temporarily restricted.
+     *
+     * See TS 27.007, section 7.7 for more information.
+     */
+    public static final int CLIR_STATUS_TEMPORARILY_RESTRICTED = 3;
+    /**
+     * Calling line identification restriction temporary mode, temporarily allowed.
+     *
+     * See TS 27.007, section 7.7 for more information.
+     */
+    public static final int CLIR_STATUS_TEMPORARILY_ALLOWED = 4;
+
+    @IntDef(value = {
+            CLIR_STATUS_NOT_PROVISIONED,
+            CLIR_STATUS_PROVISIONED_PERMANENT,
+            CLIR_STATUS_UNKNOWN,
+            CLIR_STATUS_TEMPORARILY_RESTRICTED,
+            CLIR_STATUS_TEMPORARILY_ALLOWED
+    }, prefix = "CLIR_STATUS_")
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ClirInterrogationStatus {}
+
     // 0: disabled, 1: enabled
     /** @hide */
-    // TODO: Make private, do not modify this field directly, use getter!
     @UnsupportedAppUsage
     public int mStatus;
     /** @hide */
-    // TODO: Make private, do not modify this field directly, use getter!
     @UnsupportedAppUsage
     public String mIcbNum;
     /** @hide */
     public int mProvisionStatus = SERVICE_PROVISIONING_UNKNOWN;
+    private int mClirInterrogationStatus = CLIR_STATUS_UNKNOWN;
+    private int mClirOutgoingState = CLIR_OUTGOING_DEFAULT;
 
     /**@hide*/
-    // TODO: Remove! Do not use this constructor, instead use public version.
     @UnsupportedAppUsage
     public ImsSsInfo() {
     }
 
     /**
-     *
-     * @param status The status of the service registration of activation/deactiviation. Valid
-     *    entries include:
-     *    {@link #NOT_REGISTERED},
-     *    {@link #DISABLED},
-     *    {@link #ENABLED}
-     * @param icbNum The Incoming barring number.
+     * Builds {@link ImsSsInfo} instances, which may include optional parameters.
      */
-    public ImsSsInfo(int status, String icbNum) {
+    public static class Builder {
+
+        private final ImsSsInfo mImsSsInfo;
+
+        public Builder(@ServiceStatus int status) {
+            mImsSsInfo = new ImsSsInfo();
+            mImsSsInfo.mStatus = status;
+        }
+
+        /**
+         * Set the ICB number for IMS call barring.
+         * @param number The number in E.164 international format.
+         */
+        public Builder setIncomingCommunicationBarringNumber(@NonNull String number) {
+            mImsSsInfo.mIcbNum = number;
+            return this;
+        }
+
+        /**
+         * Set the provisioning status for a Supplementary Service interrogation response.
+         */
+        public Builder setProvisionStatus(@ServiceProvisionStatus int provisionStatus) {
+            mImsSsInfo.mProvisionStatus = provisionStatus;
+            return this;
+        }
+
+        /**
+         * Set the Calling Line Identification Restriction (CLIR) status for a supplementary service
+         * interrogation response.
+         */
+        public Builder setClirInterrogationStatus(@ClirInterrogationStatus int status) {
+            mImsSsInfo.mClirInterrogationStatus = status;
+            return this;
+        }
+
+        /**
+         * Set the Calling line identification Restriction (CLIR) state for outgoing calls.
+         */
+        public Builder setClirOutgoingState(@ClirOutgoingState int state) {
+            mImsSsInfo.mClirOutgoingState = state;
+            return this;
+        }
+
+        /**
+         * @return a built {@link ImsSsInfo} containing optional the parameters that were set.
+         */
+        public ImsSsInfo build() {
+            return mImsSsInfo;
+        }
+    }
+
+    /**
+     *
+     * @param status The status of the service registration of activation/deactiviation.
+     * @param icbNum The Incoming barring number.
+     * @deprecated use {@link ImsSsInfo.Builder} instead.
+     */
+    @Deprecated
+    public ImsSsInfo(@ServiceStatus int status, @Nullable String icbNum) {
         mStatus = status;
         mIcbNum = icbNum;
     }
@@ -148,27 +287,46 @@
     };
 
     /**
-     * @return Supplementary Service Configuration status. Valid Values are:
-     *     {@link #NOT_REGISTERED},
-     *     {@link #DISABLED},
-     *     {@link #ENABLED}
+     * @return Supplementary Service Configuration status.
      */
-    public int getStatus() {
+    public @ServiceStatus int getStatus() {
         return mStatus;
     }
 
+    /** @deprecated Use {@link #getIncomingCommunicationBarringNumber()} instead.*/
+    @Deprecated
     public String getIcbNum() {
         return mIcbNum;
     }
 
     /**
-     * @return Supplementary Service Provision status. Valid Values are:
-     *     {@link #SERVICE_PROVISIONING_UNKNOWN},
-     *     {@link #SERVICE_NOT_PROVISIONED},
-     *     {@link #SERVICE_PROVISIONED}
+     * @return The Incoming Communication Barring (ICB) number.
      */
-    @ServiceProvisionStatus
-    public int getProvisionStatus() {
+    public String getIncomingCommunicationBarringNumber() {
+        return mIcbNum;
+    }
+
+    /**
+     * @return Supplementary Service Provision status.
+     */
+    public @ServiceProvisionStatus int getProvisionStatus() {
         return mProvisionStatus;
     }
+
+    /**
+     * @return the Calling Line Identification Restriction State for outgoing calls with respect to
+     * this subscription. Will be {@link #CLIR_OUTGOING_DEFAULT} if not applicable to this SS info.
+     */
+    public @ClirOutgoingState int getClirOutgoingState() {
+        return mClirOutgoingState;
+    }
+
+    /**
+     * @return the calling line identification restriction provisioning status upon interrogation of
+     * the service for this subscription. Will be {@link #CLIR_STATUS_UNKNOWN} if not applicable to
+     * this SS info.
+     */
+    public @ClirInterrogationStatus int getClirInterrogationStatus() {
+        return mClirInterrogationStatus;
+    }
 }
diff --git a/telephony/java/android/telephony/ims/feature/MmTelFeature.java b/telephony/java/android/telephony/ims/feature/MmTelFeature.java
index 9699594..898ca48 100644
--- a/telephony/java/android/telephony/ims/feature/MmTelFeature.java
+++ b/telephony/java/android/telephony/ims/feature/MmTelFeature.java
@@ -43,7 +43,6 @@
 import com.android.ims.internal.IImsEcbm;
 import com.android.ims.internal.IImsMultiEndpoint;
 import com.android.ims.internal.IImsUt;
-import com.android.internal.annotations.VisibleForTesting;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -233,7 +232,6 @@
          * @see #addCapabilities(int)
          * @see #removeCapabilities(int)
          */
-        @VisibleForTesting
         public MmTelCapabilities() {
             super();
         }
diff --git a/telephony/java/android/telephony/mbms/InternalDownloadProgressListener.java b/telephony/java/android/telephony/mbms/InternalDownloadProgressListener.java
index 403f758..6a13569 100644
--- a/telephony/java/android/telephony/mbms/InternalDownloadProgressListener.java
+++ b/telephony/java/android/telephony/mbms/InternalDownloadProgressListener.java
@@ -43,18 +43,18 @@
             return;
         }
 
-        mExecutor.execute(new Runnable() {
-            @Override
-            public void run() {
-                long token = Binder.clearCallingIdentity();
-                try {
+        long token = Binder.clearCallingIdentity();
+        try {
+            mExecutor.execute(new Runnable() {
+                @Override
+                public void run() {
                     mAppListener.onProgressUpdated(request, fileInfo, currentDownloadSize,
                             fullDownloadSize, currentDecodedSize, fullDecodedSize);
-                } finally {
-                    Binder.restoreCallingIdentity(token);
                 }
-            }
-        });
+            });
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
     }
 
     public void stop() {
diff --git a/telephony/java/android/telephony/mbms/InternalDownloadSessionCallback.java b/telephony/java/android/telephony/mbms/InternalDownloadSessionCallback.java
index 2916f81..ce32477 100644
--- a/telephony/java/android/telephony/mbms/InternalDownloadSessionCallback.java
+++ b/telephony/java/android/telephony/mbms/InternalDownloadSessionCallback.java
@@ -40,17 +40,17 @@
             return;
         }
 
-        mExecutor.execute(new Runnable() {
-            @Override
-            public void run() {
-                long token = Binder.clearCallingIdentity();
-                try {
+        long token = Binder.clearCallingIdentity();
+        try {
+            mExecutor.execute(new Runnable() {
+                @Override
+                public void run() {
                     mAppCallback.onError(errorCode, message);
-                } finally {
-                    Binder.restoreCallingIdentity(token);
                 }
-            }
-        });
+            });
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
     }
 
     @Override
@@ -59,17 +59,17 @@
             return;
         }
 
-        mExecutor.execute(new Runnable() {
-            @Override
-            public void run() {
-                long token = Binder.clearCallingIdentity();
-                try {
+        long token = Binder.clearCallingIdentity();
+        try {
+            mExecutor.execute(new Runnable() {
+                @Override
+                public void run() {
                     mAppCallback.onFileServicesUpdated(services);
-                } finally {
-                    Binder.restoreCallingIdentity(token);
                 }
-            }
-        });
+            });
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
     }
 
     @Override
@@ -78,17 +78,17 @@
             return;
         }
 
-        mExecutor.execute(new Runnable() {
-            @Override
-            public void run() {
-                long token = Binder.clearCallingIdentity();
-                try {
+        long token = Binder.clearCallingIdentity();
+        try {
+            mExecutor.execute(new Runnable() {
+                @Override
+                public void run() {
                     mAppCallback.onMiddlewareReady();
-                } finally {
-                    Binder.restoreCallingIdentity(token);
                 }
-            }
-        });
+            });
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
     }
 
     public void stop() {
diff --git a/telephony/java/android/telephony/mbms/InternalDownloadStatusListener.java b/telephony/java/android/telephony/mbms/InternalDownloadStatusListener.java
index ad6bb54..87163ff 100644
--- a/telephony/java/android/telephony/mbms/InternalDownloadStatusListener.java
+++ b/telephony/java/android/telephony/mbms/InternalDownloadStatusListener.java
@@ -42,17 +42,17 @@
             return;
         }
 
-        mExecutor.execute(new Runnable() {
-            @Override
-            public void run() {
-                long token = Binder.clearCallingIdentity();
-                try {
+        long token = Binder.clearCallingIdentity();
+        try {
+            mExecutor.execute(new Runnable() {
+                @Override
+                public void run() {
                     mAppListener.onStatusUpdated(request, fileInfo, status);
-                } finally {
-                    Binder.restoreCallingIdentity(token);
                 }
-            }
-        });
+            });
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
     }
 
     public void stop() {
diff --git a/telephony/java/android/telephony/mbms/InternalGroupCallCallback.java b/telephony/java/android/telephony/mbms/InternalGroupCallCallback.java
index 2910bb3..c7600b6 100644
--- a/telephony/java/android/telephony/mbms/InternalGroupCallCallback.java
+++ b/telephony/java/android/telephony/mbms/InternalGroupCallCallback.java
@@ -38,17 +38,17 @@
             return;
         }
 
-        mExecutor.execute(new Runnable() {
-            @Override
-            public void run() {
-                long token = Binder.clearCallingIdentity();
-                try {
+        long token = Binder.clearCallingIdentity();
+        try {
+            mExecutor.execute(new Runnable() {
+                @Override
+                public void run() {
                     mAppCallback.onError(errorCode, message);
-                } finally {
-                    Binder.restoreCallingIdentity(token);
                 }
-            }
-        });
+            });
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
     }
 
     @Override
@@ -57,17 +57,17 @@
             return;
         }
 
-        mExecutor.execute(new Runnable() {
-            @Override
-            public void run() {
-                long token = Binder.clearCallingIdentity();
-                try {
+        long token = Binder.clearCallingIdentity();
+        try {
+            mExecutor.execute(new Runnable() {
+                @Override
+                public void run() {
                     mAppCallback.onGroupCallStateChanged(state, reason);
-                } finally {
-                    Binder.restoreCallingIdentity(token);
                 }
-            }
-        });
+            });
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
     }
 
     @Override
@@ -76,17 +76,17 @@
             return;
         }
 
-        mExecutor.execute(new Runnable() {
-            @Override
-            public void run() {
-                long token = Binder.clearCallingIdentity();
-                try {
+        long token = Binder.clearCallingIdentity();
+        try {
+            mExecutor.execute(new Runnable() {
+                @Override
+                public void run() {
                     mAppCallback.onBroadcastSignalStrengthUpdated(signalStrength);
-                } finally {
-                    Binder.restoreCallingIdentity(token);
                 }
-            }
-        });
+            });
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
     }
 
     /** Prevents this callback from calling the app */
diff --git a/telephony/java/android/telephony/mbms/InternalGroupCallSessionCallback.java b/telephony/java/android/telephony/mbms/InternalGroupCallSessionCallback.java
index 4c9cf4d..0b7667e 100644
--- a/telephony/java/android/telephony/mbms/InternalGroupCallSessionCallback.java
+++ b/telephony/java/android/telephony/mbms/InternalGroupCallSessionCallback.java
@@ -39,17 +39,17 @@
             return;
         }
 
-        mExecutor.execute(new Runnable() {
-            @Override
-            public void run() {
-                long token = Binder.clearCallingIdentity();
-                try {
+        long token = Binder.clearCallingIdentity();
+        try {
+            mExecutor.execute(new Runnable() {
+                @Override
+                public void run() {
                     mAppCallback.onError(errorCode, message);
-                } finally {
-                    Binder.restoreCallingIdentity(token);
                 }
-            }
-        });
+            });
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
     }
 
     @Override
@@ -58,17 +58,17 @@
             return;
         }
 
-        mExecutor.execute(new Runnable() {
-            @Override
-            public void run() {
-                long token = Binder.clearCallingIdentity();
-                try {
+        long token = Binder.clearCallingIdentity();
+        try {
+            mExecutor.execute(new Runnable() {
+                @Override
+                public void run() {
                     mAppCallback.onAvailableSaisUpdated(currentSais, availableSais);
-                } finally {
-                    Binder.restoreCallingIdentity(token);
                 }
-            }
-        });
+            });
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
     }
 
     @Override
@@ -77,17 +77,17 @@
             return;
         }
 
-        mExecutor.execute(new Runnable() {
-            @Override
-            public void run() {
-                long token = Binder.clearCallingIdentity();
-                try {
+        long token = Binder.clearCallingIdentity();
+        try {
+            mExecutor.execute(new Runnable() {
+                @Override
+                public void run() {
                     mAppCallback.onServiceInterfaceAvailable(interfaceName, index);
-                } finally {
-                    Binder.restoreCallingIdentity(token);
                 }
-            }
-        });
+            });
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
     }
 
     @Override
@@ -96,17 +96,17 @@
             return;
         }
 
-        mExecutor.execute(new Runnable() {
-            @Override
-            public void run() {
-                long token = Binder.clearCallingIdentity();
-                try {
+        long token = Binder.clearCallingIdentity();
+        try {
+            mExecutor.execute(new Runnable() {
+                @Override
+                public void run() {
                     mAppCallback.onMiddlewareReady();
-                } finally {
-                    Binder.restoreCallingIdentity(token);
                 }
-            }
-        });
+            });
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
     }
 
     /** Prevents this callback from calling the app */
diff --git a/telephony/java/android/telephony/mbms/InternalStreamingServiceCallback.java b/telephony/java/android/telephony/mbms/InternalStreamingServiceCallback.java
index e9f39ff..3a4ed08 100644
--- a/telephony/java/android/telephony/mbms/InternalStreamingServiceCallback.java
+++ b/telephony/java/android/telephony/mbms/InternalStreamingServiceCallback.java
@@ -39,17 +39,17 @@
             return;
         }
 
-        mExecutor.execute(new Runnable() {
-            @Override
-            public void run() {
-                long token = Binder.clearCallingIdentity();
-                try {
+        long token = Binder.clearCallingIdentity();
+        try {
+            mExecutor.execute(new Runnable() {
+                @Override
+                public void run() {
                     mAppCallback.onError(errorCode, message);
-                } finally {
-                    Binder.restoreCallingIdentity(token);
                 }
-            }
-        });
+            });
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
     }
 
     @Override
@@ -58,17 +58,17 @@
             return;
         }
 
-        mExecutor.execute(new Runnable() {
-            @Override
-            public void run() {
-                long token = Binder.clearCallingIdentity();
-                try {
+        long token = Binder.clearCallingIdentity();
+        try {
+            mExecutor.execute(new Runnable() {
+                @Override
+                public void run() {
                     mAppCallback.onStreamStateUpdated(state, reason);
-                } finally {
-                    Binder.restoreCallingIdentity(token);
                 }
-            }
-        });
+            });
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
     }
 
     @Override
@@ -77,17 +77,17 @@
             return;
         }
 
-        mExecutor.execute(new Runnable() {
-            @Override
-            public void run() {
-                long token = Binder.clearCallingIdentity();
-                try {
+        long token = Binder.clearCallingIdentity();
+        try {
+            mExecutor.execute(new Runnable() {
+                @Override
+                public void run() {
                     mAppCallback.onMediaDescriptionUpdated();
-                } finally {
-                    Binder.restoreCallingIdentity(token);
                 }
-            }
-        });
+            });
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
     }
 
     @Override
@@ -96,17 +96,17 @@
             return;
         }
 
-        mExecutor.execute(new Runnable() {
-            @Override
-            public void run() {
-                long token = Binder.clearCallingIdentity();
-                try {
+        long token = Binder.clearCallingIdentity();
+        try {
+            mExecutor.execute(new Runnable() {
+                @Override
+                public void run() {
                     mAppCallback.onBroadcastSignalStrengthUpdated(signalStrength);
-                } finally {
-                    Binder.restoreCallingIdentity(token);
                 }
-            }
-        });
+            });
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
     }
 
     @Override
@@ -115,17 +115,17 @@
             return;
         }
 
-        mExecutor.execute(new Runnable() {
-            @Override
-            public void run() {
-                long token = Binder.clearCallingIdentity();
-                try {
+        long token = Binder.clearCallingIdentity();
+        try {
+            mExecutor.execute(new Runnable() {
+                @Override
+                public void run() {
                     mAppCallback.onStreamMethodUpdated(methodType);
-                } finally {
-                    Binder.restoreCallingIdentity(token);
                 }
-            }
-        });
+            });
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
     }
 
     public void stop() {
diff --git a/telephony/java/android/telephony/mbms/InternalStreamingSessionCallback.java b/telephony/java/android/telephony/mbms/InternalStreamingSessionCallback.java
index d47f5ad..2eb280e 100644
--- a/telephony/java/android/telephony/mbms/InternalStreamingSessionCallback.java
+++ b/telephony/java/android/telephony/mbms/InternalStreamingSessionCallback.java
@@ -40,17 +40,17 @@
             return;
         }
 
-        mExecutor.execute(new Runnable() {
-            @Override
-            public void run() {
-                long token = Binder.clearCallingIdentity();
-                try {
+        long token = Binder.clearCallingIdentity();
+        try {
+            mExecutor.execute(new Runnable() {
+                @Override
+                public void run() {
                     mAppCallback.onError(errorCode, message);
-                } finally {
-                    Binder.restoreCallingIdentity(token);
                 }
-            }
-        });
+            });
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
     }
 
     @Override
@@ -60,17 +60,17 @@
             return;
         }
 
-        mExecutor.execute(new Runnable() {
-            @Override
-            public void run() {
-                long token = Binder.clearCallingIdentity();
-                try {
+        long token = Binder.clearCallingIdentity();
+        try {
+            mExecutor.execute(new Runnable() {
+                @Override
+                public void run() {
                     mAppCallback.onStreamingServicesUpdated(services);
-                } finally {
-                    Binder.restoreCallingIdentity(token);
                 }
-            }
-        });
+            });
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
     }
 
     @Override
@@ -79,17 +79,17 @@
             return;
         }
 
-        mExecutor.execute(new Runnable() {
-            @Override
-            public void run() {
-                long token = Binder.clearCallingIdentity();
-                try {
+        long token = Binder.clearCallingIdentity();
+        try {
+            mExecutor.execute(new Runnable() {
+                @Override
+                public void run() {
                     mAppCallback.onMiddlewareReady();
-                } finally {
-                    Binder.restoreCallingIdentity(token);
                 }
-            }
-        });
+            });
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
     }
 
     public void stop() {
diff --git a/telephony/java/com/android/internal/telephony/ICarrierConfigLoader.aidl b/telephony/java/com/android/internal/telephony/ICarrierConfigLoader.aidl
index d9471ae..5cd67d9 100644
--- a/telephony/java/com/android/internal/telephony/ICarrierConfigLoader.aidl
+++ b/telephony/java/com/android/internal/telephony/ICarrierConfigLoader.aidl
@@ -25,6 +25,8 @@
 
     PersistableBundle getConfigForSubId(int subId, String callingPackage);
 
+    void overrideConfig(int subId, in PersistableBundle overrides);
+
     void notifyConfigChangedForSubId(int subId);
 
     void updateConfigForPhoneId(int phoneId, String simState);
diff --git a/telephony/java/com/android/internal/telephony/ISub.aidl b/telephony/java/com/android/internal/telephony/ISub.aidl
index 85b4941..4bdec08 100755
--- a/telephony/java/com/android/internal/telephony/ISub.aidl
+++ b/telephony/java/com/android/internal/telephony/ISub.aidl
@@ -186,10 +186,10 @@
     /**
      * Get User downloaded Profiles.
      *
-     *  Provide all available user downloaded profile on the phone.
-     *  @param slotId on which phone the switch will operate on
+     * Return opportunistic subscriptions that can be visible to the caller.
+     * @return the list of opportunistic subscription info. If none exists, an empty list.
      */
-    List<SubscriptionInfo> getOpportunisticSubscriptions(int slotId, String callingPackage);
+    List<SubscriptionInfo> getOpportunisticSubscriptions(String callingPackage);
 
     int getSlotIndex(int subId);
 
diff --git a/telephony/java/com/android/internal/telephony/TelephonyPermissions.java b/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
index eda8e77..eb6be65 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
@@ -456,6 +456,27 @@
     }
 
     /**
+     * Ensure the caller (or self, if not processing an IPC) has
+     * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE} or carrier privileges.
+     *
+     * @throws SecurityException if the caller does not have the required permission/privileges
+     */
+    public static void enforeceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
+            Context context, int subId, String message) {
+        if (context.checkCallingOrSelfPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+                == PERMISSION_GRANTED) {
+            return;
+        }
+
+        if (DBG) {
+            Rlog.d(LOG_TAG, "No READ_PRIVILEDED_PHONE_STATE permission, " +
+                    "check carrier privilege next.");
+        }
+
+        enforceCallingOrSelfCarrierPrivilege(subId, message);
+    }
+
+    /**
      * Make sure the caller (or self, if not processing an IPC) has carrier privileges.
      *
      * @throws SecurityException if the caller does not have the required privileges
diff --git a/tests/net/java/android/net/NetworkStatsTest.java b/tests/net/java/android/net/NetworkStatsTest.java
index 8f18d07..d6dbf5a 100644
--- a/tests/net/java/android/net/NetworkStatsTest.java
+++ b/tests/net/java/android/net/NetworkStatsTest.java
@@ -39,6 +39,7 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
+import android.net.NetworkStats.Entry;
 import android.os.Process;
 import android.support.test.runner.AndroidJUnit4;
 import android.support.test.filters.SmallTest;
@@ -785,7 +786,38 @@
         ArrayMap<String, String> stackedIface = new ArrayMap<>();
         stackedIface.put(v4Iface, baseIface);
 
-        NetworkStats.Entry otherEntry = new NetworkStats.Entry(
+        // Ipv4 traffic sent/received by an app on stacked interface.
+        final NetworkStats.Entry appEntry = new NetworkStats.Entry(
+                v4Iface, appUid, SET_DEFAULT, TAG_NONE,
+                30501490  /* rxBytes */,
+                22401 /* rxPackets */,
+                876235 /* txBytes */,
+                13805 /* txPackets */,
+                0 /* operations */);
+
+        // Traffic measured for the root uid on the base interface if eBPF is in use.
+        // Incorrectly includes appEntry's bytes and packets, plus IPv4-IPv6 translation
+        // overhead (20 bytes per packet), only for TX traffic.
+        final NetworkStats.Entry ebpfRootUidEntry = new NetworkStats.Entry(
+                baseIface, rootUid, SET_DEFAULT, TAG_NONE,
+                163577 /* rxBytes */,
+                187 /* rxPackets */,
+                1169942 /* txBytes */,
+                13902 /* txPackets */,
+                0 /* operations */);
+
+        // Traffic measured for the root uid on the base interface if xt_qtaguid is in use.
+        // Incorrectly includes appEntry's bytes and packets, plus IPv4-IPv6 translation
+        // overhead (20 bytes per packet), in both directions.
+        final NetworkStats.Entry xtRootUidEntry = new NetworkStats.Entry(
+                baseIface, rootUid, SET_DEFAULT, TAG_NONE,
+                31113087 /* rxBytes */,
+                22588 /* rxPackets */,
+                1169942 /* txBytes */,
+                13902 /* txPackets */,
+                0 /* operations */);
+
+        final NetworkStats.Entry otherEntry = new NetworkStats.Entry(
                 otherIface, appUid, SET_DEFAULT, TAG_NONE,
                 2600  /* rxBytes */,
                 2 /* rxPackets */,
@@ -793,39 +825,41 @@
                 3 /* txPackets */,
                 0 /* operations */);
 
-        NetworkStats stats = new NetworkStats(TEST_START, 3)
-                .addValues(v4Iface, appUid, SET_DEFAULT, TAG_NONE,
-                        30501490  /* rxBytes */,
-                        22401 /* rxPackets */,
-                        876235 /* txBytes */,
-                        13805 /* txPackets */,
-                        0 /* operations */)
-                .addValues(baseIface, rootUid, SET_DEFAULT, TAG_NONE,
-                        31113087,
-                        22588,
-                        1169942,
-                        13902,
-                        0)
+        final NetworkStats statsXt = new NetworkStats(TEST_START, 3)
+                .addValues(appEntry)
+                .addValues(xtRootUidEntry)
                 .addValues(otherEntry);
 
-        stats.apply464xlatAdjustments(stackedIface);
+        final NetworkStats statsEbpf = new NetworkStats(TEST_START, 3)
+                .addValues(appEntry)
+                .addValues(ebpfRootUidEntry)
+                .addValues(otherEntry);
 
-        assertEquals(3, stats.size());
-        assertValues(stats, 0, v4Iface, appUid, SET_DEFAULT, TAG_NONE,
-                METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO,
+        statsXt.apply464xlatAdjustments(stackedIface, false);
+        statsEbpf.apply464xlatAdjustments(stackedIface, true);
+
+        assertEquals(3, statsXt.size());
+        assertEquals(3, statsEbpf.size());
+        final NetworkStats.Entry expectedAppUid = new NetworkStats.Entry(
+                v4Iface, appUid, SET_DEFAULT, TAG_NONE,
                 30949510,
                 22401,
                 1152335,
                 13805,
                 0);
-        assertValues(stats, 1, baseIface, 0, SET_DEFAULT, TAG_NONE,
-                METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO,
+        final NetworkStats.Entry expectedRootUid = new NetworkStats.Entry(
+                baseIface, 0, SET_DEFAULT, TAG_NONE,
                 163577,
                 187,
                 17607,
                 97,
                 0);
-        assertEquals(otherEntry, stats.getValues(2, null));
+        assertEquals(expectedAppUid, statsXt.getValues(0, null));
+        assertEquals(expectedRootUid, statsXt.getValues(1, null));
+        assertEquals(otherEntry, statsXt.getValues(2, null));
+        assertEquals(expectedAppUid, statsEbpf.getValues(0, null));
+        assertEquals(expectedRootUid, statsEbpf.getValues(1, null));
+        assertEquals(otherEntry, statsEbpf.getValues(2, null));
     }
 
     @Test
@@ -850,7 +884,7 @@
                 .addValues(secondEntry);
 
         // Empty map: no adjustment
-        stats.apply464xlatAdjustments(new ArrayMap<>());
+        stats.apply464xlatAdjustments(new ArrayMap<>(), false);
 
         assertEquals(2, stats.size());
         assertEquals(firstEntry, stats.getValues(0, null));
diff --git a/tests/net/java/android/net/UidRangeTest.java b/tests/net/java/android/net/UidRangeTest.java
index 1d1013e..860d732 100644
--- a/tests/net/java/android/net/UidRangeTest.java
+++ b/tests/net/java/android/net/UidRangeTest.java
@@ -20,7 +20,6 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.fail;
 
-import android.os.Parcel;
 import android.support.test.runner.AndroidJUnit4;
 import android.support.test.filters.SmallTest;
 
@@ -31,34 +30,10 @@
 @SmallTest
 public class UidRangeTest {
 
-    static {
-        System.loadLibrary("frameworksnettestsjni");
-    }
-
-    private static native byte[] readAndWriteNative(byte[] inParcel);
-    private static native int getStart(byte[] inParcel);
-    private static native int getStop(byte[] inParcel);
-
-    @Test
-    public void testNativeParcelUnparcel() {
-        UidRange original = new UidRange(1234, Integer.MAX_VALUE);
-
-        byte[] inParcel = marshall(original);
-        byte[] outParcel = readAndWriteNative(inParcel);
-        UidRange roundTrip = unmarshall(outParcel);
-
-        assertEquals(original, roundTrip);
-        assertArrayEquals(inParcel, outParcel);
-    }
-
-    @Test
-    public void testIndividualNativeFields() {
-        UidRange original = new UidRange(0x11115678, 0x22224321);
-        byte[] originalBytes = marshall(original);
-
-        assertEquals(original.start, getStart(originalBytes));
-        assertEquals(original.stop, getStop(originalBytes));
-    }
+  /*
+   * UidRange is no longer passed to netd. UID ranges between the framework and netd are passed as
+   * UidRangeParcel objects.
+   */
 
     @Test
     public void testSingleItemUidRangeAllowed() {
@@ -91,28 +66,4 @@
         } catch (IllegalArgumentException expected) {
         }
     }
-
-    /**
-     * Write a {@link UidRange} into an empty parcel and return the underlying data.
-     *
-     * @see unmarshall(byte[])
-     */
-    private static byte[] marshall(UidRange range) {
-        Parcel p = Parcel.obtain();
-        range.writeToParcel(p, /* flags */ 0);
-        p.setDataPosition(0);
-        return p.marshall();
-    }
-
-    /**
-     * Read raw bytes into a parcel, and read a {@link UidRange} back out of them.
-     *
-     * @see marshall(UidRange)
-     */
-    private static UidRange unmarshall(byte[] data) {
-        Parcel p = Parcel.obtain();
-        p.unmarshall(data, 0, data.length);
-        p.setDataPosition(0);
-        return UidRange.CREATOR.createFromParcel(p);
-    }
-}
+}
\ No newline at end of file
diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java
index e377a47..9bf7587 100644
--- a/tests/net/java/com/android/server/connectivity/VpnTest.java
+++ b/tests/net/java/com/android/server/connectivity/VpnTest.java
@@ -507,13 +507,15 @@
 
     private static void assertBlocked(Vpn vpn, int... uids) {
         for (int uid : uids) {
-            assertTrue("Uid " + uid + " should be blocked", vpn.isBlockingUid(uid));
+            final boolean blocked = vpn.getLockdown() && vpn.isBlockingUid(uid);
+            assertTrue("Uid " + uid + " should be blocked", blocked);
         }
     }
 
     private static void assertUnblocked(Vpn vpn, int... uids) {
         for (int uid : uids) {
-            assertFalse("Uid " + uid + " should not be blocked", vpn.isBlockingUid(uid));
+            final boolean blocked = vpn.getLockdown() && vpn.isBlockingUid(uid);
+            assertFalse("Uid " + uid + " should not be blocked", blocked);
         }
     }
 
diff --git a/tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java b/tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java
index 3e21a2c..a22cbd4 100644
--- a/tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java
+++ b/tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java
@@ -475,6 +475,18 @@
         assertPrefixSet(local, EXCLUDES, wifiLinkPrefixes);
         assertPrefixSet(local, INCLUDES, cellLinkPrefixes);
         assertPrefixSet(local, INCLUDES, dunLinkPrefixes);
+
+        // [5] Pretend mobile disconnected.
+        cellAgent.fakeDisconnect();
+        local = mUNM.getLocalPrefixes();
+        assertPrefixSet(local, EXCLUDES, wifiLinkPrefixes);
+        assertPrefixSet(local, EXCLUDES, cellLinkPrefixes);
+        assertPrefixSet(local, INCLUDES, dunLinkPrefixes);
+
+        // [6] Pretend DUN disconnected.
+        dunAgent.fakeDisconnect();
+        local = mUNM.getLocalPrefixes();
+        assertTrue(local.isEmpty());
     }
 
     private void assertSatisfiesLegacyType(int legacyType, NetworkState ns) {
diff --git a/tests/net/jni/UidRangeTest.cpp b/tests/net/jni/UidRangeTest.cpp
deleted file mode 100644
index 7941731..0000000
--- a/tests/net/jni/UidRangeTest.cpp
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <memory>
-
-#include <binder/Parcel.h>
-
-#include "UidRangeTest.h"
-
-using android::net::UidRange;
-
-extern "C"
-JNIEXPORT jbyteArray Java_android_net_UidRangeTest_readAndWriteNative(JNIEnv* env, jclass,
-        jbyteArray inParcel) {
-    const UidRange range = unmarshall(env, inParcel);
-    return marshall(env, range);
-}
-
-extern "C"
-JNIEXPORT jint Java_android_net_UidRangeTest_getStart(JNIEnv* env, jclass, jbyteArray inParcel) {
-    const UidRange range = unmarshall(env, inParcel);
-    return range.getStart();
-}
-
-extern "C"
-JNIEXPORT jint Java_android_net_UidRangeTest_getStop(JNIEnv* env, jclass, jbyteArray inParcel) {
-    const UidRange range = unmarshall(env, inParcel);
-    return range.getStop();
-}
-
-
-/**
- * Reads exactly one UidRange from 'parcelData' assuming that it is a Parcel. Any bytes afterward
- * are ignored.
- */
-UidRange unmarshall(JNIEnv* env, jbyteArray parcelData) {
-    const int length = env->GetArrayLength(parcelData);
-
-    std::unique_ptr<uint8_t> bytes(new uint8_t[length]);
-    env->GetByteArrayRegion(parcelData, 0, length, reinterpret_cast<jbyte*>(bytes.get()));
-
-    android::Parcel p;
-    p.setData(bytes.get(), length);
-
-    UidRange range;
-    range.readFromParcel(&p);
-    return range;
-}
-
-/**
- * Creates a Java byte[] array and writes the contents of 'range' to it as a Parcel containing
- * exactly one object.
- *
- * Every UidRange maps to a unique parcel object, so both 'marshall(e, unmarshall(e, x))' and
- * 'unmarshall(e, marshall(e, x))' should be fixed points.
- */
-jbyteArray marshall(JNIEnv* env, const UidRange& range) {
-    android::Parcel p;
-    range.writeToParcel(&p);
-    const int length = p.dataSize();
-
-    jbyteArray parcelData = env->NewByteArray(length);
-    env->SetByteArrayRegion(parcelData, 0, length, reinterpret_cast<const jbyte*>(p.data()));
-
-    return parcelData;
-}
diff --git a/tests/net/jni/UidRangeTest.h b/tests/net/jni/UidRangeTest.h
deleted file mode 100644
index b7e7453..0000000
--- a/tests/net/jni/UidRangeTest.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _ANDROID_NET_UIDRANGETEST_H_
-#define _ANDROID_NET_UIDRANGETEST_H_
-
-#include <jni.h>
-
-#include "android/net/UidRange.h"
-
-android::net::UidRange unmarshall(JNIEnv* env, jbyteArray parcelData);
-
-jbyteArray marshall(JNIEnv* env, const android::net::UidRange& range);
-
-extern "C"
-JNIEXPORT jbyteArray Java_android_net_UidRangeTest_readAndWriteNative(JNIEnv* env, jclass,
-        jbyteArray inParcel);
-
-extern "C"
-JNIEXPORT jint Java_android_net_UidRangeTest_getStart(JNIEnv* env, jclass, jbyteArray inParcel);
-
-extern "C"
-JNIEXPORT jint Java_android_net_UidRangeTest_getStop(JNIEnv* env, jclass, jbyteArray inParcel);
-
-#endif  //  _ANDROID_NET_UIDRANGETEST_H_
diff --git a/tools/aapt/Android.bp b/tools/aapt/Android.bp
index a594e5b..f367397 100644
--- a/tools/aapt/Android.bp
+++ b/tools/aapt/Android.bp
@@ -71,6 +71,8 @@
     cflags: [
         "-Wno-format-y2k",
         "-DSTATIC_ANDROIDFW_FOR_TOOLS",
+        // Allow implicit fallthroughs in AaptAssets.cpp until they are fixed.
+        "-Wno-error=implicit-fallthrough",
     ],
 
     srcs: [
diff --git a/tools/aapt/Package.cpp b/tools/aapt/Package.cpp
index d631f35..f06643d 100644
--- a/tools/aapt/Package.cpp
+++ b/tools/aapt/Package.cpp
@@ -28,7 +28,7 @@
 
 /* these formats are already compressed, or don't compress well */
 static const char* kNoCompressExt[] = {
-    ".jpg", ".jpeg", ".png", ".gif",
+    ".jpg", ".jpeg", ".png", ".gif", ".opus",
     ".wav", ".mp2", ".mp3", ".ogg", ".aac",
     ".mpg", ".mpeg", ".mid", ".midi", ".smf", ".jet",
     ".rtttl", ".imy", ".xmf", ".mp4", ".m4a",
diff --git a/tools/incident_section_gen/Android.bp b/tools/incident_section_gen/Android.bp
index f07445a..0c7797e 100644
--- a/tools/incident_section_gen/Android.bp
+++ b/tools/incident_section_gen/Android.bp
@@ -24,6 +24,8 @@
         "-O0",
         "-Wall",
         "-Werror",
+        // Allow implicit fallthroughs in main.cpp until they are fixed.
+        "-Wno-error=implicit-fallthrough",
     ],
     srcs: ["main.cpp"],
     shared_libs: [
diff --git a/tools/stats_log_api_gen/Collation.cpp b/tools/stats_log_api_gen/Collation.cpp
index d1f42f8..257043b 100644
--- a/tools/stats_log_api_gen/Collation.cpp
+++ b/tools/stats_log_api_gen/Collation.cpp
@@ -47,7 +47,8 @@
       fields(that.fields),
       primaryFields(that.primaryFields),
       exclusiveField(that.exclusiveField),
-      uidField(that.uidField) {}
+      uidField(that.uidField),
+      binaryFields(that.binaryFields) {}
 
 AtomDecl::AtomDecl(int c, const string& n, const string& m)
     :code(c),
@@ -119,6 +120,9 @@
             } else if (field->message_type()->full_name() ==
                        "android.os.statsd.KeyValuePair") {
               return JAVA_TYPE_KEY_VALUE_PAIR;
+            } else if (field->options().GetExtension(os::statsd::log_mode) ==
+                       os::statsd::LogMode::MODE_BYTES) {
+                return JAVA_TYPE_BYTE_ARRAY;
             } else {
                 return JAVA_TYPE_OBJECT;
             }
@@ -188,6 +192,8 @@
   for (map<int, const FieldDescriptor *>::const_iterator it = fields.begin();
        it != fields.end(); it++) {
     const FieldDescriptor *field = it->second;
+    bool isBinaryField = field->options().GetExtension(os::statsd::log_mode) ==
+                         os::statsd::LogMode::MODE_BYTES;
 
     java_type_t javaType = java_type(field);
 
@@ -197,17 +203,24 @@
       continue;
     } else if (javaType == JAVA_TYPE_OBJECT &&
                atomDecl->code < PULL_ATOM_START_ID) {
-      // Allow attribution chain, but only at position 1.
-      print_error(field,
-                  "Message type not allowed for field in pushed atoms: %s\n",
-                  field->name().c_str());
-      errorCount++;
-      continue;
-    } else if (javaType == JAVA_TYPE_BYTE_ARRAY) {
-      print_error(field, "Raw bytes type not allowed for field: %s\n",
-                  field->name().c_str());
-      errorCount++;
-      continue;
+        // Allow attribution chain, but only at position 1.
+        print_error(field,
+                    "Message type not allowed for field in pushed atoms: %s\n",
+                    field->name().c_str());
+        errorCount++;
+        continue;
+    } else if (javaType == JAVA_TYPE_BYTE_ARRAY && !isBinaryField) {
+        print_error(field, "Raw bytes type not allowed for field: %s\n",
+                    field->name().c_str());
+        errorCount++;
+        continue;
+    }
+
+    if (isBinaryField && javaType != JAVA_TYPE_BYTE_ARRAY) {
+        print_error(field, "Cannot mark field %s as bytes.\n",
+                    field->name().c_str());
+        errorCount++;
+        continue;
     }
   }
 
@@ -233,6 +246,8 @@
        it != fields.end(); it++) {
     const FieldDescriptor *field = it->second;
     java_type_t javaType = java_type(field);
+    bool isBinaryField = field->options().GetExtension(os::statsd::log_mode) ==
+                         os::statsd::LogMode::MODE_BYTES;
 
     AtomField atField(field->name(), javaType);
     // Generate signature for pushed atoms
@@ -241,8 +256,10 @@
         // All enums are treated as ints when it comes to function signatures.
         signature->push_back(JAVA_TYPE_INT);
         collate_enums(*field->enum_type(), &atField);
+      } else if (javaType == JAVA_TYPE_OBJECT && isBinaryField) {
+          signature->push_back(JAVA_TYPE_BYTE_ARRAY);
       } else {
-        signature->push_back(javaType);
+          signature->push_back(javaType);
       }
     }
     if (javaType == JAVA_TYPE_ENUM) {
@@ -287,6 +304,10 @@
             errorCount++;
         }
     }
+    // Binary field validity is already checked above.
+    if (isBinaryField) {
+        atomDecl->binaryFields.push_back(it->first);
+    }
   }
 
   return errorCount;
diff --git a/tools/stats_log_api_gen/Collation.h b/tools/stats_log_api_gen/Collation.h
index 31b8b07..450b305 100644
--- a/tools/stats_log_api_gen/Collation.h
+++ b/tools/stats_log_api_gen/Collation.h
@@ -89,6 +89,8 @@
 
     int uidField = 0;
 
+    vector<int> binaryFields;
+
     AtomDecl();
     AtomDecl(const AtomDecl& that);
     AtomDecl(int code, const string& name, const string& message);
diff --git a/tools/stats_log_api_gen/main.cpp b/tools/stats_log_api_gen/main.cpp
index 56c8428..1ef34b9 100644
--- a/tools/stats_log_api_gen/main.cpp
+++ b/tools/stats_log_api_gen/main.cpp
@@ -66,6 +66,8 @@
             return "double";
         case JAVA_TYPE_STRING:
             return "char const*";
+        case JAVA_TYPE_BYTE_ARRAY:
+            return "char const*";
         default:
             return "UNKNOWN";
     }
@@ -88,6 +90,8 @@
             return "double";
         case JAVA_TYPE_STRING:
             return "java.lang.String";
+        case JAVA_TYPE_BYTE_ARRAY:
+            return "byte[]";
         default:
             return "UNKNOWN";
     }
@@ -198,13 +202,40 @@
     }
 
     fprintf(out, "    return options;\n");
-    fprintf(out, "  }\n");
+    fprintf(out, "}\n");
 
     fprintf(out,
             "const std::map<int, StateAtomFieldOptions> "
             "AtomsInfo::kStateAtomsFieldOptions = "
             "getStateAtomFieldOptions();\n");
 
+    fprintf(out,
+            "static std::map<int, std::vector<int>> "
+            "getBinaryFieldAtoms() {\n");
+    fprintf(out, "    std::map<int, std::vector<int>> options;\n");
+    for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
+         atom != atoms.decls.end(); atom++) {
+        if (atom->binaryFields.size() == 0) {
+            continue;
+        }
+        fprintf(out,
+                "\n    // Adding binary fields for atom "
+                "(%d)%s\n",
+                atom->code, atom->name.c_str());
+
+        for (const auto& field : atom->binaryFields) {
+            fprintf(out, "    options[static_cast<int>(%s)].push_back(%d);\n",
+                    make_constant_name(atom->name).c_str(), field);
+        }
+    }
+
+    fprintf(out, "    return options;\n");
+    fprintf(out, "}\n");
+
+    fprintf(out,
+            "const std::map<int, std::vector<int>> "
+            "AtomsInfo::kBytesFieldAtoms = "
+            "getBinaryFieldAtoms();\n");
 
     fprintf(out, "int64_t lastRetryTimestampNs = -1;\n");
     fprintf(out, "const int64_t kMinRetryIntervalNs = NS_PER_SEC * 60 * 20; // 20 minutes\n");
@@ -664,6 +695,9 @@
     fprintf(out,
             "  const static std::map<int, StateAtomFieldOptions> "
             "kStateAtomsFieldOptions;\n");
+    fprintf(out,
+            "  const static std::map<int, std::vector<int>> "
+            "kBytesFieldAtoms;");
     fprintf(out, "};\n");
 
     fprintf(out, "const static int kMaxPushedAtomId = %d;\n\n",
@@ -698,6 +732,8 @@
             fprintf(out, ", android.os.WorkSource workSource");
         } else if (field->javaType == JAVA_TYPE_KEY_VALUE_PAIR) {
             fprintf(out, ", SparseArray<Object> value_map");
+        } else if (field->javaType == JAVA_TYPE_BYTE_ARRAY) {
+            fprintf(out, ", byte[] %s", field->name.c_str());
         } else {
             fprintf(out, ", %s %s", java_type_name(field->javaType), field->name.c_str());
         }
@@ -890,6 +926,8 @@
             return "jdouble";
         case JAVA_TYPE_STRING:
             return "jstring";
+        case JAVA_TYPE_BYTE_ARRAY:
+            return "jbyteArray";
         default:
             return "UNKNOWN";
     }
@@ -942,6 +980,9 @@
             case JAVA_TYPE_KEY_VALUE_PAIR:
               result += "_KeyValuePairs";
               break;
+            case JAVA_TYPE_BYTE_ARRAY:
+                result += "_bytes";
+                break;
             default:
                 result += "_UNKNOWN";
                 break;
@@ -967,6 +1008,8 @@
             return "D";
         case JAVA_TYPE_STRING:
             return "Ljava/lang/String;";
+        case JAVA_TYPE_BYTE_ARRAY:
+            return "[B";
         default:
             return "UNKNOWN";
     }
@@ -1081,6 +1124,25 @@
                 fprintf(out, "    } else {\n");
                 fprintf(out, "        str%d = NULL;\n", argIndex);
                 fprintf(out, "    }\n");
+            } else if (*arg == JAVA_TYPE_BYTE_ARRAY) {
+                hadStringOrChain = true;
+                fprintf(out, "    jbyte* jbyte_array%d;\n", argIndex);
+                fprintf(out, "    const char* str%d;\n", argIndex);
+                fprintf(out, "    if (arg%d != NULL) {\n", argIndex);
+                fprintf(out,
+                        "        jbyte_array%d = "
+                        "env->GetByteArrayElements(arg%d, NULL);\n",
+                        argIndex, argIndex);
+                fprintf(out,
+                        "        str%d = "
+                        "reinterpret_cast<char*>(env->GetByteArrayElements(arg%"
+                        "d, NULL));\n",
+                        argIndex, argIndex);
+                fprintf(out, "    } else {\n");
+                fprintf(out, "        jbyte_array%d = NULL;\n", argIndex);
+                fprintf(out, "        str%d = NULL;\n", argIndex);
+                fprintf(out, "    }\n");
+
             } else if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
                 hadStringOrChain = true;
                 for (auto chainField : attributionDecl.fields) {
@@ -1154,7 +1216,10 @@
             } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
                 fprintf(out, ", int32_t_map, int64_t_map, string_map, float_map");
             } else {
-                const char *argName = (*arg == JAVA_TYPE_STRING) ? "str" : "arg";
+                const char* argName = (*arg == JAVA_TYPE_STRING ||
+                                       *arg == JAVA_TYPE_BYTE_ARRAY)
+                                              ? "str"
+                                              : "arg";
                 fprintf(out, ", (%s)%s%d", cpp_type_name(*arg), argName, argIndex);
             }
             argIndex++;
@@ -1171,6 +1236,13 @@
                 fprintf(out, "        env->ReleaseStringUTFChars(arg%d, str%d);\n",
                         argIndex, argIndex);
                 fprintf(out, "    }\n");
+            } else if (*arg == JAVA_TYPE_BYTE_ARRAY) {
+                fprintf(out, "    if (str%d != NULL) { \n", argIndex);
+                fprintf(out,
+                        "        env->ReleaseByteArrayElements(arg%d, "
+                        "jbyte_array%d, 0);\n",
+                        argIndex, argIndex);
+                fprintf(out, "    }\n");
             } else if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
                 for (auto chainField : attributionDecl.fields) {
                     if (chainField.javaType == JAVA_TYPE_INT) {
diff --git a/tools/stats_log_api_gen/test.proto b/tools/stats_log_api_gen/test.proto
index f635974..3be87d9 100644
--- a/tools/stats_log_api_gen/test.proto
+++ b/tools/stats_log_api_gen/test.proto
@@ -109,6 +109,28 @@
   oneof event { BadAttributionNodePositionAtom bad = 1; }
 }
 
+message GoodEventWithBinaryFieldAtom {
+    oneof event { GoodBinaryFieldAtom field1 = 1; }
+}
+
+message ComplexField {
+    optional string str = 1;
+}
+
+message GoodBinaryFieldAtom {
+    optional int32 field1 = 1;
+    optional ComplexField bf = 2 [(android.os.statsd.log_mode) = MODE_BYTES];
+}
+
+message BadEventWithBinaryFieldAtom {
+    oneof event { BadBinaryFieldAtom field1 = 1; }
+}
+
+message BadBinaryFieldAtom {
+    optional int32 field1 = 1;
+    optional ComplexField bf = 2;
+}
+
 message BadStateAtoms {
     oneof event {
         BadStateAtom1 bad1 = 1;
diff --git a/tools/stats_log_api_gen/test_collation.cpp b/tools/stats_log_api_gen/test_collation.cpp
index 1936d96..ad3bffac 100644
--- a/tools/stats_log_api_gen/test_collation.cpp
+++ b/tools/stats_log_api_gen/test_collation.cpp
@@ -212,5 +212,19 @@
     EXPECT_EQ(0, errorCount);
 }
 
+TEST(CollationTest, PassOnGoodBinaryFieldAtom) {
+    Atoms atoms;
+    int errorCount =
+            collate_atoms(GoodEventWithBinaryFieldAtom::descriptor(), &atoms);
+    EXPECT_EQ(0, errorCount);
+}
+
+TEST(CollationTest, FailOnBadBinaryFieldAtom) {
+    Atoms atoms;
+    int errorCount =
+            collate_atoms(BadEventWithBinaryFieldAtom::descriptor(), &atoms);
+    EXPECT_TRUE(errorCount > 0);
+}
+
 }  // namespace stats_log_api_gen
 }  // namespace android
\ No newline at end of file