Merge "[GLUtils] Pass the correct format into glTexImage2D and glTexSubImage2D."
diff --git a/Android.bp b/Android.bp
index ae4f974..19c0580 100644
--- a/Android.bp
+++ b/Android.bp
@@ -117,7 +117,7 @@
         "core/java/android/content/ISyncServiceAdapter.aidl",
         "core/java/android/content/ISyncStatusObserver.aidl",
         "core/java/android/content/om/IOverlayManager.aidl",
-        "core/java/android/content/pm/crossprofile/ICrossProfileApps.aidl",
+        "core/java/android/content/pm/ICrossProfileApps.aidl",
         "core/java/android/content/pm/IDexModuleRegisterCallback.aidl",
         "core/java/android/content/pm/ILauncherApps.aidl",
         "core/java/android/content/pm/IOnAppsChangedListener.aidl",
@@ -242,6 +242,7 @@
         "core/java/android/security/IKeystoreService.aidl",
         "core/java/android/security/keymaster/IKeyAttestationApplicationIdProvider.aidl",
         "core/java/android/service/autofill/IAutoFillService.aidl",
+        "core/java/android/service/autofill/IAutofillFieldClassificationService.aidl",
         "core/java/android/service/autofill/IFillCallback.aidl",
         "core/java/android/service/autofill/ISaveCallback.aidl",
         "core/java/android/service/carrier/ICarrierService.aidl",
@@ -500,6 +501,7 @@
         "telephony/java/com/android/ims/internal/IImsService.aidl",
         "telephony/java/com/android/ims/internal/IImsServiceController.aidl",
         "telephony/java/com/android/ims/internal/IImsServiceFeatureCallback.aidl",
+	"telephony/java/com/android/ims/internal/IImsSmsListener.aidl",
         "telephony/java/com/android/ims/internal/IImsStreamMediaSession.aidl",
         "telephony/java/com/android/ims/internal/IImsUt.aidl",
         "telephony/java/com/android/ims/internal/IImsUtListener.aidl",
@@ -547,6 +549,7 @@
         "telephony/java/com/android/internal/telephony/euicc/ISetDefaultSmdpAddressCallback.aidl",
         "telephony/java/com/android/internal/telephony/euicc/ISetNicknameCallback.aidl",
         "telephony/java/com/android/internal/telephony/euicc/ISwitchToProfileCallback.aidl",
+        "wifi/java/android/net/wifi/ISoftApCallback.aidl",
         "wifi/java/android/net/wifi/IWifiManager.aidl",
         "wifi/java/android/net/wifi/aware/IWifiAwareDiscoverySessionCallback.aidl",
         "wifi/java/android/net/wifi/aware/IWifiAwareEventCallback.aidl",
diff --git a/Android.mk b/Android.mk
index 73c1ccd..866d2a7 100644
--- a/Android.mk
+++ b/Android.mk
@@ -72,12 +72,6 @@
   ../opt/net/voip/src/java/android/net/rtp \
   ../opt/net/voip/src/java/android/net/sip \
 
-framework_base_android_test_base_src_files := \
-  $(call all-java-files-under, test-base/src/junit)
-
-framework_base_android_test_runner_src_files := \
-  $(call all-java-files-under, test-runner/src/junit)
-
 # Find all files in specific directories (relative to frameworks/base)
 # to document and check apis
 files_to_check_apis := \
@@ -126,8 +120,6 @@
 
 # These are relative to frameworks/base
 framework_docs_LOCAL_API_CHECK_SRC_FILES := \
-  $(framework_base_android_test_base_src_files) \
-  $(framework_base_android_test_runner_src_files) \
   $(files_to_check_apis) \
   $(common_src_files) \
 
@@ -789,6 +781,7 @@
 LOCAL_SOURCE_FILES_ALL_GENERATED := true
 LOCAL_SRC_FILES := \
     cmds/am/proto/instrumentation_data.proto \
+    cmds/statsd/src/perfetto/perfetto_config.proto \
     $(call all-proto-files-under, core/proto) \
     $(call all-proto-files-under, libs/incident/proto) \
     $(call all-proto-files-under, cmds/statsd/src)
diff --git a/apct-tests/perftests/core/AndroidManifest.xml b/apct-tests/perftests/core/AndroidManifest.xml
index bd0b944..132a2f9 100644
--- a/apct-tests/perftests/core/AndroidManifest.xml
+++ b/apct-tests/perftests/core/AndroidManifest.xml
@@ -10,7 +10,11 @@
 
     <application>
         <uses-library android:name="android.test.runner" />
-        <activity android:name="android.perftests.utils.StubActivity" />
+        <activity android:name="android.perftests.utils.StubActivity">
+          <intent-filter>
+            <action android:name="com.android.perftests.core.PERFTEST" />
+          </intent-filter>
+        </activity>
         <service android:name="android.os.SomeService" android:exported="false" android:process=":some_service" />
     </application>
 
diff --git a/apct-tests/perftests/core/src/android/os/PackageManagerPerfTest.java b/apct-tests/perftests/core/src/android/os/PackageManagerPerfTest.java
new file mode 100644
index 0000000..145fbcd
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/os/PackageManagerPerfTest.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package android.os;
+
+import static android.content.pm.PackageManager.PERMISSION_DENIED;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.LargeTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public class PackageManagerPerfTest {
+    private static final String PERMISSION_NAME_EXISTS =
+            "com.android.perftests.core.TestPermission";
+    private static final String PERMISSION_NAME_DOESNT_EXIST =
+            "com.android.perftests.core.TestBadPermission";
+    private static final ComponentName TEST_ACTIVITY =
+            new ComponentName("com.android.perftests.core", "android.perftests.utils.StubActivity");
+
+    @Rule
+    public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    @Test
+    public void testCheckPermissionExists() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        final PackageManager pm = InstrumentationRegistry.getTargetContext().getPackageManager();
+        final String packageName = TEST_ACTIVITY.getPackageName();
+
+        while (state.keepRunning()) {
+            int ret = pm.checkPermission(PERMISSION_NAME_EXISTS, packageName);
+        }
+    }
+
+    @Test
+    public void testCheckPermissionDoesntExist() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        final PackageManager pm = InstrumentationRegistry.getTargetContext().getPackageManager();
+        final String packageName = TEST_ACTIVITY.getPackageName();
+
+        while (state.keepRunning()) {
+            int ret = pm.checkPermission(PERMISSION_NAME_DOESNT_EXIST, packageName);
+        }
+    }
+
+    @Test
+    public void testQueryIntentActivities() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        final PackageManager pm = InstrumentationRegistry.getTargetContext().getPackageManager();
+        final Intent intent = new Intent("com.android.perftests.core.PERFTEST");
+
+        while (state.keepRunning()) {
+            pm.queryIntentActivities(intent, 0);
+        }
+    }
+
+    @Test
+    public void testGetPackageInfo() throws Exception {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        final PackageManager pm = InstrumentationRegistry.getTargetContext().getPackageManager();
+        final String packageName = TEST_ACTIVITY.getPackageName();
+
+        while (state.keepRunning()) {
+            pm.getPackageInfo(packageName, 0);
+        }
+    }
+
+    @Test
+    public void testGetApplicationInfo() throws Exception {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        final PackageManager pm = InstrumentationRegistry.getTargetContext().getPackageManager();
+        final String packageName = TEST_ACTIVITY.getPackageName();
+        
+        while (state.keepRunning()) {
+            pm.getApplicationInfo(packageName, 0);
+        }
+    }
+
+    @Test
+    public void testGetActivityInfo() throws Exception {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        final PackageManager pm = InstrumentationRegistry.getTargetContext().getPackageManager();
+        
+        while (state.keepRunning()) {
+            pm.getActivityInfo(TEST_ACTIVITY, 0);
+        }
+    }
+}
diff --git a/apct-tests/perftests/core/src/android/os/PermissionTest.java b/apct-tests/perftests/core/src/android/os/PermissionTest.java
deleted file mode 100644
index d292e7d..0000000
--- a/apct-tests/perftests/core/src/android/os/PermissionTest.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-
-package android.os;
-
-import static android.content.pm.PackageManager.PERMISSION_DENIED;
-import static android.content.pm.PackageManager.PERMISSION_GRANTED;
-
-import android.content.Context;
-import android.perftests.utils.BenchmarkState;
-import android.perftests.utils.PerfStatusReporter;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.LargeTest;
-import android.support.test.runner.AndroidJUnit4;
-
-import org.junit.Assert;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(AndroidJUnit4.class)
-@LargeTest
-public class PermissionTest {
-    private static final String PERMISSION_HAS_NAME = "com.android.perftests.core.TestPermission";
-    private static final String PERMISSION_DOESNT_HAVE_NAME =
-            "com.android.perftests.core.TestBadPermission";
-    private static final String THIS_PACKAGE_NAME = "com.android.perftests.core";
-
-    @Rule
-    public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
-
-    @Test
-    public void testHasPermission() {
-        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
-        final Context context = InstrumentationRegistry.getTargetContext();
-        while (state.keepRunning()) {
-            int ret = context.getPackageManager().checkPermission(PERMISSION_HAS_NAME,
-                    THIS_PACKAGE_NAME);
-        }
-    }
-
-    @Test
-    public void testDoesntHavePermission() {
-        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
-        final Context context = InstrumentationRegistry.getTargetContext();
-
-        while (state.keepRunning()) {
-            int ret = context.getPackageManager().checkPermission(PERMISSION_DOESNT_HAVE_NAME,
-                    THIS_PACKAGE_NAME);
-        }
-    }
-
-}
diff --git a/apct-tests/perftests/core/src/android/text/StaticLayoutPerfTest.java b/apct-tests/perftests/core/src/android/text/StaticLayoutPerfTest.java
index 93a0fc3..6975609 100644
--- a/apct-tests/perftests/core/src/android/text/StaticLayoutPerfTest.java
+++ b/apct-tests/perftests/core/src/android/text/StaticLayoutPerfTest.java
@@ -29,6 +29,7 @@
 import android.text.Layout;
 import android.text.style.TextAppearanceSpan;
 
+import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -52,7 +53,7 @@
     private static final boolean NO_STYLE_TEXT = false;
     private static final boolean STYLE_TEXT = true;
 
-    private final Random mRandom = new Random(31415926535L);
+    private Random mRandom;
 
     private static final String ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
     private static final int ALPHABET_LENGTH = ALPHABET.length();
@@ -98,6 +99,11 @@
         return ssb;
     }
 
+    @Before
+    public void setUp() {
+        mRandom = new Random(0);
+    }
+
     @Test
     public void testCreate_FixedText_NoStyle_Greedy_NoHyphenation() {
         final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
@@ -190,8 +196,11 @@
         final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
         while (state.keepRunning()) {
             state.pauseTiming();
-            final MeasuredText text = MeasuredText.build(
-                    generateRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT, LTR);
+            final MeasuredText text = new MeasuredText.Builder(
+                    generateRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT)
+                    .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE)
+                    .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE)
+                    .build();
             state.resumeTiming();
 
             StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH)
@@ -206,8 +215,11 @@
         final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
         while (state.keepRunning()) {
             state.pauseTiming();
-            final MeasuredText text = MeasuredText.build(
-                    generateRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT, LTR);
+            final MeasuredText text = new MeasuredText.Builder(
+                    generateRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT)
+                    .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE)
+                    .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL)
+                    .build();
             state.resumeTiming();
 
             StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH)
@@ -222,8 +234,11 @@
         final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
         while (state.keepRunning()) {
             state.pauseTiming();
-            final MeasuredText text = MeasuredText.build(
-                    generateRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT, LTR);
+            final MeasuredText text = new MeasuredText.Builder(
+                    generateRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT)
+                    .setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED)
+                    .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE)
+                    .build();
             state.resumeTiming();
 
             StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH)
@@ -238,8 +253,11 @@
         final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
         while (state.keepRunning()) {
             state.pauseTiming();
-            final MeasuredText text = MeasuredText.build(
-                    generateRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT, LTR);
+            final MeasuredText text = new MeasuredText.Builder(
+                    generateRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT)
+                    .setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED)
+                    .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL)
+                    .build();
             state.resumeTiming();
 
             StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH)
@@ -254,8 +272,11 @@
         final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
         while (state.keepRunning()) {
             state.pauseTiming();
-            final MeasuredText text = MeasuredText.build(
-                    generateRandomParagraph(WORD_LENGTH, STYLE_TEXT), PAINT, LTR);
+            final MeasuredText text = new MeasuredText.Builder(
+                    generateRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT)
+                    .setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE)
+                    .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE)
+                    .build();
             state.resumeTiming();
 
             StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH)
diff --git a/api/current.txt b/api/current.txt
index 847671e..a98b058 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -211,6 +211,7 @@
     field public static final int accessibilityEventTypes = 16843648; // 0x1010380
     field public static final int accessibilityFeedbackType = 16843650; // 0x1010382
     field public static final int accessibilityFlags = 16843652; // 0x1010384
+    field public static final int accessibilityHeading = 16844160; // 0x1010580
     field public static final int accessibilityLiveRegion = 16843758; // 0x10103ee
     field public static final int accessibilityPaneTitle = 16844156; // 0x101057c
     field public static final int accessibilityTraversalAfter = 16843986; // 0x10104d2
@@ -2795,6 +2796,7 @@
     field public static final int GLOBAL_ACTION_POWER_DIALOG = 6; // 0x6
     field public static final int GLOBAL_ACTION_QUICK_SETTINGS = 5; // 0x5
     field public static final int GLOBAL_ACTION_RECENTS = 3; // 0x3
+    field public static final int GLOBAL_ACTION_TAKE_SCREENSHOT = 9; // 0x9
     field public static final int GLOBAL_ACTION_TOGGLE_SPLIT_SCREEN = 7; // 0x7
     field public static final java.lang.String SERVICE_INTERFACE = "android.accessibilityservice.AccessibilityService";
     field public static final java.lang.String SERVICE_META_DATA = "android.accessibilityservice";
@@ -6345,6 +6347,9 @@
     method public void onTransferOwnershipComplete(android.content.Context, android.os.PersistableBundle);
     method public void onUserAdded(android.content.Context, android.content.Intent, android.os.UserHandle);
     method public void onUserRemoved(android.content.Context, android.content.Intent, android.os.UserHandle);
+    method public void onUserStarted(android.content.Context, android.content.Intent, android.os.UserHandle);
+    method public void onUserStopped(android.content.Context, android.content.Intent, android.os.UserHandle);
+    method public void onUserSwitched(android.content.Context, android.content.Intent, android.os.UserHandle);
     field public static final java.lang.String ACTION_DEVICE_ADMIN_DISABLED = "android.app.action.DEVICE_ADMIN_DISABLED";
     field public static final java.lang.String ACTION_DEVICE_ADMIN_DISABLE_REQUESTED = "android.app.action.DEVICE_ADMIN_DISABLE_REQUESTED";
     field public static final java.lang.String ACTION_DEVICE_ADMIN_ENABLED = "android.app.action.DEVICE_ADMIN_ENABLED";
@@ -6991,6 +6996,7 @@
     method public android.app.job.JobInfo.Builder setEstimatedNetworkBytes(long);
     method public android.app.job.JobInfo.Builder setExtras(android.os.PersistableBundle);
     method public android.app.job.JobInfo.Builder setImportantWhileForeground(boolean);
+    method public android.app.job.JobInfo.Builder setIsPrefetch(boolean);
     method public android.app.job.JobInfo.Builder setMinimumLatency(long);
     method public android.app.job.JobInfo.Builder setOverrideDeadline(long);
     method public android.app.job.JobInfo.Builder setPeriodic(long);
@@ -10687,6 +10693,13 @@
     field public int reqTouchScreen;
   }
 
+  public class CrossProfileApps {
+    method public android.graphics.drawable.Drawable getProfileSwitchingIconDrawable(android.os.UserHandle);
+    method public java.lang.CharSequence getProfileSwitchingLabel(android.os.UserHandle);
+    method public java.util.List<android.os.UserHandle> getTargetUserProfiles();
+    method public void startMainActivity(android.content.ComponentName, android.os.UserHandle);
+  }
+
   public final class FeatureGroupInfo implements android.os.Parcelable {
     ctor public FeatureGroupInfo();
     ctor public FeatureGroupInfo(android.content.pm.FeatureGroupInfo);
@@ -11481,17 +11494,6 @@
 
 }
 
-package android.content.pm.crossprofile {
-
-  public class CrossProfileApps {
-    method public android.graphics.drawable.Drawable getProfileSwitchingIcon(android.os.UserHandle);
-    method public java.lang.CharSequence getProfileSwitchingLabel(android.os.UserHandle);
-    method public java.util.List<android.os.UserHandle> getTargetUserProfiles();
-    method public void startMainActivity(android.content.ComponentName, android.os.UserHandle);
-  }
-
-}
-
 package android.content.res {
 
   public class AssetFileDescriptor implements java.io.Closeable android.os.Parcelable {
@@ -15729,6 +15731,7 @@
     field public static final int CONTROL_AE_MODE_ON_ALWAYS_FLASH = 3; // 0x3
     field public static final int CONTROL_AE_MODE_ON_AUTO_FLASH = 2; // 0x2
     field public static final int CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE = 4; // 0x4
+    field public static final int CONTROL_AE_MODE_ON_EXTERNAL_FLASH = 5; // 0x5
     field public static final int CONTROL_AE_PRECAPTURE_TRIGGER_CANCEL = 2; // 0x2
     field public static final int CONTROL_AE_PRECAPTURE_TRIGGER_IDLE = 0; // 0x0
     field public static final int CONTROL_AE_PRECAPTURE_TRIGGER_START = 1; // 0x1
@@ -37908,7 +37911,6 @@
   }
 
   public static final class FieldClassification.Match {
-    method public java.lang.String getAlgorithm();
     method public java.lang.String getRemoteId();
     method public float getScore();
   }
@@ -42320,10 +42322,10 @@
   }
 
   public class MeasuredText implements android.text.Spanned {
-    method public static android.text.MeasuredText build(java.lang.CharSequence, android.text.TextPaint, android.text.TextDirectionHeuristic);
-    method public static android.text.MeasuredText build(java.lang.CharSequence, android.text.TextPaint, android.text.TextDirectionHeuristic, int, int);
     method public char charAt(int);
+    method public int getBreakStrategy();
     method public int getEnd();
+    method public int getHyphenationFrequency();
     method public android.text.TextPaint getPaint();
     method public int getParagraphCount();
     method public int getParagraphEnd(int);
@@ -42340,6 +42342,15 @@
     method public java.lang.CharSequence subSequence(int, int);
   }
 
+  public static final class MeasuredText.Builder {
+    ctor public MeasuredText.Builder(java.lang.CharSequence, android.text.TextPaint);
+    method public android.text.MeasuredText build();
+    method public android.text.MeasuredText.Builder setBreakStrategy(int);
+    method public android.text.MeasuredText.Builder setHyphenationFrequency(int);
+    method public android.text.MeasuredText.Builder setRange(int, int);
+    method public android.text.MeasuredText.Builder setTextDirection(android.text.TextDirectionHeuristic);
+  }
+
   public abstract interface NoCopySpan {
   }
 
@@ -44076,6 +44087,18 @@
     field public static final deprecated boolean RELEASE = true;
   }
 
+  public class DataUnit extends java.lang.Enum {
+    method public long toBytes(long);
+    method public static android.util.DataUnit valueOf(java.lang.String);
+    method public static final android.util.DataUnit[] values();
+    enum_constant public static final android.util.DataUnit GIBIBYTES;
+    enum_constant public static final android.util.DataUnit GIGABYTES;
+    enum_constant public static final android.util.DataUnit KIBIBYTES;
+    enum_constant public static final android.util.DataUnit KILOBYTES;
+    enum_constant public static final android.util.DataUnit MEBIBYTES;
+    enum_constant public static final android.util.DataUnit MEGABYTES;
+  }
+
   public class DebugUtils {
     method public static boolean isObjectSelected(java.lang.Object);
   }
@@ -48196,6 +48219,7 @@
     method public boolean isEnabled();
     method public boolean isFocusable();
     method public boolean isFocused();
+    method public boolean isHeading();
     method public boolean isImportantForAccessibility();
     method public boolean isLongClickable();
     method public boolean isMultiLine();
@@ -48239,6 +48263,7 @@
     method public void setError(java.lang.CharSequence);
     method public void setFocusable(boolean);
     method public void setFocused(boolean);
+    method public void setHeading(boolean);
     method public void setHintText(java.lang.CharSequence);
     method public void setImportantForAccessibility(boolean);
     method public void setInputType(int);
@@ -48372,7 +48397,7 @@
     method public int getColumnSpan();
     method public int getRowIndex();
     method public int getRowSpan();
-    method public boolean isHeading();
+    method public deprecated boolean isHeading();
     method public boolean isSelected();
     method public static android.view.accessibility.AccessibilityNodeInfo.CollectionItemInfo obtain(int, int, int, int, boolean);
     method public static android.view.accessibility.AccessibilityNodeInfo.CollectionItemInfo obtain(int, int, int, int, boolean, boolean);
@@ -52597,6 +52622,7 @@
     method public android.graphics.Typeface getTypeface();
     method public android.text.style.URLSpan[] getUrls();
     method public boolean hasSelection();
+    method public boolean isAccessibilityHeading();
     method public boolean isAllCaps();
     method public boolean isCursorVisible();
     method public boolean isElegantTextHeight();
@@ -52619,6 +52645,7 @@
     method protected void onTextChanged(java.lang.CharSequence, int, int, int);
     method public boolean onTextContextMenuItem(int);
     method public void removeTextChangedListener(android.text.TextWatcher);
+    method public void setAccessibilityHeading(boolean);
     method public void setAllCaps(boolean);
     method public final void setAutoLinkMask(int);
     method public void setAutoSizeTextTypeUniformWithConfiguration(int, int, int, int);
@@ -72420,197 +72447,6 @@
 
 }
 
-package junit.framework {
-
-  public class Assert {
-    ctor protected Assert();
-    method public static void assertEquals(java.lang.String, java.lang.Object, java.lang.Object);
-    method public static void assertEquals(java.lang.Object, java.lang.Object);
-    method public static void assertEquals(java.lang.String, java.lang.String, java.lang.String);
-    method public static void assertEquals(java.lang.String, java.lang.String);
-    method public static void assertEquals(java.lang.String, double, double, double);
-    method public static void assertEquals(double, double, double);
-    method public static void assertEquals(java.lang.String, float, float, float);
-    method public static void assertEquals(float, float, float);
-    method public static void assertEquals(java.lang.String, long, long);
-    method public static void assertEquals(long, long);
-    method public static void assertEquals(java.lang.String, boolean, boolean);
-    method public static void assertEquals(boolean, boolean);
-    method public static void assertEquals(java.lang.String, byte, byte);
-    method public static void assertEquals(byte, byte);
-    method public static void assertEquals(java.lang.String, char, char);
-    method public static void assertEquals(char, char);
-    method public static void assertEquals(java.lang.String, short, short);
-    method public static void assertEquals(short, short);
-    method public static void assertEquals(java.lang.String, int, int);
-    method public static void assertEquals(int, int);
-    method public static void assertFalse(java.lang.String, boolean);
-    method public static void assertFalse(boolean);
-    method public static void assertNotNull(java.lang.Object);
-    method public static void assertNotNull(java.lang.String, java.lang.Object);
-    method public static void assertNotSame(java.lang.String, java.lang.Object, java.lang.Object);
-    method public static void assertNotSame(java.lang.Object, java.lang.Object);
-    method public static void assertNull(java.lang.Object);
-    method public static void assertNull(java.lang.String, java.lang.Object);
-    method public static void assertSame(java.lang.String, java.lang.Object, java.lang.Object);
-    method public static void assertSame(java.lang.Object, java.lang.Object);
-    method public static void assertTrue(java.lang.String, boolean);
-    method public static void assertTrue(boolean);
-    method public static void fail(java.lang.String);
-    method public static void fail();
-    method public static void failNotEquals(java.lang.String, java.lang.Object, java.lang.Object);
-    method public static void failNotSame(java.lang.String, java.lang.Object, java.lang.Object);
-    method public static void failSame(java.lang.String);
-    method public static java.lang.String format(java.lang.String, java.lang.Object, java.lang.Object);
-  }
-
-  public class AssertionFailedError extends java.lang.AssertionError {
-    ctor public AssertionFailedError();
-    ctor public AssertionFailedError(java.lang.String);
-  }
-
-  public class ComparisonFailure extends junit.framework.AssertionFailedError {
-    ctor public ComparisonFailure(java.lang.String, java.lang.String, java.lang.String);
-    method public java.lang.String getActual();
-    method public java.lang.String getExpected();
-  }
-
-  public abstract interface Protectable {
-    method public abstract void protect() throws java.lang.Throwable;
-  }
-
-  public abstract interface Test {
-    method public abstract int countTestCases();
-    method public abstract void run(junit.framework.TestResult);
-  }
-
-  public abstract class TestCase extends junit.framework.Assert implements junit.framework.Test {
-    ctor public TestCase();
-    ctor public TestCase(java.lang.String);
-    method public int countTestCases();
-    method protected junit.framework.TestResult createResult();
-    method public java.lang.String getName();
-    method public junit.framework.TestResult run();
-    method public void run(junit.framework.TestResult);
-    method public void runBare() throws java.lang.Throwable;
-    method protected void runTest() throws java.lang.Throwable;
-    method public void setName(java.lang.String);
-    method protected void setUp() throws java.lang.Exception;
-    method protected void tearDown() throws java.lang.Exception;
-  }
-
-  public class TestFailure {
-    ctor public TestFailure(junit.framework.Test, java.lang.Throwable);
-    method public java.lang.String exceptionMessage();
-    method public junit.framework.Test failedTest();
-    method public boolean isFailure();
-    method public java.lang.Throwable thrownException();
-    method public java.lang.String trace();
-    field protected junit.framework.Test fFailedTest;
-    field protected java.lang.Throwable fThrownException;
-  }
-
-  public abstract interface TestListener {
-    method public abstract void addError(junit.framework.Test, java.lang.Throwable);
-    method public abstract void addFailure(junit.framework.Test, junit.framework.AssertionFailedError);
-    method public abstract void endTest(junit.framework.Test);
-    method public abstract void startTest(junit.framework.Test);
-  }
-
-  public class TestResult {
-    ctor public TestResult();
-    method public synchronized void addError(junit.framework.Test, java.lang.Throwable);
-    method public synchronized void addFailure(junit.framework.Test, junit.framework.AssertionFailedError);
-    method public synchronized void addListener(junit.framework.TestListener);
-    method public void endTest(junit.framework.Test);
-    method public synchronized int errorCount();
-    method public synchronized java.util.Enumeration<junit.framework.TestFailure> errors();
-    method public synchronized int failureCount();
-    method public synchronized java.util.Enumeration<junit.framework.TestFailure> failures();
-    method public synchronized void removeListener(junit.framework.TestListener);
-    method protected void run(junit.framework.TestCase);
-    method public synchronized int runCount();
-    method public void runProtected(junit.framework.Test, junit.framework.Protectable);
-    method public synchronized boolean shouldStop();
-    method public void startTest(junit.framework.Test);
-    method public synchronized void stop();
-    method public synchronized boolean wasSuccessful();
-    field protected java.util.Vector<junit.framework.TestFailure> fErrors;
-    field protected java.util.Vector<junit.framework.TestFailure> fFailures;
-    field protected java.util.Vector<junit.framework.TestListener> fListeners;
-    field protected int fRunTests;
-  }
-
-  public class TestSuite implements junit.framework.Test {
-    ctor public TestSuite();
-    ctor public TestSuite(java.lang.Class<?>);
-    ctor public TestSuite(java.lang.Class<? extends junit.framework.TestCase>, java.lang.String);
-    ctor public TestSuite(java.lang.String);
-    ctor public TestSuite(java.lang.Class<?>...);
-    ctor public TestSuite(java.lang.Class<? extends junit.framework.TestCase>[], java.lang.String);
-    method public void addTest(junit.framework.Test);
-    method public void addTestSuite(java.lang.Class<? extends junit.framework.TestCase>);
-    method public int countTestCases();
-    method public static junit.framework.Test createTest(java.lang.Class<?>, java.lang.String);
-    method public java.lang.String getName();
-    method public static java.lang.reflect.Constructor<?> getTestConstructor(java.lang.Class<?>) throws java.lang.NoSuchMethodException;
-    method public void run(junit.framework.TestResult);
-    method public void runTest(junit.framework.Test, junit.framework.TestResult);
-    method public void setName(java.lang.String);
-    method public junit.framework.Test testAt(int);
-    method public int testCount();
-    method public java.util.Enumeration<junit.framework.Test> tests();
-    method public static junit.framework.Test warning(java.lang.String);
-  }
-
-}
-
-package junit.runner {
-
-  public abstract class BaseTestRunner implements junit.framework.TestListener {
-    ctor public BaseTestRunner();
-    method public synchronized void addError(junit.framework.Test, java.lang.Throwable);
-    method public synchronized void addFailure(junit.framework.Test, junit.framework.AssertionFailedError);
-    method protected void clearStatus();
-    method public java.lang.String elapsedTimeAsString(long);
-    method public synchronized void endTest(junit.framework.Test);
-    method public java.lang.String extractClassName(java.lang.String);
-    method public static java.lang.String getFilteredTrace(java.lang.Throwable);
-    method public static java.lang.String getFilteredTrace(java.lang.String);
-    method public deprecated junit.runner.TestSuiteLoader getLoader();
-    method public static java.lang.String getPreference(java.lang.String);
-    method public static int getPreference(java.lang.String, int);
-    method protected static java.util.Properties getPreferences();
-    method public junit.framework.Test getTest(java.lang.String);
-    method public static deprecated boolean inVAJava();
-    method protected java.lang.Class<?> loadSuiteClass(java.lang.String) throws java.lang.ClassNotFoundException;
-    method protected java.lang.String processArguments(java.lang.String[]);
-    method protected abstract void runFailed(java.lang.String);
-    method public static void savePreferences() throws java.io.IOException;
-    method public void setLoading(boolean);
-    method public void setPreference(java.lang.String, java.lang.String);
-    method protected static void setPreferences(java.util.Properties);
-    method protected static boolean showStackRaw();
-    method public synchronized void startTest(junit.framework.Test);
-    method public abstract void testEnded(java.lang.String);
-    method public abstract void testFailed(int, junit.framework.Test, java.lang.Throwable);
-    method public abstract void testStarted(java.lang.String);
-    method public static java.lang.String truncate(java.lang.String);
-    method protected boolean useReloadingTestSuiteLoader();
-    field public static final java.lang.String SUITE_METHODNAME = "suite";
-  }
-
-  public abstract interface TestSuiteLoader {
-    method public abstract java.lang.Class load(java.lang.String) throws java.lang.ClassNotFoundException;
-    method public abstract java.lang.Class reload(java.lang.Class) throws java.lang.ClassNotFoundException;
-  }
-
-  public class Version {
-    method public static java.lang.String id();
-  }
-
-}
-
 package org.apache.http.conn {
 
   public deprecated class ConnectTimeoutException extends java.io.InterruptedIOException {
diff --git a/api/system-current.txt b/api/system-current.txt
index a29d3a0..66b6d99 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -790,7 +790,9 @@
     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_PERMISSIONS = "android.intent.action.REVIEW_PERMISSIONS";
-    field public static final java.lang.String ACTION_SIM_STATE_CHANGED = "android.intent.action.SIM_STATE_CHANGED";
+    field public static final java.lang.String ACTION_SIM_APPLICATION_STATE_CHANGED = "android.intent.action.SIM_APPLICATION_STATE_CHANGED";
+    field public static final java.lang.String ACTION_SIM_CARD_STATE_CHANGED = "android.intent.action.SIM_CARD_STATE_CHANGED";
+    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_UPGRADE_SETUP = "android.intent.action.UPGRADE_SETUP";
     field public static final java.lang.String ACTION_USER_REMOVED = "android.intent.action.USER_REMOVED";
     field public static final java.lang.String ACTION_VOICE_ASSIST = "android.intent.action.VOICE_ASSIST";
@@ -1775,9 +1777,9 @@
     method public android.hardware.radio.ProgramSelector.Identifier[] getAllIds(int);
     method public long getFirstId(int);
     method public android.hardware.radio.ProgramSelector.Identifier getPrimaryId();
-    method public int getProgramType();
+    method public deprecated int getProgramType();
     method public android.hardware.radio.ProgramSelector.Identifier[] getSecondaryIds();
-    method public long[] getVendorIds();
+    method public deprecated long[] getVendorIds();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.hardware.radio.ProgramSelector> CREATOR;
     field public static final int IDENTIFIER_TYPE_AMFM_FREQUENCY = 1; // 0x1
@@ -1785,27 +1787,31 @@
     field public static final int IDENTIFIER_TYPE_DAB_FREQUENCY = 8; // 0x8
     field public static final int IDENTIFIER_TYPE_DAB_SCID = 7; // 0x7
     field public static final int IDENTIFIER_TYPE_DAB_SIDECC = 5; // 0x5
+    field public static final int IDENTIFIER_TYPE_DAB_SID_EXT = 5; // 0x5
     field public static final int IDENTIFIER_TYPE_DRMO_FREQUENCY = 10; // 0xa
-    field public static final int IDENTIFIER_TYPE_DRMO_MODULATION = 11; // 0xb
+    field public static final deprecated int IDENTIFIER_TYPE_DRMO_MODULATION = 11; // 0xb
     field public static final int IDENTIFIER_TYPE_DRMO_SERVICE_ID = 9; // 0x9
     field public static final int IDENTIFIER_TYPE_HD_STATION_ID_EXT = 3; // 0x3
-    field public static final int IDENTIFIER_TYPE_HD_SUBCHANNEL = 4; // 0x4
+    field public static final int IDENTIFIER_TYPE_HD_STATION_NAME = 10004; // 0x2714
+    field public static final deprecated int IDENTIFIER_TYPE_HD_SUBCHANNEL = 4; // 0x4
     field public static final int IDENTIFIER_TYPE_INVALID = 0; // 0x0
     field public static final int IDENTIFIER_TYPE_RDS_PI = 2; // 0x2
     field public static final int IDENTIFIER_TYPE_SXM_CHANNEL = 13; // 0xd
     field public static final int IDENTIFIER_TYPE_SXM_SERVICE_ID = 12; // 0xc
-    field public static final int IDENTIFIER_TYPE_VENDOR_PRIMARY_END = 1999; // 0x7cf
-    field public static final int IDENTIFIER_TYPE_VENDOR_PRIMARY_START = 1000; // 0x3e8
-    field public static final int PROGRAM_TYPE_AM = 1; // 0x1
-    field public static final int PROGRAM_TYPE_AM_HD = 3; // 0x3
-    field public static final int PROGRAM_TYPE_DAB = 5; // 0x5
-    field public static final int PROGRAM_TYPE_DRMO = 6; // 0x6
-    field public static final int PROGRAM_TYPE_FM = 2; // 0x2
-    field public static final int PROGRAM_TYPE_FM_HD = 4; // 0x4
-    field public static final int PROGRAM_TYPE_INVALID = 0; // 0x0
-    field public static final int PROGRAM_TYPE_SXM = 7; // 0x7
-    field public static final int PROGRAM_TYPE_VENDOR_END = 1999; // 0x7cf
-    field public static final int PROGRAM_TYPE_VENDOR_START = 1000; // 0x3e8
+    field public static final int IDENTIFIER_TYPE_VENDOR_END = 1999; // 0x7cf
+    field public static final deprecated int IDENTIFIER_TYPE_VENDOR_PRIMARY_END = 1999; // 0x7cf
+    field public static final deprecated int IDENTIFIER_TYPE_VENDOR_PRIMARY_START = 1000; // 0x3e8
+    field public static final int IDENTIFIER_TYPE_VENDOR_START = 1000; // 0x3e8
+    field public static final deprecated int PROGRAM_TYPE_AM = 1; // 0x1
+    field public static final deprecated int PROGRAM_TYPE_AM_HD = 3; // 0x3
+    field public static final deprecated int PROGRAM_TYPE_DAB = 5; // 0x5
+    field public static final deprecated int PROGRAM_TYPE_DRMO = 6; // 0x6
+    field public static final deprecated int PROGRAM_TYPE_FM = 2; // 0x2
+    field public static final deprecated int PROGRAM_TYPE_FM_HD = 4; // 0x4
+    field public static final deprecated int PROGRAM_TYPE_INVALID = 0; // 0x0
+    field public static final deprecated int PROGRAM_TYPE_SXM = 7; // 0x7
+    field public static final deprecated int PROGRAM_TYPE_VENDOR_END = 1999; // 0x7cf
+    field public static final deprecated int PROGRAM_TYPE_VENDOR_START = 1000; // 0x3e8
   }
 
   public static final class ProgramSelector.Identifier implements android.os.Parcelable {
@@ -1820,7 +1826,7 @@
   public static abstract class ProgramSelector.IdentifierType implements java.lang.annotation.Annotation {
   }
 
-  public static abstract class ProgramSelector.ProgramType implements java.lang.annotation.Annotation {
+  public static abstract deprecated class ProgramSelector.ProgramType implements java.lang.annotation.Annotation {
   }
 
   public class RadioManager {
@@ -2858,9 +2864,18 @@
     method public void onTetheringStarted();
   }
 
+  public final class IpSecManager {
+    method public android.net.IpSecManager.IpSecTunnelInterface createIpSecTunnelInterface(java.net.InetAddress, java.net.InetAddress, android.net.Network) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException;
+  }
+
+  public static final class IpSecManager.IpSecTunnelInterface implements java.lang.AutoCloseable {
+    method public void close();
+    method public java.lang.String getInterfaceName();
+  }
+
   public static class IpSecTransform.Builder {
+    method public android.net.IpSecTransform buildTunnelModeTransform(java.net.InetAddress, android.net.IpSecManager.SecurityParameterIndex) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException, android.net.IpSecManager.SpiUnavailableException;
     method public android.net.IpSecTransform.Builder setNattKeepalive(int);
-    method public android.net.IpSecTransform.Builder setUnderlyingNetwork(android.net.Network);
   }
 
   public class NetworkKey implements android.os.Parcelable {
@@ -3856,6 +3871,18 @@
 
 }
 
+package android.service.autofill {
+
+  public abstract class AutofillFieldClassificationService extends android.app.Service {
+    method public android.os.IBinder onBind(android.content.Intent);
+    method public float[][] onGetScores(java.lang.String, android.os.Bundle, java.util.List<android.view.autofill.AutofillValue>, java.util.List<java.lang.String>);
+    field public static final java.lang.String SERVICE_INTERFACE = "android.service.autofill.AutofillFieldClassificationService";
+    field public static final java.lang.String SERVICE_META_DATA_KEY_AVAILABLE_ALGORITHMS = "android.autofill.field_classification.available_algorithms";
+    field public static final java.lang.String SERVICE_META_DATA_KEY_DEFAULT_ALGORITHM = "android.autofill.field_classification.default_algorithm";
+  }
+
+}
+
 package android.service.notification {
 
   public final class Adjustment implements android.os.Parcelable {
@@ -4357,6 +4384,8 @@
 
   public class SubscriptionManager {
     method public java.util.List<android.telephony.SubscriptionPlan> getSubscriptionPlans(int);
+    method public void setSubscriptionOverrideCongested(int, boolean, long);
+    method public void setSubscriptionOverrideUnmetered(int, boolean, long);
     method public void setSubscriptionPlans(int, java.util.List<android.telephony.SubscriptionPlan>);
     field public static final java.lang.String ACTION_MANAGE_SUBSCRIPTION_PLANS = "android.telephony.action.MANAGE_SUBSCRIPTION_PLANS";
     field public static final java.lang.String ACTION_REFRESH_SUBSCRIPTION_PLANS = "android.telephony.action.REFRESH_SUBSCRIPTION_PLANS";
@@ -4438,6 +4467,8 @@
     method public deprecated boolean getDataEnabled();
     method public deprecated boolean getDataEnabled(int);
     method public boolean getEmergencyCallbackMode();
+    method public int getSimApplicationState();
+    method public int getSimCardState();
     method public java.util.List<android.telephony.TelephonyHistogram> getTelephonyHistograms();
     method public android.os.Bundle getVisualVoicemailSettings();
     method public int getVoiceActivationState();
@@ -4471,6 +4502,7 @@
     field public static final int CARRIER_PRIVILEGE_STATUS_HAS_ACCESS = 1; // 0x1
     field public static final int CARRIER_PRIVILEGE_STATUS_NO_ACCESS = 0; // 0x0
     field public static final int CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED = -1; // 0xffffffff
+    field public static final java.lang.String EXTRA_SIM_STATE = "android.telephony.extra.SIM_STATE";
     field public static final java.lang.String EXTRA_VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL = "android.telephony.extra.VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL";
     field public static final java.lang.String EXTRA_VOICEMAIL_SCRAMBLED_PIN_STRING = "android.telephony.extra.VOICEMAIL_SCRAMBLED_PIN_STRING";
     field public static final int SIM_ACTIVATION_STATE_ACTIVATED = 2; // 0x2
@@ -4478,6 +4510,8 @@
     field public static final int SIM_ACTIVATION_STATE_DEACTIVATED = 3; // 0x3
     field public static final int SIM_ACTIVATION_STATE_RESTRICTED = 4; // 0x4
     field public static final int SIM_ACTIVATION_STATE_UNKNOWN = 0; // 0x0
+    field public static final int SIM_STATE_LOADED = 10; // 0xa
+    field public static final int SIM_STATE_PRESENT = 11; // 0xb
   }
 
   public abstract class VisualVoicemailService extends android.app.Service {
diff --git a/api/test-current.txt b/api/test-current.txt
index 6369bb4..acc819e 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -563,11 +563,6 @@
     method public void apply(android.service.autofill.ValueFinder, android.widget.RemoteViews, int) throws java.lang.Exception;
   }
 
-  public final class EditDistanceScorer {
-    method public static android.service.autofill.EditDistanceScorer getInstance();
-    method public float getScore(android.view.autofill.AutofillValue, java.lang.String);
-  }
-
   public final class FillResponse implements android.os.Parcelable {
     method public int getFlags();
   }
@@ -966,6 +961,9 @@
 
   public final class Choreographer {
     method public static long getFrameDelay();
+    method public void postCallback(int, java.lang.Runnable, java.lang.Object);
+    method public void postCallbackDelayed(int, java.lang.Runnable, java.lang.Object, long);
+    method public void removeCallbacks(int, java.lang.Runnable, java.lang.Object);
     method public static void setFrameDelay(long);
     field public static final int CALLBACK_ANIMATION = 1; // 0x1
   }
diff --git a/cmds/incident_helper/src/TextParserBase.h b/cmds/incident_helper/src/TextParserBase.h
index c41612d..1667966 100644
--- a/cmds/incident_helper/src/TextParserBase.h
+++ b/cmds/incident_helper/src/TextParserBase.h
@@ -68,4 +68,4 @@
     virtual status_t Parse(const int in, const int out) const;
 };
 
-#endif // TEXT_PARSER_BASE_H
\ No newline at end of file
+#endif // TEXT_PARSER_BASE_H
diff --git a/cmds/incidentd/README.md b/cmds/incidentd/README.md
index ad0fa08..71c6deb 100644
--- a/cmds/incidentd/README.md
+++ b/cmds/incidentd/README.md
@@ -12,8 +12,8 @@
 
 ```
 root$ mmm -j frameworks/base/cmds/incidentd && \
-adb push $OUT/data/nativetest/incidentd_test/* /data/nativetest/incidentd_test/ && \
-adb shell /data/nativetest/incidentd_test/incidentd_test 2>/dev/null
+adb push $OUT/data/nativetest/incidentd_test/* /data/nativetest/ && \
+adb shell /data/nativetest/incidentd_test 2>/dev/null
 ```
 
 Run the test via AndroidTest.xml
diff --git a/cmds/incidentd/incidentd.rc b/cmds/incidentd/incidentd.rc
index 66667dc..1bd1468 100644
--- a/cmds/incidentd/incidentd.rc
+++ b/cmds/incidentd/incidentd.rc
@@ -19,4 +19,4 @@
 
 on post-fs-data
     # Create directory for incidentd
-    mkdir /data/misc/incidents 0770 root root
+    mkdir /data/misc/incidents 0770 incidentd incidentd
diff --git a/cmds/incidentd/src/FdBuffer.cpp b/cmds/incidentd/src/FdBuffer.cpp
index 30dd339..0fff4e6 100644
--- a/cmds/incidentd/src/FdBuffer.cpp
+++ b/cmds/incidentd/src/FdBuffer.cpp
@@ -63,12 +63,14 @@
 
         int64_t remainingTime = (mStartTime + timeout) - uptimeMillis();
         if (remainingTime <= 0) {
+            if (DEBUG) ALOGD("timed out due to long read");
             mTimedOut = true;
             break;
         }
 
         int count = poll(&pfds, 1, remainingTime);
         if (count == 0) {
+            if (DEBUG) ALOGD("timed out due to block calling poll");
             mTimedOut = true;
             break;
         } else if (count < 0) {
@@ -129,6 +131,7 @@
 
         int64_t remainingTime = (mStartTime + timeoutMs) - uptimeMillis();
         if (remainingTime <= 0) {
+            if (DEBUG) ALOGD("timed out due to long read");
             mTimedOut = true;
             break;
         }
@@ -136,6 +139,7 @@
         // wait for any pfds to be ready to perform IO
         int count = poll(pfds, 3, remainingTime);
         if (count == 0) {
+            if (DEBUG) ALOGD("timed out due to block calling poll");
             mTimedOut = true;
             break;
         } else if (count < 0) {
diff --git a/cmds/incidentd/src/IncidentService.cpp b/cmds/incidentd/src/IncidentService.cpp
index c4b54bb..a97eb86 100644
--- a/cmds/incidentd/src/IncidentService.cpp
+++ b/cmds/incidentd/src/IncidentService.cpp
@@ -43,8 +43,9 @@
 String16 const USAGE_STATS_PERMISSION("android.permission.PACKAGE_USAGE_STATS");
 
 static Status
-checkIncidentPermissions()
+checkIncidentPermissions(const IncidentReportArgs& args)
 {
+    // checking calling permission.
     if (!checkCallingPermission(DUMP_PERMISSION)) {
         ALOGW("Calling pid %d and uid %d does not have permission: android.permission.DUMP",
                 IPCThreadState::self()->getCallingPid(), IPCThreadState::self()->getCallingUid());
@@ -57,10 +58,24 @@
         return Status::fromExceptionCode(Status::EX_SECURITY,
                 "Calling process does not have permission: android.permission.USAGE_STATS");
     }
+
+    // checking calling request uid permission.
+    uid_t callingUid = IPCThreadState::self()->getCallingUid();
+    switch (args.dest()) {
+        case DEST_LOCAL:
+            if (callingUid != AID_SHELL || callingUid != AID_ROOT) {
+                return Status::fromExceptionCode(Status::EX_SECURITY,
+                    "Calling process does not have permission to get local data.");
+            }
+        case DEST_EXPLICIT:
+            if (callingUid != AID_SHELL || callingUid != AID_ROOT ||
+                callingUid != AID_STATSD || callingUid != AID_SYSTEM) {
+                return Status::fromExceptionCode(Status::EX_SECURITY,
+                    "Calling process does not have permission to get explicit data.");
+            }
+    }
     return Status::ok();
 }
-
-
 // ================================================================================
 ReportRequestQueue::ReportRequestQueue()
 {
@@ -71,7 +86,7 @@
 }
 
 void
-ReportRequestQueue::addRequest(const sp<ReportRequest>& request) 
+ReportRequestQueue::addRequest(const sp<ReportRequest>& request)
 {
     unique_lock<mutex> lock(mLock);
     mQueue.push_back(request);
@@ -196,7 +211,7 @@
 {
     ALOGI("reportIncident");
 
-    Status status = checkIncidentPermissions();
+    Status status = checkIncidentPermissions(args);
     if (!status.isOk()) {
         return status;
     }
@@ -212,7 +227,7 @@
 {
     ALOGI("reportIncidentToStream");
 
-    Status status = checkIncidentPermissions();
+    Status status = checkIncidentPermissions(args);
     if (!status.isOk()) {
         return status;
     }
diff --git a/cmds/incidentd/src/Reporter.cpp b/cmds/incidentd/src/Reporter.cpp
index 34930aa..bd559d6 100644
--- a/cmds/incidentd/src/Reporter.cpp
+++ b/cmds/incidentd/src/Reporter.cpp
@@ -251,7 +251,7 @@
     // Override umask. Not super critical. If it fails go on with life.
     chmod(filename, 0660);
 
-    if (chown(filename, AID_SYSTEM, AID_SYSTEM)) {
+    if (chown(filename, AID_INCIDENTD, AID_INCIDENTD)) {
         ALOGE("Unable to change ownership of incident file %s: %s\n", filename, strerror(errno));
         status_t err = -errno;
         unlink(mFilename.c_str());
diff --git a/cmds/incidentd/src/Section.cpp b/cmds/incidentd/src/Section.cpp
index 61d16f8..0827785 100644
--- a/cmds/incidentd/src/Section.cpp
+++ b/cmds/incidentd/src/Section.cpp
@@ -19,6 +19,7 @@
 #include "Section.h"
 
 #include <errno.h>
+#include <sys/prctl.h>
 #include <unistd.h>
 #include <wait.h>
 
@@ -30,7 +31,6 @@
 #include <log/log_event_list.h>
 #include <log/logprint.h>
 #include <log/log_read.h>
-#include <private/android_filesystem_config.h> // for AID_NOBODY
 #include <private/android_logger.h>
 
 #include "FdBuffer.h"
@@ -55,26 +55,20 @@
 fork_execute_incident_helper(const int id, const char* name, Fpipe& p2cPipe, Fpipe& c2pPipe)
 {
     const char* ihArgs[] { INCIDENT_HELPER, "-s", String8::format("%d", id).string(), NULL };
-
     // fork used in multithreaded environment, avoid adding unnecessary code in child process
     pid_t pid = fork();
     if (pid == 0) {
-        // child process executes incident helper as nobody
-        if (setgid(AID_NOBODY) == -1) {
-            ALOGW("%s can't change gid: %s", name, strerror(errno));
-            _exit(EXIT_FAILURE);
-        }
-        if (setuid(AID_NOBODY) == -1) {
-            ALOGW("%s can't change uid: %s", name, strerror(errno));
-            _exit(EXIT_FAILURE);
-        }
-
-        if (dup2(p2cPipe.readFd(),  STDIN_FILENO)  != 0 || !p2cPipe.close() ||
-            dup2(c2pPipe.writeFd(), STDOUT_FILENO) != 1 || !c2pPipe.close()) {
+        if (TEMP_FAILURE_RETRY(dup2(p2cPipe.readFd(),  STDIN_FILENO))  != 0
+            || !p2cPipe.close()
+            || TEMP_FAILURE_RETRY(dup2(c2pPipe.writeFd(), STDOUT_FILENO)) != 1
+            || !c2pPipe.close()) {
             ALOGW("%s can't setup stdin and stdout for incident helper", name);
             _exit(EXIT_FAILURE);
         }
 
+        /* make sure the child dies when incidentd dies */
+        prctl(PR_SET_PDEATHSIG, SIGKILL);
+
         execv(INCIDENT_HELPER, const_cast<char**>(ihArgs));
 
         ALOGW("%s failed in incident helper process: %s", name, strerror(errno));
@@ -87,11 +81,23 @@
 }
 
 // ================================================================================
+static status_t statusCode(int status) {
+    if (WIFSIGNALED(status)) {
+      ALOGD("return by signal: %s", strerror(WTERMSIG(status)));
+      return -WTERMSIG(status);
+    } else if (WIFEXITED(status) && WEXITSTATUS(status) > 0) {
+      ALOGD("return by exit: %s", strerror(WEXITSTATUS(status)));
+      return -WEXITSTATUS(status);
+    }
+    return NO_ERROR;
+}
+
 static status_t kill_child(pid_t pid) {
     int status;
+    ALOGD("try to kill child process %d", pid);
     kill(pid, SIGKILL);
     if (waitpid(pid, &status, 0) == -1) return -1;
-    return WIFEXITED(status) == 0 ? NO_ERROR : -WEXITSTATUS(status);
+    return statusCode(status);
 }
 
 static status_t wait_child(pid_t pid) {
@@ -104,7 +110,7 @@
         nanosleep(&WAIT_INTERVAL_NS, NULL);
     }
     if (!died) return kill_child(pid);
-    return WIFEXITED(status) == 0 ? NO_ERROR : -WEXITSTATUS(status);
+    return statusCode(status);
 }
 // ================================================================================
 static const Privacy*
@@ -275,9 +281,9 @@
     status_t readStatus = buffer.readProcessedDataInStream(fd, p2cPipe.writeFd(), c2pPipe.readFd(),
             this->timeoutMs, mIsSysfs);
     if (readStatus != NO_ERROR || buffer.timedOut()) {
-        ALOGW("FileSection '%s' failed to read data from incident helper: %s, timedout: %s, kill: %s",
-            this->name.string(), strerror(-readStatus), buffer.timedOut() ? "true" : "false",
-            strerror(-kill_child(pid)));
+        ALOGW("FileSection '%s' failed to read data from incident helper: %s, timedout: %s",
+            this->name.string(), strerror(-readStatus), buffer.timedOut() ? "true" : "false");
+        kill_child(pid);
         return readStatus;
     }
 
@@ -543,10 +549,10 @@
     close(cmdPipe.writeFd());
     status_t readStatus = buffer.read(ihPipe.readFd(), this->timeoutMs);
     if (readStatus != NO_ERROR || buffer.timedOut()) {
-        ALOGW("CommandSection '%s' failed to read data from incident helper: %s, "
-            "timedout: %s, kill command: %s, kill incident helper: %s",
-            this->name.string(), strerror(-readStatus), buffer.timedOut() ? "true" : "false",
-            strerror(-kill_child(cmdPid)), strerror(-kill_child(ihPid)));
+        ALOGW("CommandSection '%s' failed to read data from incident helper: %s, timedout: %s",
+            this->name.string(), strerror(-readStatus), buffer.timedOut() ? "true" : "false");
+        kill_child(cmdPid);
+        kill_child(ihPid);
         return readStatus;
     }
 
diff --git a/cmds/incidentd/src/io_util.cpp b/cmds/incidentd/src/io_util.cpp
index af4a35c..90f543e 100644
--- a/cmds/incidentd/src/io_util.cpp
+++ b/cmds/incidentd/src/io_util.cpp
@@ -23,7 +23,7 @@
 status_t write_all(int fd, uint8_t const* buf, size_t size)
 {
     while (size > 0) {
-        ssize_t amt = ::write(fd, buf, size);
+        ssize_t amt = TEMP_FAILURE_RETRY(::write(fd, buf, size));
         if (amt < 0) {
             return -errno;
         }
diff --git a/cmds/incidentd/src/report_directory.cpp b/cmds/incidentd/src/report_directory.cpp
index 65030b3..20111d8 100644
--- a/cmds/incidentd/src/report_directory.cpp
+++ b/cmds/incidentd/src/report_directory.cpp
@@ -58,26 +58,9 @@
                 goto done;
             }
         } else {
-            if (mkdir(dir, 0770)) {
-                ALOGE("No incident reports today. "
-                        "Unable to create incident report dir %s: %s", dir,
-                        strerror(errno));
-                err = -errno;
-                goto done;
-            }
-            if (chmod(dir, 0770)) {
-                ALOGE("No incident reports today. "
-                        "Unable to set permissions for incident report dir %s: %s", dir,
-                        strerror(errno));
-                err = -errno;
-                goto done;
-            }
-            if (chown(dir, AID_SYSTEM, AID_SYSTEM)) {
-                ALOGE("No incident reports today. Unable to change ownership of dir %s: %s\n",
-                        dir, strerror(errno));
-                err = -errno;
-                goto done;
-            }
+            ALOGE("No such directory %s, something wrong.", dir);
+            err = -1;
+            goto done;
         }
         if (!last) {
             *d++ = '/';
@@ -97,8 +80,7 @@
         err = BAD_VALUE;
         goto done;
     }
-    if ((st.st_uid != AID_SYSTEM && st.st_uid != AID_ROOT) ||
-        (st.st_gid != AID_SYSTEM && st.st_gid != AID_ROOT)) {
+    if (st.st_uid != AID_INCIDENTD || st.st_gid != AID_INCIDENTD) {
         ALOGE("No incident reports today. Owner is %d and group is %d on report directory %s",
                 st.st_uid, st.st_gid, directory);
         err = BAD_VALUE;
diff --git a/cmds/statsd/Android.mk b/cmds/statsd/Android.mk
index 9bddbcb..01f4a84 100644
--- a/cmds/statsd/Android.mk
+++ b/cmds/statsd/Android.mk
@@ -34,6 +34,7 @@
     src/config/ConfigKey.cpp \
     src/config/ConfigListener.cpp \
     src/config/ConfigManager.cpp \
+    src/external/Perfetto.cpp \
     src/external/StatsPuller.cpp \
     src/external/StatsCompanionServicePuller.cpp \
     src/external/SubsystemSleepStatePuller.cpp \
@@ -57,6 +58,7 @@
     src/metrics/MetricsManager.cpp \
     src/metrics/metrics_manager_util.cpp \
     src/packages/UidMap.cpp \
+    src/perfetto/perfetto_config.proto \
     src/storage/StorageManager.cpp \
     src/StatsLogProcessor.cpp \
     src/StatsService.cpp \
@@ -134,7 +136,7 @@
 
 LOCAL_MODULE_CLASS := EXECUTABLES
 
-LOCAL_INIT_RC := statsd.rc
+#LOCAL_INIT_RC := statsd.rc
 
 include $(BUILD_EXECUTABLE)
 
@@ -209,6 +211,7 @@
 LOCAL_SRC_FILES := \
     src/stats_log.proto \
     src/statsd_config.proto \
+    src/perfetto/perfetto_config.proto \
     src/atoms.proto
 
 LOCAL_PROTOC_OPTIMIZE_TYPE := lite
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index 0ed1c1f..ca097d0 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -185,6 +185,7 @@
  */
 void StatsService::dump_impl(FILE* out) {
     mConfigManager->Dump(out);
+    StatsdStats::getInstance().dumpStats(out);
 }
 
 /**
@@ -296,9 +297,8 @@
     fprintf(out, "  NAME          The name of the configuration\n");
     fprintf(out, "\n");
     fprintf(out, "\n");
-    fprintf(out, "usage: adb shell cmd stats print-stats [reset]\n");
+    fprintf(out, "usage: adb shell cmd stats print-stats\n");
     fprintf(out, "  Prints some basic stats.\n");
-    fprintf(out, "  reset: 1 to reset the statsd stats. default=0.\n");
 }
 
 status_t StatsService::cmd_trigger_broadcast(FILE* out, Vector<String8>& args) {
@@ -487,14 +487,8 @@
         fprintf(out, "Config %s uses %zu bytes\n", key.ToString().c_str(),
                 mProcessor->GetMetricsSize(key));
     }
-    fprintf(out, "Detailed statsd stats in logcat...\n");
     StatsdStats& statsdStats = StatsdStats::getInstance();
-    bool reset = false;
-    if (args.size() > 1) {
-        reset = strtol(args[1].string(), NULL, 10);
-    }
-    vector<uint8_t> output;
-    statsdStats.dumpStats(&output, reset);
+    statsdStats.dumpStats(out);
     return NO_ERROR;
 }
 
diff --git a/cmds/statsd/src/anomaly/AnomalyTracker.cpp b/cmds/statsd/src/anomaly/AnomalyTracker.cpp
index f10b2cf..9b65acf 100644
--- a/cmds/statsd/src/anomaly/AnomalyTracker.cpp
+++ b/cmds/statsd/src/anomaly/AnomalyTracker.cpp
@@ -18,6 +18,7 @@
 #include "Log.h"
 
 #include "AnomalyTracker.h"
+#include "external/Perfetto.h"
 #include "guardrail/StatsdStats.h"
 
 #include <android/os/IIncidentManager.h>
@@ -239,7 +240,7 @@
                 }
                 break;
             case Subscription::SubscriberInformationCase::kPerfettoDetails:
-                ALOGW("Perfetto reports not implemented.");
+                CollectPerfettoTraceAndUploadToDropbox(subscription.perfetto_details());
                 break;
             default:
                 break;
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 7d513cd..f840894 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -84,6 +84,7 @@
         AppStartChanged app_start_changed = 48;
         AppStartCancelChanged app_start_cancel_changed = 49;
         AppStartFullyDrawnChanged app_start_fully_drawn_changed = 50;
+        LmkEventOccurred lmk_event_occurred = 51;
         // TODO: Reorder the numbering so that the most frequent occur events occur in the first 15.
     }
 
@@ -101,6 +102,7 @@
         CpuTimePerUidFreq cpu_time_per_uid_freq = 10010;
         WifiActivityEnergyInfo wifi_activity_energy_info = 10011;
         ModemActivityInfo modem_activity_info = 10012;
+        MemoryStat memory_stat = 10013;
     }
 }
 
@@ -1177,3 +1179,47 @@
     // product of current(mA), voltage(V) and time(ms)
     optional uint64 energy_used = 10;
 }
+
+/*
+ * Logs the memory stats for a process
+ */
+message MemoryStat {
+    // The uid if available. -1 means not available.
+    optional int32 uid = 1;
+
+    // The app package name.
+    optional string pkg_name = 2;
+
+    // # of page-faults
+    optional int64 pgfault = 3;
+
+    // # of major page-faults
+    optional int64 pgmajfault = 4;
+
+    // RSS+CACHE(+SWAP)
+    optional int64 usage_in_bytes = 5;
+}
+
+/*
+ * Logs the event when LMKD kills a process to reduce memory pressure
+ * Logged from:
+ *      system/core/lmkd/lmkd.c
+ */
+message LmkEventOccurred {
+    // The uid if available. -1 means not available.
+    optional int32 uid = 1;
+
+    // The app package name.
+    optional string pkg_name = 2;
+
+    // oom adj score.
+    optional int32 oom_score = 3;
+
+    // Used as start/stop boundaries for the event
+    enum State {
+        UNKNOWN = 0;
+        START = 1;
+        END = 2;
+    }
+    optional State state = 4;
+}
diff --git a/cmds/statsd/src/condition/SimpleConditionTracker.cpp b/cmds/statsd/src/condition/SimpleConditionTracker.cpp
index 2525721..7a1bb0c 100644
--- a/cmds/statsd/src/condition/SimpleConditionTracker.cpp
+++ b/cmds/statsd/src/condition/SimpleConditionTracker.cpp
@@ -19,6 +19,7 @@
 
 #include "SimpleConditionTracker.h"
 #include "guardrail/StatsdStats.h"
+#include "dimension.h"
 
 #include <log/logprint.h>
 
@@ -171,12 +172,12 @@
         // We get a new output key.
         newCondition = matchStart ? ConditionState::kTrue : ConditionState::kFalse;
         if (matchStart && mInitialValue != ConditionState::kTrue) {
-            mSlicedConditionState[outputKey] = 1;
+            mSlicedConditionState.insert(std::make_pair(outputKey, 1));
             changed = true;
         } else if (mInitialValue != ConditionState::kFalse) {
             // it's a stop and we don't have history about it.
             // If the default condition is not false, it means this stop is valuable to us.
-            mSlicedConditionState[outputKey] = 0;
+            mSlicedConditionState.insert(std::make_pair(outputKey, 0));
             changed = true;
         }
     } else {
@@ -341,7 +342,23 @@
             conditionState = conditionState |
                     (startedCountIt->second > 0 ? ConditionState::kTrue : ConditionState::kFalse);
         } else {
-            conditionState = conditionState | mInitialValue;
+            // For unseen key, check whether the require dimensions are subset of sliced condition
+            // output.
+            bool seenDimension = false;
+            for (const auto& slice : mSlicedConditionState) {
+                if (IsSubDimension(slice.first.getDimensionsValue(),
+                                   key.getDimensionsValue())) {
+                    seenDimension = true;
+                    conditionState = conditionState |
+                        (slice.second > 0 ? ConditionState::kTrue : ConditionState::kFalse);
+                }
+                if (conditionState == ConditionState::kTrue) {
+                    break;
+                }
+            }
+            if (!seenDimension) {
+                conditionState = conditionState | mInitialValue;
+            }
         }
     }
     conditionCache[mIndex] = conditionState;
diff --git a/cmds/statsd/src/condition/condition_util.cpp b/cmds/statsd/src/condition/condition_util.cpp
index a5aee73..ddfb8d1 100644
--- a/cmds/statsd/src/condition/condition_util.cpp
+++ b/cmds/statsd/src/condition/condition_util.cpp
@@ -158,15 +158,15 @@
 std::vector<HashableDimensionKey> getDimensionKeysForCondition(
     const LogEvent& event, const MetricConditionLink& link) {
     std::vector<Field> whatFields;
-    getFieldsFromFieldMatcher(link.dimensions_in_what(), &whatFields);
+    getFieldsFromFieldMatcher(link.fields_in_what(), &whatFields);
     std::vector<Field> conditionFields;
-    getFieldsFromFieldMatcher(link.dimensions_in_condition(), &conditionFields);
+    getFieldsFromFieldMatcher(link.fields_in_condition(), &conditionFields);
 
     std::vector<HashableDimensionKey> hashableDimensionKeys;
 
     // TODO(yanglu): here we could simplify the logic to get the leaf value node in what and
     // directly construct the full condition value tree.
-    std::vector<DimensionsValue> whatValues = getDimensionKeys(event, link.dimensions_in_what());
+    std::vector<DimensionsValue> whatValues = getDimensionKeys(event, link.fields_in_what());
 
     for (size_t i = 0; i < whatValues.size(); ++i) {
         std::vector<DimensionsValue> whatLeaves;
@@ -185,7 +185,7 @@
             conditionValueMap.insert(std::make_pair(conditionFields[j], whatLeaves[j]));
         }
         std::vector<DimensionsValue> conditionValues;
-        findDimensionsValues(conditionValueMap, link.dimensions_in_condition(), &conditionValues);
+        findDimensionsValues(conditionValueMap, link.fields_in_condition(), &conditionValues);
         if (conditionValues.size() != 1) {
             ALOGE("Not able to find unambiguous field value in condition atom.");
             continue;
diff --git a/cmds/statsd/src/config/ConfigManager.cpp b/cmds/statsd/src/config/ConfigManager.cpp
index 1481921..42994b5 100644
--- a/cmds/statsd/src/config/ConfigManager.cpp
+++ b/cmds/statsd/src/config/ConfigManager.cpp
@@ -296,10 +296,10 @@
     metric->set_condition(204);
     MetricConditionLink* link = metric->add_links();
     link->set_condition(203);
-    link->mutable_dimensions_in_what()->set_field(WAKE_LOCK_TAG_ID);
-    link->mutable_dimensions_in_what()->add_child()->set_field(WAKE_LOCK_UID_KEY_ID);
-    link->mutable_dimensions_in_condition()->set_field(APP_USAGE_TAG_ID);
-    link->mutable_dimensions_in_condition()->add_child()->set_field(APP_USAGE_UID_KEY_ID);
+    link->mutable_fields_in_what()->set_field(WAKE_LOCK_TAG_ID);
+    link->mutable_fields_in_what()->add_child()->set_field(WAKE_LOCK_UID_KEY_ID);
+    link->mutable_fields_in_condition()->set_field(APP_USAGE_TAG_ID);
+    link->mutable_fields_in_condition()->add_child()->set_field(APP_USAGE_UID_KEY_ID);
 
     // Duration of an app holding any wl, while screen on and app in background, slice by uid
     DurationMetric* durationMetric = config.add_duration_metric();
@@ -313,10 +313,10 @@
     durationMetric->set_condition(204);
     link = durationMetric->add_links();
     link->set_condition(203);
-    link->mutable_dimensions_in_what()->set_field(WAKE_LOCK_TAG_ID);
-    link->mutable_dimensions_in_what()->add_child()->set_field(WAKE_LOCK_UID_KEY_ID);
-    link->mutable_dimensions_in_condition()->set_field(APP_USAGE_TAG_ID);
-    link->mutable_dimensions_in_condition()->add_child()->set_field(APP_USAGE_UID_KEY_ID);
+    link->mutable_fields_in_what()->set_field(WAKE_LOCK_TAG_ID);
+    link->mutable_fields_in_what()->add_child()->set_field(WAKE_LOCK_UID_KEY_ID);
+    link->mutable_fields_in_condition()->set_field(APP_USAGE_TAG_ID);
+    link->mutable_fields_in_condition()->add_child()->set_field(APP_USAGE_UID_KEY_ID);
 
     // max Duration of an app holding any wl, while screen on and app in background, slice by uid
     durationMetric = config.add_duration_metric();
@@ -330,10 +330,10 @@
     durationMetric->set_condition(204);
     link = durationMetric->add_links();
     link->set_condition(203);
-    link->mutable_dimensions_in_what()->set_field(WAKE_LOCK_TAG_ID);
-    link->mutable_dimensions_in_what()->add_child()->set_field(WAKE_LOCK_UID_KEY_ID);
-    link->mutable_dimensions_in_condition()->set_field(APP_USAGE_TAG_ID);
-    link->mutable_dimensions_in_condition()->add_child()->set_field(APP_USAGE_UID_KEY_ID);
+    link->mutable_fields_in_what()->set_field(WAKE_LOCK_TAG_ID);
+    link->mutable_fields_in_what()->add_child()->set_field(WAKE_LOCK_UID_KEY_ID);
+    link->mutable_fields_in_condition()->set_field(APP_USAGE_TAG_ID);
+    link->mutable_fields_in_condition()->add_child()->set_field(APP_USAGE_UID_KEY_ID);
 
     // Duration of an app holding any wl, while screen on and app in background
     durationMetric = config.add_duration_metric();
@@ -344,10 +344,10 @@
     durationMetric->set_condition(204);
     link = durationMetric->add_links();
     link->set_condition(203);
-    link->mutable_dimensions_in_what()->set_field(WAKE_LOCK_TAG_ID);
-    link->mutable_dimensions_in_what()->add_child()->set_field(WAKE_LOCK_UID_KEY_ID);
-    link->mutable_dimensions_in_condition()->set_field(APP_USAGE_TAG_ID);
-    link->mutable_dimensions_in_condition()->add_child()->set_field(APP_USAGE_UID_KEY_ID);
+    link->mutable_fields_in_what()->set_field(WAKE_LOCK_TAG_ID);
+    link->mutable_fields_in_what()->add_child()->set_field(WAKE_LOCK_UID_KEY_ID);
+    link->mutable_fields_in_condition()->set_field(APP_USAGE_TAG_ID);
+    link->mutable_fields_in_condition()->add_child()->set_field(APP_USAGE_UID_KEY_ID);
 
 
     // Duration of screen on time.
diff --git a/cmds/statsd/src/dimension.cpp b/cmds/statsd/src/dimension.cpp
index 09499b6..bb7a044 100644
--- a/cmds/statsd/src/dimension.cpp
+++ b/cmds/statsd/src/dimension.cpp
@@ -331,13 +331,15 @@
         case DimensionsValue::ValueCase::kValueFloat:
             return dimension.value_float() == sub.value_float();
         case DimensionsValue::ValueCase::kValueTuple: {
-            if (dimension.value_tuple().dimensions_value_size() < sub.value_tuple().dimensions_value_size()) {
+            if (dimension.value_tuple().dimensions_value_size() <
+                sub.value_tuple().dimensions_value_size()) {
                 return false;
             }
             bool allSub = true;
-            for (int i = 0; i < sub.value_tuple().dimensions_value_size(); ++i) {
+            for (int i = 0; allSub && i < sub.value_tuple().dimensions_value_size(); ++i) {
                 bool isSub = false;
-                for (int j = 0; !isSub && j < dimension.value_tuple().dimensions_value_size(); ++j) {
+                for (int j = 0; !isSub &&
+                        j < dimension.value_tuple().dimensions_value_size(); ++j) {
                     isSub |= IsSubDimension(dimension.value_tuple().dimensions_value(j),
                                             sub.value_tuple().dimensions_value(i));
                 }
diff --git a/cmds/statsd/src/external/CpuTimePerUidFreqPuller.cpp b/cmds/statsd/src/external/CpuTimePerUidFreqPuller.cpp
index a61afb4..a751273 100644
--- a/cmds/statsd/src/external/CpuTimePerUidFreqPuller.cpp
+++ b/cmds/statsd/src/external/CpuTimePerUidFreqPuller.cpp
@@ -34,7 +34,7 @@
 namespace os {
 namespace statsd {
 
-static const string sProcFile = "/proc/uid_cputime/show_uid_stat";
+static const string sProcFile = "/proc/uid_time_in_state";
 static const int kLineBufferSize = 1024;
 
 /**
diff --git a/cmds/statsd/src/external/Perfetto.cpp b/cmds/statsd/src/external/Perfetto.cpp
new file mode 100644
index 0000000..f7b33e7
--- /dev/null
+++ b/cmds/statsd/src/external/Perfetto.cpp
@@ -0,0 +1,111 @@
+/*
+ * 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 "Log.h"
+
+#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h"  // Alert
+
+#include <android-base/unique_fd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <string>
+
+namespace {
+const char kDropboxTag[] = "perfetto";
+}
+
+namespace android {
+namespace os {
+namespace statsd {
+
+bool CollectPerfettoTraceAndUploadToDropbox(const PerfettoDetails& config) {
+    ALOGD("Starting trace collection through perfetto");
+
+    if (!config.has_trace_config()) {
+        ALOGE("The perfetto trace config is empty, aborting");
+        return false;
+    }
+
+    android::base::unique_fd readPipe;
+    android::base::unique_fd writePipe;
+    if (!android::base::Pipe(&readPipe, &writePipe)) {
+        ALOGE("pipe() failed while calling the Perfetto client: %s", strerror(errno));
+        return false;
+    }
+
+    pid_t pid = fork();
+    if (pid < 0) {
+        ALOGE("fork() failed while calling the Perfetto client: %s", strerror(errno));
+        return false;
+    }
+
+    if (pid == 0) {
+        // Child process.
+
+        // No malloc calls or library calls after this point. Remember that even
+        // ALOGx (aka android_printLog()) can use dynamic memory for vsprintf().
+
+        writePipe.reset();  // Close the write end (owned by the main process).
+
+        // Replace stdin with |readPipe| so the main process can write into it.
+        if (dup2(readPipe.get(), STDIN_FILENO) < 0) _exit(1);
+        execl("/system/bin/perfetto", "perfetto", "--background", "--config", "-", "--dropbox",
+              kDropboxTag, nullptr);
+
+        // execl() doesn't return in case of success, if we get here something failed.
+        _exit(1);
+    }
+
+    // Main process.
+
+    readPipe.reset();  // Close the read end (owned by the child process).
+
+    // Using fopen() because fwrite() has the right logic to chunking write()
+    // over a pipe (see __sfvwrite()).
+    FILE* writePipeStream = fdopen(writePipe.get(), "wb");
+    if (!writePipeStream) {
+        ALOGE("fdopen() failed while calling the Perfetto client: %s", strerror(errno));
+        return false;
+    }
+
+    std::string cfgProto = config.trace_config().SerializeAsString();
+    size_t bytesWritten = fwrite(cfgProto.data(), 1, cfgProto.size(), writePipeStream);
+    fclose(writePipeStream);
+    if (bytesWritten != cfgProto.size() || cfgProto.size() == 0) {
+        ALOGE("fwrite() failed (ret: %zd) while calling the Perfetto client: %s", bytesWritten,
+              strerror(errno));
+        return false;
+    }
+
+    // This does NOT wait for the full duration of the trace. It just waits until the process
+    // has read the config from stdin and detached.
+    int childStatus = 0;
+    waitpid(pid, &childStatus, 0);
+    if (!WIFEXITED(childStatus) || WEXITSTATUS(childStatus) != 0) {
+        ALOGE("Child process failed (0x%x) while calling the Perfetto client", childStatus);
+        return false;
+    }
+
+    ALOGD("CollectPerfettoTraceAndUploadToDropbox() succeeded");
+    return true;
+}
+
+}  // namespace statsd
+}  // namespace os
+}  // namespace android
diff --git a/cmds/statsd/src/external/Perfetto.h b/cmds/statsd/src/external/Perfetto.h
new file mode 100644
index 0000000..e2e0253
--- /dev/null
+++ b/cmds/statsd/src/external/Perfetto.h
@@ -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.
+ */
+
+#pragma once
+
+using android::os::StatsLogEventWrapper;
+
+namespace android {
+namespace os {
+namespace statsd {
+
+class PerfettoDetails;  // Declared in statsd_config.pb.h
+
+// Starts the collection of a Perfetto trace with the given |config|.
+// The trace is uploaded to Dropbox by the perfetto cmdline util once done.
+// This method returns immediately after passing the config and does NOT wait
+// for the full duration of the trace.
+bool CollectPerfettoTraceAndUploadToDropbox(const PerfettoDetails& config);
+
+}  // namespace statsd
+}  // namespace os
+}  // namespace android
diff --git a/cmds/statsd/src/guardrail/StatsdStats.cpp b/cmds/statsd/src/guardrail/StatsdStats.cpp
index 4bd4f19..63bde7d 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.cpp
+++ b/cmds/statsd/src/guardrail/StatsdStats.cpp
@@ -355,73 +355,135 @@
     }
 }
 
+void StatsdStats::dumpStats(FILE* out) const {
+    lock_guard<std::mutex> lock(mLock);
+    time_t t = mStartTimeSec;
+    struct tm* tm = localtime(&t);
+    char timeBuffer[80];
+    strftime(timeBuffer, sizeof(timeBuffer), "%Y-%m-%d %I:%M%p\n", tm);
+    fprintf(out, "Stats collection start second: %s\n", timeBuffer);
+    fprintf(out, "%lu Config in icebox: \n", (unsigned long)mIceBox.size());
+    for (const auto& configStats : mIceBox) {
+        fprintf(out,
+                "Config {%d-%lld}: creation=%d, deletion=%d, #metric=%d, #condition=%d, "
+                "#matcher=%d, #alert=%d,  valid=%d\n",
+                configStats.uid(), (long long)configStats.id(), configStats.creation_time_sec(),
+                configStats.deletion_time_sec(), configStats.metric_count(),
+                configStats.condition_count(), configStats.matcher_count(),
+                configStats.alert_count(), configStats.is_valid());
+
+        for (const auto& broadcastTime : configStats.broadcast_sent_time_sec()) {
+            fprintf(out, "\tbroadcast time: %d\n", broadcastTime);
+        }
+
+        for (const auto& dataDropTime : configStats.data_drop_time_sec()) {
+            fprintf(out, "\tdata drop time: %d\n", dataDropTime);
+        }
+    }
+    fprintf(out, "%lu Active Configs\n", (unsigned long)mConfigStats.size());
+    for (auto& pair : mConfigStats) {
+        auto& key = pair.first;
+        auto& configStats = pair.second;
+
+        fprintf(out,
+                "Config {%d-%lld}: creation=%d, deletion=%d, #metric=%d, #condition=%d, "
+                "#matcher=%d, #alert=%d,  valid=%d\n",
+                configStats.uid(), (long long)configStats.id(), configStats.creation_time_sec(),
+                configStats.deletion_time_sec(), configStats.metric_count(),
+                configStats.condition_count(), configStats.matcher_count(),
+                configStats.alert_count(), configStats.is_valid());
+        for (const auto& broadcastTime : configStats.broadcast_sent_time_sec()) {
+            fprintf(out, "\tbroadcast time: %d\n", broadcastTime);
+        }
+
+        for (const auto& dataDropTime : configStats.data_drop_time_sec()) {
+            fprintf(out, "\tdata drop time: %d\n", dataDropTime);
+        }
+
+        for (const auto& dumpTime : configStats.dump_report_time_sec()) {
+            fprintf(out, "\tdump report time: %d\n", dumpTime);
+        }
+
+        // Add matcher stats
+        auto matcherIt = mMatcherStats.find(key);
+        if (matcherIt != mMatcherStats.end()) {
+            const auto& matcherStats = matcherIt->second;
+            for (const auto& stats : matcherStats) {
+                fprintf(out, "matcher %lld matched %d times\n", (long long)stats.first,
+                        stats.second);
+            }
+        }
+        // Add condition stats
+        auto conditionIt = mConditionStats.find(key);
+        if (conditionIt != mConditionStats.end()) {
+            const auto& conditionStats = conditionIt->second;
+            for (const auto& stats : conditionStats) {
+                fprintf(out, "condition %lld max output tuple size %d\n", (long long)stats.first,
+                        stats.second);
+            }
+        }
+        // Add metrics stats
+        auto metricIt = mMetricsStats.find(key);
+        if (metricIt != mMetricsStats.end()) {
+            const auto& conditionStats = metricIt->second;
+            for (const auto& stats : conditionStats) {
+                fprintf(out, "metrics %lld max output tuple size %d\n", (long long)stats.first,
+                        stats.second);
+            }
+        }
+        // Add anomaly detection alert stats
+        auto alertIt = mAlertStats.find(key);
+        if (alertIt != mAlertStats.end()) {
+            const auto& alertStats = alertIt->second;
+            for (const auto& stats : alertStats) {
+                fprintf(out, "alert %lld declared %d times\n", (long long)stats.first,
+                        stats.second);
+            }
+        }
+    }
+    fprintf(out, "********Pushed Atom stats***********\n");
+    const size_t atomCounts = mPushedAtomStats.size();
+    for (size_t i = 2; i < atomCounts; i++) {
+        if (mPushedAtomStats[i] > 0) {
+            fprintf(out, "Atom %lu->%d\n", (unsigned long)i, mPushedAtomStats[i]);
+        }
+    }
+
+    fprintf(out, "********Pulled Atom stats***********\n");
+    for (const auto& pair : mPulledAtomStats) {
+        fprintf(out, "Atom %d->%ld, %ld, %ld\n", (int)pair.first, (long)pair.second.totalPull,
+             (long)pair.second.totalPullFromCache, (long)pair.second.minPullIntervalSec);
+    }
+
+    if (mAnomalyAlarmRegisteredStats > 0) {
+        fprintf(out, "********AnomalyAlarmStats stats***********\n");
+        fprintf(out, "Anomaly alarm registrations: %d\n", mAnomalyAlarmRegisteredStats);
+    }
+
+    fprintf(out,
+            "UID map stats: bytes=%d, snapshots=%d, changes=%d, snapshots lost=%d, changes "
+            "lost=%d\n",
+            mUidMapStats.bytes_used(), mUidMapStats.snapshots(), mUidMapStats.changes(),
+            mUidMapStats.dropped_snapshots(), mUidMapStats.dropped_changes());
+}
+
 void StatsdStats::dumpStats(std::vector<uint8_t>* output, bool reset) {
     lock_guard<std::mutex> lock(mLock);
 
-    if (DEBUG) {
-        time_t t = mStartTimeSec;
-        struct tm* tm = localtime(&t);
-        char timeBuffer[80];
-        strftime(timeBuffer, sizeof(timeBuffer), "%Y-%m-%d %I:%M%p", tm);
-        VLOG("=================StatsdStats dump begins====================");
-        VLOG("Stats collection start second: %s", timeBuffer);
-    }
     ProtoOutputStream proto;
     proto.write(FIELD_TYPE_INT32 | FIELD_ID_BEGIN_TIME, mStartTimeSec);
     proto.write(FIELD_TYPE_INT32 | FIELD_ID_END_TIME, (int32_t)time(nullptr));
 
-    VLOG("%lu Config in icebox: ", (unsigned long)mIceBox.size());
     for (const auto& configStats : mIceBox) {
         const int numBytes = configStats.ByteSize();
         vector<char> buffer(numBytes);
         configStats.SerializeToArray(&buffer[0], numBytes);
         proto.write(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_CONFIG_STATS, &buffer[0],
                     buffer.size());
-
-        // surround the whole block with DEBUG, so that compiler can strip out the code
-        // in production.
-        if (DEBUG) {
-            VLOG("*****ICEBOX*****");
-            VLOG("Config {%d-%lld}: creation=%d, deletion=%d, #metric=%d, #condition=%d, "
-                 "#matcher=%d, #alert=%d,  #valid=%d",
-                 configStats.uid(), (long long)configStats.id(), configStats.creation_time_sec(),
-                 configStats.deletion_time_sec(), configStats.metric_count(),
-                 configStats.condition_count(), configStats.matcher_count(),
-                 configStats.alert_count(), configStats.is_valid());
-
-            for (const auto& broadcastTime : configStats.broadcast_sent_time_sec()) {
-                VLOG("\tbroadcast time: %d", broadcastTime);
-            }
-
-            for (const auto& dataDropTime : configStats.data_drop_time_sec()) {
-                VLOG("\tdata drop time: %d", dataDropTime);
-            }
-        }
     }
 
     for (auto& pair : mConfigStats) {
         auto& configStats = pair.second;
-        if (DEBUG) {
-            VLOG("********Active Configs***********");
-            VLOG("Config {%d-%lld}: creation=%d, deletion=%d, #metric=%d, #condition=%d, "
-                 "#matcher=%d, #alert=%d,  #valid=%d",
-                 configStats.uid(), (long long)configStats.id(), configStats.creation_time_sec(),
-                 configStats.deletion_time_sec(), configStats.metric_count(),
-                 configStats.condition_count(), configStats.matcher_count(),
-                 configStats.alert_count(), configStats.is_valid());
-            for (const auto& broadcastTime : configStats.broadcast_sent_time_sec()) {
-                VLOG("\tbroadcast time: %d", broadcastTime);
-            }
-
-            for (const auto& dataDropTime : configStats.data_drop_time_sec()) {
-                VLOG("\tdata drop time: %d", dataDropTime);
-            }
-
-            for (const auto& dumpTime : configStats.dump_report_time_sec()) {
-                VLOG("\tdump report time: %d", dumpTime);
-            }
-        }
-
         addSubStatsToConfigLocked(pair.first, configStats);
 
         const int numBytes = configStats.ByteSize();
@@ -437,7 +499,6 @@
         configStats.clear_alert_stats();
     }
 
-    VLOG("********Pushed Atom stats***********");
     const size_t atomCounts = mPushedAtomStats.size();
     for (size_t i = 2; i < atomCounts; i++) {
         if (mPushedAtomStats[i] > 0) {
@@ -446,34 +507,24 @@
             proto.write(FIELD_TYPE_INT32 | FIELD_ID_ATOM_STATS_TAG, (int32_t)i);
             proto.write(FIELD_TYPE_INT32 | FIELD_ID_ATOM_STATS_COUNT, mPushedAtomStats[i]);
             proto.end(token);
-
-            VLOG("Atom %lu->%d\n", (unsigned long)i, mPushedAtomStats[i]);
         }
     }
 
-    VLOG("********Pulled Atom stats***********");
     for (const auto& pair : mPulledAtomStats) {
         android::os::statsd::writePullerStatsToStream(pair, &proto);
-        VLOG("Atom %d->%ld, %ld, %ld\n", (int) pair.first, (long) pair.second.totalPull, (long) pair.second.totalPullFromCache, (long) pair.second.minPullIntervalSec);
     }
 
     if (mAnomalyAlarmRegisteredStats > 0) {
-        VLOG("********AnomalyAlarmStats stats***********");
         long long token = proto.start(FIELD_TYPE_MESSAGE | FIELD_ID_ANOMALY_ALARM_STATS);
         proto.write(FIELD_TYPE_INT32 | FIELD_ID_ANOMALY_ALARMS_REGISTERED,
                     mAnomalyAlarmRegisteredStats);
         proto.end(token);
-        VLOG("Anomaly alarm registrations: %d", mAnomalyAlarmRegisteredStats);
     }
 
     const int numBytes = mUidMapStats.ByteSize();
     vector<char> buffer(numBytes);
     mUidMapStats.SerializeToArray(&buffer[0], numBytes);
     proto.write(FIELD_TYPE_MESSAGE | FIELD_ID_UIDMAP_STATS, &buffer[0], buffer.size());
-    VLOG("UID map stats: bytes=%d, snapshots=%d, changes=%d, snapshots lost=%d, changes "
-         "lost=%d",
-         mUidMapStats.bytes_used(), mUidMapStats.snapshots(), mUidMapStats.changes(),
-         mUidMapStats.dropped_snapshots(), mUidMapStats.dropped_changes());
 
     output->clear();
     size_t bufferSize = proto.size();
@@ -493,7 +544,6 @@
     }
 
     VLOG("reset=%d, returned proto size %lu", reset, (unsigned long)bufferSize);
-    VLOG("=================StatsdStats dump ends====================");
 }
 
 }  // namespace statsd
diff --git a/cmds/statsd/src/guardrail/StatsdStats.h b/cmds/statsd/src/guardrail/StatsdStats.h
index 52ab253..9178daa4 100644
--- a/cmds/statsd/src/guardrail/StatsdStats.h
+++ b/cmds/statsd/src/guardrail/StatsdStats.h
@@ -189,6 +189,11 @@
      */
     void dumpStats(std::vector<uint8_t>* buffer, bool reset);
 
+    /**
+     * Output statsd stats in human readable format to [out] file.
+     */
+    void dumpStats(FILE* out) const;
+
     typedef struct {
         long totalPull;
         long totalPullFromCache;
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
index c7550f7..e985873 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
@@ -285,8 +285,15 @@
             interval.start = value;
             interval.startUpdated = true;
         } else {
+            // Generally we expect value to be monotonically increasing.
+            // If not, there was a reset event. We take the absolute value as
+            // diff in this case.
             if (interval.startUpdated) {
-                interval.sum += (value - interval.start);
+                if (value > interval.start) {
+                    interval.sum += (value - interval.start);
+                } else {
+                    interval.sum += value;
+                }
                 interval.startUpdated = false;
             } else {
                 VLOG("No start for matching end %ld", value);
diff --git a/cmds/statsd/src/packages/UidMap.cpp b/cmds/statsd/src/packages/UidMap.cpp
index dcb8eed..eefb7dc 100644
--- a/cmds/statsd/src/packages/UidMap.cpp
+++ b/cmds/statsd/src/packages/UidMap.cpp
@@ -106,9 +106,9 @@
             t->set_uid(uid[j]);
         }
         mBytesUsed += snapshot->ByteSize();
+        ensureBytesUsedBelowLimit();
         StatsdStats::getInstance().setCurrentUidMapMemory(mBytesUsed);
         StatsdStats::getInstance().setUidMapSnapshots(mOutput.snapshots_size());
-        ensureBytesUsedBelowLimit();
         getListenerListCopyLocked(&broadcastList);
     }
     // To avoid invoking callback while holding the internal lock. we get a copy of the listener
@@ -142,9 +142,9 @@
         log->set_uid(uid);
         log->set_version(versionCode);
         mBytesUsed += log->ByteSize();
+        ensureBytesUsedBelowLimit();
         StatsdStats::getInstance().setCurrentUidMapMemory(mBytesUsed);
         StatsdStats::getInstance().setUidMapChanges(mOutput.changes_size());
-        ensureBytesUsedBelowLimit();
 
         auto range = mMap.equal_range(int(uid));
         bool found = false;
@@ -222,9 +222,9 @@
         log->set_app(app);
         log->set_uid(uid);
         mBytesUsed += log->ByteSize();
+        ensureBytesUsedBelowLimit();
         StatsdStats::getInstance().setCurrentUidMapMemory(mBytesUsed);
         StatsdStats::getInstance().setUidMapChanges(mOutput.changes_size());
-        ensureBytesUsedBelowLimit();
 
         auto range = mMap.equal_range(int(uid));
         for (auto it = range.first; it != range.second; ++it) {
diff --git a/cmds/statsd/src/packages/UidMap.h b/cmds/statsd/src/packages/UidMap.h
index 4e37977..3304f6c 100644
--- a/cmds/statsd/src/packages/UidMap.h
+++ b/cmds/statsd/src/packages/UidMap.h
@@ -152,9 +152,9 @@
     // until the memory consumed by mOutput is below the specified limit.
     void ensureBytesUsedBelowLimit();
 
-    // Override used for testing the max memory allowed by uid map. -1 means we use the value
+    // Override used for testing the max memory allowed by uid map. 0 means we use the value
     // specified in StatsdStats.h with the rest of the guardrails.
-    size_t maxBytesOverride = -1;
+    size_t maxBytesOverride = 0;
 
     // Cache the size of mOutput;
     size_t mBytesUsed;
diff --git a/cmds/statsd/src/perfetto/perfetto_config.proto b/cmds/statsd/src/perfetto/perfetto_config.proto
new file mode 100644
index 0000000..dc868f9
--- /dev/null
+++ b/cmds/statsd/src/perfetto/perfetto_config.proto
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ */
+
+syntax = "proto2";
+option optimize_for = LITE_RUNTIME;
+
+package perfetto.protos;
+
+message DataSourceConfig {
+  message FtraceConfig {
+    repeated string event_names = 1;
+  }
+
+  optional string name = 1;
+
+  optional uint32 target_buffer = 2;
+
+  optional FtraceConfig ftrace_config = 100;
+}
+
+message TraceConfig {
+  message BufferConfig {
+    optional uint32 size_kb = 1;
+
+    enum OptimizeFor {
+      DEFAULT = 0;
+      ONE_SHOT_READ = 1;
+
+    }
+    optional OptimizeFor optimize_for = 3;
+
+    enum FillPolicy {
+      UNSPECIFIED = 0;
+      RING_BUFFER = 1;
+    }
+    optional FillPolicy fill_policy = 4;
+  }
+  repeated BufferConfig buffers = 1;
+
+  message DataSource {
+    optional protos.DataSourceConfig config = 1;
+
+    repeated string producer_name_filter = 2;
+  }
+  repeated DataSource data_sources = 2;
+
+  optional uint32 duration_ms = 3;
+}
diff --git a/cmds/statsd/src/stats_log.proto b/cmds/statsd/src/stats_log.proto
index 393f795..bb2193f 100644
--- a/cmds/statsd/src/stats_log.proto
+++ b/cmds/statsd/src/stats_log.proto
@@ -58,9 +58,9 @@
 message CountMetricData {
   optional DimensionsValue dimensions_in_what = 1;
 
-  optional DimensionsValue dimensions_in_condition = 3;
+  optional DimensionsValue dimensions_in_condition = 2;
 
-  repeated CountBucketInfo bucket_info = 2;
+  repeated CountBucketInfo bucket_info = 3;
 }
 
 message DurationBucketInfo {
@@ -74,9 +74,9 @@
 message DurationMetricData {
   optional DimensionsValue dimensions_in_what = 1;
 
-  optional DimensionsValue dimensions_in_condition = 3;
+  optional DimensionsValue dimensions_in_condition = 2;
 
-  repeated DurationBucketInfo bucket_info = 2;
+  repeated DurationBucketInfo bucket_info = 3;
 }
 
 message ValueBucketInfo {
@@ -90,9 +90,9 @@
 message ValueMetricData {
   optional DimensionsValue dimensions_in_what = 1;
 
-  optional DimensionsValue dimensions_in_condition = 3;
+  optional DimensionsValue dimensions_in_condition = 2;
 
-  repeated ValueBucketInfo bucket_info = 2;
+  repeated ValueBucketInfo bucket_info = 3;
 }
 
 message GaugeBucketInfo {
@@ -106,9 +106,9 @@
 message GaugeMetricData {
   optional DimensionsValue dimensions_in_what = 1;
 
-  optional DimensionsValue dimensions_in_condition = 3;
+  optional DimensionsValue dimensions_in_condition = 2;
 
-  repeated GaugeBucketInfo bucket_info = 2;
+  repeated GaugeBucketInfo bucket_info = 3;
 }
 
 message UidMapping {
diff --git a/cmds/statsd/src/statsd_config.proto b/cmds/statsd/src/statsd_config.proto
index ae8a835..cd60ee7 100644
--- a/cmds/statsd/src/statsd_config.proto
+++ b/cmds/statsd/src/statsd_config.proto
@@ -22,6 +22,8 @@
 option java_package = "com.android.internal.os";
 option java_outer_classname = "StatsdConfigProto";
 
+import "frameworks/base/cmds/statsd/src/perfetto/perfetto_config.proto";
+
 enum Position {
     POSITION_UNKNOWN = 0;
     FIRST = 1;
@@ -151,9 +153,9 @@
 message MetricConditionLink {
     optional int64 condition = 1;
 
-    optional FieldMatcher dimensions_in_what = 2;
+    optional FieldMatcher fields_in_what = 2;
 
-    optional FieldMatcher dimensions_in_condition = 3;
+    optional FieldMatcher fields_in_condition = 3;
 }
 
 message FieldFilter {
@@ -180,11 +182,11 @@
 
     optional FieldMatcher dimensions_in_what = 4;
 
-    optional FieldMatcher dimensions_in_condition = 5;
+    optional FieldMatcher dimensions_in_condition = 7;
 
-    optional TimeUnit bucket = 6;
+    optional TimeUnit bucket = 5;
 
-    repeated MetricConditionLink links = 7;
+    repeated MetricConditionLink links = 6;
 }
 
 message DurationMetric {
@@ -205,9 +207,9 @@
 
     optional FieldMatcher dimensions_in_what = 6;
 
-    optional FieldMatcher dimensions_in_condition = 7;
+    optional FieldMatcher dimensions_in_condition = 8;
 
-    optional TimeUnit bucket = 8;
+    optional TimeUnit bucket = 7;
 }
 
 message GaugeMetric {
@@ -221,11 +223,11 @@
 
     optional FieldMatcher dimensions_in_what = 5;
 
-    optional FieldMatcher dimensions_in_condition = 6;
+    optional FieldMatcher dimensions_in_condition = 8;
 
-    optional TimeUnit bucket = 7;
+    optional TimeUnit bucket = 6;
 
-    repeated MetricConditionLink links = 8;
+    repeated MetricConditionLink links = 7;
 }
 
 message ValueMetric {
@@ -239,14 +241,14 @@
 
     optional FieldMatcher dimensions_in_what = 5;
 
-    optional FieldMatcher dimensions_in_condition = 6;
+    optional FieldMatcher dimensions_in_condition = 9;
 
-    optional TimeUnit bucket = 7;
+    optional TimeUnit bucket = 6;
 
-    repeated MetricConditionLink links = 8;
+    repeated MetricConditionLink links = 7;
 
     enum AggregationType { SUM = 1; }
-    optional AggregationType aggregation_type = 9 [default = SUM];
+    optional AggregationType aggregation_type = 8 [default = SUM];
 }
 
 message Alert {
@@ -272,7 +274,7 @@
 }
 
 message PerfettoDetails {
-    optional int32 perfetto_stuff = 1;
+    optional perfetto.protos.TraceConfig trace_config = 1;
 }
 
 message Subscription {
diff --git a/cmds/statsd/src/storage/StorageManager.cpp b/cmds/statsd/src/storage/StorageManager.cpp
index c542db2..1d75e20 100644
--- a/cmds/statsd/src/storage/StorageManager.cpp
+++ b/cmds/statsd/src/storage/StorageManager.cpp
@@ -111,20 +111,21 @@
 
         int index = 0;
         int uid = 0;
-        string configName;
+        int64_t configID = 0;
         char* substr = strtok(name, "-");
         // Timestamp lives at index 2 but we skip parsing it as it's not needed.
         while (substr != nullptr && index < 2) {
-            if (index) {
+            if (index == 0) {
                 uid = atoi(substr);
-            } else {
-                configName = substr;
+            } else if (index == 1) {
+                configID = StrToInt64(substr);
             }
             index++;
+            substr = strtok(nullptr, "-");
         }
         if (index < 2) continue;
 
-        sendBroadcast(ConfigKey(uid, StrToInt64(configName)));
+        sendBroadcast(ConfigKey(uid, configID));
     }
 }
 
@@ -143,19 +144,23 @@
 
         int index = 0;
         int uid = 0;
-        string configName;
+        int64_t configID = 0;
+        int64_t timestamp = 0;
         char* substr = strtok(name, "-");
-        // Timestamp lives at index 2 but we skip parsing it as it's not needed.
-        while (substr != nullptr && index < 2) {
-            if (index) {
+        while (substr != nullptr && index < 3) {
+            if (index == 0) {
                 uid = atoi(substr);
-            } else {
-                configName = substr;
+            } else if (index == 1) {
+                configID = StrToInt64(substr);
+            } else if (index == 2) {
+                timestamp = atoi(substr);
             }
             index++;
+            substr = strtok(nullptr, "-");
         }
-        if (index < 2) continue;
-        string file_name = StringPrintf("%s/%s", path, name);
+        if (index < 3) continue;
+        string file_name = StringPrintf("%s/%d-%lld-%lld", STATS_SERVICE_DIR, uid,
+                                        (long long)configID, (long long)timestamp);
         int fd = open(file_name.c_str(), O_RDONLY | O_CLOEXEC);
         if (fd != -1) {
             string content;
@@ -186,29 +191,32 @@
 
         int index = 0;
         int uid = 0;
-        string configName;
+        int64_t configID = 0;
+        int64_t timestamp = 0;
         char* substr = strtok(name, "-");
-        // Timestamp lives at index 2 but we skip parsing it as it's not needed.
-        while (substr != nullptr && index < 2) {
-            if (index) {
+        while (substr != nullptr && index < 3) {
+            if (index == 0) {
                 uid = atoi(substr);
-            } else {
-                configName = substr;
+            } else if (index == 1) {
+                configID = StrToInt64(substr);
+            } else if (index == 2) {
+                timestamp = atoi(substr);
             }
             index++;
+            substr = strtok(nullptr, "-");
         }
-        if (index < 2) continue;
+        if (index < 3) continue;
 
-        string file_name = StringPrintf("%s/%s", STATS_SERVICE_DIR, name);
-        VLOG("full file %s", file_name.c_str());
+        string file_name = StringPrintf("%s/%d-%lld-%lld", STATS_SERVICE_DIR, uid,
+                                        (long long)configID, (long long)timestamp);
         int fd = open(file_name.c_str(), O_RDONLY | O_CLOEXEC);
         if (fd != -1) {
             string content;
             if (android::base::ReadFdToString(fd, &content)) {
                 StatsdConfig config;
                 if (config.ParseFromString(content)) {
-                    configsMap[ConfigKey(uid, StrToInt64(configName))] = config;
-                    VLOG("map key uid=%d|name=%s", uid, name);
+                    configsMap[ConfigKey(uid, configID)] = config;
+                    VLOG("map key uid=%d|configID=%lld", uid, (long long)configID);
                 }
             }
             close(fd);
diff --git a/cmds/statsd/statsd.rc b/cmds/statsd/statsd.rc
index c260ae1..920273b 100644
--- a/cmds/statsd/statsd.rc
+++ b/cmds/statsd/statsd.rc
@@ -16,6 +16,7 @@
     class main
     user statsd
     group statsd log
+    writepid /dev/cpuset/system-background/tasks
 
 on post-fs-data
     # Create directory for statsd
diff --git a/cmds/statsd/tests/ConfigManager_test.cpp b/cmds/statsd/tests/ConfigManager_test.cpp
index cc02f34..62bdba4 100644
--- a/cmds/statsd/tests/ConfigManager_test.cpp
+++ b/cmds/statsd/tests/ConfigManager_test.cpp
@@ -91,7 +91,7 @@
     {
         InSequence s;
 
-        manager->Startup();
+        manager->StartupForTest();
 
         // Add another one
         EXPECT_CALL(*(listener.get()), OnConfigUpdated(ConfigKeyEq(1, StringToId("zzz")),
diff --git a/cmds/statsd/tests/e2e/GaugeMetric_e2e_test.cpp b/cmds/statsd/tests/e2e/GaugeMetric_e2e_test.cpp
index 8250297..e56a6c5 100644
--- a/cmds/statsd/tests/e2e/GaugeMetric_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/GaugeMetric_e2e_test.cpp
@@ -57,10 +57,10 @@
 
     auto links = gaugeMetric->add_links();
     links->set_condition(isInBackgroundPredicate.id());
-    auto dimensionWhat = links->mutable_dimensions_in_what();
+    auto dimensionWhat = links->mutable_fields_in_what();
     dimensionWhat->set_field(android::util::APP_START_CHANGED);
     dimensionWhat->add_child()->set_field(1);  // uid field.
-    auto dimensionCondition = links->mutable_dimensions_in_condition();
+    auto dimensionCondition = links->mutable_fields_in_condition();
     dimensionCondition->set_field(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED);
     dimensionCondition->add_child()->set_field(1);  // uid field.
     return config;
diff --git a/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp b/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp
index 178dd71..eda16a2 100644
--- a/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp
@@ -46,7 +46,7 @@
     auto isSyncingPredicate = CreateIsSyncingPredicate();
     *isSyncingPredicate.mutable_simple_predicate()->mutable_dimensions() =
         CreateDimensions(
-            android::util::SYNC_STATE_CHANGED, {1 /* uid field */});
+            android::util::SYNC_STATE_CHANGED, {1 /* uid field */, 2 /* name field*/});
 
     auto isInBackgroundPredicate = CreateIsInBackgroundPredicate();
     *isInBackgroundPredicate.mutable_simple_predicate()->mutable_dimensions() =
@@ -75,20 +75,20 @@
     // Links between crash atom and condition of app is in syncing.
     auto links = countMetric->add_links();
     links->set_condition(isSyncingPredicate.id());
-    auto dimensionWhat = links->mutable_dimensions_in_what();
+    auto dimensionWhat = links->mutable_fields_in_what();
     dimensionWhat->set_field(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
     dimensionWhat->add_child()->set_field(1);  // uid field.
-    auto dimensionCondition = links->mutable_dimensions_in_condition();
+    auto dimensionCondition = links->mutable_fields_in_condition();
     dimensionCondition->set_field(android::util::SYNC_STATE_CHANGED);
     dimensionCondition->add_child()->set_field(1);  // uid field.
 
     // Links between crash atom and condition of app is in background.
     links = countMetric->add_links();
     links->set_condition(isInBackgroundPredicate.id());
-    dimensionWhat = links->mutable_dimensions_in_what();
+    dimensionWhat = links->mutable_fields_in_what();
     dimensionWhat->set_field(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
     dimensionWhat->add_child()->set_field(1);  // uid field.
-    dimensionCondition = links->mutable_dimensions_in_condition();
+    dimensionCondition = links->mutable_fields_in_condition();
     dimensionCondition->set_field(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED);
     dimensionCondition->add_child()->set_field(1);  // uid field.
     return config;
diff --git a/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp b/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp
index c391513..897328d 100644
--- a/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp
@@ -149,8 +149,8 @@
     metric.set_condition(StringToId("APP_IN_BACKGROUND_PER_UID_AND_SCREEN_ON"));
     MetricConditionLink* link = metric.add_links();
     link->set_condition(StringToId("APP_IN_BACKGROUND_PER_UID"));
-    *link->mutable_dimensions_in_what() = buildSimpleAtomFieldMatcher(tagId, 1);
-    *link->mutable_dimensions_in_condition() = buildSimpleAtomFieldMatcher(conditionTagId, 2);
+    *link->mutable_fields_in_what() = buildSimpleAtomFieldMatcher(tagId, 1);
+    *link->mutable_fields_in_condition() = buildSimpleAtomFieldMatcher(conditionTagId, 2);
 
     LogEvent event1(tagId, bucketStartTimeNs + 1);
     event1.write("111");  // uid
diff --git a/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp b/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp
index 7171de9..34cde60 100644
--- a/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp
@@ -98,8 +98,8 @@
     metric.set_condition(StringToId("APP_IN_BACKGROUND_PER_UID_AND_SCREEN_ON"));
     MetricConditionLink* link = metric.add_links();
     link->set_condition(StringToId("APP_IN_BACKGROUND_PER_UID"));
-    *link->mutable_dimensions_in_what() = buildSimpleAtomFieldMatcher(tagId, 1);
-    *link->mutable_dimensions_in_condition() = buildSimpleAtomFieldMatcher(conditionTagId, 2);
+    *link->mutable_fields_in_what() = buildSimpleAtomFieldMatcher(tagId, 1);
+    *link->mutable_fields_in_condition() = buildSimpleAtomFieldMatcher(conditionTagId, 2);
 
     LogEvent event1(tagId, bucketStartTimeNs + 1);
     EXPECT_TRUE(event1.write("111"));
diff --git a/cmds/statsd/tools/dogfood/Android.mk b/cmds/statsd/tools/dogfood/Android.mk
index a4c0800..73fbaa4 100644
--- a/cmds/statsd/tools/dogfood/Android.mk
+++ b/cmds/statsd/tools/dogfood/Android.mk
@@ -21,9 +21,11 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 LOCAL_SRC_FILES += ../../src/stats_log.proto \
                    ../../src/atoms.proto \
+                   ../../src/perfetto/perfetto_config.proto \
                    ../../src/statsd_config.proto
 
 LOCAL_PROTOC_FLAGS := --proto_path=$(LOCAL_PATH)/../../src/
+
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
 LOCAL_STATIC_JAVA_LIBRARIES := platformprotoslite
 
diff --git a/cmds/statsd/tools/loadtest/Android.mk b/cmds/statsd/tools/loadtest/Android.mk
index 0a0fd66..f5722c2 100644
--- a/cmds/statsd/tools/loadtest/Android.mk
+++ b/cmds/statsd/tools/loadtest/Android.mk
@@ -21,6 +21,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 LOCAL_SRC_FILES += ../../src/stats_log.proto \
                    ../../src/atoms.proto \
+                   ../../src/perfetto/perfetto_config.proto \
                    ../../src/statsd_config.proto
 LOCAL_PROTOC_FLAGS := --proto_path=$(LOCAL_PATH)/../../src/
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index 97dcb90..0a4541b 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -363,6 +363,11 @@
      */
     public static final int GLOBAL_ACTION_LOCK_SCREEN = 8;
 
+    /**
+     * Action to take a screenshot
+     */
+    public static final int GLOBAL_ACTION_TAKE_SCREENSHOT = 9;
+
     private static final String LOG_TAG = "AccessibilityService";
 
     /**
diff --git a/core/java/android/app/ActivityView.java b/core/java/android/app/ActivityView.java
index 9f1e983..ac6cba1 100644
--- a/core/java/android/app/ActivityView.java
+++ b/core/java/android/app/ActivityView.java
@@ -34,6 +34,7 @@
 import android.view.SurfaceView;
 import android.view.ViewGroup;
 import android.view.WindowManager;
+import android.view.WindowManagerGlobal;
 
 import dalvik.system.CloseGuard;
 
@@ -58,6 +59,8 @@
     private StateCallback mActivityViewCallback;
 
     private IInputForwarder mInputForwarder;
+    // Temp container to store view coordinates on screen.
+    private final int[] mLocationOnScreen = new int[2];
 
     private final CloseGuard mGuard = CloseGuard.get();
     private boolean mOpened; // Protected by mGuard.
@@ -198,11 +201,30 @@
         performRelease();
     }
 
+    /**
+     * Triggers an update of {@link ActivityView}'s location on screen to properly set touch exclude
+     * regions and avoid focus switches by touches on this view.
+     */
+    public void onLocationChanged() {
+        updateLocation();
+    }
+
     @Override
     public void onLayout(boolean changed, int l, int t, int r, int b) {
         mSurfaceView.layout(0 /* left */, 0 /* top */, r - l /* right */, b - t /* bottom */);
     }
 
+    /** Send current location and size to the WM to set tap exclude region for this view. */
+    private void updateLocation() {
+        try {
+            getLocationOnScreen(mLocationOnScreen);
+            WindowManagerGlobal.getWindowSession().updateTapExcludeRegion(getWindow(), hashCode(),
+                    mLocationOnScreen[0], mLocationOnScreen[1], getWidth(), getHeight());
+        } catch (RemoteException e) {
+            e.rethrowAsRuntimeException();
+        }
+    }
+
     @Override
     public boolean onTouchEvent(MotionEvent event) {
         return injectInputEvent(event) || super.onTouchEvent(event);
@@ -241,6 +263,7 @@
             } else {
                 mVirtualDisplay.setSurface(surfaceHolder.getSurface());
             }
+            updateLocation();
         }
 
         @Override
@@ -248,6 +271,7 @@
             if (mVirtualDisplay != null) {
                 mVirtualDisplay.resize(width, height, getBaseDisplayDensity());
             }
+            updateLocation();
         }
 
         @Override
@@ -257,6 +281,7 @@
             if (mVirtualDisplay != null) {
                 mVirtualDisplay.setSurface(null);
             }
+            cleanTapExcludeRegion();
         }
     }
 
@@ -290,6 +315,7 @@
         if (mInputForwarder != null) {
             mInputForwarder = null;
         }
+        cleanTapExcludeRegion();
 
         final boolean displayReleased;
         if (mVirtualDisplay != null) {
@@ -313,6 +339,17 @@
         mOpened = false;
     }
 
+    /** Report to server that tap exclude region on hosting display should be cleared. */
+    private void cleanTapExcludeRegion() {
+        // Update tap exclude region with an empty rect to clean the state on server.
+        try {
+            WindowManagerGlobal.getWindowSession().updateTapExcludeRegion(getWindow(), hashCode(),
+                    0 /* left */, 0 /* top */, 0 /* width */, 0 /* height */);
+        } catch (RemoteException e) {
+            e.rethrowAsRuntimeException();
+        }
+    }
+
     /** Get density of the hosting display. */
     private int getBaseDisplayDensity() {
         final WindowManager wm = mContext.getSystemService(WindowManager.class);
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 6eafcc4..33277ea 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -38,12 +38,12 @@
 import android.content.Context;
 import android.content.IRestrictionsManager;
 import android.content.RestrictionsManager;
+import android.content.pm.CrossProfileApps;
+import android.content.pm.ICrossProfileApps;
 import android.content.pm.IShortcutService;
 import android.content.pm.LauncherApps;
 import android.content.pm.PackageManager;
 import android.content.pm.ShortcutManager;
-import android.content.pm.crossprofile.CrossProfileApps;
-import android.content.pm.crossprofile.ICrossProfileApps;
 import android.content.res.Resources;
 import android.hardware.ConsumerIrManager;
 import android.hardware.ISerialManager;
diff --git a/core/java/android/app/admin/DeviceAdminReceiver.java b/core/java/android/app/admin/DeviceAdminReceiver.java
index 302d52f..ffb3aff 100644
--- a/core/java/android/app/admin/DeviceAdminReceiver.java
+++ b/core/java/android/app/admin/DeviceAdminReceiver.java
@@ -339,7 +339,7 @@
     /**
      * Broadcast action: notify the device owner that a user or profile has been removed.
      * Carries an extra {@link Intent#EXTRA_USER} that has the {@link UserHandle} of
-     * the new user.
+     * the user.
      * @hide
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
@@ -347,6 +347,36 @@
     public static final String ACTION_USER_REMOVED = "android.app.action.USER_REMOVED";
 
     /**
+     * Broadcast action: notify the device owner that a user or profile has been started.
+     * Carries an extra {@link Intent#EXTRA_USER} that has the {@link UserHandle} of
+     * the user.
+     * @hide
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    @BroadcastBehavior(explicitOnly = true)
+    public static final String ACTION_USER_STARTED = "android.app.action.USER_STARTED";
+
+    /**
+     * Broadcast action: notify the device owner that a user or profile has been stopped.
+     * Carries an extra {@link Intent#EXTRA_USER} that has the {@link UserHandle} of
+     * the user.
+     * @hide
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    @BroadcastBehavior(explicitOnly = true)
+    public static final String ACTION_USER_STOPPED = "android.app.action.USER_STOPPED";
+
+    /**
+     * Broadcast action: notify the device owner that a user or profile has been switched to.
+     * Carries an extra {@link Intent#EXTRA_USER} that has the {@link UserHandle} of
+     * the user.
+     * @hide
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    @BroadcastBehavior(explicitOnly = true)
+    public static final String ACTION_USER_SWITCHED = "android.app.action.USER_SWITCHED";
+
+    /**
      * A string containing the SHA-256 hash of the bugreport file.
      *
      * @see #ACTION_BUGREPORT_SHARE
@@ -914,6 +944,42 @@
      }
 
     /**
+     * Called when a user or profile is started.
+     *
+     * <p>This callback is only applicable to device owners.
+     *
+     * @param context The running context as per {@link #onReceive}.
+     * @param intent The received intent as per {@link #onReceive}.
+     * @param startedUser The {@link UserHandle} of the user that has just been started.
+     */
+    public void onUserStarted(Context context, Intent intent, UserHandle startedUser) {
+    }
+
+    /**
+     * Called when a user or profile is stopped.
+     *
+     * <p>This callback is only applicable to device owners.
+     *
+     * @param context The running context as per {@link #onReceive}.
+     * @param intent The received intent as per {@link #onReceive}.
+     * @param stoppedUser The {@link UserHandle} of the user that has just been stopped.
+     */
+    public void onUserStopped(Context context, Intent intent, UserHandle stoppedUser) {
+    }
+
+    /**
+     * Called when a user or profile is switched to.
+     *
+     * <p>This callback is only applicable to device owners.
+     *
+     * @param context The running context as per {@link #onReceive}.
+     * @param intent The received intent as per {@link #onReceive}.
+     * @param switchedUser The {@link UserHandle} of the user that has just been switched to.
+     */
+    public void onUserSwitched(Context context, Intent intent, UserHandle switchedUser) {
+    }
+
+    /**
      * Called on the newly assigned owner (either device owner or profile owner) when the ownership
      * transfer has completed successfully.
      *
@@ -989,6 +1055,12 @@
             onUserAdded(context, intent, intent.getParcelableExtra(Intent.EXTRA_USER));
         } else if (ACTION_USER_REMOVED.equals(action)) {
             onUserRemoved(context, intent, intent.getParcelableExtra(Intent.EXTRA_USER));
+        } else if (ACTION_USER_STARTED.equals(action)) {
+            onUserStarted(context, intent, intent.getParcelableExtra(Intent.EXTRA_USER));
+        } else if (ACTION_USER_STOPPED.equals(action)) {
+            onUserStopped(context, intent, intent.getParcelableExtra(Intent.EXTRA_USER));
+        } else if (ACTION_USER_SWITCHED.equals(action)) {
+            onUserSwitched(context, intent, intent.getParcelableExtra(Intent.EXTRA_USER));
         } else if (ACTION_TRANSFER_OWNERSHIP_COMPLETE.equals(action)) {
             PersistableBundle bundle =
                     intent.getParcelableExtra(EXTRA_TRANSFER_OWNER_ADMIN_EXTRAS_BUNDLE);
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 9329d56..0be5564 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -9197,4 +9197,50 @@
             throw re.rethrowFromSystemServer();
         }
     }
+
+    /**
+     * Allows/disallows printing.
+     *
+     * @param admin which {@link DeviceAdminReceiver} this request is associated with.
+     * @param enabled whether printing should be allowed or not.
+     * @throws SecurityException if {@code admin} is neither device, nor profile owner.
+     * @hide
+     */
+    public void setPrintingEnabled(@NonNull ComponentName admin, boolean enabled) {
+        try {
+            mService.setPrintingEnabled(admin, enabled);
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Returns whether printing is enabled for current user.
+     *
+     * @return {@code true} iff printing is enabled.
+     * @hide
+     */
+    public boolean isPrintingEnabled() {
+        try {
+            return mService.isPrintingEnabled();
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Returns error message to be displayed when printing is disabled.
+     *
+     * Used only by PrintService.
+     * @return Localized error message.
+     * @throws SecurityException if caller is not system.
+     * @hide
+     */
+    public CharSequence getPrintingDisabledReason() {
+        try {
+            return mService.getPrintingDisabledReason();
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
+        }
+    }
 }
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index eac7f7e..d2a2be7 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -396,4 +396,8 @@
     void setEndUserSessionMessage(in ComponentName admin, in CharSequence endUserSessionMessage);
     CharSequence getStartUserSessionMessage(in ComponentName admin);
     CharSequence getEndUserSessionMessage(in ComponentName admin);
+
+    void setPrintingEnabled(in ComponentName admin, boolean enabled);
+    boolean isPrintingEnabled();
+    CharSequence getPrintingDisabledReason();
 }
diff --git a/core/java/android/app/job/JobInfo.java b/core/java/android/app/job/JobInfo.java
index 7c40b4e..cba9dcc 100644
--- a/core/java/android/app/job/JobInfo.java
+++ b/core/java/android/app/job/JobInfo.java
@@ -253,6 +253,11 @@
     /**
      * @hide
      */
+    public static final int FLAG_IS_PREFETCH = 1 << 2;
+
+    /**
+     * @hide
+     */
     public static final int CONSTRAINT_FLAG_CHARGING = 1 << 0;
 
     /**
@@ -1364,6 +1369,28 @@
         }
 
         /**
+         * Setting this to true indicates that this job is designed to prefetch
+         * content that will make a material improvement to the experience of
+         * the specific user of this device. For example, fetching top headlines
+         * of interest to the current user.
+         * <p>
+         * The system may use this signal to relax the network constraints you
+         * originally requested, such as allowing a
+         * {@link JobInfo#NETWORK_TYPE_UNMETERED} job to run over a metered
+         * network when there is a surplus of metered data available. The system
+         * may also use this signal in combination with end user usage patterns
+         * to ensure data is prefetched before the user launches your app.
+         */
+        public Builder setIsPrefetch(boolean isPrefetch) {
+            if (isPrefetch) {
+                mFlags |= FLAG_IS_PREFETCH;
+            } else {
+                mFlags &= (~FLAG_IS_PREFETCH);
+            }
+            return this;
+        }
+
+        /**
          * Set whether or not to persist this job across device reboots.
          *
          * @param isPersisted True to indicate that the job will be written to
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index db566e8..9f11d6e 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -79,8 +79,9 @@
  * {@link BluetoothDevice} objects representing all paired devices with
  * {@link #getBondedDevices()}; start device discovery with
  * {@link #startDiscovery()}; or create a {@link BluetoothServerSocket} to
- * listen for incoming connection requests with
- * {@link #listenUsingRfcommWithServiceRecord(String, UUID)}; or start a scan for
+ * listen for incoming RFComm connection requests with {@link
+ * #listenUsingRfcommWithServiceRecord(String, UUID)}; listen for incoming L2CAP Connection-oriented
+ * Channels (CoC) connection requests with listenUsingL2capCoc(int)}; or start a scan for
  * Bluetooth LE devices with {@link #startLeScan(LeScanCallback callback)}.
  * </p>
  * <p>This class is thread safe.</p>
@@ -210,6 +211,14 @@
     public static final int STATE_BLE_TURNING_OFF = 16;
 
     /**
+     * UUID of the GATT Read Characteristics for LE_PSM value.
+     *
+     * @hide
+     */
+    public static final UUID LE_PSM_CHARACTERISTIC_UUID =
+            UUID.fromString("2d410339-82b6-42aa-b34e-e2e01df8cc1a");
+
+    /**
      * Human-readable string helper for AdapterState
      *
      * @hide
@@ -2160,7 +2169,9 @@
                         min16DigitPin);
         int errno = socket.mSocket.bindListen();
         if (port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
-            socket.setChannel(socket.mSocket.getPort());
+            int assignedChannel = socket.mSocket.getPort();
+            if (DBG) Log.d(TAG, "listenUsingL2capOn: set assigned channel to " + assignedChannel);
+            socket.setChannel(assignedChannel);
         }
         if (errno != 0) {
             //TODO(BT): Throw the same exception error code
@@ -2201,12 +2212,18 @@
      * @hide
      */
     public BluetoothServerSocket listenUsingInsecureL2capOn(int port) throws IOException {
+        Log.d(TAG, "listenUsingInsecureL2capOn: port=" + port);
         BluetoothServerSocket socket =
                 new BluetoothServerSocket(BluetoothSocket.TYPE_L2CAP, false, false, port, false,
-                        false);
+                                          false);
         int errno = socket.mSocket.bindListen();
         if (port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
-            socket.setChannel(socket.mSocket.getPort());
+            int assignedChannel = socket.mSocket.getPort();
+            if (DBG) {
+                Log.d(TAG, "listenUsingInsecureL2capOn: set assigned channel to "
+                        + assignedChannel);
+            }
+            socket.setChannel(assignedChannel);
         }
         if (errno != 0) {
             //TODO(BT): Throw the same exception error code
@@ -2765,4 +2782,103 @@
             scanner.stopScan(scanCallback);
         }
     }
+
+    /**
+     * Create a secure L2CAP Connection-oriented Channel (CoC) {@link BluetoothServerSocket} and
+     * assign a dynamic protocol/service multiplexer (PSM) value. This socket can be used to listen
+     * for incoming connections.
+     * <p>A remote device connecting to this socket will be authenticated and communication on this
+     * socket will be encrypted.
+     * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming connections from a listening
+     * {@link BluetoothServerSocket}.
+     * <p>The system will assign a dynamic PSM value. This PSM value can be read from the {#link
+     * BluetoothServerSocket#getPsm()} and this value will be released when this server socket is
+     * closed, Bluetooth is turned off, or the application exits unexpectedly.
+     * <p>The mechanism of disclosing the assigned dynamic PSM value to the initiating peer is
+     * defined and performed by the application.
+     * <p>Use {@link BluetoothDevice#createL2capCocSocket(int, int)} to connect to this server
+     * socket from another Android device that is given the PSM value.
+     *
+     * @param transport Bluetooth transport to use, must be {@link BluetoothDevice#TRANSPORT_LE}
+     * @return an L2CAP CoC BluetoothServerSocket
+     * @throws IOException on error, for example Bluetooth not available, or insufficient
+     * permissions, or unable to start this CoC
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.BLUETOOTH)
+    public BluetoothServerSocket listenUsingL2capCoc(int transport)
+            throws IOException {
+        if (transport != BluetoothDevice.TRANSPORT_LE) {
+            throw new IllegalArgumentException("Unsupported transport: " + transport);
+        }
+        BluetoothServerSocket socket =
+                            new BluetoothServerSocket(BluetoothSocket.TYPE_L2CAP_LE, true, true,
+                                      SOCKET_CHANNEL_AUTO_STATIC_NO_SDP, false, false);
+        int errno = socket.mSocket.bindListen();
+        if (errno != 0) {
+            throw new IOException("Error: " + errno);
+        }
+
+        int assignedPsm = socket.mSocket.getPort();
+        if (assignedPsm == 0) {
+            throw new IOException("Error: Unable to assign PSM value");
+        }
+        if (DBG) {
+            Log.d(TAG, "listenUsingL2capCoc: set assigned PSM to "
+                    + assignedPsm);
+        }
+        socket.setChannel(assignedPsm);
+
+        return socket;
+    }
+
+    /**
+     * Create an insecure L2CAP Connection-oriented Channel (CoC) {@link BluetoothServerSocket} and
+     * assign a dynamic PSM value. This socket can be used to listen for incoming connections.
+     * <p>The link key is not required to be authenticated, i.e the communication may be vulnerable
+     * to man-in-the-middle attacks. Use {@link #listenUsingL2capCoc}, if an encrypted and
+     * authenticated communication channel is desired.
+     * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming connections from a listening
+     * {@link BluetoothServerSocket}.
+     * <p>The system will assign a dynamic protocol/service multiplexer (PSM) value. This PSM value
+     * can be read from the {#link BluetoothServerSocket#getPsm()} and this value will be released
+     * when this server socket is closed, Bluetooth is turned off, or the application exits
+     * unexpectedly.
+     * <p>The mechanism of disclosing the assigned dynamic PSM value to the initiating peer is
+     * defined and performed by the application.
+     * <p>Use {@link BluetoothDevice#createInsecureL2capCocSocket(int, int)} to connect to this
+     * server socket from another Android device that is given the PSM value.
+     *
+     * @param transport Bluetooth transport to use, must be {@link BluetoothDevice#TRANSPORT_LE}
+     * @return an L2CAP CoC BluetoothServerSocket
+     * @throws IOException on error, for example Bluetooth not available, or insufficient
+     * permissions, or unable to start this CoC
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.BLUETOOTH)
+    public BluetoothServerSocket listenUsingInsecureL2capCoc(int transport)
+            throws IOException {
+        if (transport != BluetoothDevice.TRANSPORT_LE) {
+            throw new IllegalArgumentException("Unsupported transport: " + transport);
+        }
+        BluetoothServerSocket socket =
+                            new BluetoothServerSocket(BluetoothSocket.TYPE_L2CAP_LE, false, false,
+                                      SOCKET_CHANNEL_AUTO_STATIC_NO_SDP, false, false);
+        int errno = socket.mSocket.bindListen();
+        if (errno != 0) {
+            throw new IOException("Error: " + errno);
+        }
+
+        int assignedPsm = socket.mSocket.getPort();
+        if (assignedPsm == 0) {
+            throw new IOException("Error: Unable to assign PSM value");
+        }
+        if (DBG) {
+            Log.d(TAG, "listenUsingInsecureL2capOn: set assigned PSM to "
+                    + assignedPsm);
+        }
+        socket.setChannel(assignedPsm);
+
+        return socket;
+    }
 }
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index 9b736b7..ac21395 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -1921,4 +1921,75 @@
         }
         return null;
     }
+
+    /**
+     * Create a Bluetooth L2CAP Connection-oriented Channel (CoC) {@link BluetoothSocket} that can
+     * be used to start a secure outgoing connection to the remote device with the same dynamic
+     * protocol/service multiplexer (PSM) value.
+     * <p>This is designed to be used with {@link BluetoothAdapter#listenUsingL2capCoc(int)} for
+     * peer-peer Bluetooth applications.
+     * <p>Use {@link BluetoothSocket#connect} to initiate the outgoing connection.
+     * <p>Application using this API is responsible for obtaining PSM value from remote device.
+     * <p>The remote device will be authenticated and communication on this socket will be
+     * encrypted.
+     * <p> Use this socket if an authenticated socket link is possible. Authentication refers
+     * to the authentication of the link key to prevent man-in-the-middle type of attacks. When a
+     * secure socket connection is not possible, use {#link createInsecureLeL2capCocSocket(int,
+     * int)}.
+     *
+     * @param transport Bluetooth transport to use, must be {@link #TRANSPORT_LE}
+     * @param psm dynamic PSM value from remote device
+     * @return a CoC #BluetoothSocket ready for an outgoing connection
+     * @throws IOException on error, for example Bluetooth not available, or insufficient
+     * permissions
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.BLUETOOTH)
+    public BluetoothSocket createL2capCocSocket(int transport, int psm) throws IOException {
+        if (!isBluetoothEnabled()) {
+            Log.e(TAG, "createL2capCocSocket: Bluetooth is not enabled");
+            throw new IOException();
+        }
+        if (transport != BluetoothDevice.TRANSPORT_LE) {
+            throw new IllegalArgumentException("Unsupported transport: " + transport);
+        }
+        if (DBG) Log.d(TAG, "createL2capCocSocket: transport=" + transport + ", psm=" + psm);
+        return new BluetoothSocket(BluetoothSocket.TYPE_L2CAP_LE, -1, true, true, this, psm,
+                null);
+    }
+
+    /**
+     * Create a Bluetooth L2CAP Connection-oriented Channel (CoC) {@link BluetoothSocket} that can
+     * be used to start a secure outgoing connection to the remote device with the same dynamic
+     * protocol/service multiplexer (PSM) value.
+     * <p>This is designed to be used with {@link BluetoothAdapter#listenUsingInsecureL2capCoc(int)}
+     * for peer-peer Bluetooth applications.
+     * <p>Use {@link BluetoothSocket#connect} to initiate the outgoing connection.
+     * <p>Application using this API is responsible for obtaining PSM value from remote device.
+     * <p> The communication channel may not have an authenticated link key, i.e. it may be subject
+     * to man-in-the-middle attacks. Use {@link #createL2capCocSocket(int, int)} if an encrypted and
+     * authenticated communication channel is possible.
+     *
+     * @param transport Bluetooth transport to use, must be {@link #TRANSPORT_LE}
+     * @param psm dynamic PSM value from remote device
+     * @return a CoC #BluetoothSocket ready for an outgoing connection
+     * @throws IOException on error, for example Bluetooth not available, or insufficient
+     * permissions
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.BLUETOOTH)
+    public BluetoothSocket createInsecureL2capCocSocket(int transport, int psm) throws IOException {
+        if (!isBluetoothEnabled()) {
+            Log.e(TAG, "createInsecureL2capCocSocket: Bluetooth is not enabled");
+            throw new IOException();
+        }
+        if (transport != BluetoothDevice.TRANSPORT_LE) {
+            throw new IllegalArgumentException("Unsupported transport: " + transport);
+        }
+        if (DBG) {
+            Log.d(TAG, "createInsecureL2capCocSocket: transport=" + transport + ", psm=" + psm);
+        }
+        return new BluetoothSocket(BluetoothSocket.TYPE_L2CAP_LE, -1, false, false, this, psm,
+                null);
+    }
 }
diff --git a/core/java/android/bluetooth/BluetoothServerSocket.java b/core/java/android/bluetooth/BluetoothServerSocket.java
index 58d090d..ebb7f18 100644
--- a/core/java/android/bluetooth/BluetoothServerSocket.java
+++ b/core/java/android/bluetooth/BluetoothServerSocket.java
@@ -68,6 +68,7 @@
 public final class BluetoothServerSocket implements Closeable {
 
     private static final String TAG = "BluetoothServerSocket";
+    private static final boolean DBG = false;
     /*package*/ final BluetoothSocket mSocket;
     private Handler mHandler;
     private int mMessage;
@@ -169,6 +170,7 @@
      * close any {@link BluetoothSocket} received from {@link #accept()}.
      */
     public void close() throws IOException {
+        if (DBG) Log.d(TAG, "BluetoothServerSocket:close() called. mChannel=" + mChannel);
         synchronized (this) {
             if (mHandler != null) {
                 mHandler.obtainMessage(mMessage).sendToTarget();
@@ -197,6 +199,20 @@
     }
 
     /**
+     * Returns the assigned dynamic protocol/service multiplexer (PSM) value for the listening L2CAP
+     * Connection-oriented Channel (CoC) server socket. This server socket must be returned by the
+     * {#link BluetoothAdapter.listenUsingL2capCoc(int)} or {#link
+     * BluetoothAdapter.listenUsingInsecureL2capCoc(int)}. The returned value is undefined if this
+     * method is called on non-L2CAP server sockets.
+     *
+     * @return the assigned PSM or LE_PSM value depending on transport
+     * @hide
+     */
+    public int getPsm() {
+        return mChannel;
+    }
+
+    /**
      * Sets the channel on which future sockets are bound.
      * Currently used only when a channel is auto generated.
      */
@@ -227,6 +243,10 @@
                 sb.append("TYPE_L2CAP");
                 break;
             }
+            case BluetoothSocket.TYPE_L2CAP_LE: {
+                sb.append("TYPE_L2CAP_LE");
+                break;
+            }
             case BluetoothSocket.TYPE_SCO: {
                 sb.append("TYPE_SCO");
                 break;
diff --git a/core/java/android/bluetooth/BluetoothSocket.java b/core/java/android/bluetooth/BluetoothSocket.java
index 0569913..09f9684 100644
--- a/core/java/android/bluetooth/BluetoothSocket.java
+++ b/core/java/android/bluetooth/BluetoothSocket.java
@@ -99,6 +99,16 @@
     /** L2CAP socket */
     public static final int TYPE_L2CAP = 3;
 
+    /** L2CAP socket on BR/EDR transport
+     * @hide
+     */
+    public static final int TYPE_L2CAP_BREDR = TYPE_L2CAP;
+
+    /** L2CAP socket on LE transport
+     * @hide
+     */
+    public static final int TYPE_L2CAP_LE = 4;
+
     /*package*/ static final int EBADFD = 77;
     /*package*/ static final int EADDRINUSE = 98;
 
@@ -417,6 +427,7 @@
             return -1;
         }
         try {
+            if (DBG) Log.d(TAG, "bindListen(): mPort=" + mPort + ", mType=" + mType);
             mPfd = bluetoothProxy.getSocketManager().createSocketChannel(mType, mServiceName,
                     mUuid, mPort, getSecurityFlags());
         } catch (RemoteException e) {
@@ -451,7 +462,7 @@
                     mSocketState = SocketState.LISTENING;
                 }
             }
-            if (DBG) Log.d(TAG, "channel: " + channel);
+            if (DBG) Log.d(TAG, "bindListen(): channel=" + channel + ", mPort=" + mPort);
             if (mPort <= -1) {
                 mPort = channel;
             } // else ASSERT(mPort == channel)
@@ -515,7 +526,7 @@
     /*package*/ int read(byte[] b, int offset, int length) throws IOException {
         int ret = 0;
         if (VDBG) Log.d(TAG, "read in:  " + mSocketIS + " len: " + length);
-        if (mType == TYPE_L2CAP) {
+        if ((mType == TYPE_L2CAP) || (mType == TYPE_L2CAP_LE)) {
             int bytesToRead = length;
             if (VDBG) {
                 Log.v(TAG, "l2cap: read(): offset: " + offset + " length:" + length
@@ -558,7 +569,7 @@
         //      Rfcomm uses dynamic allocation, and should not have any bindings
         //      to the actual message length.
         if (VDBG) Log.d(TAG, "write: " + mSocketOS + " length: " + length);
-        if (mType == TYPE_L2CAP) {
+        if ((mType == TYPE_L2CAP) || (mType == TYPE_L2CAP_LE)) {
             if (length <= mMaxTxPacketSize) {
                 mSocketOS.write(b, offset, length);
             } else {
@@ -702,7 +713,7 @@
     }
 
     private void createL2capRxBuffer() {
-        if (mType == TYPE_L2CAP) {
+        if ((mType == TYPE_L2CAP) || (mType == TYPE_L2CAP_LE)) {
             // Allocate the buffer to use for reads.
             if (VDBG) Log.v(TAG, "  Creating mL2capBuffer: mMaxPacketSize: " + mMaxRxPacketSize);
             mL2capBuffer = ByteBuffer.wrap(new byte[mMaxRxPacketSize]);
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index f69e764..265f7c7 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -4146,7 +4146,7 @@
 
     /**
      * Use with {@link #getSystemService(String)} to retrieve a
-     * {@link android.content.pm.crossprofile.CrossProfileApps} for cross profile operations.
+     * {@link android.content.pm.CrossProfileApps} for cross profile operations.
      *
      * @see #getSystemService(String)
      */
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 6e99709..f05a4d1 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -3516,12 +3516,83 @@
      * For more details see TelephonyIntents.ACTION_SIM_STATE_CHANGED. This is here
      * because TelephonyIntents is an internal class.
      * @hide
+     * @deprecated Use {@link #ACTION_SIM_CARD_STATE_CHANGED} or
+     * {@link #ACTION_SIM_APPLICATION_STATE_CHANGED}
      */
+    @Deprecated
     @SystemApi
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_SIM_STATE_CHANGED = "android.intent.action.SIM_STATE_CHANGED";
 
     /**
+     * Broadcast Action: The sim card state has changed.
+     * The intent will have the following extra values:</p>
+     * <dl>
+     *   <dt>{@link android.telephony.TelephonyManager.EXTRA_SIM_STATE}</dt>
+     *   <dd>The sim card state. One of:
+     *     <dl>
+     *       <dt>{@link android.telephony.TelephonyManager.SIM_STATE_ABSENT}</dt>
+     *       <dd>SIM card not found</dd>
+     *       <dt>{@link android.telephony.TelephonyManager.SIM_STATE_CARD_IO_ERROR}</dt>
+     *       <dd>SIM card IO error</dd>
+     *       <dt>{@link android.telephony.TelephonyManager.SIM_STATE_CARD_RESTRICTED}</dt>
+     *       <dd>SIM card is restricted</dd>
+     *       <dt>{@link android.telephony.TelephonyManager.SIM_STATE_PRESENT}</dt>
+     *       <dd>SIM card is present</dd>
+     *     </dl>
+     *   </dd>
+     * </dl>
+     *
+     * <p class="note">Requires the READ_PRIVILEGED_PHONE_STATE permission.
+     *
+     * <p class="note">The current state can also be queried using
+     * {@link android.telephony.TelephonyManager.getSimCardState()}
+     *
+     * <p class="note">This is a protected intent that can only be sent by the system.
+     * @hide
+     */
+    @SystemApi
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_SIM_CARD_STATE_CHANGED =
+            "android.intent.action.SIM_CARD_STATE_CHANGED";
+
+    /**
+     * Broadcast Action: The sim application state has changed.
+     * The intent will have the following extra values:</p>
+     * <dl>
+     *   <dt>{@link android.telephony.TelephonyManager.EXTRA_SIM_STATE}</dt>
+     *   <dd>The sim application state. One of:
+     *     <dl>
+     *       <dt>{@link android.telephony.TelephonyManager.SIM_STATE_NOT_READY}</dt>
+     *       <dd>SIM card applications not ready</dd>
+     *       <dt>{@link android.telephony.TelephonyManager.SIM_STATE_PIN_REQUIRED}</dt>
+     *       <dd>SIM card PIN locked</dd>
+     *       <dt>{@link android.telephony.TelephonyManager.SIM_STATE_PUK_REQUIRED}</dt>
+     *       <dd>SIM card PUK locked</dd>
+     *       <dt>{@link android.telephony.TelephonyManager.SIM_STATE_NETWORK_LOCKED}</dt>
+     *       <dd>SIM card network locked</dd>
+     *       <dt>{@link android.telephony.TelephonyManager.SIM_STATE_PERM_DISABLED}</dt>
+     *       <dd>SIM card permanently disabled due to PUK failures</dd>
+     *       <dt>{@link android.telephony.TelephonyManager.SIM_STATE_LOADED}</dt>
+     *       <dd>SIM card data loaded</dd>
+     *     </dl>
+     *   </dd>
+     * </dl>
+     *
+     * <p class="note">Requires the READ_PRIVILEGED_PHONE_STATE permission.
+     *
+     * <p class="note">The current state can also be queried using
+     * {@link android.telephony.TelephonyManager.getSimApplicationState()}
+     *
+     * <p class="note">This is a protected intent that can only be sent by the system.
+     * @hide
+     */
+    @SystemApi
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_SIM_APPLICATION_STATE_CHANGED =
+            "android.intent.action.SIM_APPLICATION_STATE_CHANGED";
+
+    /**
      * Broadcast Action: indicate that the phone service state has changed.
      * The intent will have the following extra values:</p>
      * <p>
diff --git a/core/java/android/content/pm/crossprofile/CrossProfileApps.java b/core/java/android/content/pm/CrossProfileApps.java
similarity index 92%
rename from core/java/android/content/pm/crossprofile/CrossProfileApps.java
rename to core/java/android/content/pm/CrossProfileApps.java
index 414c138..7d5d609 100644
--- a/core/java/android/content/pm/crossprofile/CrossProfileApps.java
+++ b/core/java/android/content/pm/CrossProfileApps.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.content.pm.crossprofile;
+package android.content.pm;
 
 import android.annotation.NonNull;
 import android.content.ComponentName;
@@ -57,13 +57,14 @@
      *        action {@link android.content.Intent#ACTION_MAIN}, category
      *        {@link android.content.Intent#CATEGORY_LAUNCHER}. Otherwise, SecurityException will
      *        be thrown.
-     * @param user The UserHandle of the profile, must be one of the users returned by
+     * @param targetUser The UserHandle of the profile, must be one of the users returned by
      *        {@link #getTargetUserProfiles()}, otherwise a {@link SecurityException} will
      *        be thrown.
      */
-    public void startMainActivity(@NonNull ComponentName component, @NonNull UserHandle user) {
+    public void startMainActivity(@NonNull ComponentName component,
+            @NonNull UserHandle targetUser) {
         try {
-            mService.startActivityAsUser(mContext.getPackageName(), component, user);
+            mService.startActivityAsUser(mContext.getPackageName(), component, targetUser);
         } catch (RemoteException ex) {
             throw ex.rethrowFromSystemServer();
         }
@@ -114,7 +115,7 @@
     }
 
     /**
-     * Return an icon that calling app can show to user for the semantic of profile switching --
+     * Return a drawable that calling app can show to user for the semantic of profile switching --
      * launching its own activity in specified user profile. For example, it may return a briefcase
      * icon if the given user handle is the managed profile one.
      *
@@ -124,9 +125,9 @@
      * @return an icon that calling app can show user for the semantic of launching its own
      *         activity in specified user profile.
      *
-     * @see #startMainActivity(ComponentName, UserHandle, Rect, Bundle)
+     * @see #startMainActivity(ComponentName, UserHandle)
      */
-    public @NonNull Drawable getProfileSwitchingIcon(@NonNull UserHandle userHandle) {
+    public @NonNull Drawable getProfileSwitchingIconDrawable(@NonNull UserHandle userHandle) {
         verifyCanAccessUser(userHandle);
 
         final boolean isManagedProfile =
diff --git a/core/java/android/content/pm/crossprofile/ICrossProfileApps.aidl b/core/java/android/content/pm/ICrossProfileApps.aidl
similarity index 95%
rename from core/java/android/content/pm/crossprofile/ICrossProfileApps.aidl
rename to core/java/android/content/pm/ICrossProfileApps.aidl
index 227f91f5..e79deb9 100644
--- a/core/java/android/content/pm/crossprofile/ICrossProfileApps.aidl
+++ b/core/java/android/content/pm/ICrossProfileApps.aidl
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.content.pm.crossprofile;
+package android.content.pm;
 
 import android.content.ComponentName;
 import android.content.Intent;
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 44b4a33..bcf80ee 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1297,6 +1297,15 @@
      */
     public static final int INSTALL_FAILED_INSTANT_APP_INVALID = -116;
 
+    /**
+     * Installation parse return code: this is passed in the
+     * {@link PackageInstaller#EXTRA_LEGACY_STATUS} if the dex metadata file is invalid or
+     * if there was no matching apk file for a dex metadata file.
+     *
+     * @hide
+     */
+    public static final int INSTALL_FAILED_BAD_DEX_METADATA = -117;
+
     /** @hide */
     @IntDef(flag = true, prefix = { "DELETE_" }, value = {
             DELETE_KEEP_DATA,
@@ -5618,6 +5627,8 @@
             case INSTALL_FAILED_DUPLICATE_PERMISSION: return "INSTALL_FAILED_DUPLICATE_PERMISSION";
             case INSTALL_FAILED_NO_MATCHING_ABIS: return "INSTALL_FAILED_NO_MATCHING_ABIS";
             case INSTALL_FAILED_ABORTED: return "INSTALL_FAILED_ABORTED";
+            case INSTALL_FAILED_BAD_DEX_METADATA:
+                return "INSTALL_FAILED_BAD_DEX_METADATA";
             default: return Integer.toString(status);
         }
     }
@@ -5662,6 +5673,7 @@
             case INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID: return PackageInstaller.STATUS_FAILURE_INVALID;
             case INSTALL_PARSE_FAILED_MANIFEST_MALFORMED: return PackageInstaller.STATUS_FAILURE_INVALID;
             case INSTALL_PARSE_FAILED_MANIFEST_EMPTY: return PackageInstaller.STATUS_FAILURE_INVALID;
+            case INSTALL_FAILED_BAD_DEX_METADATA: return PackageInstaller.STATUS_FAILURE_INVALID;
             case INSTALL_FAILED_INTERNAL_ERROR: return PackageInstaller.STATUS_FAILURE;
             case INSTALL_FAILED_USER_RESTRICTED: return PackageInstaller.STATUS_FAILURE_INCOMPATIBLE;
             case INSTALL_FAILED_DUPLICATE_PERMISSION: return PackageInstaller.STATUS_FAILURE_CONFLICT;
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index 2c45b8d..6f093ba 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -436,6 +436,11 @@
      */
     public abstract int getUidTargetSdkVersion(int uid);
 
+    /**
+     * Return the taget SDK version for the app with the given package name.
+     */
+    public abstract int getPackageTargetSdkVersion(String packageName);
+
     /** Whether the binder caller can access instant apps. */
     public abstract boolean canAccessInstantApps(int callingUid, int userId);
 
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 6d6c02a..4a71467 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -240,6 +240,9 @@
     }
 
     /** @hide */
+    public static final String APK_FILE_EXTENSION = ".apk";
+
+    /** @hide */
     public static class NewPermissionInfo {
         public final String name;
         public final int sdkVersion;
@@ -613,7 +616,7 @@
     }
 
     public static boolean isApkPath(String path) {
-        return path.endsWith(".apk");
+        return path.endsWith(APK_FILE_EXTENSION);
     }
 
     /**
diff --git a/core/java/android/content/pm/dex/DexMetadataHelper.java b/core/java/android/content/pm/dex/DexMetadataHelper.java
new file mode 100644
index 0000000..c5f1c85
--- /dev/null
+++ b/core/java/android/content/pm/dex/DexMetadataHelper.java
@@ -0,0 +1,230 @@
+/**
+ * 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.
+ */
+
+package android.content.pm.dex;
+
+import static android.content.pm.PackageManager.INSTALL_FAILED_BAD_DEX_METADATA;
+import static android.content.pm.PackageParser.APK_FILE_EXTENSION;
+
+import android.content.pm.PackageParser;
+import android.content.pm.PackageParser.PackageLite;
+import android.content.pm.PackageParser.PackageParserException;
+import android.util.ArrayMap;
+import android.util.jar.StrictJarFile;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Helper class used to compute and validate the location of dex metadata files.
+ *
+ * @hide
+ */
+public class DexMetadataHelper {
+    private static final String DEX_METADATA_FILE_EXTENSION = ".dm";
+
+    private DexMetadataHelper() {}
+
+    /** Return true if the given file is a dex metadata file. */
+    public static boolean isDexMetadataFile(File file) {
+        return isDexMetadataPath(file.getName());
+    }
+
+    /** Return true if the given path is a dex metadata path. */
+    private static boolean isDexMetadataPath(String path) {
+        return path.endsWith(DEX_METADATA_FILE_EXTENSION);
+    }
+
+    /**
+     * Return the size (in bytes) of all dex metadata files associated with the given package.
+     */
+    public static long getPackageDexMetadataSize(PackageLite pkg) {
+        long sizeBytes = 0;
+        Collection<String> dexMetadataList = DexMetadataHelper.getPackageDexMetadata(pkg).values();
+        for (String dexMetadata : dexMetadataList) {
+            sizeBytes += new File(dexMetadata).length();
+        }
+        return sizeBytes;
+    }
+
+    /**
+     * Search for the dex metadata file associated with the given target file.
+     * If it exists, the method returns the dex metadata file; otherwise it returns null.
+     *
+     * Note that this performs a loose matching suitable to be used in the InstallerSession logic.
+     * i.e. the method will attempt to match the {@code dmFile} regardless of {@code targetFile}
+     * extension (e.g. 'foo.dm' will match 'foo' or 'foo.apk').
+     */
+    public static File findDexMetadataForFile(File targetFile) {
+        String dexMetadataPath = buildDexMetadataPathForFile(targetFile);
+        File dexMetadataFile = new File(dexMetadataPath);
+        return dexMetadataFile.exists() ? dexMetadataFile : null;
+    }
+
+    /**
+     * Return the dex metadata files for the given package as a map
+     * [code path -> dex metadata path].
+     *
+     * NOTE: involves I/O checks.
+     */
+    public static Map<String, String> getPackageDexMetadata(PackageParser.Package pkg) {
+        return buildPackageApkToDexMetadataMap(pkg.getAllCodePaths());
+    }
+
+    /**
+     * Return the dex metadata files for the given package as a map
+     * [code path -> dex metadata path].
+     *
+     * NOTE: involves I/O checks.
+     */
+    private static Map<String, String> getPackageDexMetadata(PackageLite pkg) {
+        return buildPackageApkToDexMetadataMap(pkg.getAllCodePaths());
+    }
+
+    /**
+     * Look up the dex metadata files for the given code paths building the map
+     * [code path -> dex metadata].
+     *
+     * For each code path (.apk) the method checks if a matching dex metadata file (.dm) exists.
+     * If it does it adds the pair to the returned map.
+     *
+     * Note that this method will do a strict
+     * matching based on the extension ('foo.dm' will only match 'foo.apk').
+     *
+     * This should only be used for code paths extracted from a package structure after the naming
+     * was enforced in the installer.
+     */
+    private static Map<String, String> buildPackageApkToDexMetadataMap(
+            List<String> codePaths) {
+        ArrayMap<String, String> result = new ArrayMap<>();
+        for (int i = codePaths.size() - 1; i >= 0; i--) {
+            String codePath = codePaths.get(i);
+            String dexMetadataPath = buildDexMetadataPathForApk(codePath);
+
+            if (Files.exists(Paths.get(dexMetadataPath))) {
+                result.put(codePath, dexMetadataPath);
+            }
+        }
+
+        return result;
+    }
+
+    /**
+     * Return the dex metadata path associated with the given code path.
+     * (replaces '.apk' extension with '.dm')
+     *
+     * @throws IllegalArgumentException if the code path is not an .apk.
+     */
+    public static String buildDexMetadataPathForApk(String codePath) {
+        if (!PackageParser.isApkPath(codePath)) {
+            throw new IllegalStateException(
+                    "Corrupted package. Code path is not an apk " + codePath);
+        }
+        return codePath.substring(0, codePath.length() - APK_FILE_EXTENSION.length())
+                + DEX_METADATA_FILE_EXTENSION;
+    }
+
+    /**
+     * Return the dex metadata path corresponding to the given {@code targetFile} using a loose
+     * matching.
+     * i.e. the method will attempt to match the {@code dmFile} regardless of {@code targetFile}
+     * extension (e.g. 'foo.dm' will match 'foo' or 'foo.apk').
+     */
+    private static String buildDexMetadataPathForFile(File targetFile) {
+        return PackageParser.isApkFile(targetFile)
+                ? buildDexMetadataPathForApk(targetFile.getPath())
+                : targetFile.getPath() + DEX_METADATA_FILE_EXTENSION;
+    }
+
+    /**
+     * Validate the dex metadata files installed for the given package.
+     *
+     * @throws PackageParserException in case of errors.
+     */
+    public static void validatePackageDexMetadata(PackageParser.Package pkg)
+            throws PackageParserException {
+        Collection<String> apkToDexMetadataList = getPackageDexMetadata(pkg).values();
+        for (String dexMetadata : apkToDexMetadataList) {
+            validateDexMetadataFile(dexMetadata);
+        }
+    }
+
+    /**
+     * Validate that the given file is a dex metadata archive.
+     * This is just a sanity validation that the file is a zip archive.
+     *
+     * @throws PackageParserException if the file is not a .dm file.
+     */
+    private static void validateDexMetadataFile(String dmaPath) throws PackageParserException {
+        StrictJarFile jarFile = null;
+        try {
+            jarFile = new StrictJarFile(dmaPath, false, false);
+        } catch (IOException e) {
+            throw new PackageParserException(INSTALL_FAILED_BAD_DEX_METADATA,
+                    "Error opening " + dmaPath, e);
+        } finally {
+            if (jarFile != null) {
+                try {
+                    jarFile.close();
+                } catch (IOException ignored) {
+                }
+            }
+        }
+    }
+
+    /**
+     * Validates that all dex metadata paths in the given list have a matching apk.
+     * (for any foo.dm there should be either a 'foo' of a 'foo.apk' file).
+     * If that's not the case it throws {@code IllegalStateException}.
+     *
+     * This is used to perform a basic sanity check during adb install commands.
+     * (The installer does not support stand alone .dm files)
+     */
+    public static void validateDexPaths(String[] paths) {
+        ArrayList<String> apks = new ArrayList<>();
+        for (int i = 0; i < paths.length; i++) {
+            if (PackageParser.isApkPath(paths[i])) {
+                apks.add(paths[i]);
+            }
+        }
+        ArrayList<String> unmatchedDmFiles = new ArrayList<>();
+        for (int i = 0; i < paths.length; i++) {
+            String dmPath = paths[i];
+            if (isDexMetadataPath(dmPath)) {
+                boolean valid = false;
+                for (int j = apks.size() - 1; j >= 0; j--) {
+                    if (dmPath.equals(buildDexMetadataPathForFile(new File(apks.get(j))))) {
+                        valid = true;
+                        break;
+                    }
+                }
+                if (!valid) {
+                    unmatchedDmFiles.add(dmPath);
+                }
+            }
+        }
+        if (!unmatchedDmFiles.isEmpty()) {
+            throw new IllegalStateException("Unmatched .dm files: " + unmatchedDmFiles);
+        }
+    }
+
+}
diff --git a/core/java/android/database/sqlite/SQLiteOpenHelper.java b/core/java/android/database/sqlite/SQLiteOpenHelper.java
index 49f357e..a2991e6 100644
--- a/core/java/android/database/sqlite/SQLiteOpenHelper.java
+++ b/core/java/android/database/sqlite/SQLiteOpenHelper.java
@@ -66,7 +66,7 @@
      * created or opened until one of {@link #getWritableDatabase} or
      * {@link #getReadableDatabase} is called.
      *
-     * @param context to use to open or create the database
+     * @param context to use for locating paths to the the database
      * @param name of the database file, or null for an in-memory database
      * @param factory to use for creating cursor objects, or null for the default
      * @param version number of the database (starting at 1); if the database is older,
@@ -86,7 +86,7 @@
      * <p>Accepts input param: a concrete instance of {@link DatabaseErrorHandler} to be
      * used to handle corruption when sqlite reports database corruption.</p>
      *
-     * @param context to use to open or create the database
+     * @param context to use for locating paths to the the database
      * @param name of the database file, or null for an in-memory database
      * @param factory to use for creating cursor objects, or null for the default
      * @param version number of the database (starting at 1); if the database is older,
@@ -107,7 +107,7 @@
      * created or opened until one of {@link #getWritableDatabase} or
      * {@link #getReadableDatabase} is called.
      *
-     * @param context to use to open or create the database
+     * @param context to use for locating paths to the the database
      * @param name of the database file, or null for an in-memory database
      * @param version number of the database (starting at 1); if the database is older,
      *     {@link #onUpgrade} will be used to upgrade the database; if the database is
@@ -128,7 +128,7 @@
      * minimumSupportedVersion is found, it is simply deleted and a new database is created with the
      * given name and version
      *
-     * @param context to use to open or create the database
+     * @param context to use for locating paths to the the database
      * @param name the name of the database file, null for a temporary in-memory database
      * @param factory to use for creating cursor objects, null for default
      * @param version the required version of the database
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index ce1fba7..639795a 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -183,7 +183,9 @@
           TEMPLATE_RECORD,
           TEMPLATE_VIDEO_SNAPSHOT,
           TEMPLATE_ZERO_SHUTTER_LAG,
-          TEMPLATE_MANUAL })
+          TEMPLATE_MANUAL,
+          TEMPLATE_MOTION_TRACKING_PREVIEW,
+          TEMPLATE_MOTION_TRACKING_BEST})
      public @interface RequestTemplate {};
 
     /**
@@ -424,14 +426,17 @@
      * {@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED LIMITED} devices. The
      * {@code FULL FOV 640} entry means that the device will support a resolution that's 640 pixels
      * wide, with the height set so that the resolution aspect ratio matches the MAXIMUM output
-     * aspect ratio.  So for a device with a 4:3 image sensor, this will be 640x480, and for a
-     * device with a 16:9 sensor, this will be 640x360, and so on.
+     * aspect ratio, rounded down.  So for a device with a 4:3 image sensor, this will be 640x480,
+     * and for a device with a 16:9 sensor, this will be 640x360, and so on. And the
+     * {@code MAX 30FPS} entry means the largest JPEG resolution on the device for which
+     * {@link android.hardware.camera2.params.StreamConfigurationMap#getOutputMinFrameDuration}
+     * returns a value less than or equal to 1/30s.
      *
      * <table>
      * <tr><th colspan="7">MOTION_TRACKING-capability additional guaranteed configurations</th></tr>
      * <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th colspan="2" id="rb">Target 3</th><th rowspan="2">Sample use case(s)</th> </tr>
      * <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th></tr>
-     * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code FULL FOV 640}</td> <td>{@code YUV }</td><td id="rb">{@code MAXIMUM}</td> <td>Live preview with a tracking YUV output and a maximum-resolution YUV for still captures.</td> </tr>
+     * <tr> <td>{@code YUV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code FULL FOV 640}</td> <td>{@code JPEG}</td><td id="rb">{@code MAX 30FPS}</td> <td>Preview with a tracking YUV output and a as-large-as-possible JPEG for still captures.</td> </tr>
      * </table><br>
      * </p>
      *
@@ -899,12 +904,6 @@
      * @throws CameraAccessException if the camera device is no longer connected or has
      *                               encountered a fatal error
      * @throws IllegalStateException if the camera device has been closed
-     *
-     * @see #TEMPLATE_PREVIEW
-     * @see #TEMPLATE_RECORD
-     * @see #TEMPLATE_STILL_CAPTURE
-     * @see #TEMPLATE_VIDEO_SNAPSHOT
-     * @see #TEMPLATE_MANUAL
      */
     @NonNull
     public abstract CaptureRequest.Builder createCaptureRequest(@RequestTemplate int templateType)
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index 1c7f289..2294ec5 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -1359,6 +1359,20 @@
      */
     public static final int CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE = 4;
 
+    /**
+     * <p>An external flash has been turned on.</p>
+     * <p>It informs the camera device that an external flash has been turned on, and that
+     * metering (and continuous focus if active) should be quickly recaculated to account
+     * for the external flash. Otherwise, this mode acts like ON.</p>
+     * <p>When the external flash is turned off, AE mode should be changed to one of the
+     * other available AE modes.</p>
+     * <p>If the camera device supports AE external flash mode, aeState must be
+     * FLASH_REQUIRED after the camera device finishes AE scan and it's too dark without
+     * flash.</p>
+     * @see CaptureRequest#CONTROL_AE_MODE
+     */
+    public static final int CONTROL_AE_MODE_ON_EXTERNAL_FLASH = 5;
+
     //
     // Enumeration values for CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER
     //
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index cf27c70..ce75fa52 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -1076,6 +1076,7 @@
      *   <li>{@link #CONTROL_AE_MODE_ON_AUTO_FLASH ON_AUTO_FLASH}</li>
      *   <li>{@link #CONTROL_AE_MODE_ON_ALWAYS_FLASH ON_ALWAYS_FLASH}</li>
      *   <li>{@link #CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE ON_AUTO_FLASH_REDEYE}</li>
+     *   <li>{@link #CONTROL_AE_MODE_ON_EXTERNAL_FLASH ON_EXTERNAL_FLASH}</li>
      * </ul></p>
      * <p><b>Available values for this device:</b><br>
      * {@link CameraCharacteristics#CONTROL_AE_AVAILABLE_MODES android.control.aeAvailableModes}</p>
@@ -1093,6 +1094,7 @@
      * @see #CONTROL_AE_MODE_ON_AUTO_FLASH
      * @see #CONTROL_AE_MODE_ON_ALWAYS_FLASH
      * @see #CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE
+     * @see #CONTROL_AE_MODE_ON_EXTERNAL_FLASH
      */
     @PublicKey
     public static final Key<Integer> CONTROL_AE_MODE =
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index b6b0c90..237a92d 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -691,6 +691,7 @@
      *   <li>{@link #CONTROL_AE_MODE_ON_AUTO_FLASH ON_AUTO_FLASH}</li>
      *   <li>{@link #CONTROL_AE_MODE_ON_ALWAYS_FLASH ON_ALWAYS_FLASH}</li>
      *   <li>{@link #CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE ON_AUTO_FLASH_REDEYE}</li>
+     *   <li>{@link #CONTROL_AE_MODE_ON_EXTERNAL_FLASH ON_EXTERNAL_FLASH}</li>
      * </ul></p>
      * <p><b>Available values for this device:</b><br>
      * {@link CameraCharacteristics#CONTROL_AE_AVAILABLE_MODES android.control.aeAvailableModes}</p>
@@ -708,6 +709,7 @@
      * @see #CONTROL_AE_MODE_ON_AUTO_FLASH
      * @see #CONTROL_AE_MODE_ON_ALWAYS_FLASH
      * @see #CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE
+     * @see #CONTROL_AE_MODE_ON_EXTERNAL_FLASH
      */
     @PublicKey
     public static final Key<Integer> CONTROL_AE_MODE =
@@ -877,7 +879,7 @@
      * </tr>
      * </tbody>
      * </table>
-     * <p>When {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode} is AE_MODE_ON_*:</p>
+     * <p>When {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode} is AE_MODE_ON*:</p>
      * <table>
      * <thead>
      * <tr>
@@ -998,10 +1000,13 @@
      * </tr>
      * </tbody>
      * </table>
+     * <p>If the camera device supports AE external flash mode (ON_EXTERNAL_FLASH is included in
+     * {@link CameraCharacteristics#CONTROL_AE_AVAILABLE_MODES android.control.aeAvailableModes}), aeState must be FLASH_REQUIRED after the camera device
+     * finishes AE scan and it's too dark without flash.</p>
      * <p>For the above table, the camera device may skip reporting any state changes that happen
      * without application intervention (i.e. mode switch, trigger, locking). Any state that
      * can be skipped in that manner is called a transient state.</p>
-     * <p>For example, for above AE modes (AE_MODE_ON_*), in addition to the state transitions
+     * <p>For example, for above AE modes (AE_MODE_ON*), in addition to the state transitions
      * listed in above table, it is also legal for the camera device to skip one or more
      * transient states between two results. See below table for examples:</p>
      * <table>
@@ -1072,6 +1077,7 @@
      * Present on all camera devices that report being at least {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED HARDWARE_LEVEL_LIMITED} devices in the
      * {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel} key</p>
      *
+     * @see CameraCharacteristics#CONTROL_AE_AVAILABLE_MODES
      * @see CaptureRequest#CONTROL_AE_LOCK
      * @see CaptureRequest#CONTROL_AE_MODE
      * @see CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER
diff --git a/core/java/android/hardware/radio/ProgramSelector.java b/core/java/android/hardware/radio/ProgramSelector.java
index 3556751..0cf7605 100644
--- a/core/java/android/hardware/radio/ProgramSelector.java
+++ b/core/java/android/hardware/radio/ProgramSelector.java
@@ -59,24 +59,56 @@
  */
 @SystemApi
 public final class ProgramSelector implements Parcelable {
+    /** Invalid program type.
+     * @deprecated use {@link ProgramIdentifier} instead
+     */
+    @Deprecated
     public static final int PROGRAM_TYPE_INVALID = 0;
-    /** Analogue AM radio (with or without RDS). */
+    /** Analogue AM radio (with or without RDS).
+     * @deprecated use {@link ProgramIdentifier} instead
+     */
+    @Deprecated
     public static final int PROGRAM_TYPE_AM = 1;
-    /** analogue FM radio (with or without RDS). */
+    /** analogue FM radio (with or without RDS).
+     * @deprecated use {@link ProgramIdentifier} instead
+     */
+    @Deprecated
     public static final int PROGRAM_TYPE_FM = 2;
-    /** AM HD Radio. */
+    /** AM HD Radio.
+     * @deprecated use {@link ProgramIdentifier} instead
+     */
+    @Deprecated
     public static final int PROGRAM_TYPE_AM_HD = 3;
-    /** FM HD Radio. */
+    /** FM HD Radio.
+     * @deprecated use {@link ProgramIdentifier} instead
+     */
+    @Deprecated
     public static final int PROGRAM_TYPE_FM_HD = 4;
-    /** Digital audio broadcasting. */
+    /** Digital audio broadcasting.
+     * @deprecated use {@link ProgramIdentifier} instead
+     */
+    @Deprecated
     public static final int PROGRAM_TYPE_DAB = 5;
-    /** Digital Radio Mondiale. */
+    /** Digital Radio Mondiale.
+     * @deprecated use {@link ProgramIdentifier} instead
+     */
+    @Deprecated
     public static final int PROGRAM_TYPE_DRMO = 6;
-    /** SiriusXM Satellite Radio. */
+    /** SiriusXM Satellite Radio.
+     * @deprecated use {@link ProgramIdentifier} instead
+     */
+    @Deprecated
     public static final int PROGRAM_TYPE_SXM = 7;
-    /** Vendor-specific, not synced across devices. */
+    /** Vendor-specific, not synced across devices.
+     * @deprecated use {@link ProgramIdentifier} instead
+     */
+    @Deprecated
     public static final int PROGRAM_TYPE_VENDOR_START = 1000;
+    /** @deprecated use {@link ProgramIdentifier} instead */
+    @Deprecated
     public static final int PROGRAM_TYPE_VENDOR_END = 1999;
+    /** @deprecated use {@link ProgramIdentifier} instead */
+    @Deprecated
     @IntDef(prefix = { "PROGRAM_TYPE_" }, value = {
         PROGRAM_TYPE_INVALID,
         PROGRAM_TYPE_AM,
@@ -112,18 +144,46 @@
      *
      * The subchannel index is 0-based (where 0 is MPS and 1..7 are SPS),
      * as opposed to HD Radio standard (where it's 1-based).
+     *
+     * @deprecated use IDENTIFIER_TYPE_HD_STATION_ID_EXT instead
      */
+    @Deprecated
     public static final int IDENTIFIER_TYPE_HD_SUBCHANNEL = 4;
     /**
-     * 24bit compound primary identifier for DAB.
+     * 64bit additional identifier for HD Radio.
+     *
+     * Due to Station ID abuse, some HD_STATION_ID_EXT identifiers may be not
+     * globally unique. To provide a best-effort solution, a short version of
+     * station name may be carried as additional identifier and may be used
+     * by the tuner hardware to double-check tuning.
+     *
+     * The name is limited to the first 8 A-Z0-9 characters (lowercase letters
+     * must be converted to uppercase). Encoded in little-endian ASCII:
+     * the first character of the name is the LSB.
+     *
+     * For example: "Abc" is encoded as 0x434241.
+     */
+    public static final int IDENTIFIER_TYPE_HD_STATION_NAME = 10004;
+    /**
+     * @see {@link IDENTIFIER_TYPE_DAB_SID_EXT}
+     */
+    public static final int IDENTIFIER_TYPE_DAB_SIDECC = 5;
+    /**
+     * 28bit compound primary identifier for Digital Audio Broadcasting.
      *
      * Consists of (from the LSB):
      * - 16bit: SId;
-     * - 8bit: ECC code.
+     * - 8bit: ECC code;
+     * - 4bit: SCIdS.
+     *
+     * SCIdS (Service Component Identifier within the Service) value
+     * of 0 represents the main service, while 1 and above represents
+     * secondary services.
+     *
      * The remaining bits should be set to zeros when writing on the chip side
      * and ignored when read.
      */
-    public static final int IDENTIFIER_TYPE_DAB_SIDECC = 5;
+    public static final int IDENTIFIER_TYPE_DAB_SID_EXT = IDENTIFIER_TYPE_DAB_SIDECC;
     /** 16bit */
     public static final int IDENTIFIER_TYPE_DAB_ENSEMBLE = 6;
     /** 12bit */
@@ -134,7 +194,11 @@
     public static final int IDENTIFIER_TYPE_DRMO_SERVICE_ID = 9;
     /** kHz */
     public static final int IDENTIFIER_TYPE_DRMO_FREQUENCY = 10;
-    /** 1: AM, 2:FM */
+    /**
+     * 1: AM, 2:FM
+     * @deprecated use {@link IDENTIFIER_TYPE_DRMO_FREQUENCY} instead
+     */
+    @Deprecated
     public static final int IDENTIFIER_TYPE_DRMO_MODULATION = 11;
     /** 32bit */
     public static final int IDENTIFIER_TYPE_SXM_SERVICE_ID = 12;
@@ -148,14 +212,29 @@
      * type between VENDOR_START and VENDOR_END (eg. identifier type 1015 must
      * not be used in any program type other than 1015).
      */
-    public static final int IDENTIFIER_TYPE_VENDOR_PRIMARY_START = PROGRAM_TYPE_VENDOR_START;
-    public static final int IDENTIFIER_TYPE_VENDOR_PRIMARY_END = PROGRAM_TYPE_VENDOR_END;
+    public static final int IDENTIFIER_TYPE_VENDOR_START = PROGRAM_TYPE_VENDOR_START;
+    /**
+     * @see {@link IDENTIFIER_TYPE_VENDOR_START}
+     */
+    public static final int IDENTIFIER_TYPE_VENDOR_END = PROGRAM_TYPE_VENDOR_END;
+    /**
+     * @deprecated use {@link IDENTIFIER_TYPE_VENDOR_START} instead
+     */
+    @Deprecated
+    public static final int IDENTIFIER_TYPE_VENDOR_PRIMARY_START = IDENTIFIER_TYPE_VENDOR_START;
+    /**
+     * @deprecated use {@link IDENTIFIER_TYPE_VENDOR_END} instead
+     */
+    @Deprecated
+    public static final int IDENTIFIER_TYPE_VENDOR_PRIMARY_END = IDENTIFIER_TYPE_VENDOR_END;
     @IntDef(prefix = { "IDENTIFIER_TYPE_" }, value = {
         IDENTIFIER_TYPE_INVALID,
         IDENTIFIER_TYPE_AMFM_FREQUENCY,
         IDENTIFIER_TYPE_RDS_PI,
         IDENTIFIER_TYPE_HD_STATION_ID_EXT,
         IDENTIFIER_TYPE_HD_SUBCHANNEL,
+        IDENTIFIER_TYPE_HD_STATION_NAME,
+        IDENTIFIER_TYPE_DAB_SID_EXT,
         IDENTIFIER_TYPE_DAB_SIDECC,
         IDENTIFIER_TYPE_DAB_ENSEMBLE,
         IDENTIFIER_TYPE_DAB_SCID,
@@ -166,7 +245,7 @@
         IDENTIFIER_TYPE_SXM_SERVICE_ID,
         IDENTIFIER_TYPE_SXM_CHANNEL,
     })
-    @IntRange(from = IDENTIFIER_TYPE_VENDOR_PRIMARY_START, to = IDENTIFIER_TYPE_VENDOR_PRIMARY_END)
+    @IntRange(from = IDENTIFIER_TYPE_VENDOR_START, to = IDENTIFIER_TYPE_VENDOR_END)
     @Retention(RetentionPolicy.SOURCE)
     public @interface IdentifierType {}
 
@@ -205,7 +284,9 @@
      * Type of a radio technology.
      *
      * @return program type.
+     * @deprecated use {@link getPrimaryId} instead
      */
+    @Deprecated
     public @ProgramType int getProgramType() {
         return mProgramType;
     }
@@ -273,7 +354,10 @@
      * preserving elements order.
      *
      * @return an array of vendor identifiers, must not be modified.
+     * @deprecated for HAL 1.x compatibility;
+     *             HAL 2.x uses standard primary/secondary lists for vendor IDs
      */
+    @Deprecated
     public @NonNull long[] getVendorIds() {
         return mVendorIds;
     }
@@ -427,6 +511,10 @@
         private final long mValue;
 
         public Identifier(@IdentifierType int type, long value) {
+            if (type == IDENTIFIER_TYPE_HD_STATION_NAME) {
+                // see getType
+                type = IDENTIFIER_TYPE_HD_SUBCHANNEL;
+            }
             mType = type;
             mValue = value;
         }
@@ -437,6 +525,13 @@
          * @return type of an identifier.
          */
         public @IdentifierType int getType() {
+            if (mType == IDENTIFIER_TYPE_HD_SUBCHANNEL && mValue > 10) {
+                /* HD_SUBCHANNEL and HD_STATION_NAME use the same identifier type, but they differ
+                 * in possible values: sub channel is 0-7, station name is greater than ASCII space
+                 * code (32).
+                 */
+                return IDENTIFIER_TYPE_HD_STATION_NAME;
+            }
             return mType;
         }
 
diff --git a/core/java/android/net/INetworkPolicyListener.aidl b/core/java/android/net/INetworkPolicyListener.aidl
index 005dd6e..10667ae 100644
--- a/core/java/android/net/INetworkPolicyListener.aidl
+++ b/core/java/android/net/INetworkPolicyListener.aidl
@@ -18,10 +18,9 @@
 
 /** {@hide} */
 oneway interface INetworkPolicyListener {
-
     void onUidRulesChanged(int uid, int uidRules);
     void onMeteredIfacesChanged(in String[] meteredIfaces);
     void onRestrictBackgroundChanged(boolean restrictBackground);
     void onUidPoliciesChanged(int uid, int uidPolicies);
-
+    void onSubscriptionOverride(int subId, int overrideMask, int overrideValue);
 }
diff --git a/core/java/android/net/INetworkPolicyManager.aidl b/core/java/android/net/INetworkPolicyManager.aidl
index 7e37432..476e2f4 100644
--- a/core/java/android/net/INetworkPolicyManager.aidl
+++ b/core/java/android/net/INetworkPolicyManager.aidl
@@ -71,6 +71,7 @@
     SubscriptionPlan[] getSubscriptionPlans(int subId, String callingPackage);
     void setSubscriptionPlans(int subId, in SubscriptionPlan[] plans, String callingPackage);
     String getSubscriptionPlansOwner(int subId);
+    void setSubscriptionOverride(int subId, int overrideMask, int overrideValue, long timeoutMillis, String callingPackage);
 
     void factoryReset(String subscriber);
 
diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl
index 95e7f60..90e3ffd 100644
--- a/core/java/android/net/INetworkStatsService.aidl
+++ b/core/java/android/net/INetworkStatsService.aidl
@@ -18,6 +18,7 @@
 
 import android.net.DataUsageRequest;
 import android.net.INetworkStatsSession;
+import android.net.Network;
 import android.net.NetworkStats;
 import android.net.NetworkStatsHistory;
 import android.net.NetworkTemplate;
@@ -53,7 +54,7 @@
     void setUidForeground(int uid, boolean uidForeground);
 
     /** Force update of ifaces. */
-    void forceUpdateIfaces();
+    void forceUpdateIfaces(in Network[] defaultNetworks);
     /** Force update of statistics. */
     void forceUpdate();
 
diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java
index 2cda58c..f04f03f6 100644
--- a/core/java/android/net/IpSecManager.java
+++ b/core/java/android/net/IpSecManager.java
@@ -19,6 +19,7 @@
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.SystemApi;
 import android.annotation.SystemService;
 import android.annotation.TestApi;
 import android.content.Context;
@@ -625,6 +626,133 @@
     }
 
     /**
+     * This class represents an IpSecTunnelInterface
+     *
+     * <p>IpSecTunnelInterface objects track tunnel interfaces that serve as
+     * local endpoints for IPsec tunnels.
+     *
+     * <p>Creating an IpSecTunnelInterface creates a device to which IpSecTransforms may be
+     * applied to provide IPsec security to packets sent through the tunnel. While a tunnel
+     * cannot be used in standalone mode within Android, the higher layers may use the tunnel
+     * to create Network objects which are accessible to the Android system.
+     * @hide
+     */
+    @SystemApi
+    public static final class IpSecTunnelInterface implements AutoCloseable {
+        private final IIpSecService mService;
+        private final InetAddress mRemoteAddress;
+        private final InetAddress mLocalAddress;
+        private final Network mUnderlyingNetwork;
+        private final CloseGuard mCloseGuard = CloseGuard.get();
+        private String mInterfaceName;
+        private int mResourceId = INVALID_RESOURCE_ID;
+
+        /** Get the underlying SPI held by this object. */
+        public String getInterfaceName() {
+            return mInterfaceName;
+        }
+
+        /**
+         * Add an address to the IpSecTunnelInterface
+         *
+         * <p>Add an address which may be used as the local inner address for
+         * tunneled traffic.
+         *
+         * @param address the local address for traffic inside the tunnel
+         * @throws IOException if the address could not be added
+         * @hide
+         */
+        public void addAddress(LinkAddress address) throws IOException {
+        }
+
+        /**
+         * Remove an address from the IpSecTunnelInterface
+         *
+         * <p>Remove an address which was previously added to the IpSecTunnelInterface
+         *
+         * @param address to be removed
+         * @throws IOException if the address could not be removed
+         * @hide
+         */
+        public void removeAddress(LinkAddress address) throws IOException {
+        }
+
+        private IpSecTunnelInterface(@NonNull IIpSecService service,
+                @NonNull InetAddress localAddress, @NonNull InetAddress remoteAddress,
+                @NonNull Network underlyingNetwork)
+                throws ResourceUnavailableException, IOException {
+            mService = service;
+            mLocalAddress = localAddress;
+            mRemoteAddress = remoteAddress;
+            mUnderlyingNetwork = underlyingNetwork;
+            // TODO: Call IpSecService
+        }
+
+        /**
+         * Delete an IpSecTunnelInterface
+         *
+         * <p>Calling close will deallocate the IpSecTunnelInterface and all of its system
+         * resources. Any packets bound for this interface either inbound or outbound will
+         * all be lost.
+         */
+        @Override
+        public void close() {
+            // try {
+            // TODO: Call IpSecService
+            mResourceId = INVALID_RESOURCE_ID;
+            // } catch (RemoteException e) {
+            //    throw e.rethrowFromSystemServer();
+            // }
+            mCloseGuard.close();
+        }
+
+        /** Check that the Interface was closed properly. */
+        @Override
+        protected void finalize() throws Throwable {
+            if (mCloseGuard != null) {
+                mCloseGuard.warnIfOpen();
+            }
+            close();
+        }
+    }
+
+    /**
+     * Create a new IpSecTunnelInterface as a local endpoint for tunneled IPsec traffic.
+     *
+     * @param localAddress The local addres of the tunnel
+     * @param remoteAddress The local addres of the tunnel
+     * @param underlyingNetwork the {@link Network} that will carry traffic for this tunnel.
+     *        This network should almost certainly be a network such as WiFi with an L2 address.
+     * @return a new {@link IpSecManager#IpSecTunnelInterface} with the specified properties
+     * @throws IOException indicating that the socket could not be opened or bound
+     * @throws ResourceUnavailableException indicating that too many encapsulation sockets are open
+     * @hide
+     */
+    @SystemApi
+    public IpSecTunnelInterface createIpSecTunnelInterface(@NonNull InetAddress localAddress,
+            @NonNull InetAddress remoteAddress, @NonNull Network underlyingNetwork)
+            throws ResourceUnavailableException, IOException {
+        return new IpSecTunnelInterface(mService, localAddress, remoteAddress, underlyingNetwork);
+    }
+
+    /**
+     * Apply a transform to the IpSecTunnelInterface
+     *
+     * @param tunnel The {@link IpSecManager#IpSecTunnelInterface} that will use the supplied
+     *        transform.
+     * @param direction the direction, {@link DIRECTION_OUT} or {@link #DIRECTION_IN} in which
+     *        the transform will be used.
+     * @param transform an {@link IpSecTransform} created in tunnel mode
+     * @throws IOException indicating that the transform could not be applied due to a lower
+     *         layer failure.
+     * @hide
+     */
+    @SystemApi
+    void applyTunnelModeTransform(IpSecTunnelInterface tunnel, int direction,
+            IpSecTransform transform) throws IOException {
+        // TODO: call IpSecService
+    }
+    /**
      * Construct an instance of IpSecManager within an application context.
      *
      * @param context the application context for this manager
diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java
index 7b9b483..be6026f 100644
--- a/core/java/android/net/IpSecTransform.java
+++ b/core/java/android/net/IpSecTransform.java
@@ -300,21 +300,6 @@
         }
 
         /**
-         * Set the {@link Network} which will carry tunneled traffic.
-         *
-         * <p>Restricts the transformed traffic to a particular {@link Network}. This is required
-         * for tunnel mode, otherwise tunneled traffic would be sent on the default network.
-         *
-         * @hide
-         */
-        @SystemApi
-        public IpSecTransform.Builder setUnderlyingNetwork(@NonNull Network net) {
-            Preconditions.checkNotNull(net);
-            mConfig.setNetwork(net);
-            return this;
-        }
-
-        /**
          * Add UDP encapsulation to an IPv4 transform.
          *
          * <p>This allows IPsec traffic to pass through a NAT.
@@ -415,6 +400,7 @@
          * @throws IOException indicating other errors
          * @hide
          */
+        @SystemApi
         public IpSecTransform buildTunnelModeTransform(
                 @NonNull InetAddress sourceAddress,
                 @NonNull IpSecManager.SecurityParameterIndex spi)
diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java
index d3b3599..fd118f3 100644
--- a/core/java/android/net/NetworkIdentity.java
+++ b/core/java/android/net/NetworkIdentity.java
@@ -58,21 +58,24 @@
     final String mNetworkId;
     final boolean mRoaming;
     final boolean mMetered;
+    final boolean mDefaultNetwork;
 
     public NetworkIdentity(
             int type, int subType, String subscriberId, String networkId, boolean roaming,
-            boolean metered) {
+            boolean metered, boolean defaultNetwork) {
         mType = type;
         mSubType = COMBINE_SUBTYPE_ENABLED ? SUBTYPE_COMBINED : subType;
         mSubscriberId = subscriberId;
         mNetworkId = networkId;
         mRoaming = roaming;
         mMetered = metered;
+        mDefaultNetwork = defaultNetwork;
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(mType, mSubType, mSubscriberId, mNetworkId, mRoaming, mMetered);
+        return Objects.hash(mType, mSubType, mSubscriberId, mNetworkId, mRoaming, mMetered,
+                mDefaultNetwork);
     }
 
     @Override
@@ -82,7 +85,8 @@
             return mType == ident.mType && mSubType == ident.mSubType && mRoaming == ident.mRoaming
                     && Objects.equals(mSubscriberId, ident.mSubscriberId)
                     && Objects.equals(mNetworkId, ident.mNetworkId)
-                    && mMetered == ident.mMetered;
+                    && mMetered == ident.mMetered
+                    && mDefaultNetwork == ident.mDefaultNetwork;
         }
         return false;
     }
@@ -109,6 +113,7 @@
             builder.append(", ROAMING");
         }
         builder.append(", metered=").append(mMetered);
+        builder.append(", defaultNetwork=").append(mDefaultNetwork);
         return builder.append("}").toString();
     }
 
@@ -153,6 +158,10 @@
         return mMetered;
     }
 
+    public boolean getDefaultNetwork() {
+        return mDefaultNetwork;
+    }
+
     /**
      * Scrub given IMSI on production builds.
      */
@@ -183,7 +192,8 @@
      * Build a {@link NetworkIdentity} from the given {@link NetworkState},
      * assuming that any mobile networks are using the current IMSI.
      */
-    public static NetworkIdentity buildNetworkIdentity(Context context, NetworkState state) {
+    public static NetworkIdentity buildNetworkIdentity(Context context, NetworkState state,
+            boolean defaultNetwork) {
         final int type = state.networkInfo.getType();
         final int subType = state.networkInfo.getSubtype();
 
@@ -216,7 +226,8 @@
             }
         }
 
-        return new NetworkIdentity(type, subType, subscriberId, networkId, roaming, metered);
+        return new NetworkIdentity(type, subType, subscriberId, networkId, roaming, metered,
+                defaultNetwork);
     }
 
     @Override
@@ -237,6 +248,9 @@
         if (res == 0) {
             res = Boolean.compare(mMetered, another.mMetered);
         }
+        if (res == 0) {
+            res = Boolean.compare(mDefaultNetwork, another.mDefaultNetwork);
+        }
         return res;
     }
 }
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index 9ef26a9..2c5a021 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -113,6 +113,9 @@
      */
     public static final String EXTRA_NETWORK_TEMPLATE = "android.net.NETWORK_TEMPLATE";
 
+    public static final int OVERRIDE_UNMETERED = 1 << 0;
+    public static final int OVERRIDE_CONGESTED = 1 << 1;
+
     private final Context mContext;
     private INetworkPolicyManager mService;
 
@@ -347,4 +350,13 @@
     public static String resolveNetworkId(String ssid) {
         return WifiInfo.removeDoubleQuotes(ssid);
     }
+
+    /** {@hide} */
+    public static class Listener extends INetworkPolicyListener.Stub {
+        @Override public void onUidRulesChanged(int uid, int uidRules) { }
+        @Override public void onMeteredIfacesChanged(String[] meteredIfaces) { }
+        @Override public void onRestrictBackgroundChanged(boolean restrictBackground) { }
+        @Override public void onUidPoliciesChanged(int uid, int uidPolicies) { }
+        @Override public void onSubscriptionOverride(int subId, int overrideMask, int overrideValue) { }
+    }
 }
diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java
index 171adc0..a85f80e 100644
--- a/core/java/android/net/NetworkStats.java
+++ b/core/java/android/net/NetworkStats.java
@@ -82,6 +82,13 @@
     /** {@link #roaming} value where roaming data is accounted. */
     public static final int ROAMING_YES = 1;
 
+    /** {@link #onDefaultNetwork} value to account for all default network states. */
+    public static final int DEFAULT_NETWORK_ALL = -1;
+    /** {@link #onDefaultNetwork} value to account for usage while not the default network. */
+    public static final int DEFAULT_NETWORK_NO = 0;
+    /** {@link #onDefaultNetwork} value to account for usage while the default network. */
+    public static final int DEFAULT_NETWORK_YES = 1;
+
     /** Denotes a request for stats at the interface level. */
     public static final int STATS_PER_IFACE = 0;
     /** Denotes a request for stats at the interface and UID level. */
@@ -102,6 +109,7 @@
     private int[] tag;
     private int[] metered;
     private int[] roaming;
+    private int[] defaultNetwork;
     private long[] rxBytes;
     private long[] rxPackets;
     private long[] txBytes;
@@ -125,6 +133,12 @@
          * getSummary().
          */
         public int roaming;
+        /**
+         * Note that this is only populated w/ the default value when read from /proc or written
+         * to disk. We merge in the correct value when reporting this value to clients of
+         * getSummary().
+         */
+        public int defaultNetwork;
         public long rxBytes;
         public long rxPackets;
         public long txBytes;
@@ -142,18 +156,27 @@
 
         public Entry(String iface, int uid, int set, int tag, long rxBytes, long rxPackets,
                 long txBytes, long txPackets, long operations) {
-            this(iface, uid, set, tag, METERED_NO, ROAMING_NO, rxBytes, rxPackets, txBytes,
-                    txPackets, operations);
+            this(iface, uid, set, tag, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO,
+                    rxBytes, rxPackets, txBytes, txPackets, operations);
+        }
+
+        // TODO: fix the the telephony code to pass DEFAULT_NETWORK_YES and remove this constructor.
+        public Entry(String iface, int uid, int set, int tag, int metered, int roaming,
+                 long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) {
+            this(iface, uid, set, tag, metered, roaming, DEFAULT_NETWORK_YES, rxBytes, rxPackets,
+                    txBytes, txPackets, operations);
         }
 
         public Entry(String iface, int uid, int set, int tag, int metered, int roaming,
-                 long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) {
+                 int defaultNetwork, long rxBytes, long rxPackets, long txBytes, long txPackets,
+                 long operations) {
             this.iface = iface;
             this.uid = uid;
             this.set = set;
             this.tag = tag;
             this.metered = metered;
             this.roaming = roaming;
+            this.defaultNetwork = defaultNetwork;
             this.rxBytes = rxBytes;
             this.rxPackets = rxPackets;
             this.txBytes = txBytes;
@@ -187,6 +210,7 @@
             builder.append(" tag=").append(tagToString(tag));
             builder.append(" metered=").append(meteredToString(metered));
             builder.append(" roaming=").append(roamingToString(roaming));
+            builder.append(" defaultNetwork=").append(defaultNetworkToString(defaultNetwork));
             builder.append(" rxBytes=").append(rxBytes);
             builder.append(" rxPackets=").append(rxPackets);
             builder.append(" txBytes=").append(txBytes);
@@ -200,7 +224,8 @@
             if (o instanceof Entry) {
                 final Entry e = (Entry) o;
                 return uid == e.uid && set == e.set && tag == e.tag && metered == e.metered
-                        && roaming == e.roaming && rxBytes == e.rxBytes && rxPackets == e.rxPackets
+                        && roaming == e.roaming && defaultNetwork == e.defaultNetwork
+                        && rxBytes == e.rxBytes && rxPackets == e.rxPackets
                         && txBytes == e.txBytes && txPackets == e.txPackets
                         && operations == e.operations && iface.equals(e.iface);
             }
@@ -209,7 +234,7 @@
 
         @Override
         public int hashCode() {
-            return Objects.hash(uid, set, tag, metered, roaming, iface);
+            return Objects.hash(uid, set, tag, metered, roaming, defaultNetwork, iface);
         }
     }
 
@@ -224,6 +249,7 @@
             this.tag = new int[initialSize];
             this.metered = new int[initialSize];
             this.roaming = new int[initialSize];
+            this.defaultNetwork = new int[initialSize];
             this.rxBytes = new long[initialSize];
             this.rxPackets = new long[initialSize];
             this.txBytes = new long[initialSize];
@@ -238,6 +264,7 @@
             this.tag = EmptyArray.INT;
             this.metered = EmptyArray.INT;
             this.roaming = EmptyArray.INT;
+            this.defaultNetwork = EmptyArray.INT;
             this.rxBytes = EmptyArray.LONG;
             this.rxPackets = EmptyArray.LONG;
             this.txBytes = EmptyArray.LONG;
@@ -256,6 +283,7 @@
         tag = parcel.createIntArray();
         metered = parcel.createIntArray();
         roaming = parcel.createIntArray();
+        defaultNetwork = parcel.createIntArray();
         rxBytes = parcel.createLongArray();
         rxPackets = parcel.createLongArray();
         txBytes = parcel.createLongArray();
@@ -274,6 +302,7 @@
         dest.writeIntArray(tag);
         dest.writeIntArray(metered);
         dest.writeIntArray(roaming);
+        dest.writeIntArray(defaultNetwork);
         dest.writeLongArray(rxBytes);
         dest.writeLongArray(rxPackets);
         dest.writeLongArray(txBytes);
@@ -308,10 +337,11 @@
 
     @VisibleForTesting
     public NetworkStats addValues(String iface, int uid, int set, int tag, int metered, int roaming,
-            long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) {
+            int defaultNetwork, long rxBytes, long rxPackets, long txBytes, long txPackets,
+            long operations) {
         return addValues(new Entry(
-                iface, uid, set, tag, metered, roaming, rxBytes, rxPackets, txBytes, txPackets,
-                operations));
+                iface, uid, set, tag, metered, roaming, defaultNetwork, rxBytes, rxPackets,
+                txBytes, txPackets, operations));
     }
 
     /**
@@ -327,6 +357,7 @@
             tag = Arrays.copyOf(tag, newLength);
             metered = Arrays.copyOf(metered, newLength);
             roaming = Arrays.copyOf(roaming, newLength);
+            defaultNetwork = Arrays.copyOf(defaultNetwork, newLength);
             rxBytes = Arrays.copyOf(rxBytes, newLength);
             rxPackets = Arrays.copyOf(rxPackets, newLength);
             txBytes = Arrays.copyOf(txBytes, newLength);
@@ -341,6 +372,7 @@
         tag[size] = entry.tag;
         metered[size] = entry.metered;
         roaming[size] = entry.roaming;
+        defaultNetwork[size] = entry.defaultNetwork;
         rxBytes[size] = entry.rxBytes;
         rxPackets[size] = entry.rxPackets;
         txBytes[size] = entry.txBytes;
@@ -362,6 +394,7 @@
         entry.tag = tag[i];
         entry.metered = metered[i];
         entry.roaming = roaming[i];
+        entry.defaultNetwork = defaultNetwork[i];
         entry.rxBytes = rxBytes[i];
         entry.rxPackets = rxPackets[i];
         entry.txBytes = txBytes[i];
@@ -416,7 +449,7 @@
      */
     public NetworkStats combineValues(Entry entry) {
         final int i = findIndex(entry.iface, entry.uid, entry.set, entry.tag, entry.metered,
-                entry.roaming);
+                entry.roaming, entry.defaultNetwork);
         if (i == -1) {
             // only create new entry when positive contribution
             addValues(entry);
@@ -444,10 +477,12 @@
     /**
      * Find first stats index that matches the requested parameters.
      */
-    public int findIndex(String iface, int uid, int set, int tag, int metered, int roaming) {
+    public int findIndex(String iface, int uid, int set, int tag, int metered, int roaming,
+            int defaultNetwork) {
         for (int i = 0; i < size; i++) {
             if (uid == this.uid[i] && set == this.set[i] && tag == this.tag[i]
                     && metered == this.metered[i] && roaming == this.roaming[i]
+                    && defaultNetwork == this.defaultNetwork[i]
                     && Objects.equals(iface, this.iface[i])) {
                 return i;
             }
@@ -461,7 +496,7 @@
      */
     @VisibleForTesting
     public int findIndexHinted(String iface, int uid, int set, int tag, int metered, int roaming,
-            int hintIndex) {
+            int defaultNetwork, int hintIndex) {
         for (int offset = 0; offset < size; offset++) {
             final int halfOffset = offset / 2;
 
@@ -475,6 +510,7 @@
 
             if (uid == this.uid[i] && set == this.set[i] && tag == this.tag[i]
                     && metered == this.metered[i] && roaming == this.roaming[i]
+                    && defaultNetwork == this.defaultNetwork[i]
                     && Objects.equals(iface, this.iface[i])) {
                 return i;
             }
@@ -489,7 +525,8 @@
      */
     public void spliceOperationsFrom(NetworkStats stats) {
         for (int i = 0; i < size; i++) {
-            final int j = stats.findIndex(iface[i], uid[i], set[i], tag[i], metered[i], roaming[i]);
+            final int j = stats.findIndex(iface[i], uid[i], set[i], tag[i], metered[i], roaming[i],
+                    defaultNetwork[i]);
             if (j == -1) {
                 operations[i] = 0;
             } else {
@@ -581,6 +618,7 @@
         entry.tag = TAG_NONE;
         entry.metered = METERED_ALL;
         entry.roaming = ROAMING_ALL;
+        entry.defaultNetwork = DEFAULT_NETWORK_ALL;
         entry.rxBytes = 0;
         entry.rxPackets = 0;
         entry.txBytes = 0;
@@ -677,6 +715,7 @@
             entry.tag = left.tag[i];
             entry.metered = left.metered[i];
             entry.roaming = left.roaming[i];
+            entry.defaultNetwork = left.defaultNetwork[i];
             entry.rxBytes = left.rxBytes[i];
             entry.rxPackets = left.rxPackets[i];
             entry.txBytes = left.txBytes[i];
@@ -685,7 +724,7 @@
 
             // find remote row that matches, and subtract
             final int j = right.findIndexHinted(entry.iface, entry.uid, entry.set, entry.tag,
-                    entry.metered, entry.roaming, i);
+                    entry.metered, entry.roaming, entry.defaultNetwork, i);
             if (j != -1) {
                 // Found matching row, subtract remote value.
                 entry.rxBytes -= right.rxBytes[j];
@@ -725,6 +764,7 @@
         entry.tag = TAG_NONE;
         entry.metered = METERED_ALL;
         entry.roaming = ROAMING_ALL;
+        entry.defaultNetwork = DEFAULT_NETWORK_ALL;
         entry.operations = 0L;
 
         for (int i = 0; i < size; i++) {
@@ -755,6 +795,7 @@
         entry.tag = TAG_NONE;
         entry.metered = METERED_ALL;
         entry.roaming = ROAMING_ALL;
+        entry.defaultNetwork = DEFAULT_NETWORK_ALL;
 
         for (int i = 0; i < size; i++) {
             // skip specific tags, since already counted in TAG_NONE
@@ -802,6 +843,7 @@
             pw.print(" tag="); pw.print(tagToString(tag[i]));
             pw.print(" metered="); pw.print(meteredToString(metered[i]));
             pw.print(" roaming="); pw.print(roamingToString(roaming[i]));
+            pw.print(" defaultNetwork="); pw.print(defaultNetworkToString(defaultNetwork[i]));
             pw.print(" rxBytes="); pw.print(rxBytes[i]);
             pw.print(" rxPackets="); pw.print(rxPackets[i]);
             pw.print(" txBytes="); pw.print(txBytes[i]);
@@ -900,6 +942,22 @@
         }
     }
 
+    /**
+     * Return text description of {@link #defaultNetwork} value.
+     */
+    public static String defaultNetworkToString(int defaultNetwork) {
+        switch (defaultNetwork) {
+            case DEFAULT_NETWORK_ALL:
+                return "ALL";
+            case DEFAULT_NETWORK_NO:
+                return "NO";
+            case DEFAULT_NETWORK_YES:
+                return "YES";
+            default:
+                return "UNKNOWN";
+        }
+    }
+
     @Override
     public String toString() {
         final CharArrayWriter writer = new CharArrayWriter();
@@ -1055,6 +1113,7 @@
                 tmpEntry.set = set[i];
                 tmpEntry.metered = metered[i];
                 tmpEntry.roaming = roaming[i];
+                tmpEntry.defaultNetwork = defaultNetwork[i];
                 combineValues(tmpEntry);
                 if (tag[i] == TAG_NONE) {
                     moved.add(tmpEntry);
@@ -1075,6 +1134,7 @@
         moved.iface = underlyingIface;
         moved.metered = METERED_ALL;
         moved.roaming = ROAMING_ALL;
+        moved.defaultNetwork = DEFAULT_NETWORK_ALL;
         combineValues(moved);
 
         // Caveat: if the vpn software uses tag, the total tagged traffic may be greater than
@@ -1085,13 +1145,13 @@
         // roaming data after applying these adjustments, by checking the NetworkIdentity of the
         // underlying iface.
         int idxVpnBackground = findIndex(underlyingIface, tunUid, SET_DEFAULT, TAG_NONE,
-                METERED_NO, ROAMING_NO);
+                METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO);
         if (idxVpnBackground != -1) {
             tunSubtract(idxVpnBackground, this, moved);
         }
 
         int idxVpnForeground = findIndex(underlyingIface, tunUid, SET_FOREGROUND, TAG_NONE,
-                METERED_NO, ROAMING_NO);
+                METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO);
         if (idxVpnForeground != -1) {
             tunSubtract(idxVpnForeground, this, moved);
         }
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index dc271d8..49879a8 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -35,6 +35,7 @@
 import android.view.Display;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.location.gnssmetrics.GnssMetrics;
 import com.android.internal.os.BatterySipper;
 import com.android.internal.os.BatteryStatsHelper;
 
@@ -683,6 +684,14 @@
 
         public abstract long[] getCpuFreqTimes(int which);
         public abstract long[] getScreenOffCpuFreqTimes(int which);
+        /**
+         * Returns cpu active time of an uid.
+         */
+        public abstract long getCpuActiveTime();
+        /**
+         * Returns cpu times of an uid on each cluster
+         */
+        public abstract long[] getCpuClusterTimes();
 
         /**
          * Returns cpu times of an uid at a particular process state.
@@ -1500,6 +1509,10 @@
         public static final int STATE2_WIFI_SIGNAL_STRENGTH_SHIFT = 4;
         public static final int STATE2_WIFI_SIGNAL_STRENGTH_MASK =
                 0x7 << STATE2_WIFI_SIGNAL_STRENGTH_SHIFT;
+        // Values for NUM_GPS_SIGNAL_QUALITY_LEVELS
+        public static final int STATE2_GPS_SIGNAL_QUALITY_SHIFT = 7;
+        public static final int STATE2_GPS_SIGNAL_QUALITY_MASK =
+            0x1 << STATE2_GPS_SIGNAL_QUALITY_SHIFT;
 
         public static final int STATE2_POWER_SAVE_FLAG = 1<<31;
         public static final int STATE2_VIDEO_ON_FLAG = 1<<30;
@@ -2088,6 +2101,23 @@
      */
     public abstract int getNumConnectivityChange(int which);
 
+
+    /**
+     * Returns the time in microseconds that the phone has been running with
+     * the given GPS signal quality level
+     *
+     * {@hide}
+     */
+    public abstract long getGpsSignalQualityTime(int strengthBin,
+        long elapsedRealtimeUs, int which);
+
+    /**
+     * Returns the GPS battery drain in mA-ms
+     *
+     * {@hide}
+     */
+    public abstract long getGpsBatteryDrainMaMs();
+
     /**
      * Returns the time in microseconds that the phone has been on while the device was
      * running on battery.
@@ -2312,6 +2342,9 @@
                 WIFI_SUPPL_STATE_NAMES, WIFI_SUPPL_STATE_SHORT_NAMES),
         new BitDescription(HistoryItem.STATE2_CAMERA_FLAG, "camera", "ca"),
         new BitDescription(HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG, "ble_scan", "bles"),
+        new BitDescription(HistoryItem.STATE2_GPS_SIGNAL_QUALITY_MASK,
+            HistoryItem.STATE2_GPS_SIGNAL_QUALITY_SHIFT, "gps_signal_quality", "Gss",
+            new String[] { "poor", "good"}, new String[] { "poor", "good"}),
     };
 
     public static final String[] HISTORY_EVENT_NAMES = new String[] {
@@ -4732,6 +4765,43 @@
         pw.print(prefix);
         sb.setLength(0);
         sb.append(prefix);
+        sb.append("  GPS Statistics:");
+        pw.println(sb.toString());
+
+        sb.setLength(0);
+        sb.append(prefix);
+        sb.append("     GPS signal quality (Top 4 Average CN0):");
+        final String[] gpsSignalQualityDescription = new String[]{
+            "poor (less than 20 dBHz): ",
+            "good (greater than 20 dBHz): "};
+        final int numGpsSignalQualityBins = Math.min(GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS,
+            gpsSignalQualityDescription.length);
+        for (int i=0; i<numGpsSignalQualityBins; i++) {
+            final long time = getGpsSignalQualityTime(i, rawRealtime, which);
+            sb.append("\n    ");
+            sb.append(prefix);
+            sb.append("  ");
+            sb.append(gpsSignalQualityDescription[i]);
+            formatTimeMs(sb, time/1000);
+            sb.append("(");
+            sb.append(formatRatioLocked(time, whichBatteryRealtime));
+            sb.append(") ");
+        }
+        pw.println(sb.toString());
+
+        final long gpsBatteryDrainMaMs = getGpsBatteryDrainMaMs();
+        if (gpsBatteryDrainMaMs > 0) {
+            pw.print(prefix);
+            sb.setLength(0);
+            sb.append(prefix);
+            sb.append("     Battery Drain (mAh): ");
+            sb.append(Double.toString(((double) gpsBatteryDrainMaMs)/(3600 * 1000)));
+            pw.println(sb.toString());
+        }
+
+        pw.print(prefix);
+        sb.setLength(0);
+        sb.append(prefix);
         sb.append("  CONNECTIVITY POWER SUMMARY END");
         pw.println(sb.toString());
         pw.println("");
diff --git a/core/java/android/os/IPermissionController.aidl b/core/java/android/os/IPermissionController.aidl
index 5e8590a..3de953a 100644
--- a/core/java/android/os/IPermissionController.aidl
+++ b/core/java/android/os/IPermissionController.aidl
@@ -22,4 +22,5 @@
     boolean checkPermission(String permission, int pid, int uid);
     String[] getPackagesForUid(int uid);
     boolean isRuntimePermission(String permission);
+    int getPackageUid(String packageName, int flags);
 }
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index e6cf5e6..7654e9b 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -151,6 +151,12 @@
      */
     public static final int OTA_UPDATE_UID = 1061;
 
+    /**
+     * Defines the UID used for incidentd.
+     * @hide
+     */
+    public static final int INCIDENTD_UID = 1067;
+
     /** {@hide} */
     public static final int NOBODY_UID = 9999;
 
diff --git a/core/java/android/os/connectivity/GpsBatteryStats.aidl b/core/java/android/os/connectivity/GpsBatteryStats.aidl
new file mode 100644
index 0000000..7b96d1a
--- /dev/null
+++ b/core/java/android/os/connectivity/GpsBatteryStats.aidl
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os.connectivity;
+
+/** {@hide} */
+parcelable GpsBatteryStats;
\ No newline at end of file
diff --git a/core/java/android/os/connectivity/GpsBatteryStats.java b/core/java/android/os/connectivity/GpsBatteryStats.java
new file mode 100644
index 0000000..f2ac5ef
--- /dev/null
+++ b/core/java/android/os/connectivity/GpsBatteryStats.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.os.connectivity;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.location.gnssmetrics.GnssMetrics;
+
+import java.util.Arrays;
+
+/**
+ * API for GPS power stats
+ *
+ * @hide
+ */
+public final class GpsBatteryStats implements Parcelable {
+
+  private long mLoggingDurationMs;
+  private long mEnergyConsumedMaMs;
+  private long[] mTimeInGpsSignalQualityLevel;
+
+  public static final Parcelable.Creator<GpsBatteryStats> CREATOR = new
+      Parcelable.Creator<GpsBatteryStats>() {
+        public GpsBatteryStats createFromParcel(Parcel in) {
+          return new GpsBatteryStats(in);
+        }
+
+        public GpsBatteryStats[] newArray(int size) {
+          return new GpsBatteryStats[size];
+        }
+      };
+
+  public GpsBatteryStats() {
+    initialize();
+  }
+
+  @Override
+  public void writeToParcel(Parcel out, int flags) {
+    out.writeLong(mLoggingDurationMs);
+    out.writeLong(mEnergyConsumedMaMs);
+    out.writeLongArray(mTimeInGpsSignalQualityLevel);
+  }
+
+  public void readFromParcel(Parcel in) {
+    mLoggingDurationMs = in.readLong();
+    mEnergyConsumedMaMs = in.readLong();
+    in.readLongArray(mTimeInGpsSignalQualityLevel);
+  }
+
+  public long getLoggingDurationMs() {
+    return mLoggingDurationMs;
+  }
+
+  public long getEnergyConsumedMaMs() {
+    return mEnergyConsumedMaMs;
+  }
+
+  public long[] getTimeInGpsSignalQualityLevel() {
+    return mTimeInGpsSignalQualityLevel;
+  }
+
+  public void setLoggingDurationMs(long t) {
+    mLoggingDurationMs = t;
+    return;
+  }
+
+  public void setEnergyConsumedMaMs(long e) {
+    mEnergyConsumedMaMs = e;
+    return;
+  }
+
+  public void setTimeInGpsSignalQualityLevel(long[] t) {
+    mTimeInGpsSignalQualityLevel = Arrays.copyOfRange(t, 0,
+        Math.min(t.length, GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS));
+    return;
+  }
+
+  @Override
+  public int describeContents() {
+    return 0;
+  }
+
+  private GpsBatteryStats(Parcel in) {
+    initialize();
+    readFromParcel(in);
+  }
+
+  private void initialize() {
+    mLoggingDurationMs = 0;
+    mEnergyConsumedMaMs = 0;
+    mTimeInGpsSignalQualityLevel = new long[GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS];
+    return;
+  }
+}
\ No newline at end of file
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 396c897..b2cc18b 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -16,6 +16,16 @@
 
 package android.provider;
 
+import static android.provider.SettingsValidators.ANY_INTEGER_VALIDATOR;
+import static android.provider.SettingsValidators.ANY_STRING_VALIDATOR;
+import static android.provider.SettingsValidators.BOOLEAN_VALIDATOR;
+import static android.provider.SettingsValidators.COMPONENT_NAME_VALIDATOR;
+import static android.provider.SettingsValidators.LENIENT_IP_ADDRESS_VALIDATOR;
+import static android.provider.SettingsValidators.LOCALE_VALIDATOR;
+import static android.provider.SettingsValidators.NON_NEGATIVE_INTEGER_VALIDATOR;
+import static android.provider.SettingsValidators.PACKAGE_NAME_VALIDATOR;
+import static android.provider.SettingsValidators.URI_VALIDATOR;
+
 import android.Manifest;
 import android.annotation.IntDef;
 import android.annotation.IntRange;
@@ -65,6 +75,8 @@
 import android.os.ResultReceiver;
 import android.os.ServiceManager;
 import android.os.UserHandle;
+import android.provider.SettingsValidators;
+import android.provider.SettingsValidators.Validator;
 import android.speech.tts.TextToSpeech;
 import android.telephony.SubscriptionManager;
 import android.text.TextUtils;
@@ -76,7 +88,6 @@
 import android.util.StatsLog;
 
 import com.android.internal.annotations.GuardedBy;
-import com.android.internal.util.ArrayUtils;
 import com.android.internal.widget.ILockSettings;
 
 import java.io.IOException;
@@ -2119,11 +2130,6 @@
 
         private static final float DEFAULT_FONT_SCALE = 1.0f;
 
-        /** @hide */
-        public static interface Validator {
-            public boolean validate(String value);
-        }
-
         /**
          * The content:// style URL for this table
          */
@@ -2228,41 +2234,6 @@
             MOVED_TO_GLOBAL.add(Settings.Global.CERT_PIN_UPDATE_METADATA_URL);
         }
 
-        private static final Validator sBooleanValidator =
-                new DiscreteValueValidator(new String[] {"0", "1"});
-
-        private static final Validator sNonNegativeIntegerValidator = new Validator() {
-            @Override
-            public boolean validate(String value) {
-                try {
-                    return Integer.parseInt(value) >= 0;
-                } catch (NumberFormatException e) {
-                    return false;
-                }
-            }
-        };
-
-        private static final Validator sUriValidator = new Validator() {
-            @Override
-            public boolean validate(String value) {
-                try {
-                    Uri.decode(value);
-                    return true;
-                } catch (IllegalArgumentException e) {
-                    return false;
-                }
-            }
-        };
-
-        private static final Validator sLenientIpAddressValidator = new Validator() {
-            private static final int MAX_IPV6_LENGTH = 45;
-
-            @Override
-            public boolean validate(String value) {
-                return value.length() <= MAX_IPV6_LENGTH;
-            }
-        };
-
         /** @hide */
         public static void getMovedToGlobalSettings(Set<String> outKeySet) {
             outKeySet.addAll(MOVED_TO_GLOBAL);
@@ -2730,65 +2701,36 @@
             putIntForUser(cr, SHOW_GTALK_SERVICE_STATUS, flag ? 1 : 0, userHandle);
         }
 
-        private static final class DiscreteValueValidator implements Validator {
-            private final String[] mValues;
-
-            public DiscreteValueValidator(String[] values) {
-                mValues = values;
-            }
-
-            @Override
-            public boolean validate(String value) {
-                return ArrayUtils.contains(mValues, value);
-            }
-        }
-
-        private static final class InclusiveIntegerRangeValidator implements Validator {
-            private final int mMin;
-            private final int mMax;
-
-            public InclusiveIntegerRangeValidator(int min, int max) {
-                mMin = min;
-                mMax = max;
-            }
-
-            @Override
-            public boolean validate(String value) {
-                try {
-                    final int intValue = Integer.parseInt(value);
-                    return intValue >= mMin && intValue <= mMax;
-                } catch (NumberFormatException e) {
-                    return false;
-                }
-            }
-        }
-
-        private static final class InclusiveFloatRangeValidator implements Validator {
-            private final float mMin;
-            private final float mMax;
-
-            public InclusiveFloatRangeValidator(float min, float max) {
-                mMin = min;
-                mMax = max;
-            }
-
-            @Override
-            public boolean validate(String value) {
-                try {
-                    final float floatValue = Float.parseFloat(value);
-                    return floatValue >= mMin && floatValue <= mMax;
-                } catch (NumberFormatException e) {
-                    return false;
-                }
-            }
-        }
-
         /**
          * @deprecated Use {@link android.provider.Settings.Global#STAY_ON_WHILE_PLUGGED_IN} instead
          */
         @Deprecated
         public static final String STAY_ON_WHILE_PLUGGED_IN = Global.STAY_ON_WHILE_PLUGGED_IN;
 
+        private static final Validator STAY_ON_WHILE_PLUGGED_IN_VALIDATOR = new Validator() {
+            @Override
+            public boolean validate(String value) {
+                try {
+                    int val = Integer.parseInt(value);
+                    return (val == 0)
+                            || (val == BatteryManager.BATTERY_PLUGGED_AC)
+                            || (val == BatteryManager.BATTERY_PLUGGED_USB)
+                            || (val == BatteryManager.BATTERY_PLUGGED_WIRELESS)
+                            || (val == (BatteryManager.BATTERY_PLUGGED_AC
+                                    | BatteryManager.BATTERY_PLUGGED_USB))
+                            || (val == (BatteryManager.BATTERY_PLUGGED_AC
+                                    | BatteryManager.BATTERY_PLUGGED_WIRELESS))
+                            || (val == (BatteryManager.BATTERY_PLUGGED_USB
+                                    | BatteryManager.BATTERY_PLUGGED_WIRELESS))
+                            || (val == (BatteryManager.BATTERY_PLUGGED_AC
+                                    | BatteryManager.BATTERY_PLUGGED_USB
+                                    | BatteryManager.BATTERY_PLUGGED_WIRELESS));
+                } catch (NumberFormatException e) {
+                    return false;
+                }
+            }
+        };
+
         /**
          * What happens when the user presses the end call button if they're not
          * on a call.<br/>
@@ -2802,7 +2744,7 @@
         public static final String END_BUTTON_BEHAVIOR = "end_button_behavior";
 
         private static final Validator END_BUTTON_BEHAVIOR_VALIDATOR =
-                new InclusiveIntegerRangeValidator(0, 3);
+                new SettingsValidators.InclusiveIntegerRangeValidator(0, 3);
 
         /**
          * END_BUTTON_BEHAVIOR value for "go home".
@@ -2828,7 +2770,7 @@
          */
         public static final String ADVANCED_SETTINGS = "advanced_settings";
 
-        private static final Validator ADVANCED_SETTINGS_VALIDATOR = sBooleanValidator;
+        private static final Validator ADVANCED_SETTINGS_VALIDATOR = BOOLEAN_VALIDATOR;
 
         /**
          * ADVANCED_SETTINGS default value.
@@ -2929,7 +2871,7 @@
         @Deprecated
         public static final String WIFI_USE_STATIC_IP = "wifi_use_static_ip";
 
-        private static final Validator WIFI_USE_STATIC_IP_VALIDATOR = sBooleanValidator;
+        private static final Validator WIFI_USE_STATIC_IP_VALIDATOR = BOOLEAN_VALIDATOR;
 
         /**
          * The static IP address.
@@ -2941,7 +2883,7 @@
         @Deprecated
         public static final String WIFI_STATIC_IP = "wifi_static_ip";
 
-        private static final Validator WIFI_STATIC_IP_VALIDATOR = sLenientIpAddressValidator;
+        private static final Validator WIFI_STATIC_IP_VALIDATOR = LENIENT_IP_ADDRESS_VALIDATOR;
 
         /**
          * If using static IP, the gateway's IP address.
@@ -2953,7 +2895,7 @@
         @Deprecated
         public static final String WIFI_STATIC_GATEWAY = "wifi_static_gateway";
 
-        private static final Validator WIFI_STATIC_GATEWAY_VALIDATOR = sLenientIpAddressValidator;
+        private static final Validator WIFI_STATIC_GATEWAY_VALIDATOR = LENIENT_IP_ADDRESS_VALIDATOR;
 
         /**
          * If using static IP, the net mask.
@@ -2965,7 +2907,7 @@
         @Deprecated
         public static final String WIFI_STATIC_NETMASK = "wifi_static_netmask";
 
-        private static final Validator WIFI_STATIC_NETMASK_VALIDATOR = sLenientIpAddressValidator;
+        private static final Validator WIFI_STATIC_NETMASK_VALIDATOR = LENIENT_IP_ADDRESS_VALIDATOR;
 
         /**
          * If using static IP, the primary DNS's IP address.
@@ -2977,7 +2919,7 @@
         @Deprecated
         public static final String WIFI_STATIC_DNS1 = "wifi_static_dns1";
 
-        private static final Validator WIFI_STATIC_DNS1_VALIDATOR = sLenientIpAddressValidator;
+        private static final Validator WIFI_STATIC_DNS1_VALIDATOR = LENIENT_IP_ADDRESS_VALIDATOR;
 
         /**
          * If using static IP, the secondary DNS's IP address.
@@ -2989,7 +2931,7 @@
         @Deprecated
         public static final String WIFI_STATIC_DNS2 = "wifi_static_dns2";
 
-        private static final Validator WIFI_STATIC_DNS2_VALIDATOR = sLenientIpAddressValidator;
+        private static final Validator WIFI_STATIC_DNS2_VALIDATOR = LENIENT_IP_ADDRESS_VALIDATOR;
 
         /**
          * Determines whether remote devices may discover and/or connect to
@@ -3003,7 +2945,7 @@
             "bluetooth_discoverability";
 
         private static final Validator BLUETOOTH_DISCOVERABILITY_VALIDATOR =
-                new InclusiveIntegerRangeValidator(0, 2);
+                new SettingsValidators.InclusiveIntegerRangeValidator(0, 2);
 
         /**
          * Bluetooth discoverability timeout.  If this value is nonzero, then
@@ -3014,7 +2956,7 @@
             "bluetooth_discoverability_timeout";
 
         private static final Validator BLUETOOTH_DISCOVERABILITY_TIMEOUT_VALIDATOR =
-                sNonNegativeIntegerValidator;
+                NON_NEGATIVE_INTEGER_VALIDATOR;
 
         /**
          * @deprecated Use {@link android.provider.Settings.Secure#LOCK_PATTERN_ENABLED}
@@ -3110,7 +3052,7 @@
         @Deprecated
         public static final String DIM_SCREEN = "dim_screen";
 
-        private static final Validator DIM_SCREEN_VALIDATOR = sBooleanValidator;
+        private static final Validator DIM_SCREEN_VALIDATOR = BOOLEAN_VALIDATOR;
 
         /**
          * The display color mode.
@@ -3130,7 +3072,8 @@
          */
         public static final String SCREEN_OFF_TIMEOUT = "screen_off_timeout";
 
-        private static final Validator SCREEN_OFF_TIMEOUT_VALIDATOR = sNonNegativeIntegerValidator;
+        private static final Validator SCREEN_OFF_TIMEOUT_VALIDATOR =
+                NON_NEGATIVE_INTEGER_VALIDATOR;
 
         /**
          * The screen backlight brightness between 0 and 255.
@@ -3138,7 +3081,7 @@
         public static final String SCREEN_BRIGHTNESS = "screen_brightness";
 
         private static final Validator SCREEN_BRIGHTNESS_VALIDATOR =
-                new InclusiveIntegerRangeValidator(0, 255);
+                new SettingsValidators.InclusiveIntegerRangeValidator(0, 255);
 
         /**
          * The screen backlight brightness between 0 and 255.
@@ -3147,14 +3090,14 @@
         public static final String SCREEN_BRIGHTNESS_FOR_VR = "screen_brightness_for_vr";
 
         private static final Validator SCREEN_BRIGHTNESS_FOR_VR_VALIDATOR =
-                new InclusiveIntegerRangeValidator(0, 255);
+                new SettingsValidators.InclusiveIntegerRangeValidator(0, 255);
 
         /**
          * Control whether to enable automatic brightness mode.
          */
         public static final String SCREEN_BRIGHTNESS_MODE = "screen_brightness_mode";
 
-        private static final Validator SCREEN_BRIGHTNESS_MODE_VALIDATOR = sBooleanValidator;
+        private static final Validator SCREEN_BRIGHTNESS_MODE_VALIDATOR = BOOLEAN_VALIDATOR;
 
         /**
          * Adjustment to auto-brightness to make it generally more (>0.0 <1.0)
@@ -3164,7 +3107,7 @@
         public static final String SCREEN_AUTO_BRIGHTNESS_ADJ = "screen_auto_brightness_adj";
 
         private static final Validator SCREEN_AUTO_BRIGHTNESS_ADJ_VALIDATOR =
-                new InclusiveFloatRangeValidator(-1, 1);
+                new SettingsValidators.InclusiveFloatRangeValidator(-1, 1);
 
         /**
          * SCREEN_BRIGHTNESS_MODE value for manual mode.
@@ -3203,7 +3146,7 @@
         public static final String MODE_RINGER_STREAMS_AFFECTED = "mode_ringer_streams_affected";
 
         private static final Validator MODE_RINGER_STREAMS_AFFECTED_VALIDATOR =
-                sNonNegativeIntegerValidator;
+                NON_NEGATIVE_INTEGER_VALIDATOR;
 
         /**
           * Determines which streams are affected by mute. The
@@ -3213,7 +3156,7 @@
         public static final String MUTE_STREAMS_AFFECTED = "mute_streams_affected";
 
         private static final Validator MUTE_STREAMS_AFFECTED_VALIDATOR =
-                sNonNegativeIntegerValidator;
+                NON_NEGATIVE_INTEGER_VALIDATOR;
 
         /**
          * Whether vibrate is on for different events. This is used internally,
@@ -3221,7 +3164,7 @@
          */
         public static final String VIBRATE_ON = "vibrate_on";
 
-        private static final Validator VIBRATE_ON_VALIDATOR = sBooleanValidator;
+        private static final Validator VIBRATE_ON_VALIDATOR = BOOLEAN_VALIDATOR;
 
         /**
          * If 1, redirects the system vibrator to all currently attached input devices
@@ -3237,7 +3180,7 @@
          */
         public static final String VIBRATE_INPUT_DEVICES = "vibrate_input_devices";
 
-        private static final Validator VIBRATE_INPUT_DEVICES_VALIDATOR = sBooleanValidator;
+        private static final Validator VIBRATE_INPUT_DEVICES_VALIDATOR = BOOLEAN_VALIDATOR;
 
         /**
          * Ringer volume. This is used internally, changing this value will not
@@ -3316,7 +3259,7 @@
          */
         public static final String MASTER_MONO = "master_mono";
 
-        private static final Validator MASTER_MONO_VALIDATOR = sBooleanValidator;
+        private static final Validator MASTER_MONO_VALIDATOR = BOOLEAN_VALIDATOR;
 
         /**
          * Whether the notifications should use the ring volume (value of 1) or
@@ -3336,7 +3279,7 @@
         public static final String NOTIFICATIONS_USE_RING_VOLUME =
             "notifications_use_ring_volume";
 
-        private static final Validator NOTIFICATIONS_USE_RING_VOLUME_VALIDATOR = sBooleanValidator;
+        private static final Validator NOTIFICATIONS_USE_RING_VOLUME_VALIDATOR = BOOLEAN_VALIDATOR;
 
         /**
          * Whether silent mode should allow vibration feedback. This is used
@@ -3352,7 +3295,7 @@
          */
         public static final String VIBRATE_IN_SILENT = "vibrate_in_silent";
 
-        private static final Validator VIBRATE_IN_SILENT_VALIDATOR = sBooleanValidator;
+        private static final Validator VIBRATE_IN_SILENT_VALIDATOR = BOOLEAN_VALIDATOR;
 
         /**
          * The mapping of stream type (integer) to its setting.
@@ -3400,7 +3343,7 @@
          */
         public static final String RINGTONE = "ringtone";
 
-        private static final Validator RINGTONE_VALIDATOR = sUriValidator;
+        private static final Validator RINGTONE_VALIDATOR = URI_VALIDATOR;
 
         /**
          * A {@link Uri} that will point to the current default ringtone at any
@@ -3425,7 +3368,7 @@
          */
         public static final String NOTIFICATION_SOUND = "notification_sound";
 
-        private static final Validator NOTIFICATION_SOUND_VALIDATOR = sUriValidator;
+        private static final Validator NOTIFICATION_SOUND_VALIDATOR = URI_VALIDATOR;
 
         /**
          * A {@link Uri} that will point to the current default notification
@@ -3448,7 +3391,7 @@
          */
         public static final String ALARM_ALERT = "alarm_alert";
 
-        private static final Validator ALARM_ALERT_VALIDATOR = sUriValidator;
+        private static final Validator ALARM_ALERT_VALIDATOR = URI_VALIDATOR;
 
         /**
          * A {@link Uri} that will point to the current default alarm alert at
@@ -3470,31 +3413,21 @@
          */
         public static final String MEDIA_BUTTON_RECEIVER = "media_button_receiver";
 
-        private static final Validator MEDIA_BUTTON_RECEIVER_VALIDATOR = new Validator() {
-            @Override
-            public boolean validate(String value) {
-                try {
-                    ComponentName.unflattenFromString(value);
-                    return true;
-                } catch (NullPointerException e) {
-                    return false;
-                }
-            }
-        };
+        private static final Validator MEDIA_BUTTON_RECEIVER_VALIDATOR = COMPONENT_NAME_VALIDATOR;
 
         /**
          * Setting to enable Auto Replace (AutoText) in text editors. 1 = On, 0 = Off
          */
         public static final String TEXT_AUTO_REPLACE = "auto_replace";
 
-        private static final Validator TEXT_AUTO_REPLACE_VALIDATOR = sBooleanValidator;
+        private static final Validator TEXT_AUTO_REPLACE_VALIDATOR = BOOLEAN_VALIDATOR;
 
         /**
          * Setting to enable Auto Caps in text editors. 1 = On, 0 = Off
          */
         public static final String TEXT_AUTO_CAPS = "auto_caps";
 
-        private static final Validator TEXT_AUTO_CAPS_VALIDATOR = sBooleanValidator;
+        private static final Validator TEXT_AUTO_CAPS_VALIDATOR = BOOLEAN_VALIDATOR;
 
         /**
          * Setting to enable Auto Punctuate in text editors. 1 = On, 0 = Off. This
@@ -3502,19 +3435,19 @@
          */
         public static final String TEXT_AUTO_PUNCTUATE = "auto_punctuate";
 
-        private static final Validator TEXT_AUTO_PUNCTUATE_VALIDATOR = sBooleanValidator;
+        private static final Validator TEXT_AUTO_PUNCTUATE_VALIDATOR = BOOLEAN_VALIDATOR;
 
         /**
          * Setting to showing password characters in text editors. 1 = On, 0 = Off
          */
         public static final String TEXT_SHOW_PASSWORD = "show_password";
 
-        private static final Validator TEXT_SHOW_PASSWORD_VALIDATOR = sBooleanValidator;
+        private static final Validator TEXT_SHOW_PASSWORD_VALIDATOR = BOOLEAN_VALIDATOR;
 
         public static final String SHOW_GTALK_SERVICE_STATUS =
                 "SHOW_GTALK_SERVICE_STATUS";
 
-        private static final Validator SHOW_GTALK_SERVICE_STATUS_VALIDATOR = sBooleanValidator;
+        private static final Validator SHOW_GTALK_SERVICE_STATUS_VALIDATOR = BOOLEAN_VALIDATOR;
 
         /**
          * Name of activity to use for wallpaper on the home screen.
@@ -3543,6 +3476,8 @@
         @Deprecated
         public static final String AUTO_TIME = Global.AUTO_TIME;
 
+        private static final Validator AUTO_TIME_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * @deprecated Use {@link android.provider.Settings.Global#AUTO_TIME_ZONE}
          * instead
@@ -3550,6 +3485,8 @@
         @Deprecated
         public static final String AUTO_TIME_ZONE = Global.AUTO_TIME_ZONE;
 
+        private static final Validator AUTO_TIME_ZONE_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * Display times as 12 or 24 hours
          *   12
@@ -3559,7 +3496,7 @@
 
         /** @hide */
         public static final Validator TIME_12_24_VALIDATOR =
-                new DiscreteValueValidator(new String[] {"12", "24", null});
+                new SettingsValidators.DiscreteValueValidator(new String[] {"12", "24", null});
 
         /**
          * Date format string
@@ -3592,7 +3529,7 @@
         public static final String SETUP_WIZARD_HAS_RUN = "setup_wizard_has_run";
 
         /** @hide */
-        public static final Validator SETUP_WIZARD_HAS_RUN_VALIDATOR = sBooleanValidator;
+        public static final Validator SETUP_WIZARD_HAS_RUN_VALIDATOR = BOOLEAN_VALIDATOR;
 
         /**
          * Scaling factor for normal window animations. Setting to 0 will disable window
@@ -3631,7 +3568,7 @@
         public static final String ACCELEROMETER_ROTATION = "accelerometer_rotation";
 
         /** @hide */
-        public static final Validator ACCELEROMETER_ROTATION_VALIDATOR = sBooleanValidator;
+        public static final Validator ACCELEROMETER_ROTATION_VALIDATOR = BOOLEAN_VALIDATOR;
 
         /**
          * Default screen rotation when no other policy applies.
@@ -3645,7 +3582,7 @@
 
         /** @hide */
         public static final Validator USER_ROTATION_VALIDATOR =
-                new InclusiveIntegerRangeValidator(0, 3);
+                new SettingsValidators.InclusiveIntegerRangeValidator(0, 3);
 
         /**
          * Control whether the rotation lock toggle in the System UI should be hidden.
@@ -3663,7 +3600,7 @@
 
         /** @hide */
         public static final Validator HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY_VALIDATOR =
-                sBooleanValidator;
+                BOOLEAN_VALIDATOR;
 
         /**
          * Whether the phone vibrates when it is ringing due to an incoming call. This will
@@ -3678,7 +3615,7 @@
         public static final String VIBRATE_WHEN_RINGING = "vibrate_when_ringing";
 
         /** @hide */
-        public static final Validator VIBRATE_WHEN_RINGING_VALIDATOR = sBooleanValidator;
+        public static final Validator VIBRATE_WHEN_RINGING_VALIDATOR = BOOLEAN_VALIDATOR;
 
         /**
          * Whether the audible DTMF tones are played by the dialer when dialing. The value is
@@ -3687,7 +3624,7 @@
         public static final String DTMF_TONE_WHEN_DIALING = "dtmf_tone";
 
         /** @hide */
-        public static final Validator DTMF_TONE_WHEN_DIALING_VALIDATOR = sBooleanValidator;
+        public static final Validator DTMF_TONE_WHEN_DIALING_VALIDATOR = BOOLEAN_VALIDATOR;
 
         /**
          * CDMA only settings
@@ -3698,7 +3635,7 @@
         public static final String DTMF_TONE_TYPE_WHEN_DIALING = "dtmf_tone_type";
 
         /** @hide */
-        public static final Validator DTMF_TONE_TYPE_WHEN_DIALING_VALIDATOR = sBooleanValidator;
+        public static final Validator DTMF_TONE_TYPE_WHEN_DIALING_VALIDATOR = BOOLEAN_VALIDATOR;
 
         /**
          * Whether the hearing aid is enabled. The value is
@@ -3708,7 +3645,7 @@
         public static final String HEARING_AID = "hearing_aid";
 
         /** @hide */
-        public static final Validator HEARING_AID_VALIDATOR = sBooleanValidator;
+        public static final Validator HEARING_AID_VALIDATOR = BOOLEAN_VALIDATOR;
 
         /**
          * CDMA only settings
@@ -3722,7 +3659,8 @@
         public static final String TTY_MODE = "tty_mode";
 
         /** @hide */
-        public static final Validator TTY_MODE_VALIDATOR = new InclusiveIntegerRangeValidator(0, 3);
+        public static final Validator TTY_MODE_VALIDATOR =
+                new SettingsValidators.InclusiveIntegerRangeValidator(0, 3);
 
         /**
          * Whether the sounds effects (key clicks, lid open ...) are enabled. The value is
@@ -3731,7 +3669,7 @@
         public static final String SOUND_EFFECTS_ENABLED = "sound_effects_enabled";
 
         /** @hide */
-        public static final Validator SOUND_EFFECTS_ENABLED_VALIDATOR = sBooleanValidator;
+        public static final Validator SOUND_EFFECTS_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
 
         /**
          * Whether the haptic feedback (long presses, ...) are enabled. The value is
@@ -3740,7 +3678,7 @@
         public static final String HAPTIC_FEEDBACK_ENABLED = "haptic_feedback_enabled";
 
         /** @hide */
-        public static final Validator HAPTIC_FEEDBACK_ENABLED_VALIDATOR = sBooleanValidator;
+        public static final Validator HAPTIC_FEEDBACK_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
 
         /**
          * @deprecated Each application that shows web suggestions should have its own
@@ -3750,7 +3688,7 @@
         public static final String SHOW_WEB_SUGGESTIONS = "show_web_suggestions";
 
         /** @hide */
-        public static final Validator SHOW_WEB_SUGGESTIONS_VALIDATOR = sBooleanValidator;
+        public static final Validator SHOW_WEB_SUGGESTIONS_VALIDATOR = BOOLEAN_VALIDATOR;
 
         /**
          * Whether the notification LED should repeatedly flash when a notification is
@@ -3760,7 +3698,7 @@
         public static final String NOTIFICATION_LIGHT_PULSE = "notification_light_pulse";
 
         /** @hide */
-        public static final Validator NOTIFICATION_LIGHT_PULSE_VALIDATOR = sBooleanValidator;
+        public static final Validator NOTIFICATION_LIGHT_PULSE_VALIDATOR = BOOLEAN_VALIDATOR;
 
         /**
          * Show pointer location on screen?
@@ -3771,7 +3709,7 @@
         public static final String POINTER_LOCATION = "pointer_location";
 
         /** @hide */
-        public static final Validator POINTER_LOCATION_VALIDATOR = sBooleanValidator;
+        public static final Validator POINTER_LOCATION_VALIDATOR = BOOLEAN_VALIDATOR;
 
         /**
          * Show touch positions on screen?
@@ -3782,7 +3720,7 @@
         public static final String SHOW_TOUCHES = "show_touches";
 
         /** @hide */
-        public static final Validator SHOW_TOUCHES_VALIDATOR = sBooleanValidator;
+        public static final Validator SHOW_TOUCHES_VALIDATOR = BOOLEAN_VALIDATOR;
 
         /**
          * Log raw orientation data from
@@ -3796,7 +3734,7 @@
                 "window_orientation_listener_log";
 
         /** @hide */
-        public static final Validator WINDOW_ORIENTATION_LISTENER_LOG_VALIDATOR = sBooleanValidator;
+        public static final Validator WINDOW_ORIENTATION_LISTENER_LOG_VALIDATOR = BOOLEAN_VALIDATOR;
 
         /**
          * @deprecated Use {@link android.provider.Settings.Global#POWER_SOUNDS_ENABLED}
@@ -3806,6 +3744,8 @@
         @Deprecated
         public static final String POWER_SOUNDS_ENABLED = Global.POWER_SOUNDS_ENABLED;
 
+        private static final Validator POWER_SOUNDS_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * @deprecated Use {@link android.provider.Settings.Global#DOCK_SOUNDS_ENABLED}
          * instead
@@ -3814,6 +3754,8 @@
         @Deprecated
         public static final String DOCK_SOUNDS_ENABLED = Global.DOCK_SOUNDS_ENABLED;
 
+        private static final Validator DOCK_SOUNDS_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * Whether to play sounds when the keyguard is shown and dismissed.
          * @hide
@@ -3821,7 +3763,7 @@
         public static final String LOCKSCREEN_SOUNDS_ENABLED = "lockscreen_sounds_enabled";
 
         /** @hide */
-        public static final Validator LOCKSCREEN_SOUNDS_ENABLED_VALIDATOR = sBooleanValidator;
+        public static final Validator LOCKSCREEN_SOUNDS_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
 
         /**
          * Whether the lockscreen should be completely disabled.
@@ -3830,7 +3772,7 @@
         public static final String LOCKSCREEN_DISABLED = "lockscreen.disabled";
 
         /** @hide */
-        public static final Validator LOCKSCREEN_DISABLED_VALIDATOR = sBooleanValidator;
+        public static final Validator LOCKSCREEN_DISABLED_VALIDATOR = BOOLEAN_VALIDATOR;
 
         /**
          * @deprecated Use {@link android.provider.Settings.Global#LOW_BATTERY_SOUND}
@@ -3897,7 +3839,7 @@
         public static final String SIP_RECEIVE_CALLS = "sip_receive_calls";
 
         /** @hide */
-        public static final Validator SIP_RECEIVE_CALLS_VALIDATOR = sBooleanValidator;
+        public static final Validator SIP_RECEIVE_CALLS_VALIDATOR = BOOLEAN_VALIDATOR;
 
         /**
          * Call Preference String.
@@ -3908,8 +3850,9 @@
         public static final String SIP_CALL_OPTIONS = "sip_call_options";
 
         /** @hide */
-        public static final Validator SIP_CALL_OPTIONS_VALIDATOR = new DiscreteValueValidator(
-                new String[] {"SIP_ALWAYS", "SIP_ADDRESS_ONLY"});
+        public static final Validator SIP_CALL_OPTIONS_VALIDATOR =
+                new SettingsValidators.DiscreteValueValidator(
+                        new String[] {"SIP_ALWAYS", "SIP_ADDRESS_ONLY"});
 
         /**
          * One of the sip call options: Always use SIP with network access.
@@ -3918,7 +3861,7 @@
         public static final String SIP_ALWAYS = "SIP_ALWAYS";
 
         /** @hide */
-        public static final Validator SIP_ALWAYS_VALIDATOR = sBooleanValidator;
+        public static final Validator SIP_ALWAYS_VALIDATOR = BOOLEAN_VALIDATOR;
 
         /**
          * One of the sip call options: Only if destination is a SIP address.
@@ -3927,7 +3870,7 @@
         public static final String SIP_ADDRESS_ONLY = "SIP_ADDRESS_ONLY";
 
         /** @hide */
-        public static final Validator SIP_ADDRESS_ONLY_VALIDATOR = sBooleanValidator;
+        public static final Validator SIP_ADDRESS_ONLY_VALIDATOR = BOOLEAN_VALIDATOR;
 
         /**
          * @deprecated Use SIP_ALWAYS or SIP_ADDRESS_ONLY instead.  Formerly used to indicate that
@@ -3940,7 +3883,7 @@
         public static final String SIP_ASK_ME_EACH_TIME = "SIP_ASK_ME_EACH_TIME";
 
         /** @hide */
-        public static final Validator SIP_ASK_ME_EACH_TIME_VALIDATOR = sBooleanValidator;
+        public static final Validator SIP_ASK_ME_EACH_TIME_VALIDATOR = BOOLEAN_VALIDATOR;
 
         /**
          * Pointer speed setting.
@@ -3954,7 +3897,7 @@
 
         /** @hide */
         public static final Validator POINTER_SPEED_VALIDATOR =
-                new InclusiveFloatRangeValidator(-7, 7);
+                new SettingsValidators.InclusiveFloatRangeValidator(-7, 7);
 
         /**
          * Whether lock-to-app will be triggered by long-press on recents.
@@ -3963,7 +3906,7 @@
         public static final String LOCK_TO_APP_ENABLED = "lock_to_app_enabled";
 
         /** @hide */
-        public static final Validator LOCK_TO_APP_ENABLED_VALIDATOR = sBooleanValidator;
+        public static final Validator LOCK_TO_APP_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
 
         /**
          * I am the lolrus.
@@ -3995,7 +3938,7 @@
         public static final String SHOW_BATTERY_PERCENT = "status_bar_show_battery_percent";
 
         /** @hide */
-        private static final Validator SHOW_BATTERY_PERCENT_VALIDATOR = sBooleanValidator;
+        private static final Validator SHOW_BATTERY_PERCENT_VALIDATOR = BOOLEAN_VALIDATOR;
 
         /**
          * IMPORTANT: If you add a new public settings you also have to add it to
@@ -4067,6 +4010,9 @@
          * Keys we no longer back up under the current schema, but want to continue to
          * process when restoring historical backup datasets.
          *
+         * All settings in {@link LEGACY_RESTORE_SETTINGS} array *must* have a non-null validator,
+         * otherwise they won't be restored.
+         *
          * @hide
          */
         public static final String[] LEGACY_RESTORE_SETTINGS = {
@@ -4175,11 +4121,15 @@
         /**
          * These are all public system settings
          *
+         * All settings in {@link SETTINGS_TO_BACKUP} array *must* have a non-null validator,
+         * otherwise they won't be restored.
+         *
          * @hide
          */
         public static final Map<String, Validator> VALIDATORS = new ArrayMap<>();
         static {
-            VALIDATORS.put(END_BUTTON_BEHAVIOR,END_BUTTON_BEHAVIOR_VALIDATOR);
+            VALIDATORS.put(STAY_ON_WHILE_PLUGGED_IN, STAY_ON_WHILE_PLUGGED_IN_VALIDATOR);
+            VALIDATORS.put(END_BUTTON_BEHAVIOR, END_BUTTON_BEHAVIOR_VALIDATOR);
             VALIDATORS.put(WIFI_USE_STATIC_IP, WIFI_USE_STATIC_IP_VALIDATOR);
             VALIDATORS.put(BLUETOOTH_DISCOVERABILITY, BLUETOOTH_DISCOVERABILITY_VALIDATOR);
             VALIDATORS.put(BLUETOOTH_DISCOVERABILITY_TIMEOUT,
@@ -4201,6 +4151,8 @@
             VALIDATORS.put(TEXT_AUTO_CAPS, TEXT_AUTO_CAPS_VALIDATOR);
             VALIDATORS.put(TEXT_AUTO_PUNCTUATE, TEXT_AUTO_PUNCTUATE_VALIDATOR);
             VALIDATORS.put(TEXT_SHOW_PASSWORD, TEXT_SHOW_PASSWORD_VALIDATOR);
+            VALIDATORS.put(AUTO_TIME, AUTO_TIME_VALIDATOR);
+            VALIDATORS.put(AUTO_TIME_ZONE, AUTO_TIME_ZONE_VALIDATOR);
             VALIDATORS.put(SHOW_GTALK_SERVICE_STATUS, SHOW_GTALK_SERVICE_STATUS_VALIDATOR);
             VALIDATORS.put(WALLPAPER_ACTIVITY, WALLPAPER_ACTIVITY_VALIDATOR);
             VALIDATORS.put(TIME_12_24, TIME_12_24_VALIDATOR);
@@ -4211,6 +4163,8 @@
             VALIDATORS.put(DTMF_TONE_WHEN_DIALING, DTMF_TONE_WHEN_DIALING_VALIDATOR);
             VALIDATORS.put(SOUND_EFFECTS_ENABLED, SOUND_EFFECTS_ENABLED_VALIDATOR);
             VALIDATORS.put(HAPTIC_FEEDBACK_ENABLED, HAPTIC_FEEDBACK_ENABLED_VALIDATOR);
+            VALIDATORS.put(POWER_SOUNDS_ENABLED, POWER_SOUNDS_ENABLED_VALIDATOR);
+            VALIDATORS.put(DOCK_SOUNDS_ENABLED, DOCK_SOUNDS_ENABLED_VALIDATOR);
             VALIDATORS.put(SHOW_WEB_SUGGESTIONS, SHOW_WEB_SUGGESTIONS_VALIDATOR);
             VALIDATORS.put(WIFI_USE_STATIC_IP, WIFI_USE_STATIC_IP_VALIDATOR);
             VALIDATORS.put(END_BUTTON_BEHAVIOR, END_BUTTON_BEHAVIOR_VALIDATOR);
@@ -4335,6 +4289,8 @@
         @Deprecated
         public static final String BLUETOOTH_ON = Global.BLUETOOTH_ON;
 
+        private static final Validator BLUETOOTH_ON_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * @deprecated Use {@link android.provider.Settings.Global#DATA_ROAMING} instead
          */
@@ -4412,6 +4368,8 @@
         @Deprecated
         public static final String USB_MASS_STORAGE_ENABLED = Global.USB_MASS_STORAGE_ENABLED;
 
+        private static final Validator USB_MASS_STORAGE_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * @deprecated Use {@link android.provider.Settings.Global#USE_GOOGLE_MAIL} instead
          */
@@ -4441,6 +4399,9 @@
         public static final String WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON =
                 Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON;
 
+        private static final Validator WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON_VALIDATOR =
+                BOOLEAN_VALIDATOR;
+
         /**
          * @deprecated Use
          * {@link android.provider.Settings.Global#WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY} instead
@@ -4449,6 +4410,9 @@
         public static final String WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY =
                 Global.WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY;
 
+        private static final Validator WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY_VALIDATOR =
+                NON_NEGATIVE_INTEGER_VALIDATOR;
+
         /**
          * @deprecated Use {@link android.provider.Settings.Global#WIFI_NUM_OPEN_NETWORKS_KEPT}
          * instead
@@ -4456,6 +4420,9 @@
         @Deprecated
         public static final String WIFI_NUM_OPEN_NETWORKS_KEPT = Global.WIFI_NUM_OPEN_NETWORKS_KEPT;
 
+        private static final Validator WIFI_NUM_OPEN_NETWORKS_KEPT_VALIDATOR =
+                NON_NEGATIVE_INTEGER_VALIDATOR;
+
         /**
          * @deprecated Use {@link android.provider.Settings.Global#WIFI_ON} instead
          */
@@ -5218,6 +5185,8 @@
         @Deprecated
         public static final String BUGREPORT_IN_POWER_MENU = "bugreport_in_power_menu";
 
+        private static final Validator BUGREPORT_IN_POWER_MENU_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * @deprecated Use {@link android.provider.Settings.Global#ADB_ENABLED} instead
          */
@@ -5235,6 +5204,8 @@
         @Deprecated
         public static final String ALLOW_MOCK_LOCATION = "mock_location";
 
+        private static final Validator ALLOW_MOCK_LOCATION_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * On Android 8.0 (API level 26) and higher versions of the platform,
          * a 64-bit number (expressed as a hexadecimal string), unique to
@@ -5280,6 +5251,8 @@
         @Deprecated
         public static final String BLUETOOTH_ON = Global.BLUETOOTH_ON;
 
+        private static final Validator BLUETOOTH_ON_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * @deprecated Use {@link android.provider.Settings.Global#DATA_ROAMING} instead
          */
@@ -5327,6 +5300,8 @@
         @TestApi
         public static final String AUTOFILL_SERVICE = "autofill_service";
 
+        private static final Validator AUTOFILL_SERVICE_VALIDATOR = COMPONENT_NAME_VALIDATOR;
+
         /**
          * Boolean indicating if Autofill supports field classification.
          *
@@ -5413,9 +5388,38 @@
          * List of input methods that are currently enabled.  This is a string
          * containing the IDs of all enabled input methods, each ID separated
          * by ':'.
+         *
+         * Format like "ime0;subtype0;subtype1;subtype2:ime1:ime2;subtype0"
+         * where imeId is ComponentName and subtype is int32.
          */
         public static final String ENABLED_INPUT_METHODS = "enabled_input_methods";
 
+        private static final Validator ENABLED_INPUT_METHODS_VALIDATOR = new Validator() {
+            @Override
+            public boolean validate(String value) {
+                if (value == null) {
+                    return false;
+                }
+                String[] inputMethods = value.split(":");
+                boolean valid = true;
+                for (String inputMethod : inputMethods) {
+                    if (inputMethod.length() == 0) {
+                        return false;
+                    }
+                    String[] subparts = inputMethod.split(";");
+                    for (String subpart : subparts) {
+                        // allow either a non negative integer or a ComponentName
+                        valid |= (NON_NEGATIVE_INTEGER_VALIDATOR.validate(subpart)
+                                || COMPONENT_NAME_VALIDATOR.validate(subpart));
+                    }
+                    if (!valid) {
+                        return false;
+                    }
+                }
+                return valid;
+            }
+        };
+
         /**
          * List of system input methods that are currently disabled.  This is a string
          * containing the IDs of all disabled input methods, each ID separated
@@ -5431,6 +5435,8 @@
          */
         public static final String SHOW_IME_WITH_HARD_KEYBOARD = "show_ime_with_hard_keyboard";
 
+        private static final Validator SHOW_IME_WITH_HARD_KEYBOARD_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * Host name and port for global http proxy. Uses ':' seperator for
          * between host and port.
@@ -5707,6 +5713,8 @@
         @Deprecated
         public static final String USB_MASS_STORAGE_ENABLED = Global.USB_MASS_STORAGE_ENABLED;
 
+        private static final Validator USB_MASS_STORAGE_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * @deprecated Use {@link android.provider.Settings.Global#USE_GOOGLE_MAIL} instead
          */
@@ -5718,6 +5726,8 @@
          */
         public static final String ACCESSIBILITY_ENABLED = "accessibility_enabled";
 
+        private static final Validator ACCESSIBILITY_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * Setting specifying if the accessibility shortcut is enabled.
          * @hide
@@ -5725,6 +5735,8 @@
         public static final String ACCESSIBILITY_SHORTCUT_ENABLED =
                 "accessibility_shortcut_enabled";
 
+        private static final Validator ACCESSIBILITY_SHORTCUT_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * Setting specifying if the accessibility shortcut is enabled.
          * @hide
@@ -5732,6 +5744,9 @@
         public static final String ACCESSIBILITY_SHORTCUT_ON_LOCK_SCREEN =
                 "accessibility_shortcut_on_lock_screen";
 
+        private static final Validator ACCESSIBILITY_SHORTCUT_ON_LOCK_SCREEN_VALIDATOR =
+                BOOLEAN_VALIDATOR;
+
         /**
          * Setting specifying if the accessibility shortcut dialog has been shown to this user.
          * @hide
@@ -5739,6 +5754,9 @@
         public static final String ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN =
                 "accessibility_shortcut_dialog_shown";
 
+        private static final Validator ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN_VALIDATOR =
+                BOOLEAN_VALIDATOR;
+
         /**
          * Setting specifying the accessibility service to be toggled via the accessibility
          * shortcut. Must be its flattened {@link ComponentName}.
@@ -5747,6 +5765,9 @@
         public static final String ACCESSIBILITY_SHORTCUT_TARGET_SERVICE =
                 "accessibility_shortcut_target_service";
 
+        private static final Validator ACCESSIBILITY_SHORTCUT_TARGET_SERVICE_VALIDATOR =
+                COMPONENT_NAME_VALIDATOR;
+
         /**
          * Setting specifying the accessibility service or feature to be toggled via the
          * accessibility button in the navigation bar. This is either a flattened
@@ -5757,17 +5778,32 @@
         public static final String ACCESSIBILITY_BUTTON_TARGET_COMPONENT =
                 "accessibility_button_target_component";
 
+        private static final Validator ACCESSIBILITY_BUTTON_TARGET_COMPONENT_VALIDATOR =
+                new Validator() {
+                    @Override
+                    public boolean validate(String value) {
+                        // technically either ComponentName or class name, but there's proper value
+                        // validation at callsites, so allow any non-null string
+                        return value != null;
+                    }
+                };
+
         /**
          * If touch exploration is enabled.
          */
         public static final String TOUCH_EXPLORATION_ENABLED = "touch_exploration_enabled";
 
+        private static final Validator TOUCH_EXPLORATION_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * List of the enabled accessibility providers.
          */
         public static final String ENABLED_ACCESSIBILITY_SERVICES =
             "enabled_accessibility_services";
 
+        private static final Validator ENABLED_ACCESSIBILITY_SERVICES_VALIDATOR =
+                new SettingsValidators.ComponentNameListValidator(":");
+
         /**
          * List of the accessibility services to which the user has granted
          * permission to put the device into touch exploration mode.
@@ -5777,6 +5813,9 @@
         public static final String TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES =
             "touch_exploration_granted_accessibility_services";
 
+        private static final Validator TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES_VALIDATOR =
+                new SettingsValidators.ComponentNameListValidator(":");
+
         /**
          * Uri of the slice that's presented on the keyguard.
          * Defaults to a slice with the date and next alarm.
@@ -5795,6 +5834,8 @@
         @Deprecated
         public static final String ACCESSIBILITY_SPEAK_PASSWORD = "speak_password";
 
+        private static final Validator ACCESSIBILITY_SPEAK_PASSWORD_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * Whether to draw text with high contrast while in accessibility mode.
          *
@@ -5803,6 +5844,9 @@
         public static final String ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED =
                 "high_text_contrast_enabled";
 
+        private static final Validator ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED_VALIDATOR =
+                BOOLEAN_VALIDATOR;
+
         /**
          * Setting that specifies whether the display magnification is enabled via a system-wide
          * triple tap gesture. Display magnifications allows the user to zoom in the display content
@@ -5815,6 +5859,9 @@
         public static final String ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED =
                 "accessibility_display_magnification_enabled";
 
+        private static final Validator ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED_VALIDATOR =
+                BOOLEAN_VALIDATOR;
+
         /**
          * Setting that specifies whether the display magnification is enabled via a shortcut
          * affordance within the system's navigation area. Display magnifications allows the user to
@@ -5826,6 +5873,9 @@
         public static final String ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED =
                 "accessibility_display_magnification_navbar_enabled";
 
+        private static final Validator ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED_VALIDATOR
+                = BOOLEAN_VALIDATOR;
+
         /**
          * Setting that specifies what the display magnification scale is.
          * Display magnifications allows the user to zoom in the display
@@ -5839,6 +5889,9 @@
         public static final String ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE =
                 "accessibility_display_magnification_scale";
 
+        private static final Validator ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE_VALIDATOR =
+                new SettingsValidators.InclusiveFloatRangeValidator(1.0f, Float.MAX_VALUE);
+
         /**
          * Unused mangnification setting
          *
@@ -5891,6 +5944,9 @@
         public static final String ACCESSIBILITY_CAPTIONING_ENABLED =
                 "accessibility_captioning_enabled";
 
+        private static final Validator ACCESSIBILITY_CAPTIONING_ENABLED_VALIDATOR =
+                BOOLEAN_VALIDATOR;
+
         /**
          * Setting that specifies the language for captions as a locale string,
          * e.g. en_US.
@@ -5901,6 +5957,8 @@
         public static final String ACCESSIBILITY_CAPTIONING_LOCALE =
                 "accessibility_captioning_locale";
 
+        private static final Validator ACCESSIBILITY_CAPTIONING_LOCALE_VALIDATOR = LOCALE_VALIDATOR;
+
         /**
          * Integer property that specifies the preset style for captions, one
          * of:
@@ -5915,6 +5973,10 @@
         public static final String ACCESSIBILITY_CAPTIONING_PRESET =
                 "accessibility_captioning_preset";
 
+        private static final Validator ACCESSIBILITY_CAPTIONING_PRESET_VALIDATOR =
+                new SettingsValidators.DiscreteValueValidator(new String[]{"-1", "0", "1", "2",
+                        "3", "4"});
+
         /**
          * Integer property that specifes the background color for captions as a
          * packed 32-bit color.
@@ -5925,6 +5987,9 @@
         public static final String ACCESSIBILITY_CAPTIONING_BACKGROUND_COLOR =
                 "accessibility_captioning_background_color";
 
+        private static final Validator ACCESSIBILITY_CAPTIONING_BACKGROUND_COLOR_VALIDATOR =
+                ANY_INTEGER_VALIDATOR;
+
         /**
          * Integer property that specifes the foreground color for captions as a
          * packed 32-bit color.
@@ -5935,6 +6000,9 @@
         public static final String ACCESSIBILITY_CAPTIONING_FOREGROUND_COLOR =
                 "accessibility_captioning_foreground_color";
 
+        private static final Validator ACCESSIBILITY_CAPTIONING_FOREGROUND_COLOR_VALIDATOR =
+                ANY_INTEGER_VALIDATOR;
+
         /**
          * Integer property that specifes the edge type for captions, one of:
          * <ul>
@@ -5949,6 +6017,9 @@
         public static final String ACCESSIBILITY_CAPTIONING_EDGE_TYPE =
                 "accessibility_captioning_edge_type";
 
+        private static final Validator ACCESSIBILITY_CAPTIONING_EDGE_TYPE_VALIDATOR =
+                new SettingsValidators.DiscreteValueValidator(new String[]{"0", "1", "2"});
+
         /**
          * Integer property that specifes the edge color for captions as a
          * packed 32-bit color.
@@ -5960,6 +6031,9 @@
         public static final String ACCESSIBILITY_CAPTIONING_EDGE_COLOR =
                 "accessibility_captioning_edge_color";
 
+        private static final Validator ACCESSIBILITY_CAPTIONING_EDGE_COLOR_VALIDATOR =
+                ANY_INTEGER_VALIDATOR;
+
         /**
          * Integer property that specifes the window color for captions as a
          * packed 32-bit color.
@@ -5970,6 +6044,9 @@
         public static final String ACCESSIBILITY_CAPTIONING_WINDOW_COLOR =
                 "accessibility_captioning_window_color";
 
+        private static final Validator ACCESSIBILITY_CAPTIONING_WINDOW_COLOR_VALIDATOR =
+                ANY_INTEGER_VALIDATOR;
+
         /**
          * String property that specifies the typeface for captions, one of:
          * <ul>
@@ -5985,6 +6062,10 @@
         public static final String ACCESSIBILITY_CAPTIONING_TYPEFACE =
                 "accessibility_captioning_typeface";
 
+        private static final Validator ACCESSIBILITY_CAPTIONING_TYPEFACE_VALIDATOR =
+                new SettingsValidators.DiscreteValueValidator(new String[]{"DEFAULT",
+                        "MONOSPACE", "SANS_SERIF", "SERIF"});
+
         /**
          * Floating point property that specifies font scaling for captions.
          *
@@ -5993,12 +6074,18 @@
         public static final String ACCESSIBILITY_CAPTIONING_FONT_SCALE =
                 "accessibility_captioning_font_scale";
 
+        private static final Validator ACCESSIBILITY_CAPTIONING_FONT_SCALE_VALIDATOR =
+                new SettingsValidators.InclusiveFloatRangeValidator(0.5f, 2.0f);
+
         /**
          * Setting that specifies whether display color inversion is enabled.
          */
         public static final String ACCESSIBILITY_DISPLAY_INVERSION_ENABLED =
                 "accessibility_display_inversion_enabled";
 
+        private static final Validator ACCESSIBILITY_DISPLAY_INVERSION_ENABLED_VALIDATOR =
+                BOOLEAN_VALIDATOR;
+
         /**
          * Setting that specifies whether display color space adjustment is
          * enabled.
@@ -6008,15 +6095,24 @@
         public static final String ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED =
                 "accessibility_display_daltonizer_enabled";
 
+        private static final Validator ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED_VALIDATOR =
+                BOOLEAN_VALIDATOR;
+
         /**
          * Integer property that specifies the type of color space adjustment to
-         * perform. Valid values are defined in AccessibilityManager.
+         * perform. Valid values are defined in AccessibilityManager:
+         * - AccessibilityManager.DALTONIZER_DISABLED = -1
+         * - AccessibilityManager.DALTONIZER_SIMULATE_MONOCHROMACY = 0
+         * - AccessibilityManager.DALTONIZER_CORRECT_DEUTERANOMALY = 12
          *
          * @hide
          */
         public static final String ACCESSIBILITY_DISPLAY_DALTONIZER =
                 "accessibility_display_daltonizer";
 
+        private static final Validator ACCESSIBILITY_DISPLAY_DALTONIZER_VALIDATOR =
+                new SettingsValidators.DiscreteValueValidator(new String[] {"-1", "0", "12"});
+
         /**
          * Setting that specifies whether automatic click when the mouse pointer stops moving is
          * enabled.
@@ -6026,6 +6122,9 @@
         public static final String ACCESSIBILITY_AUTOCLICK_ENABLED =
                 "accessibility_autoclick_enabled";
 
+        private static final Validator ACCESSIBILITY_AUTOCLICK_ENABLED_VALIDATOR =
+                BOOLEAN_VALIDATOR;
+
         /**
          * Integer setting specifying amount of time in ms the mouse pointer has to stay still
          * before performing click when {@link #ACCESSIBILITY_AUTOCLICK_ENABLED} is set.
@@ -6036,6 +6135,9 @@
         public static final String ACCESSIBILITY_AUTOCLICK_DELAY =
                 "accessibility_autoclick_delay";
 
+        private static final Validator ACCESSIBILITY_AUTOCLICK_DELAY_VALIDATOR =
+                NON_NEGATIVE_INTEGER_VALIDATOR;
+
         /**
          * Whether or not larger size icons are used for the pointer of mouse/trackpad for
          * accessibility.
@@ -6045,12 +6147,18 @@
         public static final String ACCESSIBILITY_LARGE_POINTER_ICON =
                 "accessibility_large_pointer_icon";
 
+        private static final Validator ACCESSIBILITY_LARGE_POINTER_ICON_VALIDATOR =
+                BOOLEAN_VALIDATOR;
+
         /**
          * The timeout for considering a press to be a long press in milliseconds.
          * @hide
          */
         public static final String LONG_PRESS_TIMEOUT = "long_press_timeout";
 
+        private static final Validator LONG_PRESS_TIMEOUT_VALIDATOR =
+                NON_NEGATIVE_INTEGER_VALIDATOR;
+
         /**
          * The duration in milliseconds between the first tap's up event and the second tap's
          * down event for an interaction to be considered part of the same multi-press.
@@ -6104,16 +6212,22 @@
          */
         public static final String TTS_DEFAULT_RATE = "tts_default_rate";
 
+        private static final Validator TTS_DEFAULT_RATE_VALIDATOR = NON_NEGATIVE_INTEGER_VALIDATOR;
+
         /**
          * Default text-to-speech engine pitch. 100 = 1x
          */
         public static final String TTS_DEFAULT_PITCH = "tts_default_pitch";
 
+        private static final Validator TTS_DEFAULT_PITCH_VALIDATOR = NON_NEGATIVE_INTEGER_VALIDATOR;
+
         /**
          * Default text-to-speech engine.
          */
         public static final String TTS_DEFAULT_SYNTH = "tts_default_synth";
 
+        private static final Validator TTS_DEFAULT_SYNTH_VALIDATOR = PACKAGE_NAME_VALIDATOR;
+
         /**
          * Default text-to-speech language.
          *
@@ -6161,11 +6275,33 @@
          */
         public static final String TTS_DEFAULT_LOCALE = "tts_default_locale";
 
+        private static final Validator TTS_DEFAULT_LOCALE_VALIDATOR = new Validator() {
+            @Override
+            public boolean validate(String value) {
+                if (value == null || value.length() == 0) {
+                    return false;
+                }
+                String[] ttsLocales = value.split(",");
+                boolean valid = true;
+                for (String ttsLocale : ttsLocales) {
+                    String[] parts = ttsLocale.split(":");
+                    valid |= ((parts.length == 2)
+                            && (parts[0].length() > 0)
+                            && ANY_STRING_VALIDATOR.validate(parts[0])
+                            && LOCALE_VALIDATOR.validate(parts[1]));
+                }
+                return valid;
+            }
+        };
+
         /**
          * Space delimited list of plugin packages that are enabled.
          */
         public static final String TTS_ENABLED_PLUGINS = "tts_enabled_plugins";
 
+        private static final Validator TTS_ENABLED_PLUGINS_VALIDATOR =
+                new SettingsValidators.PackageNameListValidator(" ");
+
         /**
          * @deprecated Use {@link android.provider.Settings.Global#WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON}
          * instead.
@@ -6174,6 +6310,9 @@
         public static final String WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON =
                 Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON;
 
+        private static final Validator WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON_VALIDATOR =
+                BOOLEAN_VALIDATOR;
+
         /**
          * @deprecated Use {@link android.provider.Settings.Global#WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY}
          * instead.
@@ -6182,6 +6321,9 @@
         public static final String WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY =
                 Global.WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY;
 
+        private static final Validator WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY_VALIDATOR =
+                NON_NEGATIVE_INTEGER_VALIDATOR;
+
         /**
          * @deprecated Use {@link android.provider.Settings.Global#WIFI_NUM_OPEN_NETWORKS_KEPT}
          * instead.
@@ -6190,6 +6332,9 @@
         public static final String WIFI_NUM_OPEN_NETWORKS_KEPT =
                 Global.WIFI_NUM_OPEN_NETWORKS_KEPT;
 
+        private static final Validator WIFI_NUM_OPEN_NETWORKS_KEPT_VALIDATOR =
+                NON_NEGATIVE_INTEGER_VALIDATOR;
+
         /**
          * @deprecated Use {@link android.provider.Settings.Global#WIFI_ON}
          * instead.
@@ -6348,6 +6493,9 @@
         public static final String PREFERRED_TTY_MODE =
                 "preferred_tty_mode";
 
+        private static final Validator PREFERRED_TTY_MODE_VALIDATOR =
+                new SettingsValidators.DiscreteValueValidator(new String[]{"0", "1", "2", "3"});
+
         /**
          * Whether the enhanced voice privacy mode is enabled.
          * 0 = normal voice privacy
@@ -6356,6 +6504,8 @@
          */
         public static final String ENHANCED_VOICE_PRIVACY_ENABLED = "enhanced_voice_privacy_enabled";
 
+        private static final Validator ENHANCED_VOICE_PRIVACY_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * Whether the TTY mode mode is enabled.
          * 0 = disabled
@@ -6364,6 +6514,8 @@
          */
         public static final String TTY_MODE_ENABLED = "tty_mode_enabled";
 
+        private static final Validator TTY_MODE_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * Controls whether settings backup is enabled.
          * Type: int ( 0 = disabled, 1 = enabled )
@@ -6534,24 +6686,32 @@
          */
         public static final String MOUNT_PLAY_NOTIFICATION_SND = "mount_play_not_snd";
 
+        private static final Validator MOUNT_PLAY_NOTIFICATION_SND_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * Whether or not UMS auto-starts on UMS host detection. (0 = false, 1 = true)
          * @hide
          */
         public static final String MOUNT_UMS_AUTOSTART = "mount_ums_autostart";
 
+        private static final Validator MOUNT_UMS_AUTOSTART_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * Whether or not a notification is displayed on UMS host detection. (0 = false, 1 = true)
          * @hide
          */
         public static final String MOUNT_UMS_PROMPT = "mount_ums_prompt";
 
+        private static final Validator MOUNT_UMS_PROMPT_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * Whether or not a notification is displayed while UMS is enabled. (0 = false, 1 = true)
          * @hide
          */
         public static final String MOUNT_UMS_NOTIFY_ENABLED = "mount_ums_notify_enabled";
 
+        private static final Validator MOUNT_UMS_NOTIFY_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * If nonzero, ANRs in invisible background processes bring up a dialog.
          * Otherwise, the process will be silently killed.
@@ -6569,6 +6729,9 @@
         public static final String SHOW_FIRST_CRASH_DIALOG_DEV_OPTION =
                 "show_first_crash_dialog_dev_option";
 
+        private static final Validator SHOW_FIRST_CRASH_DIALOG_DEV_OPTION_VALIDATOR =
+                BOOLEAN_VALIDATOR;
+
         /**
          * The {@link ComponentName} string of the service to be used as the voice recognition
          * service.
@@ -6594,6 +6757,8 @@
          */
         public static final String SELECTED_SPELL_CHECKER = "selected_spell_checker";
 
+        private static final Validator SELECTED_SPELL_CHECKER_VALIDATOR = COMPONENT_NAME_VALIDATOR;
+
         /**
          * The {@link ComponentName} string of the selected subtype of the selected spell checker
          * service which is one of the services managed by the text service manager.
@@ -6603,13 +6768,18 @@
         public static final String SELECTED_SPELL_CHECKER_SUBTYPE =
                 "selected_spell_checker_subtype";
 
+        private static final Validator SELECTED_SPELL_CHECKER_SUBTYPE_VALIDATOR =
+                COMPONENT_NAME_VALIDATOR;
+
         /**
-         * The {@link ComponentName} string whether spell checker is enabled or not.
+         * Whether spell checker is enabled or not.
          *
          * @hide
          */
         public static final String SPELL_CHECKER_ENABLED = "spell_checker_enabled";
 
+        private static final Validator SPELL_CHECKER_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * What happens when the user presses the Power button while in-call
          * and the screen is on.<br/>
@@ -6621,6 +6791,9 @@
          */
         public static final String INCALL_POWER_BUTTON_BEHAVIOR = "incall_power_button_behavior";
 
+        private static final Validator INCALL_POWER_BUTTON_BEHAVIOR_VALIDATOR =
+                new SettingsValidators.DiscreteValueValidator(new String[]{"1", "2"});
+
         /**
          * INCALL_POWER_BUTTON_BEHAVIOR value for "turn off screen".
          * @hide
@@ -6676,12 +6849,16 @@
          */
         public static final String WAKE_GESTURE_ENABLED = "wake_gesture_enabled";
 
+        private static final Validator WAKE_GESTURE_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * Whether the device should doze if configured.
          * @hide
          */
         public static final String DOZE_ENABLED = "doze_enabled";
 
+        private static final Validator DOZE_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * Whether doze should be always on.
          * @hide
@@ -6694,6 +6871,8 @@
          */
         public static final String DOZE_PULSE_ON_PICK_UP = "doze_pulse_on_pick_up";
 
+        private static final Validator DOZE_PULSE_ON_PICK_UP_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * Whether the device should pulse on long press gesture.
          * @hide
@@ -6706,6 +6885,8 @@
          */
         public static final String DOZE_PULSE_ON_DOUBLE_TAP = "doze_pulse_on_double_tap";
 
+        private static final Validator DOZE_PULSE_ON_DOUBLE_TAP_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * The current night mode that has been selected by the user.  Owned
          * and controlled by UiModeManagerService.  Constants are as per
@@ -6720,6 +6901,8 @@
          */
         public static final String SCREENSAVER_ENABLED = "screensaver_enabled";
 
+        private static final Validator SCREENSAVER_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * The user's chosen screensaver components.
          *
@@ -6729,6 +6912,9 @@
          */
         public static final String SCREENSAVER_COMPONENTS = "screensaver_components";
 
+        private static final Validator SCREENSAVER_COMPONENTS_VALIDATOR =
+                new SettingsValidators.ComponentNameListValidator(",");
+
         /**
          * If screensavers are enabled, whether the screensaver should be automatically launched
          * when the device is inserted into a (desk) dock.
@@ -6736,6 +6922,8 @@
          */
         public static final String SCREENSAVER_ACTIVATE_ON_DOCK = "screensaver_activate_on_dock";
 
+        private static final Validator SCREENSAVER_ACTIVATE_ON_DOCK_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * If screensavers are enabled, whether the screensaver should be automatically launched
          * when the screen times out when not on battery.
@@ -6743,6 +6931,8 @@
          */
         public static final String SCREENSAVER_ACTIVATE_ON_SLEEP = "screensaver_activate_on_sleep";
 
+        private static final Validator SCREENSAVER_ACTIVATE_ON_SLEEP_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * If screensavers are enabled, the default screensaver component.
          * @hide
@@ -6755,6 +6945,9 @@
          */
         public static final String NFC_PAYMENT_DEFAULT_COMPONENT = "nfc_payment_default_component";
 
+        private static final Validator NFC_PAYMENT_DEFAULT_COMPONENT_VALIDATOR =
+                COMPONENT_NAME_VALIDATOR;
+
         /**
          * Whether NFC payment is handled by the foreground application or a default.
          * @hide
@@ -6852,6 +7045,9 @@
         public static final String ENABLED_NOTIFICATION_ASSISTANT =
                 "enabled_notification_assistant";
 
+        private static final Validator ENABLED_NOTIFICATION_ASSISTANT_VALIDATOR =
+                new SettingsValidators.ComponentNameListValidator(":");
+
         /**
          * Read only list of the service components that the current user has explicitly allowed to
          * see all of the user's notifications, separated by ':'.
@@ -6863,6 +7059,9 @@
         @Deprecated
         public static final String ENABLED_NOTIFICATION_LISTENERS = "enabled_notification_listeners";
 
+        private static final Validator ENABLED_NOTIFICATION_LISTENERS_VALIDATOR =
+                new SettingsValidators.ComponentNameListValidator(":");
+
         /**
          * Read only list of the packages that the current user has explicitly allowed to
          * manage do not disturb, separated by ':'.
@@ -6875,6 +7074,9 @@
         public static final String ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES =
                 "enabled_notification_policy_access_packages";
 
+        private static final Validator ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES_VALIDATOR =
+                new SettingsValidators.PackageNameListValidator(":");
+
         /**
          * Defines whether managed profile ringtones should be synced from it's parent profile
          * <p>
@@ -6888,6 +7090,8 @@
         @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
         public static final String SYNC_PARENT_SOUNDS = "sync_parent_sounds";
 
+        private static final Validator SYNC_PARENT_SOUNDS_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /** @hide */
         public static final String IMMERSIVE_MODE_CONFIRMATIONS = "immersive_mode_confirmations";
 
@@ -6974,12 +7178,17 @@
          */
         public static final String SLEEP_TIMEOUT = "sleep_timeout";
 
+        private static final Validator SLEEP_TIMEOUT_VALIDATOR =
+                new SettingsValidators.InclusiveIntegerRangeValidator(-1, Integer.MAX_VALUE);
+
         /**
          * Controls whether double tap to wake is enabled.
          * @hide
          */
         public static final String DOUBLE_TAP_TO_WAKE = "double_tap_to_wake";
 
+        private static final Validator DOUBLE_TAP_TO_WAKE_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * The current assistant component. It could be a voice interaction service,
          * or an activity that handles ACTION_ASSIST, or empty which means using the default
@@ -6996,6 +7205,8 @@
          */
         public static final String CAMERA_GESTURE_DISABLED = "camera_gesture_disabled";
 
+        private static final Validator CAMERA_GESTURE_DISABLED_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * Whether the camera launch gesture to double tap the power button when the screen is off
          * should be disabled.
@@ -7005,6 +7216,9 @@
         public static final String CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED =
                 "camera_double_tap_power_gesture_disabled";
 
+        private static final Validator CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED_VALIDATOR =
+                BOOLEAN_VALIDATOR;
+
         /**
          * Whether the camera double twist gesture to flip between front and back mode should be
          * enabled.
@@ -7014,6 +7228,9 @@
         public static final String CAMERA_DOUBLE_TWIST_TO_FLIP_ENABLED =
                 "camera_double_twist_to_flip_enabled";
 
+        private static final Validator CAMERA_DOUBLE_TWIST_TO_FLIP_ENABLED_VALIDATOR =
+                BOOLEAN_VALIDATOR;
+
         /**
          * Whether or not the smart camera lift trigger that launches the camera when the user moves
          * the phone into a position for taking photos should be enabled.
@@ -7036,6 +7253,9 @@
          */
         public static final String ASSIST_GESTURE_ENABLED = "assist_gesture_enabled";
 
+        private static final Validator ASSIST_GESTURE_ENABLED_VALIDATOR =
+                BOOLEAN_VALIDATOR;
+
         /**
          * Sensitivity control for the assist gesture.
          *
@@ -7043,6 +7263,9 @@
          */
         public static final String ASSIST_GESTURE_SENSITIVITY = "assist_gesture_sensitivity";
 
+        private static final Validator ASSIST_GESTURE_SENSITIVITY_VALIDATOR =
+                new SettingsValidators.InclusiveFloatRangeValidator(0.0f, 1.0f);
+
         /**
          * Whether the assist gesture should silence alerts.
          *
@@ -7051,6 +7274,9 @@
         public static final String ASSIST_GESTURE_SILENCE_ALERTS_ENABLED =
                 "assist_gesture_silence_alerts_enabled";
 
+        private static final Validator ASSIST_GESTURE_SILENCE_ALERTS_ENABLED_VALIDATOR =
+                BOOLEAN_VALIDATOR;
+
         /**
          * Whether the assist gesture should wake the phone.
          *
@@ -7059,6 +7285,9 @@
         public static final String ASSIST_GESTURE_WAKE_ENABLED =
                 "assist_gesture_wake_enabled";
 
+        private static final Validator ASSIST_GESTURE_WAKE_ENABLED_VALIDATOR =
+                BOOLEAN_VALIDATOR;
+
         /**
          * Whether Assist Gesture Deferred Setup has been completed
          *
@@ -7066,6 +7295,8 @@
          */
         public static final String ASSIST_GESTURE_SETUP_COMPLETE = "assist_gesture_setup_complete";
 
+        private static final Validator ASSIST_GESTURE_SETUP_COMPLETE_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * Control whether Night display is currently activated.
          * @hide
@@ -7078,6 +7309,8 @@
          */
         public static final String NIGHT_DISPLAY_AUTO_MODE = "night_display_auto_mode";
 
+        private static final Validator NIGHT_DISPLAY_AUTO_MODE_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * Control the color temperature of Night Display, represented in Kelvin.
          * @hide
@@ -7085,6 +7318,9 @@
         public static final String NIGHT_DISPLAY_COLOR_TEMPERATURE =
                 "night_display_color_temperature";
 
+        private static final Validator NIGHT_DISPLAY_COLOR_TEMPERATURE_VALIDATOR =
+                NON_NEGATIVE_INTEGER_VALIDATOR;
+
         /**
          * Custom time when Night display is scheduled to activate.
          * Represented as milliseconds from midnight (e.g. 79200000 == 10pm).
@@ -7093,6 +7329,9 @@
         public static final String NIGHT_DISPLAY_CUSTOM_START_TIME =
                 "night_display_custom_start_time";
 
+        private static final Validator NIGHT_DISPLAY_CUSTOM_START_TIME_VALIDATOR =
+                NON_NEGATIVE_INTEGER_VALIDATOR;
+
         /**
          * Custom time when Night display is scheduled to deactivate.
          * Represented as milliseconds from midnight (e.g. 21600000 == 6am).
@@ -7100,6 +7339,9 @@
          */
         public static final String NIGHT_DISPLAY_CUSTOM_END_TIME = "night_display_custom_end_time";
 
+        private static final Validator NIGHT_DISPLAY_CUSTOM_END_TIME_VALIDATOR =
+                NON_NEGATIVE_INTEGER_VALIDATOR;
+
         /**
          * A String representing the LocalDateTime when Night display was last activated. Use to
          * decide whether to apply the current activated state after a reboot or user change. In
@@ -7117,6 +7359,9 @@
          */
         public static final String ENABLED_VR_LISTENERS = "enabled_vr_listeners";
 
+        private static final Validator ENABLED_VR_LISTENERS_VALIDATOR =
+                new SettingsValidators.ComponentNameListValidator(":");
+
         /**
          * Behavior of the display while in VR mode.
          *
@@ -7126,6 +7371,9 @@
          */
         public static final String VR_DISPLAY_MODE = "vr_display_mode";
 
+        private static final Validator VR_DISPLAY_MODE_VALIDATOR =
+                new SettingsValidators.DiscreteValueValidator(new String[]{"0", "1"});
+
         /**
          * Lower the display persistence while the system is in VR mode.
          *
@@ -7182,6 +7430,9 @@
         public static final String AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN =
                 "automatic_storage_manager_days_to_retain";
 
+        private static final Validator AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN_VALIDATOR =
+                NON_NEGATIVE_INTEGER_VALIDATOR;
+
         /**
          * Default number of days of information for the automatic storage manager to retain.
          *
@@ -7223,12 +7474,30 @@
         public static final String SYSTEM_NAVIGATION_KEYS_ENABLED =
                 "system_navigation_keys_enabled";
 
+        private static final Validator SYSTEM_NAVIGATION_KEYS_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * Holds comma separated list of ordering of QS tiles.
          * @hide
          */
         public static final String QS_TILES = "sysui_qs_tiles";
 
+        private static final Validator QS_TILES_VALIDATOR = new Validator() {
+            @Override
+            public boolean validate(String value) {
+                if (value == null) {
+                    return false;
+                }
+                String[] tiles = value.split(",");
+                boolean valid = true;
+                for (String tile : tiles) {
+                    // tile can be any non-empty string as specified by OEM
+                    valid |= ((tile.length() > 0) && ANY_STRING_VALIDATOR.validate(tile));
+                }
+                return valid;
+            }
+        };
+
         /**
          * Specifies whether the web action API is enabled.
          *
@@ -7264,18 +7533,38 @@
          */
         public static final String NOTIFICATION_BADGING = "notification_badging";
 
+        private static final Validator NOTIFICATION_BADGING_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * Comma separated list of QS tiles that have been auto-added already.
          * @hide
          */
         public static final String QS_AUTO_ADDED_TILES = "qs_auto_tiles";
 
+        private static final Validator QS_AUTO_ADDED_TILES_VALIDATOR = new Validator() {
+            @Override
+            public boolean validate(String value) {
+                if (value == null) {
+                    return false;
+                }
+                String[] tiles = value.split(",");
+                boolean valid = true;
+                for (String tile : tiles) {
+                    // tile can be any non-empty string as specified by OEM
+                    valid |= ((tile.length() > 0) && ANY_STRING_VALIDATOR.validate(tile));
+                }
+                return valid;
+            }
+        };
+
         /**
          * Whether the Lockdown button should be shown in the power menu.
          * @hide
          */
         public static final String LOCKDOWN_IN_POWER_MENU = "lockdown_in_power_menu";
 
+        private static final Validator LOCKDOWN_IN_POWER_MENU_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * Backup manager behavioral parameters.
          * This is encoded as a key=value list, separated by commas. Ex:
@@ -7315,8 +7604,6 @@
         public static final String[] SETTINGS_TO_BACKUP = {
             BUGREPORT_IN_POWER_MENU,                            // moved to global
             ALLOW_MOCK_LOCATION,
-            PARENTAL_CONTROL_ENABLED,
-            PARENTAL_CONTROL_REDIRECT_URL,
             USB_MASS_STORAGE_ENABLED,                           // moved to global
             ACCESSIBILITY_DISPLAY_INVERSION_ENABLED,
             ACCESSIBILITY_DISPLAY_DALTONIZER,
@@ -7348,12 +7635,9 @@
             ACCESSIBILITY_CAPTIONING_TYPEFACE,
             ACCESSIBILITY_CAPTIONING_FONT_SCALE,
             ACCESSIBILITY_CAPTIONING_WINDOW_COLOR,
-            TTS_USE_DEFAULTS,
             TTS_DEFAULT_RATE,
             TTS_DEFAULT_PITCH,
             TTS_DEFAULT_SYNTH,
-            TTS_DEFAULT_LANG,
-            TTS_DEFAULT_COUNTRY,
             TTS_ENABLED_PLUGINS,
             TTS_DEFAULT_LOCALE,
             SHOW_IME_WITH_HARD_KEYBOARD,
@@ -7409,7 +7693,158 @@
             SHOW_FIRST_CRASH_DIALOG_DEV_OPTION,
         };
 
-        /** @hide */
+        /**
+         * All settings in {@link SETTINGS_TO_BACKUP} array *must* have a non-null validator,
+         * otherwise they won't be restored.
+         *
+         * @hide
+         */
+        public static final Map<String, Validator> VALIDATORS = new ArrayMap<>();
+        static {
+            VALIDATORS.put(BUGREPORT_IN_POWER_MENU, BUGREPORT_IN_POWER_MENU_VALIDATOR);
+            VALIDATORS.put(ALLOW_MOCK_LOCATION, ALLOW_MOCK_LOCATION_VALIDATOR);
+            VALIDATORS.put(USB_MASS_STORAGE_ENABLED, USB_MASS_STORAGE_ENABLED_VALIDATOR);
+            VALIDATORS.put(ACCESSIBILITY_DISPLAY_INVERSION_ENABLED,
+                    ACCESSIBILITY_DISPLAY_INVERSION_ENABLED_VALIDATOR);
+            VALIDATORS.put(ACCESSIBILITY_DISPLAY_DALTONIZER,
+                    ACCESSIBILITY_DISPLAY_DALTONIZER_VALIDATOR);
+            VALIDATORS.put(ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED,
+                    ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED_VALIDATOR);
+            VALIDATORS.put(ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED,
+                    ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED_VALIDATOR);
+            VALIDATORS.put(ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED,
+                    ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED_VALIDATOR);
+            VALIDATORS.put(AUTOFILL_SERVICE, AUTOFILL_SERVICE_VALIDATOR);
+            VALIDATORS.put(ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE,
+                    ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE_VALIDATOR);
+            VALIDATORS.put(ENABLED_ACCESSIBILITY_SERVICES,
+                    ENABLED_ACCESSIBILITY_SERVICES_VALIDATOR);
+            VALIDATORS.put(ENABLED_VR_LISTENERS, ENABLED_VR_LISTENERS_VALIDATOR);
+            VALIDATORS.put(ENABLED_INPUT_METHODS, ENABLED_INPUT_METHODS_VALIDATOR);
+            VALIDATORS.put(TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
+                    TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES_VALIDATOR);
+            VALIDATORS.put(TOUCH_EXPLORATION_ENABLED, TOUCH_EXPLORATION_ENABLED_VALIDATOR);
+            VALIDATORS.put(ACCESSIBILITY_ENABLED, ACCESSIBILITY_ENABLED_VALIDATOR);
+            VALIDATORS.put(ACCESSIBILITY_SHORTCUT_TARGET_SERVICE,
+                    ACCESSIBILITY_SHORTCUT_TARGET_SERVICE_VALIDATOR);
+            VALIDATORS.put(ACCESSIBILITY_BUTTON_TARGET_COMPONENT,
+                    ACCESSIBILITY_BUTTON_TARGET_COMPONENT_VALIDATOR);
+            VALIDATORS.put(ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN,
+                    ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN_VALIDATOR);
+            VALIDATORS.put(ACCESSIBILITY_SHORTCUT_ENABLED,
+                    ACCESSIBILITY_SHORTCUT_ENABLED_VALIDATOR);
+            VALIDATORS.put(ACCESSIBILITY_SHORTCUT_ON_LOCK_SCREEN,
+                    ACCESSIBILITY_SHORTCUT_ON_LOCK_SCREEN_VALIDATOR);
+            VALIDATORS.put(ACCESSIBILITY_SPEAK_PASSWORD, ACCESSIBILITY_SPEAK_PASSWORD_VALIDATOR);
+            VALIDATORS.put(ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED,
+                    ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED_VALIDATOR);
+            VALIDATORS.put(ACCESSIBILITY_CAPTIONING_PRESET,
+                    ACCESSIBILITY_CAPTIONING_PRESET_VALIDATOR);
+            VALIDATORS.put(ACCESSIBILITY_CAPTIONING_ENABLED,
+                    ACCESSIBILITY_CAPTIONING_ENABLED_VALIDATOR);
+            VALIDATORS.put(ACCESSIBILITY_CAPTIONING_LOCALE,
+                    ACCESSIBILITY_CAPTIONING_LOCALE_VALIDATOR);
+            VALIDATORS.put(ACCESSIBILITY_CAPTIONING_BACKGROUND_COLOR,
+                    ACCESSIBILITY_CAPTIONING_BACKGROUND_COLOR_VALIDATOR);
+            VALIDATORS.put(ACCESSIBILITY_CAPTIONING_FOREGROUND_COLOR,
+                    ACCESSIBILITY_CAPTIONING_FOREGROUND_COLOR_VALIDATOR);
+            VALIDATORS.put(ACCESSIBILITY_CAPTIONING_EDGE_TYPE,
+                    ACCESSIBILITY_CAPTIONING_EDGE_TYPE_VALIDATOR);
+            VALIDATORS.put(ACCESSIBILITY_CAPTIONING_EDGE_COLOR,
+                    ACCESSIBILITY_CAPTIONING_EDGE_COLOR_VALIDATOR);
+            VALIDATORS.put(ACCESSIBILITY_CAPTIONING_TYPEFACE,
+                    ACCESSIBILITY_CAPTIONING_TYPEFACE_VALIDATOR);
+            VALIDATORS.put(ACCESSIBILITY_CAPTIONING_FONT_SCALE,
+                    ACCESSIBILITY_CAPTIONING_FONT_SCALE_VALIDATOR);
+            VALIDATORS.put(ACCESSIBILITY_CAPTIONING_WINDOW_COLOR,
+                    ACCESSIBILITY_CAPTIONING_WINDOW_COLOR_VALIDATOR);
+            VALIDATORS.put(TTS_DEFAULT_RATE, TTS_DEFAULT_RATE_VALIDATOR);
+            VALIDATORS.put(TTS_DEFAULT_PITCH, TTS_DEFAULT_PITCH_VALIDATOR);
+            VALIDATORS.put(TTS_DEFAULT_SYNTH, TTS_DEFAULT_SYNTH_VALIDATOR);
+            VALIDATORS.put(TTS_ENABLED_PLUGINS, TTS_ENABLED_PLUGINS_VALIDATOR);
+            VALIDATORS.put(TTS_DEFAULT_LOCALE, TTS_DEFAULT_LOCALE_VALIDATOR);
+            VALIDATORS.put(SHOW_IME_WITH_HARD_KEYBOARD, SHOW_IME_WITH_HARD_KEYBOARD_VALIDATOR);
+            VALIDATORS.put(WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON,
+                    WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON_VALIDATOR);
+            VALIDATORS.put(WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY,
+                    WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY_VALIDATOR);
+            VALIDATORS.put(WIFI_NUM_OPEN_NETWORKS_KEPT, WIFI_NUM_OPEN_NETWORKS_KEPT_VALIDATOR);
+            VALIDATORS.put(SELECTED_SPELL_CHECKER, SELECTED_SPELL_CHECKER_VALIDATOR);
+            VALIDATORS.put(SELECTED_SPELL_CHECKER_SUBTYPE,
+                    SELECTED_SPELL_CHECKER_SUBTYPE_VALIDATOR);
+            VALIDATORS.put(SPELL_CHECKER_ENABLED, SPELL_CHECKER_ENABLED_VALIDATOR);
+            VALIDATORS.put(MOUNT_PLAY_NOTIFICATION_SND, MOUNT_PLAY_NOTIFICATION_SND_VALIDATOR);
+            VALIDATORS.put(MOUNT_UMS_AUTOSTART, MOUNT_UMS_AUTOSTART_VALIDATOR);
+            VALIDATORS.put(MOUNT_UMS_PROMPT, MOUNT_UMS_PROMPT_VALIDATOR);
+            VALIDATORS.put(MOUNT_UMS_NOTIFY_ENABLED, MOUNT_UMS_NOTIFY_ENABLED_VALIDATOR);
+            VALIDATORS.put(SLEEP_TIMEOUT, SLEEP_TIMEOUT_VALIDATOR);
+            VALIDATORS.put(DOUBLE_TAP_TO_WAKE, DOUBLE_TAP_TO_WAKE_VALIDATOR);
+            VALIDATORS.put(WAKE_GESTURE_ENABLED, WAKE_GESTURE_ENABLED_VALIDATOR);
+            VALIDATORS.put(LONG_PRESS_TIMEOUT, LONG_PRESS_TIMEOUT_VALIDATOR);
+            VALIDATORS.put(CAMERA_GESTURE_DISABLED, CAMERA_GESTURE_DISABLED_VALIDATOR);
+            VALIDATORS.put(ACCESSIBILITY_AUTOCLICK_ENABLED,
+                    ACCESSIBILITY_AUTOCLICK_ENABLED_VALIDATOR);
+            VALIDATORS.put(ACCESSIBILITY_AUTOCLICK_DELAY, ACCESSIBILITY_AUTOCLICK_DELAY_VALIDATOR);
+            VALIDATORS.put(ACCESSIBILITY_LARGE_POINTER_ICON,
+                    ACCESSIBILITY_LARGE_POINTER_ICON_VALIDATOR);
+            VALIDATORS.put(PREFERRED_TTY_MODE, PREFERRED_TTY_MODE_VALIDATOR);
+            VALIDATORS.put(ENHANCED_VOICE_PRIVACY_ENABLED,
+                    ENHANCED_VOICE_PRIVACY_ENABLED_VALIDATOR);
+            VALIDATORS.put(TTY_MODE_ENABLED, TTY_MODE_ENABLED_VALIDATOR);
+            VALIDATORS.put(INCALL_POWER_BUTTON_BEHAVIOR, INCALL_POWER_BUTTON_BEHAVIOR_VALIDATOR);
+            VALIDATORS.put(NIGHT_DISPLAY_CUSTOM_START_TIME,
+                    NIGHT_DISPLAY_CUSTOM_START_TIME_VALIDATOR);
+            VALIDATORS.put(NIGHT_DISPLAY_CUSTOM_END_TIME, NIGHT_DISPLAY_CUSTOM_END_TIME_VALIDATOR);
+            VALIDATORS.put(NIGHT_DISPLAY_COLOR_TEMPERATURE,
+                    NIGHT_DISPLAY_COLOR_TEMPERATURE_VALIDATOR);
+            VALIDATORS.put(NIGHT_DISPLAY_AUTO_MODE, NIGHT_DISPLAY_AUTO_MODE_VALIDATOR);
+            VALIDATORS.put(SYNC_PARENT_SOUNDS, SYNC_PARENT_SOUNDS_VALIDATOR);
+            VALIDATORS.put(CAMERA_DOUBLE_TWIST_TO_FLIP_ENABLED,
+                    CAMERA_DOUBLE_TWIST_TO_FLIP_ENABLED_VALIDATOR);
+            VALIDATORS.put(CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED,
+                    CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED_VALIDATOR);
+            VALIDATORS.put(SYSTEM_NAVIGATION_KEYS_ENABLED,
+                    SYSTEM_NAVIGATION_KEYS_ENABLED_VALIDATOR);
+            VALIDATORS.put(QS_TILES, QS_TILES_VALIDATOR);
+            VALIDATORS.put(DOZE_ENABLED, DOZE_ENABLED_VALIDATOR);
+            VALIDATORS.put(DOZE_PULSE_ON_PICK_UP, DOZE_PULSE_ON_PICK_UP_VALIDATOR);
+            VALIDATORS.put(DOZE_PULSE_ON_DOUBLE_TAP, DOZE_PULSE_ON_DOUBLE_TAP_VALIDATOR);
+            VALIDATORS.put(NFC_PAYMENT_DEFAULT_COMPONENT, NFC_PAYMENT_DEFAULT_COMPONENT_VALIDATOR);
+            VALIDATORS.put(AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN,
+                    AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN_VALIDATOR);
+            VALIDATORS.put(ASSIST_GESTURE_ENABLED, ASSIST_GESTURE_ENABLED_VALIDATOR);
+            VALIDATORS.put(ASSIST_GESTURE_SENSITIVITY, ASSIST_GESTURE_SENSITIVITY_VALIDATOR);
+            VALIDATORS.put(ASSIST_GESTURE_SETUP_COMPLETE, ASSIST_GESTURE_SETUP_COMPLETE_VALIDATOR);
+            VALIDATORS.put(ASSIST_GESTURE_SILENCE_ALERTS_ENABLED,
+                    ASSIST_GESTURE_SILENCE_ALERTS_ENABLED_VALIDATOR);
+            VALIDATORS.put(ASSIST_GESTURE_WAKE_ENABLED, ASSIST_GESTURE_WAKE_ENABLED_VALIDATOR);
+            VALIDATORS.put(VR_DISPLAY_MODE, VR_DISPLAY_MODE_VALIDATOR);
+            VALIDATORS.put(NOTIFICATION_BADGING, NOTIFICATION_BADGING_VALIDATOR);
+            VALIDATORS.put(QS_AUTO_ADDED_TILES, QS_AUTO_ADDED_TILES_VALIDATOR);
+            VALIDATORS.put(SCREENSAVER_ENABLED, SCREENSAVER_ENABLED_VALIDATOR);
+            VALIDATORS.put(SCREENSAVER_COMPONENTS, SCREENSAVER_COMPONENTS_VALIDATOR);
+            VALIDATORS.put(SCREENSAVER_ACTIVATE_ON_DOCK, SCREENSAVER_ACTIVATE_ON_DOCK_VALIDATOR);
+            VALIDATORS.put(SCREENSAVER_ACTIVATE_ON_SLEEP, SCREENSAVER_ACTIVATE_ON_SLEEP_VALIDATOR);
+            VALIDATORS.put(LOCKDOWN_IN_POWER_MENU, LOCKDOWN_IN_POWER_MENU_VALIDATOR);
+            VALIDATORS.put(SHOW_FIRST_CRASH_DIALOG_DEV_OPTION,
+                    SHOW_FIRST_CRASH_DIALOG_DEV_OPTION_VALIDATOR);
+            VALIDATORS.put(ENABLED_NOTIFICATION_LISTENERS,
+                    ENABLED_NOTIFICATION_LISTENERS_VALIDATOR); //legacy restore setting
+            VALIDATORS.put(ENABLED_NOTIFICATION_ASSISTANT,
+                    ENABLED_NOTIFICATION_ASSISTANT_VALIDATOR); //legacy restore setting
+            VALIDATORS.put(ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES,
+                    ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES_VALIDATOR); //legacy restore setting
+        }
+
+        /**
+         * Keys we no longer back up under the current schema, but want to continue to
+         * process when restoring historical backup datasets.
+         *
+         * All settings in {@link LEGACY_RESTORE_SETTINGS} array *must* have a non-null validator,
+         * otherwise they won't be restored.
+         *
+         * @hide
+         */
         public static final String[] LEGACY_RESTORE_SETTINGS = {
                 ENABLED_NOTIFICATION_LISTENERS,
                 ENABLED_NOTIFICATION_ASSISTANT,
@@ -7805,12 +8240,16 @@
          */
         public static final String AUTO_TIME = "auto_time";
 
+        private static final Validator AUTO_TIME_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * Value to specify if the user prefers the time zone
          * to be automatically fetched from the network (NITZ). 1=yes, 0=no
          */
         public static final String AUTO_TIME_ZONE = "auto_time_zone";
 
+        private static final Validator AUTO_TIME_ZONE_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * URI for the car dock "in" event sound.
          * @hide
@@ -7841,6 +8280,8 @@
          */
         public static final String DOCK_SOUNDS_ENABLED = "dock_sounds_enabled";
 
+        private static final Validator DOCK_SOUNDS_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * Whether to play a sound for dock events, only when an accessibility service is on.
          * @hide
@@ -7878,6 +8319,8 @@
          */
         public static final String POWER_SOUNDS_ENABLED = "power_sounds_enabled";
 
+        private static final Validator POWER_SOUNDS_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * URI for the "wireless charging started" sound.
          * @hide
@@ -7891,6 +8334,8 @@
          */
         public static final String CHARGING_SOUNDS_ENABLED = "charging_sounds_enabled";
 
+        private static final Validator CHARGING_SOUNDS_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * Whether we keep the device on while the device is plugged in.
          * Supported values are:
@@ -7904,6 +8349,30 @@
          */
         public static final String STAY_ON_WHILE_PLUGGED_IN = "stay_on_while_plugged_in";
 
+        private static final Validator STAY_ON_WHILE_PLUGGED_IN_VALIDATOR = new Validator() {
+            @Override
+            public boolean validate(String value) {
+                try {
+                    int val = Integer.parseInt(value);
+                    return (val == 0)
+                            || (val == BatteryManager.BATTERY_PLUGGED_AC)
+                            || (val == BatteryManager.BATTERY_PLUGGED_USB)
+                            || (val == BatteryManager.BATTERY_PLUGGED_WIRELESS)
+                            || (val == (BatteryManager.BATTERY_PLUGGED_AC
+                                    | BatteryManager.BATTERY_PLUGGED_USB))
+                            || (val == (BatteryManager.BATTERY_PLUGGED_AC
+                                    | BatteryManager.BATTERY_PLUGGED_WIRELESS))
+                            || (val == (BatteryManager.BATTERY_PLUGGED_USB
+                                    | BatteryManager.BATTERY_PLUGGED_WIRELESS))
+                            || (val == (BatteryManager.BATTERY_PLUGGED_AC
+                                    | BatteryManager.BATTERY_PLUGGED_USB
+                                    | BatteryManager.BATTERY_PLUGGED_WIRELESS));
+                } catch (NumberFormatException e) {
+                    return false;
+                }
+            }
+        };
+
         /**
          * When the user has enable the option to have a "bug report" command
          * in the power menu.
@@ -7911,6 +8380,8 @@
          */
         public static final String BUGREPORT_IN_POWER_MENU = "bugreport_in_power_menu";
 
+        private static final Validator BUGREPORT_IN_POWER_MENU_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * Whether ADB is enabled.
          */
@@ -7934,6 +8405,8 @@
          */
         public static final String BLUETOOTH_ON = "bluetooth_on";
 
+        private static final Validator BLUETOOTH_ON_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * CDMA Cell Broadcast SMS
          *                            0 = CDMA Cell Broadcast SMS disabled
@@ -8552,6 +9025,8 @@
         */
        public static final String USB_MASS_STORAGE_ENABLED = "usb_mass_storage_enabled";
 
+       private static final Validator USB_MASS_STORAGE_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
+
        /**
         * If this setting is set (to anything), then all references
         * to Gmail on the device must change to Google Mail.
@@ -8688,6 +9163,9 @@
        public static final String WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON =
                "wifi_networks_available_notification_on";
 
+       private static final Validator WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON_VALIDATOR =
+               BOOLEAN_VALIDATOR;
+
        /**
         * {@hide}
         */
@@ -8701,6 +9179,9 @@
        public static final String WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY =
                "wifi_networks_available_repeat_delay";
 
+       private static final Validator WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY_VALIDATOR =
+               NON_NEGATIVE_INTEGER_VALIDATOR;
+
        /**
         * 802.11 country code in ISO 3166 format
         * @hide
@@ -8730,6 +9211,9 @@
         */
        public static final String WIFI_NUM_OPEN_NETWORKS_KEPT = "wifi_num_open_networks_kept";
 
+       private static final Validator WIFI_NUM_OPEN_NETWORKS_KEPT_VALIDATOR =
+               NON_NEGATIVE_INTEGER_VALIDATOR;
+
        /**
         * Whether the Wi-Fi should be on.  Only the Wi-Fi service should touch this.
         */
@@ -8750,6 +9234,8 @@
          */
         public static final String SOFT_AP_TIMEOUT_ENABLED = "soft_ap_timeout_enabled";
 
+        private static final Validator SOFT_AP_TIMEOUT_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * Value to specify if Wi-Fi Wakeup feature is enabled.
          *
@@ -8759,6 +9245,8 @@
         @SystemApi
         public static final String WIFI_WAKEUP_ENABLED = "wifi_wakeup_enabled";
 
+        private static final Validator WIFI_WAKEUP_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * Value to specify if Wi-Fi Wakeup is available.
          *
@@ -8805,6 +9293,9 @@
         public static final String NETWORK_RECOMMENDATIONS_ENABLED =
                 "network_recommendations_enabled";
 
+        private static final Validator NETWORK_RECOMMENDATIONS_ENABLED_VALIDATOR =
+                new SettingsValidators.DiscreteValueValidator(new String[] {"-1", "0", "1"});
+
         /**
          * Which package name to use for network recommendations. If null, network recommendations
          * will neither be requested nor accepted.
@@ -8828,6 +9319,13 @@
         @TestApi
         public static final String USE_OPEN_WIFI_PACKAGE = "use_open_wifi_package";
 
+        private static final Validator USE_OPEN_WIFI_PACKAGE_VALIDATOR = new Validator() {
+            @Override
+            public boolean validate(String value) {
+                return (value == null) || PACKAGE_NAME_VALIDATOR.validate(value);
+            }
+        };
+
         /**
          * The number of milliseconds the {@link com.android.server.NetworkScoreService}
          * will give a recommendation request to complete before returning a default response.
@@ -8907,6 +9405,9 @@
        public static final String WIFI_WATCHDOG_POOR_NETWORK_TEST_ENABLED =
                "wifi_watchdog_poor_network_test_enabled";
 
+       private static final Validator WIFI_WATCHDOG_POOR_NETWORK_TEST_ENABLED_VALIDATOR =
+               ANY_STRING_VALIDATOR;
+
        /**
         * Setting to turn on suspend optimizations at screen off on Wi-Fi. Enabled by default and
         * needs to be set to 0 to disable it.
@@ -9442,11 +9943,16 @@
          * @hide
          */
         public static final String PRIVATE_DNS_MODE = "private_dns_mode";
+
+        private static final Validator PRIVATE_DNS_MODE_VALIDATOR = ANY_STRING_VALIDATOR;
+
         /**
          * @hide
          */
         public static final String PRIVATE_DNS_SPECIFIER = "private_dns_specifier";
 
+        private static final Validator PRIVATE_DNS_SPECIFIER_VALIDATOR = ANY_STRING_VALIDATOR;
+
         /** {@hide} */
         public static final String
                 BLUETOOTH_HEADSET_PRIORITY_PREFIX = "bluetooth_headset_priority_";
@@ -9673,6 +10179,14 @@
         public static final String SYS_VDSO = "sys_vdso";
 
         /**
+         * An integer to reduce the FPS by this factor. Only for experiments. Need to reboot the
+         * device for this setting to take full effect.
+         *
+         * @hide
+         */
+        public static final String FPS_DEVISOR = "fps_divisor";
+
+        /**
          * App standby (app idle) specific settings.
          * This is encoded as a key=value list, separated by commas. Ex:
          * <p>
@@ -9861,15 +10375,6 @@
         public static final String FORCED_APP_STANDBY_ENABLED = "forced_app_standby_enabled";
 
         /**
-         * Whether or not to enable Forced App Standby on small battery devices.
-         * Type: int (0 for false, 1 for true)
-         * Default: 0
-         * @hide
-         */
-        public static final String FORCED_APP_STANDBY_FOR_SMALL_BATTERY_ENABLED
-                = "forced_app_standby_for_small_battery_enabled";
-
-        /**
          * Whether or not Network Watchlist feature is enabled.
          * Type: int (0 for false, 1 for true)
          * Default: 0
@@ -10020,6 +10525,9 @@
          */
         public static final String EMERGENCY_TONE = "emergency_tone";
 
+        private static final Validator EMERGENCY_TONE_VALIDATOR =
+                new SettingsValidators.DiscreteValueValidator(new String[] {"0", "1", "2"});
+
         /**
          * CDMA only settings
          * Whether the auto retry is enabled. The value is
@@ -10028,6 +10536,8 @@
          */
         public static final String CALL_AUTO_RETRY = "call_auto_retry";
 
+        private static final Validator CALL_AUTO_RETRY_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * A setting that can be read whether the emergency affordance is currently needed.
          * The value is a boolean (1 or 0).
@@ -10097,6 +10607,9 @@
          */
         public static final String LOW_POWER_MODE_TRIGGER_LEVEL = "low_power_trigger_level";
 
+        private static final Validator LOW_POWER_MODE_TRIGGER_LEVEL_VALIDATOR =
+                new SettingsValidators.InclusiveIntegerRangeValidator(0, 99);
+
          /**
          * If not 0, the activity manager will aggressively finish activities and
          * processes as soon as they are no longer needed.  If 0, the normal
@@ -10112,6 +10625,8 @@
          */
         public static final String DOCK_AUDIO_MEDIA_ENABLED = "dock_audio_media_enabled";
 
+        private static final Validator DOCK_AUDIO_MEDIA_ENABLED_VALIDATOR = BOOLEAN_VALIDATOR;
+
         /**
          * The surround sound formats AC3, DTS or IEC61937 are
          * available for use if they are detected.
@@ -10158,6 +10673,9 @@
          */
         public static final String ENCODED_SURROUND_OUTPUT = "encoded_surround_output";
 
+        private static final Validator ENCODED_SURROUND_OUTPUT_VALIDATOR =
+                new SettingsValidators.DiscreteValueValidator(new String[] {"0", "1", "2"});
+
         /**
          * Persisted safe headphone volume management state by AudioService
          * @hide
@@ -10698,6 +11216,41 @@
         };
 
         /**
+         * All settings in {@link SETTINGS_TO_BACKUP} array *must* have a non-null validator,
+         * otherwise they won't be restored.
+         *
+         * @hide
+         */
+        public static final Map<String, Validator> VALIDATORS = new ArrayMap<>();
+        static {
+            VALIDATORS.put(BUGREPORT_IN_POWER_MENU, BUGREPORT_IN_POWER_MENU_VALIDATOR);
+            VALIDATORS.put(STAY_ON_WHILE_PLUGGED_IN, STAY_ON_WHILE_PLUGGED_IN_VALIDATOR);
+            VALIDATORS.put(AUTO_TIME, AUTO_TIME_VALIDATOR);
+            VALIDATORS.put(AUTO_TIME_ZONE, AUTO_TIME_ZONE_VALIDATOR);
+            VALIDATORS.put(POWER_SOUNDS_ENABLED, POWER_SOUNDS_ENABLED_VALIDATOR);
+            VALIDATORS.put(DOCK_SOUNDS_ENABLED, DOCK_SOUNDS_ENABLED_VALIDATOR);
+            VALIDATORS.put(CHARGING_SOUNDS_ENABLED, CHARGING_SOUNDS_ENABLED_VALIDATOR);
+            VALIDATORS.put(USB_MASS_STORAGE_ENABLED, USB_MASS_STORAGE_ENABLED_VALIDATOR);
+            VALIDATORS.put(NETWORK_RECOMMENDATIONS_ENABLED,
+                    NETWORK_RECOMMENDATIONS_ENABLED_VALIDATOR);
+            VALIDATORS.put(WIFI_WAKEUP_ENABLED, WIFI_WAKEUP_ENABLED_VALIDATOR);
+            VALIDATORS.put(WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON,
+                    WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON_VALIDATOR);
+            VALIDATORS.put(USE_OPEN_WIFI_PACKAGE, USE_OPEN_WIFI_PACKAGE_VALIDATOR);
+            VALIDATORS.put(WIFI_WATCHDOG_POOR_NETWORK_TEST_ENABLED,
+                    WIFI_WATCHDOG_POOR_NETWORK_TEST_ENABLED_VALIDATOR);
+            VALIDATORS.put(EMERGENCY_TONE, EMERGENCY_TONE_VALIDATOR);
+            VALIDATORS.put(CALL_AUTO_RETRY, CALL_AUTO_RETRY_VALIDATOR);
+            VALIDATORS.put(DOCK_AUDIO_MEDIA_ENABLED, DOCK_AUDIO_MEDIA_ENABLED_VALIDATOR);
+            VALIDATORS.put(ENCODED_SURROUND_OUTPUT, ENCODED_SURROUND_OUTPUT_VALIDATOR);
+            VALIDATORS.put(LOW_POWER_MODE_TRIGGER_LEVEL, LOW_POWER_MODE_TRIGGER_LEVEL_VALIDATOR);
+            VALIDATORS.put(BLUETOOTH_ON, BLUETOOTH_ON_VALIDATOR);
+            VALIDATORS.put(PRIVATE_DNS_MODE, PRIVATE_DNS_MODE_VALIDATOR);
+            VALIDATORS.put(PRIVATE_DNS_SPECIFIER, PRIVATE_DNS_SPECIFIER_VALIDATOR);
+            VALIDATORS.put(SOFT_AP_TIMEOUT_ENABLED, SOFT_AP_TIMEOUT_ENABLED_VALIDATOR);
+        }
+
+        /**
          * Global settings that shouldn't be persisted.
          *
          * @hide
@@ -10706,7 +11259,15 @@
                 LOCATION_GLOBAL_KILL_SWITCH,
         };
 
-        /** @hide */
+        /**
+         * Keys we no longer back up under the current schema, but want to continue to
+         * process when restoring historical backup datasets.
+         *
+         * All settings in {@link LEGACY_RESTORE_SETTINGS} array *must* have a non-null validator,
+         * otherwise they won't be restored.
+         *
+         * @hide
+         */
         public static final String[] LEGACY_RESTORE_SETTINGS = {
         };
 
diff --git a/core/java/android/provider/SettingsValidators.java b/core/java/android/provider/SettingsValidators.java
new file mode 100644
index 0000000..c384a2a
--- /dev/null
+++ b/core/java/android/provider/SettingsValidators.java
@@ -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.
+ */
+
+package android.provider;
+
+import android.content.ComponentName;
+import android.net.Uri;
+
+import com.android.internal.util.ArrayUtils;
+
+import java.util.Locale;
+
+/**
+ * This class provides both interface for validation and common validators
+ * used to ensure Settings have meaningful values.
+ *
+ * @hide
+ */
+public class SettingsValidators {
+
+    public static final Validator BOOLEAN_VALIDATOR =
+            new DiscreteValueValidator(new String[] {"0", "1"});
+
+    public static final Validator ANY_STRING_VALIDATOR = new Validator() {
+        @Override
+        public boolean validate(String value) {
+            return true;
+        }
+    };
+
+    public static final Validator NON_NEGATIVE_INTEGER_VALIDATOR = new Validator() {
+        @Override
+        public boolean validate(String value) {
+            try {
+                return Integer.parseInt(value) >= 0;
+            } catch (NumberFormatException e) {
+                return false;
+            }
+        }
+    };
+
+    public static final Validator ANY_INTEGER_VALIDATOR = new Validator() {
+        @Override
+        public boolean validate(String value) {
+            try {
+                Integer.parseInt(value);
+                return true;
+            } catch (NumberFormatException e) {
+                return false;
+            }
+        }
+    };
+
+    public static final Validator URI_VALIDATOR = new Validator() {
+        @Override
+        public boolean validate(String value) {
+            try {
+                Uri.decode(value);
+                return true;
+            } catch (IllegalArgumentException e) {
+                return false;
+            }
+        }
+    };
+
+    public static final Validator COMPONENT_NAME_VALIDATOR = new Validator() {
+        @Override
+        public boolean validate(String value) {
+            return ComponentName.unflattenFromString(value) != null;
+        }
+    };
+
+    public static final Validator PACKAGE_NAME_VALIDATOR = new Validator() {
+        @Override
+        public boolean validate(String value) {
+            return value != null && isStringPackageName(value);
+        }
+
+        private boolean isStringPackageName(String value) {
+            // The name may contain uppercase or lowercase letters ('A' through 'Z'), numbers,
+            // and underscores ('_'). However, individual package name parts may only
+            // start with letters.
+            // (https://developer.android.com/guide/topics/manifest/manifest-element.html#package)
+            if (value == null) {
+                return false;
+            }
+            String[] subparts = value.split(".");
+            boolean isValidPackageName = true;
+            for (String subpart : subparts) {
+                isValidPackageName |= isSubpartValidForPackageName(subpart);
+                if (!isValidPackageName) break;
+            }
+            return isValidPackageName;
+        }
+
+        private boolean isSubpartValidForPackageName(String subpart) {
+            if (subpart.length() == 0) return false;
+            boolean isValidSubpart = Character.isLetter(subpart.charAt(0));
+            for (int i = 1; i < subpart.length(); i++) {
+                isValidSubpart |= (Character.isLetterOrDigit(subpart.charAt(i))
+                                || (subpart.charAt(i) == '_'));
+                if (!isValidSubpart) break;
+            }
+            return isValidSubpart;
+        }
+    };
+
+    public static final Validator LENIENT_IP_ADDRESS_VALIDATOR = new Validator() {
+        private static final int MAX_IPV6_LENGTH = 45;
+
+        @Override
+        public boolean validate(String value) {
+            if (value == null) {
+                return false;
+            }
+            return value.length() <= MAX_IPV6_LENGTH;
+        }
+    };
+
+    public static final Validator LOCALE_VALIDATOR = new Validator() {
+        @Override
+        public boolean validate(String value) {
+            if (value == null) {
+                return false;
+            }
+            Locale[] validLocales = Locale.getAvailableLocales();
+            for (Locale locale : validLocales) {
+                if (value.equals(locale.toString())) {
+                    return true;
+                }
+            }
+            return false;
+        }
+    };
+
+    public interface Validator {
+        boolean validate(String value);
+    }
+
+    public static final class DiscreteValueValidator implements Validator {
+        private final String[] mValues;
+
+        public DiscreteValueValidator(String[] values) {
+            mValues = values;
+        }
+
+        @Override
+        public boolean validate(String value) {
+            return ArrayUtils.contains(mValues, value);
+        }
+    }
+
+    public static final class InclusiveIntegerRangeValidator implements Validator {
+        private final int mMin;
+        private final int mMax;
+
+        public InclusiveIntegerRangeValidator(int min, int max) {
+            mMin = min;
+            mMax = max;
+        }
+
+        @Override
+        public boolean validate(String value) {
+            try {
+                final int intValue = Integer.parseInt(value);
+                return intValue >= mMin && intValue <= mMax;
+            } catch (NumberFormatException e) {
+                return false;
+            }
+        }
+    }
+
+    public static final class InclusiveFloatRangeValidator implements Validator {
+        private final float mMin;
+        private final float mMax;
+
+        public InclusiveFloatRangeValidator(float min, float max) {
+            mMin = min;
+            mMax = max;
+        }
+
+        @Override
+        public boolean validate(String value) {
+            try {
+                final float floatValue = Float.parseFloat(value);
+                return floatValue >= mMin && floatValue <= mMax;
+            } catch (NumberFormatException e) {
+                return false;
+            }
+        }
+    }
+
+    public static final class ComponentNameListValidator implements Validator {
+        private final String mSeparator;
+
+        public ComponentNameListValidator(String separator) {
+            mSeparator = separator;
+        }
+
+        @Override
+        public boolean validate(String value) {
+            if (value == null) {
+                return false;
+            }
+            String[] elements = value.split(mSeparator);
+            for (String element : elements) {
+                if (!COMPONENT_NAME_VALIDATOR.validate(element)) {
+                    return false;
+                }
+            }
+            return true;
+        }
+    }
+
+    public static final class PackageNameListValidator implements Validator {
+        private final String mSeparator;
+
+        public PackageNameListValidator(String separator) {
+            mSeparator = separator;
+        }
+
+        @Override
+        public boolean validate(String value) {
+            if (value == null) {
+                return false;
+            }
+            String[] elements = value.split(mSeparator);
+            for (String element : elements) {
+                if (!PACKAGE_NAME_VALIDATOR.validate(element)) {
+                    return false;
+                }
+            }
+            return true;
+        }
+    }
+}
diff --git a/core/java/android/security/keystore/KeychainSnapshot.java b/core/java/android/security/keystore/KeychainSnapshot.java
index 2029114..e03dd4a 100644
--- a/core/java/android/security/keystore/KeychainSnapshot.java
+++ b/core/java/android/security/keystore/KeychainSnapshot.java
@@ -43,7 +43,14 @@
  * @hide
  */
 public final class KeychainSnapshot implements Parcelable {
+    private static final int DEFAULT_MAX_ATTEMPTS = 10;
+    private static final long DEFAULT_COUNTER_ID = 1L;
+
     private int mSnapshotVersion;
+    private int mMaxAttempts = DEFAULT_MAX_ATTEMPTS;
+    private long mCounterId = DEFAULT_COUNTER_ID;
+    private byte[] mServerParams;
+    private byte[] mPublicKey;
     private List<KeychainProtectionParams> mKeychainProtectionParams;
     private List<WrappedApplicationKey> mEntryRecoveryData;
     private byte[] mEncryptedRecoveryKeyBlob;
@@ -79,6 +86,37 @@
     }
 
     /**
+     * Number of user secret guesses allowed during Keychain recovery.
+     */
+    public int getMaxAttempts() {
+        return mMaxAttempts;
+    }
+
+    /**
+     * CounterId which is rotated together with user secret.
+     */
+    public long getCounterId() {
+        return mCounterId;
+    }
+
+    /**
+     * Server parameters.
+     */
+    public @NonNull byte[] getServerParams() {
+        return mServerParams;
+    }
+
+    /**
+     * Public key used to encrypt {@code encryptedRecoveryKeyBlob}.
+     *
+     * See implementation for binary key format
+     */
+    // TODO: document key format.
+    public @NonNull byte[] getTrustedHardwarePublicKey() {
+        return mPublicKey;
+    }
+
+    /**
      * UI and key derivation parameters. Note that combination of secrets may be used.
      */
     public @NonNull List<KeychainProtectionParams> getKeychainProtectionParams() {
@@ -129,6 +167,50 @@
         }
 
         /**
+         * Sets the number of user secret guesses allowed during Keychain recovery.
+         *
+         * @param maxAttempts The maximum number of guesses.
+         * @return This builder.
+         */
+        public Builder setMaxAttempts(int maxAttempts) {
+            mInstance.mMaxAttempts = maxAttempts;
+            return this;
+        }
+
+        /**
+         * Sets counter id.
+         *
+         * @param counterId The counter id.
+         * @return This builder.
+         */
+        public Builder setCounterId(long counterId) {
+            mInstance.mCounterId = counterId;
+            return this;
+        }
+
+        /**
+         * Sets server parameters.
+         *
+         * @param serverParams The server parameters
+         * @return This builder.
+         */
+        public Builder setServerParams(byte[] serverParams) {
+            mInstance.mServerParams = serverParams;
+            return this;
+        }
+
+        /**
+         * Sets public key used to encrypt recovery blob.
+         *
+         * @param publicKey The public key
+         * @return This builder.
+         */
+        public Builder setTrustedHardwarePublicKey(byte[] publicKey) {
+            mInstance.mPublicKey = publicKey;
+            return this;
+        }
+
+        /**
          * Sets UI and key derivation parameters
          *
          * @param recoveryMetadata The UI and key derivation parameters
@@ -175,6 +257,8 @@
             Preconditions.checkCollectionElementsNotNull(mInstance.mEntryRecoveryData,
                     "entryRecoveryData");
             Preconditions.checkNotNull(mInstance.mEncryptedRecoveryKeyBlob);
+            Preconditions.checkNotNull(mInstance.mServerParams);
+            Preconditions.checkNotNull(mInstance.mPublicKey);
             return mInstance;
         }
     }
diff --git a/core/java/android/security/keystore/RecoveryManager.java b/core/java/android/security/keystore/RecoveryController.java
similarity index 94%
rename from core/java/android/security/keystore/RecoveryManager.java
rename to core/java/android/security/keystore/RecoveryController.java
index a381a2c..87283cb 100644
--- a/core/java/android/security/keystore/RecoveryManager.java
+++ b/core/java/android/security/keystore/RecoveryController.java
@@ -31,12 +31,25 @@
 import java.util.Map;
 
 /**
- * A wrapper around KeyStore which lets key be exported to trusted hardware on server side and
- * recovered later.
+ * An assistant for generating {@link javax.crypto.SecretKey} instances that can be recovered by
+ * other Android devices belonging to the user. The exported keychain is protected by the user's
+ * lock screen.
+ *
+ * <p>The RecoveryController must be paired with a recovery agent. The recovery agent is responsible
+ * for transporting the keychain to remote trusted hardware. This hardware must prevent brute force
+ * attempts against the user's lock screen by limiting the number of allowed guesses (to, e.g., 10).
+ * After  that number of incorrect guesses, the trusted hardware no longer allows access to the
+ * key chain.
+ *
+ * <p>For now only the recovery agent itself is able to create keys, so it is expected that the
+ * recovery agent is itself the system app.
+ *
+ * <p>A recovery agent requires the privileged permission
+ * {@code android.Manifest.permission#RECOVER_KEYSTORE}.
  *
  * @hide
  */
-public class RecoveryManager {
+public class RecoveryController {
     private static final String TAG = "RecoveryController";
 
     /** Key has been successfully synced. */
@@ -96,28 +109,28 @@
 
     private final ILockSettings mBinder;
 
-    private RecoveryManager(ILockSettings binder) {
+    private RecoveryController(ILockSettings binder) {
         mBinder = binder;
     }
 
     /**
      * Gets a new instance of the class.
      */
-    public static RecoveryManager getInstance() {
+    public static RecoveryController getInstance() {
         ILockSettings lockSettings =
                 ILockSettings.Stub.asInterface(ServiceManager.getService("lock_settings"));
-        return new RecoveryManager(lockSettings);
+        return new RecoveryController(lockSettings);
     }
 
     /**
-     * Initializes key recovery service for the calling application. RecoveryManager
+     * Initializes key recovery service for the calling application. RecoveryController
      * randomly chooses one of the keys from the list and keeps it to use for future key export
      * operations. Collection of all keys in the list must be signed by the provided {@code
      * rootCertificateAlias}, which must also be present in the list of root certificates
-     * preinstalled on the device. The random selection allows RecoveryManager to select
+     * preinstalled on the device. The random selection allows RecoveryController to select
      * which of a set of remote recovery service devices will be used.
      *
-     * <p>In addition, RecoveryManager enforces a delay of three months between
+     * <p>In addition, RecoveryController enforces a delay of three months between
      * consecutive initialization attempts, to limit the ability of an attacker to often switch
      * remote recovery devices and significantly increase number of recovery attempts.
      *
@@ -373,7 +386,6 @@
      * The method generates symmetric key for a session, which trusted remote device can use to
      * return recovery key.
      *
-     * @param sessionId ID for recovery session.
      * @param verifierPublicKey Encoded {@code java.security.cert.X509Certificate} with Public key
      * used to create the recovery blob on the source device.
      * Keystore will verify the certificate using root of trust.
diff --git a/core/java/android/security/keystore/RecoveryControllerException.java b/core/java/android/security/keystore/RecoveryControllerException.java
index 31fd4af..5b806b7 100644
--- a/core/java/android/security/keystore/RecoveryControllerException.java
+++ b/core/java/android/security/keystore/RecoveryControllerException.java
@@ -19,7 +19,7 @@
 import java.security.GeneralSecurityException;
 
 /**
- * Base exception for errors thrown by {@link RecoveryManager}.
+ * Base exception for errors thrown by {@link RecoveryController}.
  *
  * @hide
  */
diff --git a/core/java/android/security/keystore/RecoverySession.java b/core/java/android/security/keystore/RecoverySession.java
index f78551f..ae8d91a 100644
--- a/core/java/android/security/keystore/RecoverySession.java
+++ b/core/java/android/security/keystore/RecoverySession.java
@@ -29,18 +29,18 @@
     private static final int SESSION_ID_LENGTH_BYTES = 16;
 
     private final String mSessionId;
-    private final RecoveryManager mRecoveryManager;
+    private final RecoveryController mRecoveryController;
 
-    private RecoverySession(RecoveryManager recoveryManager, String sessionId) {
-        mRecoveryManager = recoveryManager;
+    private RecoverySession(RecoveryController recoveryController, String sessionId) {
+        mRecoveryController = recoveryController;
         mSessionId = sessionId;
     }
 
     /**
      * A new session, started by {@code recoveryManager}.
      */
-    static RecoverySession newInstance(RecoveryManager recoveryManager) {
-        return new RecoverySession(recoveryManager, newSessionId());
+    static RecoverySession newInstance(RecoveryController recoveryController) {
+        return new RecoverySession(recoveryController, newSessionId());
     }
 
     /**
@@ -66,6 +66,6 @@
 
     @Override
     public void close() {
-        mRecoveryManager.closeSession(this);
+        mRecoveryController.closeSession(this);
     }
 }
diff --git a/core/java/android/service/autofill/AutofillFieldClassificationService.java b/core/java/android/service/autofill/AutofillFieldClassificationService.java
new file mode 100644
index 0000000..4e4caf0
--- /dev/null
+++ b/core/java/android/service/autofill/AutofillFieldClassificationService.java
@@ -0,0 +1,219 @@
+/*
+ * 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.service.autofill;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.app.Service;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.RemoteCallback;
+import android.os.RemoteException;
+import android.util.Log;
+import android.view.autofill.AutofillValue;
+
+import com.android.internal.os.HandlerCaller;
+import com.android.internal.os.SomeArgs;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * A service that calculates field classification scores.
+ *
+ * <p>A field classification score is a {@code float} representing how well an
+ * {@link AutofillValue} filled matches a expected value predicted by an autofill service
+ * &mdash;a full-match is {@code 1.0} (representing 100%), while a full mismatch is {@code 0.0}.
+ *
+ * <p>The exact score depends on the algorithm used to calculate it&mdash; the service must provide
+ * at least one default algorithm (which is used when the algorithm is not specified or is invalid),
+ * but it could provide more (in which case the algorithm name should be specifiied by the caller
+ * when calculating the scores).
+ *
+ * {@hide}
+ */
+@SystemApi
+public abstract class AutofillFieldClassificationService extends Service {
+
+    private static final String TAG = "AutofillFieldClassificationService";
+
+    private static final int MSG_GET_SCORES = 1;
+
+    /**
+     * The {@link Intent} action that must be declared as handled by a service
+     * in its manifest for the system to recognize it as a quota providing service.
+     */
+    public static final String SERVICE_INTERFACE =
+            "android.service.autofill.AutofillFieldClassificationService";
+
+    /**
+     * Manifest metadata key for the resource string containing the name of the default field
+     * classification algorithm.
+     */
+    public static final String SERVICE_META_DATA_KEY_DEFAULT_ALGORITHM =
+            "android.autofill.field_classification.default_algorithm";
+    /**
+     * Manifest metadata key for the resource string array containing the names of all field
+     * classification algorithms provided by the service.
+     */
+    public static final String SERVICE_META_DATA_KEY_AVAILABLE_ALGORITHMS =
+            "android.autofill.field_classification.available_algorithms";
+
+
+    /** {@hide} **/
+    public static final String EXTRA_SCORES = "scores";
+
+    private AutofillFieldClassificationServiceWrapper mWrapper;
+
+    private final HandlerCaller.Callback mHandlerCallback = (msg) -> {
+        final int action = msg.what;
+        final Bundle data = new Bundle();
+        final RemoteCallback callback;
+        switch (action) {
+            case MSG_GET_SCORES:
+                final SomeArgs args = (SomeArgs) msg.obj;
+                callback = (RemoteCallback) args.arg1;
+                final String algorithmName = (String) args.arg2;
+                final Bundle algorithmArgs = (Bundle) args.arg3;
+                @SuppressWarnings("unchecked")
+                final List<AutofillValue> actualValues = ((List<AutofillValue>) args.arg4);
+                @SuppressWarnings("unchecked")
+                final String[] userDataValues = (String[]) args.arg5;
+                final float[][] scores = onGetScores(algorithmName, algorithmArgs, actualValues,
+                        Arrays.asList(userDataValues));
+                data.putParcelable(EXTRA_SCORES, new Scores(scores));
+                break;
+            default:
+                Log.w(TAG, "Handling unknown message: " + action);
+                return;
+        }
+        callback.sendResult(data);
+    };
+
+    private final HandlerCaller mHandlerCaller = new HandlerCaller(null, Looper.getMainLooper(),
+            mHandlerCallback, true);
+
+    /** @hide */
+    public AutofillFieldClassificationService() {
+
+    }
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        mWrapper = new AutofillFieldClassificationServiceWrapper();
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return mWrapper;
+    }
+
+    /**
+     * Calculates field classification scores in a batch.
+     *
+     * <p>See {@link AutofillFieldClassificationService} for more info about field classification
+     * scores.
+     *
+     * @param algorithm name of the algorithm to be used to calculate the scores. If invalid, the
+     * default algorithm will be used instead.
+     * @param args optional arguments to be passed to the algorithm.
+     * @param actualValues values entered by the user.
+     * @param userDataValues values predicted from the user data.
+     * @return the calculated scores, with the first dimension representing actual values and the
+     * second dimension values from {@link UserData}.
+     *
+     * {@hide}
+     */
+    @Nullable
+    @SystemApi
+    public float[][] onGetScores(@Nullable String algorithm,
+            @Nullable Bundle args, @NonNull List<AutofillValue> actualValues,
+            @NonNull List<String> userDataValues) {
+        throw new UnsupportedOperationException("Must be implemented by external service");
+    }
+
+    private final class AutofillFieldClassificationServiceWrapper
+            extends IAutofillFieldClassificationService.Stub {
+        @Override
+        public void getScores(RemoteCallback callback, String algorithmName, Bundle algorithmArgs,
+                List<AutofillValue> actualValues, String[] userDataValues)
+                        throws RemoteException {
+            // TODO(b/70939974): refactor to use PooledLambda
+            mHandlerCaller.obtainMessageOOOOO(MSG_GET_SCORES, callback, algorithmName,
+                    algorithmArgs, actualValues, userDataValues).sendToTarget();
+        }
+    }
+
+    /**
+     * Helper class used to encapsulate a float[][] in a Parcelable.
+     *
+     * {@hide}
+     */
+    public static final class Scores implements Parcelable {
+        public final float[][] scores;
+
+        private Scores(Parcel parcel) {
+            final int size1 = parcel.readInt();
+            final int size2 = parcel.readInt();
+            scores = new float[size1][size2];
+            for (int i = 0; i < size1; i++) {
+                for (int j = 0; j < size2; j++) {
+                    scores[i][j] = parcel.readFloat();
+                }
+            }
+        }
+
+        private  Scores(float[][] scores) {
+            this.scores = scores;
+        }
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        @Override
+        public void writeToParcel(Parcel parcel, int flags) {
+            int size1 = scores.length;
+            int size2 = scores[0].length;
+            parcel.writeInt(size1);
+            parcel.writeInt(size2);
+            for (int i = 0; i < size1; i++) {
+                for (int j = 0; j < size2; j++) {
+                    parcel.writeFloat(scores[i][j]);
+                }
+            }
+        }
+
+        public static final Creator<Scores> CREATOR = new Creator<Scores>() {
+            @Override
+            public Scores createFromParcel(Parcel parcel) {
+                return new Scores(parcel);
+            }
+
+            @Override
+            public Scores[] newArray(int size) {
+                return new Scores[size];
+            }
+        };
+    }
+}
diff --git a/core/java/android/service/autofill/CharSequenceTransformation.java b/core/java/android/service/autofill/CharSequenceTransformation.java
index 2413e97..f52ac85 100644
--- a/core/java/android/service/autofill/CharSequenceTransformation.java
+++ b/core/java/android/service/autofill/CharSequenceTransformation.java
@@ -22,7 +22,6 @@
 import android.annotation.TestApi;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.util.ArrayMap;
 import android.util.Log;
 import android.util.Pair;
 import android.view.autofill.AutofillId;
@@ -31,6 +30,8 @@
 
 import com.android.internal.util.Preconditions;
 
+import java.util.LinkedHashMap;
+import java.util.Map.Entry;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -62,7 +63,9 @@
 public final class CharSequenceTransformation extends InternalTransformation implements
         Transformation, Parcelable {
     private static final String TAG = "CharSequenceTransformation";
-    @NonNull private final ArrayMap<AutofillId, Pair<Pattern, String>> mFields;
+
+    // Must use LinkedHashMap to preserve insertion order.
+    @NonNull private final LinkedHashMap<AutofillId, Pair<Pattern, String>> mFields;
 
     private CharSequenceTransformation(Builder builder) {
         mFields = builder.mFields;
@@ -76,9 +79,9 @@
         final StringBuilder converted = new StringBuilder();
         final int size = mFields.size();
         if (sDebug) Log.d(TAG, size + " multiple fields on id " + childViewId);
-        for (int i = 0; i < size; i++) {
-            final AutofillId id = mFields.keyAt(i);
-            final Pair<Pattern, String> field = mFields.valueAt(i);
+        for (Entry<AutofillId, Pair<Pattern, String>> entry : mFields.entrySet()) {
+            final AutofillId id = entry.getKey();
+            final Pair<Pattern, String> field = entry.getValue();
             final String value = finder.findByAutofillId(id);
             if (value == null) {
                 Log.w(TAG, "No value for id " + id);
@@ -107,8 +110,10 @@
      * Builder for {@link CharSequenceTransformation} objects.
      */
     public static class Builder {
-        @NonNull private final ArrayMap<AutofillId, Pair<Pattern, String>> mFields =
-                new ArrayMap<>();
+
+        // Must use LinkedHashMap to preserve insertion order.
+        @NonNull private final LinkedHashMap<AutofillId, Pair<Pattern, String>> mFields =
+                new LinkedHashMap<>();
         private boolean mDestroyed;
 
         /**
@@ -186,12 +191,15 @@
         final Pattern[] regexs = new Pattern[size];
         final String[] substs = new String[size];
         Pair<Pattern, String> pair;
-        for (int i = 0; i < size; i++) {
-            ids[i] = mFields.keyAt(i);
-            pair = mFields.valueAt(i);
+        int i = 0;
+        for (Entry<AutofillId, Pair<Pattern, String>> entry : mFields.entrySet()) {
+            ids[i] = entry.getKey();
+            pair = entry.getValue();
             regexs[i] = pair.first;
             substs[i] = pair.second;
+            i++;
         }
+
         parcel.writeParcelableArray(ids, flags);
         parcel.writeSerializable(regexs);
         parcel.writeStringArray(substs);
diff --git a/core/java/android/service/autofill/FieldClassification.java b/core/java/android/service/autofill/FieldClassification.java
index 5361803..cd1efd6 100644
--- a/core/java/android/service/autofill/FieldClassification.java
+++ b/core/java/android/service/autofill/FieldClassification.java
@@ -105,21 +105,16 @@
 
     /**
      * Represents the score of a {@link UserData} entry for the field.
-     *
-     * <p>The score is calculated by the given {@link #getAlgorithm() algorithm} and
-     * the entry is identified by {@link #getRemoteId()}.
      */
     public static final class Match {
 
         private final String mRemoteId;
         private final float mScore;
-        private final String mAlgorithm;
 
         /** @hide */
-        public Match(String remoteId, float score, String algorithm) {
+        public Match(String remoteId, float score) {
             mRemoteId = Preconditions.checkNotNull(remoteId);
             mScore = score;
-            mAlgorithm = algorithm;
         }
 
         /**
@@ -150,38 +145,22 @@
             return mScore;
         }
 
-        /**
-         * Gets the algorithm used to calculate this score.
-         *
-         * <p>Typically, this is either the algorithm set by
-         * {@link UserData.Builder#setFieldClassificationAlgorithm(String, android.os.Bundle)},
-         * or the
-         * {@link android.view.autofill.AutofillManager#getDefaultFieldClassificationAlgorithm()}.
-         */
-        @NonNull
-        public String getAlgorithm() {
-            return mAlgorithm;
-        }
-
         @Override
         public String toString() {
             if (!sDebug) return super.toString();
 
             final StringBuilder string = new StringBuilder("Match: remoteId=");
             Helper.appendRedacted(string, mRemoteId);
-            return string.append(", score=").append(mScore)
-                    .append(", algorithm=").append(mAlgorithm)
-                    .toString();
+            return string.append(", score=").append(mScore).toString();
         }
 
         private void writeToParcel(@NonNull Parcel parcel) {
             parcel.writeString(mRemoteId);
             parcel.writeFloat(mScore);
-            parcel.writeString(mAlgorithm);
         }
 
         private static Match readFromParcel(@NonNull Parcel parcel) {
-            return new Match(parcel.readString(), parcel.readFloat(), parcel.readString());
+            return new Match(parcel.readString(), parcel.readFloat());
         }
     }
 }
diff --git a/core/java/android/service/autofill/IAutofillFieldClassificationService.aidl b/core/java/android/service/autofill/IAutofillFieldClassificationService.aidl
new file mode 100644
index 0000000..398557d
--- /dev/null
+++ b/core/java/android/service/autofill/IAutofillFieldClassificationService.aidl
@@ -0,0 +1,32 @@
+/*
+ * 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.service.autofill;
+
+import android.os.Bundle;
+import android.os.RemoteCallback;
+import android.view.autofill.AutofillValue;
+import java.util.List;
+
+/**
+ * Service used to calculate match scores for Autofill Field Classification.
+ *
+ * @hide
+ */
+oneway interface IAutofillFieldClassificationService {
+    void getScores(in RemoteCallback callback, String algorithmName, in Bundle algorithmArgs,
+                   in List<AutofillValue> actualValues, in String[] userDataValues);
+}
diff --git a/core/java/android/service/autofill/UserData.java b/core/java/android/service/autofill/UserData.java
index 2f9225a..9017848 100644
--- a/core/java/android/service/autofill/UserData.java
+++ b/core/java/android/service/autofill/UserData.java
@@ -155,12 +155,9 @@
          * <p>The currently available algorithms can be retrieve through
          * {@link AutofillManager#getAvailableFieldClassificationAlgorithms()}.
          *
-         * <p><b>Note: </b>The available algorithms in the Android System can change dinamically,
-         * so it's not guaranteed that the algorithm set here is the one that will be effectually
-         * used. If the algorithm set here is not available at runtime, the
-         * {@link AutofillManager#getDefaultFieldClassificationAlgorithm()} is used instead.
-         * You can verify which algorithm was used by calling
-         * {@link FieldClassification.Match#getAlgorithm()}.
+         * <p>If not set, the
+         * {@link AutofillManager#getDefaultFieldClassificationAlgorithm() default algorithm} is
+         * used instead.
          *
          * @param name name of the algorithm or {@code null} to used default.
          * @param args optional arguments to the algorithm.
diff --git a/core/java/android/text/MeasuredParagraph.java b/core/java/android/text/MeasuredParagraph.java
index c93e036..c7d4a4a 100644
--- a/core/java/android/text/MeasuredParagraph.java
+++ b/core/java/android/text/MeasuredParagraph.java
@@ -356,6 +356,7 @@
             @IntRange(from = 0) int start,
             @IntRange(from = 0) int end,
             @NonNull TextDirectionHeuristic textDir,
+            boolean computeHyphenation,
             @Nullable MeasuredParagraph recycle) {
         final MeasuredParagraph mt = recycle == null ? obtain() : recycle;
         mt.resetAndAnalyzeBidi(text, start, end, textDir);
@@ -365,7 +366,8 @@
             long nativeBuilderPtr = nInitBuilder();
             try {
                 mt.bindNativeObject(
-                        nBuildNativeMeasuredParagraph(nativeBuilderPtr, mt.mCopiedBuffer));
+                        nBuildNativeMeasuredParagraph(nativeBuilderPtr, mt.mCopiedBuffer,
+                              computeHyphenation));
             } finally {
                 nFreeBuilder(nativeBuilderPtr);
             }
@@ -394,7 +396,8 @@
                     mt.mSpanEndCache.append(spanEnd);
                 }
             }
-            mt.bindNativeObject(nBuildNativeMeasuredParagraph(nativeBuilderPtr, mt.mCopiedBuffer));
+            mt.bindNativeObject(nBuildNativeMeasuredParagraph(nativeBuilderPtr, mt.mCopiedBuffer,
+                      computeHyphenation));
         } finally {
             nFreeBuilder(nativeBuilderPtr);
         }
@@ -668,7 +671,8 @@
                                                   @FloatRange(from = 0) float width);
 
     private static native long nBuildNativeMeasuredParagraph(/* Non Zero */ long nativeBuilderPtr,
-                                                 @NonNull char[] text);
+                                                 @NonNull char[] text,
+                                                 boolean computeHyphenation);
 
     private static native void nFreeBuilder(/* Non Zero */ long nativeBuilderPtr);
 
diff --git a/core/java/android/text/MeasuredText.java b/core/java/android/text/MeasuredText.java
index 2c30360..b96b489 100644
--- a/core/java/android/text/MeasuredText.java
+++ b/core/java/android/text/MeasuredText.java
@@ -52,70 +52,147 @@
     // The sorted paragraph end offsets.
     private final @NonNull int[] mParagraphBreakPoints;
 
-    /**
-     * Build MeasuredText from the text.
-     *
-     * @param text The text to be measured.
-     * @param paint The paint to be used for drawing.
-     * @param textDir The text direction.
-     * @return The measured text.
-     */
-    public static @NonNull MeasuredText build(@NonNull CharSequence text,
-                                              @NonNull TextPaint paint,
-                                              @NonNull TextDirectionHeuristic textDir) {
-        return MeasuredText.build(text, paint, textDir, 0, text.length());
-    }
+    // The break strategy for this measured text.
+    private final @Layout.BreakStrategy int mBreakStrategy;
+
+    // The hyphenation frequency for this measured text.
+    private final @Layout.HyphenationFrequency int mHyphenationFrequency;
 
     /**
-     * Build MeasuredText from the specific range of the text..
-     *
-     * @param text The text to be measured.
-     * @param paint The paint to be used for drawing.
-     * @param textDir The text direction.
-     * @param start The inclusive start offset of the text.
-     * @param end The exclusive start offset of the text.
-     * @return The measured text.
+     * A Builder for MeasuredText
      */
-    public static @NonNull MeasuredText build(@NonNull CharSequence text,
-                                              @NonNull TextPaint paint,
-                                              @NonNull TextDirectionHeuristic textDir,
-                                              @IntRange(from = 0) int start,
-                                              @IntRange(from = 0) int end) {
-        Preconditions.checkNotNull(text);
-        Preconditions.checkNotNull(paint);
-        Preconditions.checkNotNull(textDir);
-        Preconditions.checkArgumentInRange(start, 0, text.length(), "start");
-        Preconditions.checkArgumentInRange(end, 0, text.length(), "end");
+    public static final class Builder {
+        // Mandatory parameters.
+        private final @NonNull CharSequence mText;
+        private final @NonNull TextPaint mPaint;
 
-        final IntArray paragraphEnds = new IntArray();
-        final ArrayList<MeasuredParagraph> measuredTexts = new ArrayList<>();
+        // Members to be updated by setters.
+        private @IntRange(from = 0) int mStart;
+        private @IntRange(from = 0) int mEnd;
+        private TextDirectionHeuristic mTextDir = TextDirectionHeuristics.FIRSTSTRONG_LTR;
+        private @Layout.BreakStrategy int mBreakStrategy = Layout.BREAK_STRATEGY_HIGH_QUALITY;
+        private @Layout.HyphenationFrequency int mHyphenationFrequency =
+                Layout.HYPHENATION_FREQUENCY_NORMAL;
 
-        int paraEnd = 0;
-        for (int paraStart = start; paraStart < end; paraStart = paraEnd) {
-            paraEnd = TextUtils.indexOf(text, LINE_FEED, paraStart, end);
-            if (paraEnd < 0) {
-                // No LINE_FEED(U+000A) character found. Use end of the text as the paragraph end.
-                paraEnd = end;
-            } else {
-                paraEnd++;  // Includes LINE_FEED(U+000A) to the prev paragraph.
-            }
 
-            paragraphEnds.add(paraEnd);
-            measuredTexts.add(MeasuredParagraph.buildForStaticLayout(
-                    paint, text, paraStart, paraEnd, textDir, null /* no recycle */));
+        /**
+         * Builder constructor
+         *
+         * @param text The text to be measured.
+         * @param paint The paint to be used for drawing.
+         */
+        public Builder(@NonNull CharSequence text, @NonNull TextPaint paint) {
+            Preconditions.checkNotNull(text);
+            Preconditions.checkNotNull(paint);
+
+            mText = text;
+            mPaint = paint;
+            mStart = 0;
+            mEnd = text.length();
         }
 
-        return new MeasuredText(text, start, end, paint, textDir,
-                                measuredTexts.toArray(new MeasuredParagraph[measuredTexts.size()]),
-                                paragraphEnds.toArray());
-    }
+        /**
+         * Set the range of measuring target.
+         *
+         * @param start The measuring target start offset in the text.
+         * @param end The measuring target end offset in the text.
+         */
+        public @NonNull Builder setRange(@IntRange(from = 0) int start,
+                                         @IntRange(from = 0) int end) {
+            Preconditions.checkArgumentInRange(start, 0, mText.length(), "start");
+            Preconditions.checkArgumentInRange(end, 0, mText.length(), "end");
+            Preconditions.checkArgument(start <= end, "The range is reversed.");
 
-    // Use MeasuredText.build instead.
+            mStart = start;
+            mEnd = end;
+            return this;
+        }
+
+        /**
+         * Set the text direction heuristic
+         *
+         * The default value is {@link TextDirectionHeuristics#FIRSTSTRONG_LTR}.
+         *
+         * @param textDir The text direction heuristic for resolving bidi behavior.
+         * @return this builder, useful for chaining.
+         */
+        public @NonNull Builder setTextDirection(@NonNull TextDirectionHeuristic textDir) {
+            Preconditions.checkNotNull(textDir);
+            mTextDir = textDir;
+            return this;
+        }
+
+        /**
+         * Set the break strategy
+         *
+         * The default value is {@link Layout#BREAK_STRATEGY_HIGH_QUALITY}.
+         *
+         * @param breakStrategy The break strategy.
+         * @return this builder, useful for chaining.
+         */
+        public @NonNull Builder setBreakStrategy(@Layout.BreakStrategy int breakStrategy) {
+            mBreakStrategy = breakStrategy;
+            return this;
+        }
+
+        /**
+         * Set the hyphenation frequency
+         *
+         * The default value is {@link Layout#HYPHENATION_FREQUENCY_NORMAL}.
+         *
+         * @param hyphenationFrequency The hyphenation frequency.
+         * @return this builder, useful for chaining.
+         */
+        public @NonNull Builder setHyphenationFrequency(
+                @Layout.HyphenationFrequency int hyphenationFrequency) {
+            mHyphenationFrequency = hyphenationFrequency;
+            return this;
+        }
+
+        /**
+         * Build the measured text
+         *
+         * @return the measured text.
+         */
+        public @NonNull MeasuredText build() {
+            final boolean needHyphenation = mBreakStrategy != Layout.BREAK_STRATEGY_SIMPLE
+                    && mHyphenationFrequency != Layout.HYPHENATION_FREQUENCY_NONE;
+
+            final IntArray paragraphEnds = new IntArray();
+            final ArrayList<MeasuredParagraph> measuredTexts = new ArrayList<>();
+
+            int paraEnd = 0;
+            for (int paraStart = mStart; paraStart < mEnd; paraStart = paraEnd) {
+                paraEnd = TextUtils.indexOf(mText, LINE_FEED, paraStart, mEnd);
+                if (paraEnd < 0) {
+                    // No LINE_FEED(U+000A) character found. Use end of the text as the paragraph
+                    // end.
+                    paraEnd = mEnd;
+                } else {
+                    paraEnd++;  // Includes LINE_FEED(U+000A) to the prev paragraph.
+                }
+
+                paragraphEnds.add(paraEnd);
+                measuredTexts.add(MeasuredParagraph.buildForStaticLayout(
+                        mPaint, mText, paraStart, paraEnd, mTextDir, needHyphenation,
+                        null /* no recycle */));
+            }
+
+            return new MeasuredText(mText, mStart, mEnd, mPaint, mTextDir, mBreakStrategy,
+                                    mHyphenationFrequency, measuredTexts.toArray(
+                                            new MeasuredParagraph[measuredTexts.size()]),
+                                    paragraphEnds.toArray());
+        }
+    };
+
+    // Use MeasuredText.Builder instead.
     private MeasuredText(@NonNull CharSequence text,
                          @IntRange(from = 0) int start,
                          @IntRange(from = 0) int end,
                          @NonNull TextPaint paint,
                          @NonNull TextDirectionHeuristic textDir,
+                         @Layout.BreakStrategy int breakStrategy,
+                         @Layout.HyphenationFrequency int frequency,
                          @NonNull MeasuredParagraph[] measuredTexts,
                          @NonNull int[] paragraphBreakPoints) {
         mText = text;
@@ -125,6 +202,8 @@
         mMeasuredParagraphs = measuredTexts;
         mParagraphBreakPoints = paragraphBreakPoints;
         mTextDir = textDir;
+        mBreakStrategy = breakStrategy;
+        mHyphenationFrequency = frequency;
     }
 
     /**
@@ -190,6 +269,20 @@
         return mMeasuredParagraphs[paraIndex];
     }
 
+    /**
+     * Returns the break strategy for this text.
+     */
+    public @Layout.BreakStrategy int getBreakStrategy() {
+        return mBreakStrategy;
+    }
+
+    /**
+     * Returns the hyphenation frequency for this text.
+     */
+    public @Layout.HyphenationFrequency int getHyphenationFrequency() {
+        return mHyphenationFrequency;
+    }
+
     ///////////////////////////////////////////////////////////////////////////////////////////////
     // Spanned overrides
     //
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index 36bec86..70d6486 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -653,26 +653,40 @@
 
         MeasuredText measured = null;
         final Spanned spanned;
+        final boolean canUseMeasuredText;
         if (source instanceof MeasuredText) {
             measured = (MeasuredText) source;
 
-            final CharSequence original = measured.getText();
-            spanned = (original instanceof Spanned) ? (Spanned) original : null;
-
             if (bufStart != measured.getStart() || bufEnd != measured.getEnd()) {
                 // The buffer position has changed. Re-measure here.
-                measured = MeasuredText.build(original, paint, textDir, bufStart, bufEnd);
+                canUseMeasuredText = false;
+            } else if (b.mBreakStrategy != measured.getBreakStrategy()
+                    || b.mHyphenationFrequency != measured.getHyphenationFrequency()) {
+                // The computed hyphenation pieces may not be able to used. Re-measure it.
+                canUseMeasuredText = false;
             } else {
                 // We can use measured information.
-
-                // Overwrite with the one when emeasured.
-                // TODO: Give an option for developer not to overwrite and measure again here?
-                textDir = measured.getTextDir();
-                paint = measured.getPaint();
+                canUseMeasuredText = true;
             }
         } else {
-            measured = MeasuredText.build(source, paint, textDir, bufStart, bufEnd);
+            canUseMeasuredText = false;
+        }
+
+        if (!canUseMeasuredText) {
+            measured = new MeasuredText.Builder(source, paint)
+                    .setRange(bufStart, bufEnd)
+                    .setTextDirection(textDir)
+                    .setBreakStrategy(b.mBreakStrategy)
+                    .setHyphenationFrequency(b.mHyphenationFrequency)
+                    .build();
             spanned = (source instanceof Spanned) ? (Spanned) source : null;
+        } else {
+            final CharSequence original = measured.getText();
+            spanned = (original instanceof Spanned) ? (Spanned) original : null;
+            // Overwrite with the one when measured.
+            // TODO: Give an option for developer not to overwrite and measure again here?
+            textDir = measured.getTextDir();
+            paint = measured.getPaint();
         }
 
         try {
diff --git a/core/java/android/text/style/BackgroundColorSpan.java b/core/java/android/text/style/BackgroundColorSpan.java
index de05f50..4f471a8 100644
--- a/core/java/android/text/style/BackgroundColorSpan.java
+++ b/core/java/android/text/style/BackgroundColorSpan.java
@@ -16,24 +16,48 @@
 
 package android.text.style;
 
+import android.annotation.ColorInt;
+import android.annotation.NonNull;
 import android.os.Parcel;
 import android.text.ParcelableSpan;
 import android.text.TextPaint;
 import android.text.TextUtils;
 
+/**
+ * Changes the background color of the text to which the span is attached.
+ * <p>
+ * For example, to set a green background color for a text you would create a {@link
+ * android.text.SpannableStringBuilder} based on the text and set the span.
+ * <pre>{@code
+ * SpannableString string = new SpannableString("Text with a background color span");
+ *string.setSpan(new BackgroundColorSpan(color), 12, 28, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ * }</pre>
+ * <img src="{@docRoot}reference/android/images/text/style/backgroundcolorspan.png" />
+ * <figcaption>Set a background color for the text.</figcaption>
+ */
 public class BackgroundColorSpan extends CharacterStyle
         implements UpdateAppearance, ParcelableSpan {
 
     private final int mColor;
 
-    public BackgroundColorSpan(int color) {
+    /**
+     * Creates a {@link BackgroundColorSpan} from a color integer.
+     * <p>
+     *
+     * @param color color integer that defines the background color
+     * @see android.content.res.Resources#getColor(int, Resources.Theme)
+     */
+    public BackgroundColorSpan(@ColorInt int color) {
         mColor = color;
     }
 
-    public BackgroundColorSpan(Parcel src) {
+    /**
+     * Creates a {@link BackgroundColorSpan} from a parcel.
+     */
+    public BackgroundColorSpan(@NonNull Parcel src) {
         mColor = src.readInt();
     }
-    
+
     public int getSpanTypeId() {
         return getSpanTypeIdInternal();
     }
@@ -42,26 +66,40 @@
     public int getSpanTypeIdInternal() {
         return TextUtils.BACKGROUND_COLOR_SPAN;
     }
-    
+
     public int describeContents() {
         return 0;
     }
 
-    public void writeToParcel(Parcel dest, int flags) {
+    /**
+     * Flatten this object into a Parcel.
+     *
+     * @param dest The Parcel in which the object should be written.
+     * @param flags Additional flags about how the object should be written.
+     */
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
         writeToParcelInternal(dest, flags);
     }
 
     /** @hide */
-    public void writeToParcelInternal(Parcel dest, int flags) {
+    public void writeToParcelInternal(@NonNull Parcel dest, int flags) {
         dest.writeInt(mColor);
     }
 
+    /**
+     * @return the background color of this span.
+     * @see BackgroundColorSpan#BackgroundColorSpan(int)
+     */
+    @ColorInt
     public int getBackgroundColor() {
         return mColor;
     }
 
+    /**
+     * Updates the background color of the TextPaint.
+     */
     @Override
-    public void updateDrawState(TextPaint ds) {
-        ds.bgColor = mColor;
+    public void updateDrawState(@NonNull TextPaint textPaint) {
+        textPaint.bgColor = mColor;
     }
 }
diff --git a/core/java/android/text/style/ForegroundColorSpan.java b/core/java/android/text/style/ForegroundColorSpan.java
index 2bc6d54..08ab2a1 100644
--- a/core/java/android/text/style/ForegroundColorSpan.java
+++ b/core/java/android/text/style/ForegroundColorSpan.java
@@ -17,24 +17,48 @@
 package android.text.style;
 
 import android.annotation.ColorInt;
+import android.annotation.NonNull;
 import android.os.Parcel;
 import android.text.ParcelableSpan;
 import android.text.TextPaint;
 import android.text.TextUtils;
 
+/**
+ * Changes the color of the text to which the span is attached.
+ * <p>
+ * For example, to set a green text color you would create a {@link
+ * android.text.SpannableStringBuilder} based on the text and set the span.
+ * <pre>{@code
+ * SpannableString string = new SpannableString("Text with a foreground color span");
+ *string.setSpan(new ForegroundColorSpan(color), 12, 28, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ * }</pre>
+ * <img src="{@docRoot}reference/android/images/text/style/foregroundcolorspan.png" />
+ * <figcaption>Set a text color.</figcaption>
+ */
 public class ForegroundColorSpan extends CharacterStyle
         implements UpdateAppearance, ParcelableSpan {
 
     private final int mColor;
 
+    /**
+     * Creates a {@link ForegroundColorSpan} from a color integer.
+     * <p>
+     * To get the color integer associated with a particular color resource ID, use
+     * {@link android.content.res.Resources#getColor(int, Resources.Theme)}
+     *
+     * @param color color integer that defines the text color
+     */
     public ForegroundColorSpan(@ColorInt int color) {
         mColor = color;
     }
 
-    public ForegroundColorSpan(Parcel src) {
+    /**
+     * Creates a {@link ForegroundColorSpan} from a parcel.
+     */
+    public ForegroundColorSpan(@NonNull Parcel src) {
         mColor = src.readInt();
     }
-    
+
     public int getSpanTypeId() {
         return getSpanTypeIdInternal();
     }
@@ -48,22 +72,35 @@
         return 0;
     }
 
-    public void writeToParcel(Parcel dest, int flags) {
+    /**
+     * Flatten this object into a Parcel.
+     *
+     * @param dest  The Parcel in which the object should be written.
+     * @param flags Additional flags about how the object should be written.
+     */
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
         writeToParcelInternal(dest, flags);
     }
 
     /** @hide */
-    public void writeToParcelInternal(Parcel dest, int flags) {
+    public void writeToParcelInternal(@NonNull Parcel dest, int flags) {
         dest.writeInt(mColor);
     }
 
+    /**
+     * @return the foreground color of this span.
+     * @see ForegroundColorSpan#ForegroundColorSpan(int)
+     */
     @ColorInt
     public int getForegroundColor() {
         return mColor;
     }
 
+    /**
+     * Updates the color of the TextPaint to the foreground color.
+     */
     @Override
-    public void updateDrawState(TextPaint ds) {
-        ds.setColor(mColor);
+    public void updateDrawState(@NonNull TextPaint textPaint) {
+        textPaint.setColor(mColor);
     }
 }
diff --git a/core/java/android/util/DataUnit.java b/core/java/android/util/DataUnit.java
index 3cc1bd8..ea4266e 100644
--- a/core/java/android/util/DataUnit.java
+++ b/core/java/android/util/DataUnit.java
@@ -20,12 +20,15 @@
 import java.util.concurrent.TimeUnit;
 
 /**
- * Constants for common byte-related units. Note that both SI and IEC units are
- * supported, and you'll need to pick the correct one for your use-case.
+ * A {@code DataUnit} represents data sizes at a given unit of granularity and
+ * provides utility methods to convert across units.
+ * <p>
+ * Note that both SI units (powers of 10) and IEC units (powers of 2) are
+ * supported, and you'll need to pick the correct one for your use-case. For
+ * example, Wikipedia defines a "kilobyte" as an SI unit of 1000 bytes, and a
+ * "kibibyte" as an IEC unit of 1024 bytes.
  * <p>
  * This design is mirrored after {@link TimeUnit} and {@link ChronoUnit}.
- *
- * @hide
  */
 public enum DataUnit {
     KILOBYTES { @Override public long toBytes(long v) { return v * 1_000; } },
diff --git a/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java b/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java
index ce8998f..5a09dab 100644
--- a/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java
+++ b/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java
@@ -16,6 +16,7 @@
 
 package android.util.apk;
 
+import static android.util.apk.ApkSigningBlockUtils.CONTENT_DIGEST_VERITY_CHUNKED_SHA256;
 import static android.util.apk.ApkSigningBlockUtils.SIGNATURE_DSA_WITH_SHA256;
 import static android.util.apk.ApkSigningBlockUtils.SIGNATURE_ECDSA_WITH_SHA256;
 import static android.util.apk.ApkSigningBlockUtils.SIGNATURE_ECDSA_WITH_SHA512;
@@ -42,6 +43,7 @@
 import java.io.RandomAccessFile;
 import java.nio.BufferUnderflowException;
 import java.nio.ByteBuffer;
+import java.security.DigestException;
 import java.security.InvalidAlgorithmParameterException;
 import java.security.InvalidKeyException;
 import java.security.KeyFactory;
@@ -105,7 +107,8 @@
      */
     public static X509Certificate[][] verify(String apkFile)
             throws SignatureNotFoundException, SecurityException, IOException {
-        return verify(apkFile, true);
+        VerifiedSigner vSigner = verify(apkFile, true);
+        return vSigner.certs;
     }
 
     /**
@@ -119,10 +122,11 @@
      */
     public static X509Certificate[][] plsCertsNoVerifyOnlyCerts(String apkFile)
             throws SignatureNotFoundException, SecurityException, IOException {
-        return verify(apkFile, false);
+        VerifiedSigner vSigner = verify(apkFile, false);
+        return vSigner.certs;
     }
 
-    private static X509Certificate[][] verify(String apkFile, boolean verifyIntegrity)
+    private static VerifiedSigner verify(String apkFile, boolean verifyIntegrity)
             throws SignatureNotFoundException, SecurityException, IOException {
         try (RandomAccessFile apk = new RandomAccessFile(apkFile, "r")) {
             return verify(apk, verifyIntegrity);
@@ -138,7 +142,7 @@
      *         verify.
      * @throws IOException if an I/O error occurs while reading the APK file.
      */
-    private static X509Certificate[][] verify(RandomAccessFile apk, boolean verifyIntegrity)
+    private static VerifiedSigner verify(RandomAccessFile apk, boolean verifyIntegrity)
             throws SignatureNotFoundException, SecurityException, IOException {
         SignatureInfo signatureInfo = findSignature(apk);
         return verify(apk, signatureInfo, verifyIntegrity);
@@ -163,7 +167,7 @@
      * @param signatureInfo APK Signature Scheme v2 Block and information relevant for verifying it
      *        against the APK file.
      */
-    private static X509Certificate[][] verify(
+    private static VerifiedSigner verify(
             RandomAccessFile apk,
             SignatureInfo signatureInfo,
             boolean doVerifyIntegrity) throws SecurityException, IOException {
@@ -207,7 +211,14 @@
             ApkSigningBlockUtils.verifyIntegrity(contentDigests, apk, signatureInfo);
         }
 
-        return signerCerts.toArray(new X509Certificate[signerCerts.size()][]);
+        byte[] verityRootHash = null;
+        if (contentDigests.containsKey(CONTENT_DIGEST_VERITY_CHUNKED_SHA256)) {
+            verityRootHash = contentDigests.get(CONTENT_DIGEST_VERITY_CHUNKED_SHA256);
+        }
+
+        return new VerifiedSigner(
+                signerCerts.toArray(new X509Certificate[signerCerts.size()][]),
+                verityRootHash);
     }
 
     private static X509Certificate[] verifySigner(
@@ -383,6 +394,24 @@
         return;
     }
 
+    static byte[] getVerityRootHash(String apkPath)
+            throws IOException, SignatureNotFoundException, SecurityException {
+        try (RandomAccessFile apk = new RandomAccessFile(apkPath, "r")) {
+            SignatureInfo signatureInfo = findSignature(apk);
+            VerifiedSigner vSigner = verify(apk, false);
+            return vSigner.verityRootHash;
+        }
+    }
+
+    static byte[] generateApkVerity(String apkPath, ByteBufferFactory bufferFactory)
+            throws IOException, SignatureNotFoundException, SecurityException, DigestException,
+                   NoSuchAlgorithmException {
+        try (RandomAccessFile apk = new RandomAccessFile(apkPath, "r")) {
+            SignatureInfo signatureInfo = findSignature(apk);
+            return ApkSigningBlockUtils.generateApkVerity(apkPath, bufferFactory, signatureInfo);
+        }
+    }
+
     private static boolean isSupportedSignatureAlgorithm(int sigAlgorithm) {
         switch (sigAlgorithm) {
             case SIGNATURE_RSA_PSS_WITH_SHA256:
@@ -400,4 +429,20 @@
                 return false;
         }
     }
+
+    /**
+     * Verified APK Signature Scheme v2 signer.
+     *
+     * @hide for internal use only.
+     */
+    public static class VerifiedSigner {
+        public final X509Certificate[][] certs;
+        public final byte[] verityRootHash;
+
+        public VerifiedSigner(X509Certificate[][] certs, byte[] verityRootHash) {
+            this.certs = certs;
+            this.verityRootHash = verityRootHash;
+        }
+
+    }
 }
diff --git a/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java b/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java
index c9e67fe..1b04eb2 100644
--- a/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java
+++ b/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java
@@ -16,6 +16,7 @@
 
 package android.util.apk;
 
+import static android.util.apk.ApkSigningBlockUtils.CONTENT_DIGEST_VERITY_CHUNKED_SHA256;
 import static android.util.apk.ApkSigningBlockUtils.SIGNATURE_DSA_WITH_SHA256;
 import static android.util.apk.ApkSigningBlockUtils.SIGNATURE_ECDSA_WITH_SHA256;
 import static android.util.apk.ApkSigningBlockUtils.SIGNATURE_ECDSA_WITH_SHA512;
@@ -43,6 +44,7 @@
 import java.io.RandomAccessFile;
 import java.nio.BufferUnderflowException;
 import java.nio.ByteBuffer;
+import java.security.DigestException;
 import java.security.InvalidAlgorithmParameterException;
 import java.security.InvalidKeyException;
 import java.security.KeyFactory;
@@ -211,6 +213,10 @@
             ApkSigningBlockUtils.verifyIntegrity(contentDigests, apk, signatureInfo);
         }
 
+        if (contentDigests.containsKey(CONTENT_DIGEST_VERITY_CHUNKED_SHA256)) {
+            result.verityRootHash = contentDigests.get(CONTENT_DIGEST_VERITY_CHUNKED_SHA256);
+        }
+
         return result;
     }
 
@@ -499,6 +505,24 @@
         return new VerifiedProofOfRotation(certs, flagsList);
     }
 
+    static byte[] getVerityRootHash(String apkPath)
+            throws IOException, SignatureNotFoundException, SecurityException {
+        try (RandomAccessFile apk = new RandomAccessFile(apkPath, "r")) {
+            SignatureInfo signatureInfo = findSignature(apk);
+            VerifiedSigner vSigner = verify(apk, false);
+            return vSigner.verityRootHash;
+        }
+    }
+
+    static byte[] generateApkVerity(String apkPath, ByteBufferFactory bufferFactory)
+            throws IOException, SignatureNotFoundException, SecurityException, DigestException,
+                   NoSuchAlgorithmException {
+        try (RandomAccessFile apk = new RandomAccessFile(apkPath, "r")) {
+            SignatureInfo signatureInfo = findSignature(apk);
+            return ApkSigningBlockUtils.generateApkVerity(apkPath, bufferFactory, signatureInfo);
+        }
+    }
+
     private static boolean isSupportedSignatureAlgorithm(int sigAlgorithm) {
         switch (sigAlgorithm) {
             case SIGNATURE_RSA_PSS_WITH_SHA256:
@@ -541,6 +565,8 @@
         public final X509Certificate[] certs;
         public final VerifiedProofOfRotation por;
 
+        public byte[] verityRootHash;
+
         public VerifiedSigner(X509Certificate[] certs, VerifiedProofOfRotation por) {
             this.certs = certs;
             this.por = por;
diff --git a/core/java/android/util/apk/ApkSignatureVerifier.java b/core/java/android/util/apk/ApkSignatureVerifier.java
index 555c474..a2a7616 100644
--- a/core/java/android/util/apk/ApkSignatureVerifier.java
+++ b/core/java/android/util/apk/ApkSignatureVerifier.java
@@ -36,7 +36,9 @@
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.security.DigestException;
 import java.security.GeneralSecurityException;
+import java.security.NoSuchAlgorithmException;
 import java.security.cert.Certificate;
 import java.security.cert.CertificateEncodingException;
 import java.util.ArrayList;
@@ -367,4 +369,51 @@
         // v2 didn't work, try jarsigner
         return verifyV1Signature(apkPath, false);
     }
+
+    /**
+     * @return the verity root hash in the Signing Block.
+     */
+    public static byte[] getVerityRootHash(String apkPath)
+            throws IOException, SignatureNotFoundException, SecurityException {
+        // first try v3
+        try {
+            return ApkSignatureSchemeV3Verifier.getVerityRootHash(apkPath);
+        } catch (SignatureNotFoundException e) {
+            // try older version
+        }
+        return ApkSignatureSchemeV2Verifier.getVerityRootHash(apkPath);
+    }
+
+    /**
+     * Generates the Merkle tree and verity metadata to the buffer allocated by the {@code
+     * ByteBufferFactory}.
+     *
+     * @return the verity root hash of the generated Merkle tree.
+     */
+    public static byte[] generateApkVerity(String apkPath, ByteBufferFactory bufferFactory)
+            throws IOException, SignatureNotFoundException, SecurityException, DigestException,
+                   NoSuchAlgorithmException {
+        // first try v3
+        try {
+            return ApkSignatureSchemeV3Verifier.generateApkVerity(apkPath, bufferFactory);
+        } catch (SignatureNotFoundException e) {
+            // try older version
+        }
+        return ApkSignatureSchemeV2Verifier.generateApkVerity(apkPath, bufferFactory);
+    }
+
+    /**
+     * Result of a successful APK verification operation.
+     */
+    public static class Result {
+        public final Certificate[][] certs;
+        public final Signature[] sigs;
+        public final int signatureSchemeVersion;
+
+        public Result(Certificate[][] certs, Signature[] sigs, int signingVersion) {
+            this.certs = certs;
+            this.sigs = sigs;
+            this.signatureSchemeVersion = signingVersion;
+        }
+    }
 }
diff --git a/core/java/android/util/apk/ApkSigningBlockUtils.java b/core/java/android/util/apk/ApkSigningBlockUtils.java
index 9d53847..4146f6f 100644
--- a/core/java/android/util/apk/ApkSigningBlockUtils.java
+++ b/core/java/android/util/apk/ApkSigningBlockUtils.java
@@ -306,6 +306,26 @@
     }
 
     /**
+     * Generates the fsverity header and hash tree to be used by kernel for the given apk. This
+     * method does not check whether the root hash exists in the Signing Block or not.
+     *
+     * <p>The output is stored in the {@link ByteBuffer} created by the given {@link
+     * ByteBufferFactory}.
+     *
+     * @return the root hash of the generated hash tree.
+     */
+    public static byte[] generateApkVerity(String apkPath, ByteBufferFactory bufferFactory,
+            SignatureInfo signatureInfo)
+            throws IOException, SignatureNotFoundException, SecurityException, DigestException,
+                   NoSuchAlgorithmException {
+        try (RandomAccessFile apk = new RandomAccessFile(apkPath, "r")) {
+            ApkVerityBuilder.ApkVerityResult result = ApkVerityBuilder.generateApkVerity(apk,
+                    signatureInfo, bufferFactory);
+            return result.rootHash;
+        }
+    }
+
+    /**
      * Returns the ZIP End of Central Directory (EoCD) and its offset in the file.
      *
      * @throws IOException if an I/O error occurs while reading the file.
diff --git a/core/java/android/util/apk/ApkVerityBuilder.java b/core/java/android/util/apk/ApkVerityBuilder.java
index 7412ef4..a0d5e4c 100644
--- a/core/java/android/util/apk/ApkVerityBuilder.java
+++ b/core/java/android/util/apk/ApkVerityBuilder.java
@@ -164,11 +164,11 @@
         }
 
         private void fillUpLastOutputChunk() {
-            int extra = (int) (BUFFER_SIZE - mOutput.position() % BUFFER_SIZE);
-            if (extra == 0) {
+            int lastBlockSize = (int) (mOutput.position() % BUFFER_SIZE);
+            if (lastBlockSize == 0) {
                 return;
             }
-            mOutput.put(ByteBuffer.allocate(extra));
+            mOutput.put(ByteBuffer.allocate(BUFFER_SIZE - lastBlockSize));
         }
     }
 
diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java
index 33fbf73..1caea57 100644
--- a/core/java/android/view/Choreographer.java
+++ b/core/java/android/view/Choreographer.java
@@ -373,6 +373,7 @@
      * @see #removeCallbacks
      * @hide
      */
+    @TestApi
     public void postCallback(int callbackType, Runnable action, Object token) {
         postCallbackDelayed(callbackType, action, token, 0);
     }
@@ -391,6 +392,7 @@
      * @see #removeCallback
      * @hide
      */
+    @TestApi
     public void postCallbackDelayed(int callbackType,
             Runnable action, Object token, long delayMillis) {
         if (action == null) {
@@ -440,6 +442,7 @@
      * @see #postCallbackDelayed
      * @hide
      */
+    @TestApi
     public void removeCallbacks(int callbackType, Runnable action, Object token) {
         if (callbackType < 0 || callbackType > CALLBACK_LAST) {
             throw new IllegalArgumentException("callbackType is invalid");
diff --git a/core/java/android/view/DisplayCutout.java b/core/java/android/view/DisplayCutout.java
index 1ef5f09..a61c8c1 100644
--- a/core/java/android/view/DisplayCutout.java
+++ b/core/java/android/view/DisplayCutout.java
@@ -23,6 +23,8 @@
 import static android.view.Surface.ROTATION_270;
 import static android.view.Surface.ROTATION_90;
 
+import android.content.res.Resources;
+import android.graphics.Matrix;
 import android.graphics.Path;
 import android.graphics.Point;
 import android.graphics.Rect;
@@ -30,8 +32,12 @@
 import android.graphics.Region;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.text.TextUtils;
+import android.util.Log;
+import android.util.PathParser;
 import android.util.proto.ProtoOutputStream;
 
+import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
 
 import java.util.List;
@@ -43,6 +49,9 @@
  */
 public final class DisplayCutout {
 
+    private static final String TAG = "DisplayCutout";
+    private static final String DP_MARKER = "@dp";
+
     private static final Rect ZERO_RECT = new Rect();
     private static final Region EMPTY_REGION = new Region();
 
@@ -312,6 +321,40 @@
     }
 
     /**
+     * Creates an instance according to @android:string/config_mainBuiltInDisplayCutout.
+     *
+     * @hide
+     */
+    public static DisplayCutout fromResources(Resources res, int displayWidth) {
+        String spec = res.getString(R.string.config_mainBuiltInDisplayCutout);
+        if (TextUtils.isEmpty(spec)) {
+            return null;
+        }
+        spec = spec.trim();
+        final boolean inDp = spec.endsWith(DP_MARKER);
+        if (inDp) {
+            spec = spec.substring(0, spec.length() - DP_MARKER.length());
+        }
+
+        Path p;
+        try {
+            p = PathParser.createPathFromPathData(spec);
+        } catch (Throwable e) {
+            Log.wtf(TAG, "Could not inflate cutout: ", e);
+            return null;
+        }
+
+        final Matrix m = new Matrix();
+        if (inDp) {
+            final float dpToPx = res.getDisplayMetrics().density;
+            m.postScale(dpToPx, dpToPx);
+        }
+        m.postTranslate(displayWidth / 2f, 0);
+        p.transform(m);
+        return fromBounds(p);
+    }
+
+    /**
      * Helper class for passing {@link DisplayCutout} through binder.
      *
      * Needed, because {@code readFromParcel} cannot be used with immutable classes.
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index ed167c8..17b6ddc 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -29,6 +29,7 @@
 import android.view.MotionEvent;
 import android.view.WindowManager;
 import android.view.Surface;
+import android.view.SurfaceControl;
 
 /**
  * System private per-application interface to the window manager.
@@ -150,25 +151,32 @@
     boolean performHapticFeedback(IWindow window, int effectId, boolean always);
 
     /**
-     * Allocate the drag's thumbnail surface.  Also assigns a token that identifies
-     * the drag to the OS and passes that as the return value.  A return value of
-     * null indicates failure.
-     */
-    IBinder prepareDrag(IWindow window, int flags,
-            int thumbnailWidth, int thumbnailHeight, out Surface outSurface);
-
-    /**
      * Initiate the drag operation itself
+     *
+     * @param window Window which initiates drag operation.
+     * @param flags See {@code View#startDragAndDrop}
+     * @param surface Surface containing drag shadow image
+     * @param touchSource See {@code InputDevice#getSource()}
+     * @param touchX TODO (b/72072998): Fix the issue that the system server misuse the arguments as
+     *         initial touch point while the framework passes drag shadow size.
+     * @param touchY TODO (b/72072998): Fix the issue that the system server misuse the arguments as
+     *         initial touch point while the framework passes drag shadow size.
+     * @param thumbCenterX X coordinate for the position within the shadow image that should be
+     *         underneath the touch point during the drag and drop operation.
+     * @param thumbCenterY Y coordinate for the position within the shadow image that should be
+     *         underneath the touch point during the drag and drop operation.
+     * @param data Data transferred by drag and drop
+     * @return Token of drag operation which will be passed to cancelDragAndDrop.
      */
-    boolean performDrag(IWindow window, IBinder dragToken, int touchSource,
+    IBinder performDrag(IWindow window, int flags, in SurfaceControl surface, int touchSource,
             float touchX, float touchY, float thumbCenterX, float thumbCenterY, in ClipData data);
 
-   /**
+    /**
      * Report the result of a drop action targeted to the given window.
      * consumed is 'true' when the drop was accepted by a valid recipient,
      * 'false' otherwise.
      */
-	void reportDropResult(IWindow window, boolean consumed);
+    void reportDropResult(IWindow window, boolean consumed);
 
     /**
      * Cancel the current drag operation.
@@ -236,4 +244,12 @@
     boolean startMovingTask(IWindow window, float startX, float startY);
 
     void updatePointerIcon(IWindow window);
+
+    /**
+     * Update a tap exclude region with a rectangular area identified by provided id in the window.
+     * Touches on this region will not switch focus to this window. Passing an empty rect will
+     * remove the area from the exclude region of this window.
+     */
+    void updateTapExcludeRegion(IWindow window, int regionId, int left, int top, int width,
+            int height);
 }
diff --git a/core/java/android/view/SurfaceControl.aidl b/core/java/android/view/SurfaceControl.aidl
new file mode 100644
index 0000000..744ead2
--- /dev/null
+++ b/core/java/android/view/SurfaceControl.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+parcelable SurfaceControl;
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index f461e45..05770c3 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -17886,6 +17886,15 @@
     }
 
     /**
+     * Return the window this view is currently attached to. Used in
+     * {@link android.app.ActivityView} to communicate with WM.
+     * @hide
+     */
+    protected IWindow getWindow() {
+        return mAttachInfo != null ? mAttachInfo.mWindow : null;
+    }
+
+    /**
      * Return the visibility value of the least visible component passed.
      */
     int combineVisibility(int vis1, int vis2) {
@@ -23553,15 +23562,13 @@
             data.prepareToLeaveProcess((flags & View.DRAG_FLAG_GLOBAL) != 0);
         }
 
-        boolean okay = false;
-
         Point shadowSize = new Point();
         Point shadowTouchPoint = new Point();
         shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
 
-        if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
-                (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
-            throw new IllegalStateException("Drag shadow dimensions must not be negative");
+        if ((shadowSize.x <= 0) || (shadowSize.y <= 0)
+                || (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
+            throw new IllegalStateException("Drag shadow dimensions must be positive");
         }
 
         if (ViewDebug.DEBUG_DRAG) {
@@ -23572,40 +23579,50 @@
             mAttachInfo.mDragSurface.release();
         }
         mAttachInfo.mDragSurface = new Surface();
+        mAttachInfo.mDragToken = null;
+
+        final ViewRootImpl root = mAttachInfo.mViewRootImpl;
+        final SurfaceSession session = new SurfaceSession(root.mSurface);
+        final SurfaceControl surface = new SurfaceControl.Builder(session)
+                .setName("drag surface")
+                .setSize(shadowSize.x, shadowSize.y)
+                .setFormat(PixelFormat.TRANSLUCENT)
+                .build();
         try {
-            mAttachInfo.mDragToken = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
-                    flags, shadowSize.x, shadowSize.y, mAttachInfo.mDragSurface);
-            if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token="
-                    + mAttachInfo.mDragToken + " surface=" + mAttachInfo.mDragSurface);
-            if (mAttachInfo.mDragToken != null) {
-                Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
-                try {
-                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
-                    shadowBuilder.onDrawShadow(canvas);
-                } finally {
-                    mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
-                }
-
-                final ViewRootImpl root = getViewRootImpl();
-
-                // Cache the local state object for delivery with DragEvents
-                root.setLocalDragState(myLocalState);
-
-                // repurpose 'shadowSize' for the last touch point
-                root.getLastTouchPoint(shadowSize);
-
-                okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, mAttachInfo.mDragToken,
-                        root.getLastTouchSource(), shadowSize.x, shadowSize.y,
-                        shadowTouchPoint.x, shadowTouchPoint.y, data);
-                if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
+            mAttachInfo.mDragSurface.copyFrom(surface);
+            final Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
+            try {
+                canvas.drawColor(0, PorterDuff.Mode.CLEAR);
+                shadowBuilder.onDrawShadow(canvas);
+            } finally {
+                mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
             }
+
+            // Cache the local state object for delivery with DragEvents
+            root.setLocalDragState(myLocalState);
+
+            // repurpose 'shadowSize' for the last touch point
+            root.getLastTouchPoint(shadowSize);
+
+            mAttachInfo.mDragToken = mAttachInfo.mSession.performDrag(
+                    mAttachInfo.mWindow, flags, surface, root.getLastTouchSource(),
+                    shadowSize.x, shadowSize.y, shadowTouchPoint.x, shadowTouchPoint.y, data);
+            if (ViewDebug.DEBUG_DRAG) {
+                Log.d(VIEW_LOG_TAG, "performDrag returned " + mAttachInfo.mDragToken);
+            }
+
+            return mAttachInfo.mDragToken != null;
         } catch (Exception e) {
             Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
-            mAttachInfo.mDragSurface.destroy();
-            mAttachInfo.mDragSurface = null;
+            return false;
+        } finally {
+            if (mAttachInfo.mDragToken == null) {
+                mAttachInfo.mDragSurface.destroy();
+                mAttachInfo.mDragSurface = null;
+                root.setLocalDragState(null);
+            }
+            session.kill();
         }
-
-        return okay;
     }
 
     /**
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 311dd4b..3ee282e 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -639,6 +639,8 @@
 
     private static final int BOOLEAN_PROPERTY_IS_SHOWING_HINT = 0x0100000;
 
+    private static final int BOOLEAN_PROPERTY_IS_HEADING = 0x0200000;
+
     /**
      * Bits that provide the id of a virtual descendant of a view.
      */
@@ -2409,6 +2411,30 @@
     }
 
     /**
+     * Returns whether node represents a heading.
+     *
+     * @return {@code true} if the node is a heading, {@code false} otherwise.
+     */
+    public boolean isHeading() {
+        return getBooleanProperty(BOOLEAN_PROPERTY_IS_HEADING);
+    }
+
+    /**
+     * Sets whether the node represents a heading.
+     *
+     * <p>
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
+     *   This class is made immutable before being delivered to an AccessibilityService.
+     * </p>
+     *
+     * @param isHeading {@code true} if the node is a heading, {@code false} otherwise.
+     */
+    public void setHeading(boolean isHeading) {
+        setBooleanProperty(BOOLEAN_PROPERTY_IS_HEADING, isHeading);
+    }
+
+    /**
      * Gets the package this node comes from.
      *
      * @return The package name.
@@ -4597,7 +4623,8 @@
          * @param rowSpan The number of rows the item spans.
          * @param columnIndex The column index at which the item is located.
          * @param columnSpan The number of columns the item spans.
-         * @param heading Whether the item is a heading.
+         * @param heading Whether the item is a heading. (Prefer
+         *                {@link AccessibilityNodeInfo#setHeading(boolean)}).
          */
         public static CollectionItemInfo obtain(int rowIndex, int rowSpan,
                 int columnIndex, int columnSpan, boolean heading) {
@@ -4611,7 +4638,8 @@
          * @param rowSpan The number of rows the item spans.
          * @param columnIndex The column index at which the item is located.
          * @param columnSpan The number of columns the item spans.
-         * @param heading Whether the item is a heading.
+         * @param heading Whether the item is a heading. (Prefer
+         *                {@link AccessibilityNodeInfo#setHeading(boolean)})
          * @param selected Whether the item is selected.
          */
         public static CollectionItemInfo obtain(int rowIndex, int rowSpan,
@@ -4698,6 +4726,7 @@
          * heading, table header, etc.
          *
          * @return If the item is a heading.
+         * @deprecated Use {@link AccessibilityNodeInfo#isHeading()}
          */
         public boolean isHeading() {
             return mHeading;
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index de9b0d7..4b24a71 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -53,6 +53,7 @@
 import java.lang.annotation.RetentionPolicy;
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 import java.util.Objects;
@@ -169,7 +170,6 @@
     public static final String EXTRA_CLIENT_STATE =
             "android.view.autofill.extra.CLIENT_STATE";
 
-
     /** @hide */
     public static final String EXTRA_RESTORE_SESSION_TOKEN =
             "android.view.autofill.extra.RESTORE_SESSION_TOKEN";
@@ -259,6 +259,12 @@
     public static final int STATE_DISABLED_BY_SERVICE = 4;
 
     /**
+     * Timeout in ms for calls to the field classification service.
+     * @hide
+     */
+    public static final int FC_SERVICE_TIMEOUT = 5000;
+
+    /**
      * Makes an authentication id from a request id and a dataset id.
      *
      * @param requestId The request id.
@@ -1175,17 +1181,15 @@
      * <a href="AutofillService.html#FieldClassification">field classification</a>.
      *
      * <p><b>Note:</b> This method should only be called by an app providing an autofill service,
-     * and it's ignored if the caller currently doesn't have an enabled autofill service for
-     * the user.
-     *
-     * @return list of all algorithms currently available, or an empty list if the caller currently
-     * does not have an enabled autofill service for the user.
+     * and it returns an empty list if the caller currently doesn't have an enabled autofill service
+     * for the user.
      */
     @NonNull
     public List<String> getAvailableFieldClassificationAlgorithms() {
+        final String[] algorithms;
         try {
-            final List<String> names = mService.getAvailableFieldClassificationAlgorithms();
-            return names != null ? names : Collections.emptyList();
+            algorithms = mService.getAvailableFieldClassificationAlgorithms();
+            return algorithms != null ? Arrays.asList(algorithms) : Collections.emptyList();
         } catch (RemoteException e) {
             e.rethrowFromSystemServer();
             return null;
diff --git a/core/java/android/view/autofill/IAutoFillManager.aidl b/core/java/android/view/autofill/IAutoFillManager.aidl
index 1afa35e..1a11fbb 100644
--- a/core/java/android/view/autofill/IAutoFillManager.aidl
+++ b/core/java/android/view/autofill/IAutoFillManager.aidl
@@ -20,6 +20,7 @@
 import android.graphics.Rect;
 import android.os.Bundle;
 import android.os.IBinder;
+import android.os.RemoteCallback;
 import android.service.autofill.FillEventHistory;
 import android.service.autofill.UserData;
 import android.view.autofill.AutofillId;
@@ -58,6 +59,6 @@
     void setUserData(in UserData userData);
     boolean isFieldClassificationEnabled();
     ComponentName getAutofillServiceComponentName();
-    List<String> getAvailableFieldClassificationAlgorithms();
+    String[] getAvailableFieldClassificationAlgorithms();
     String getDefaultFieldClassificationAlgorithm();
 }
diff --git a/core/java/android/widget/EditText.java b/core/java/android/widget/EditText.java
index 336c20c..728824c 100644
--- a/core/java/android/widget/EditText.java
+++ b/core/java/android/widget/EditText.java
@@ -106,6 +106,10 @@
     @Override
     public Editable getText() {
         CharSequence text = super.getText();
+        // This can only happen during construction.
+        if (text == null) {
+            return null;
+        }
         if (text instanceof Editable) {
             return (Editable) super.getText();
         }
diff --git a/core/java/android/widget/MediaController2.java b/core/java/android/widget/MediaControlView2.java
similarity index 63%
rename from core/java/android/widget/MediaController2.java
rename to core/java/android/widget/MediaControlView2.java
index 9035137..6e85ece 100644
--- a/core/java/android/widget/MediaController2.java
+++ b/core/java/android/widget/MediaControlView2.java
@@ -19,130 +19,145 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
-import android.graphics.Canvas;
 import android.media.session.MediaController;
 import android.media.update.ApiLoader;
-import android.media.update.MediaController2Provider;
+import android.media.update.MediaControlView2Provider;
 import android.media.update.ViewProvider;
 import android.util.AttributeSet;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
-import android.view.View;
-import android.view.View.OnClickListener;
 
 /**
  * TODO PUBLIC API
  * @hide
  */
-public class MediaController2 extends FrameLayout {
-    private final MediaController2Provider mProvider;
+public class MediaControlView2 extends FrameLayout {
+    private final MediaControlView2Provider mProvider;
 
-    public MediaController2(@NonNull Context context) {
+    public MediaControlView2(@NonNull Context context) {
         this(context, null);
     }
 
-    public MediaController2(@NonNull Context context, @Nullable AttributeSet attrs) {
+    public MediaControlView2(@NonNull Context context, @Nullable AttributeSet attrs) {
         this(context, attrs, 0);
     }
 
-    public MediaController2(@NonNull Context context, @Nullable AttributeSet attrs,
+    public MediaControlView2(@NonNull Context context, @Nullable AttributeSet attrs,
                             int defStyleAttr) {
         this(context, attrs, defStyleAttr, 0);
     }
 
-    public MediaController2(@NonNull Context context, @Nullable AttributeSet attrs,
+    public MediaControlView2(@NonNull Context context, @Nullable AttributeSet attrs,
                             int defStyleAttr, int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
 
         mProvider = ApiLoader.getProvider(context)
-                .createMediaController2(this, new SuperProvider());
+                .createMediaControlView2(this, new SuperProvider());
     }
 
+    public MediaControlView2Provider getProvider() {
+        return mProvider;
+    }
+
+    /**
+     * TODO: add docs
+     */
     public void setController(MediaController controller) {
         mProvider.setController_impl(controller);
     }
 
-    public void setAnchorView(View view) {
-        mProvider.setAnchorView_impl(view);
-    }
-
+    /**
+     * TODO: add docs
+     */
     public void show() {
         mProvider.show_impl();
     }
 
+    /**
+     * TODO: add docs
+     */
     public void show(int timeout) {
         mProvider.show_impl(timeout);
     }
 
+    /**
+     * TODO: add docs
+     */
     public boolean isShowing() {
         return mProvider.isShowing_impl();
     }
 
+    /**
+     * TODO: add docs
+     */
     public void hide() {
         mProvider.hide_impl();
     }
 
-    public void setPrevNextListeners(OnClickListener next, OnClickListener prev) {
-        mProvider.setPrevNextListeners_impl(next, prev);
-    }
-
+    /**
+     * TODO: add docs
+     */
     public void showCCButton() {
         mProvider.showCCButton_impl();
     }
 
+    /**
+     * TODO: add docs
+     */
     public boolean isPlaying() {
         return mProvider.isPlaying_impl();
     }
 
+    /**
+     * TODO: add docs
+     */
     public int getCurrentPosition() {
         return mProvider.getCurrentPosition_impl();
     }
 
+    /**
+     * TODO: add docs
+     */
     public int getBufferPercentage() {
         return mProvider.getBufferPercentage_impl();
     }
 
+    /**
+     * TODO: add docs
+     */
     public boolean canPause() {
         return mProvider.canPause_impl();
     }
 
+    /**
+     * TODO: add docs
+     */
     public boolean canSeekBackward() {
         return mProvider.canSeekBackward_impl();
     }
 
+    /**
+     * TODO: add docs
+     */
     public boolean canSeekForward() {
         return mProvider.canSeekForward_impl();
     }
 
+    /**
+     * TODO: add docs
+     */
     public void showSubtitle() {
         mProvider.showSubtitle_impl();
     }
 
+    /**
+     * TODO: add docs
+     */
     public void hideSubtitle() {
         mProvider.hideSubtitle_impl();
     }
 
     @Override
-    protected void onAttachedToWindow() {
-        mProvider.onAttachedToWindow_impl();
-    }
-
-    @Override
-    protected void onDetachedFromWindow() {
-        mProvider.onDetachedFromWindow_impl();
-    }
-
-    @Override
-    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
-        mProvider.onLayout_impl(changed, left, top, right, bottom);
-    }
-
-    @Override
-    public void draw(Canvas canvas) {
-        mProvider.draw_impl(canvas);
-    }
-
-    @Override
     public CharSequence getAccessibilityClassName() {
         return mProvider.getAccessibilityClassName_impl();
     }
@@ -179,58 +194,38 @@
 
     private class SuperProvider implements ViewProvider {
         @Override
-        public void onAttachedToWindow_impl() {
-            MediaController2.super.onAttachedToWindow();
-        }
-
-        @Override
-        public void onDetachedFromWindow_impl() {
-            MediaController2.super.onDetachedFromWindow();
-        }
-
-        @Override
-        public void onLayout_impl(boolean changed, int left, int top, int right, int bottom) {
-            MediaController2.super.onLayout(changed, left, top, right, bottom);
-        }
-
-        @Override
-        public void draw_impl(Canvas canvas) {
-            MediaController2.super.draw(canvas);
-        }
-
-        @Override
         public CharSequence getAccessibilityClassName_impl() {
-            return MediaController2.super.getAccessibilityClassName();
+            return MediaControlView2.super.getAccessibilityClassName();
         }
 
         @Override
         public boolean onTouchEvent_impl(MotionEvent ev) {
-            return MediaController2.super.onTouchEvent(ev);
+            return MediaControlView2.super.onTouchEvent(ev);
         }
 
         @Override
         public boolean onTrackballEvent_impl(MotionEvent ev) {
-            return MediaController2.super.onTrackballEvent(ev);
+            return MediaControlView2.super.onTrackballEvent(ev);
         }
 
         @Override
         public boolean onKeyDown_impl(int keyCode, KeyEvent event) {
-            return MediaController2.super.onKeyDown(keyCode, event);
+            return MediaControlView2.super.onKeyDown(keyCode, event);
         }
 
         @Override
         public void onFinishInflate_impl() {
-            MediaController2.super.onFinishInflate();
+            MediaControlView2.super.onFinishInflate();
         }
 
         @Override
         public boolean dispatchKeyEvent_impl(KeyEvent event) {
-            return MediaController2.super.dispatchKeyEvent(event);
+            return MediaControlView2.super.dispatchKeyEvent(event);
         }
 
         @Override
         public void setEnabled_impl(boolean enabled) {
-            MediaController2.super.setEnabled(enabled);
+            MediaControlView2.super.setEnabled(enabled);
         }
     }
 }
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index dac6c02..7d3fcf4 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -309,6 +309,7 @@
  * @attr ref android.R.styleable#TextView_autoSizeMaxTextSize
  * @attr ref android.R.styleable#TextView_autoSizeStepGranularity
  * @attr ref android.R.styleable#TextView_autoSizePresetSizes
+ * @attr ref android.R.styleable#TextView_accessibilityHeading
  */
 @RemoteView
 public class TextView extends View implements ViewTreeObserver.OnPreDrawListener {
@@ -403,6 +404,7 @@
     private int mCurTextColor;
     private int mCurHintTextColor;
     private boolean mFreezesText;
+    private boolean mIsAccessibilityHeading;
 
     private Editable.Factory mEditableFactory = Editable.Factory.getInstance();
     private Spannable.Factory mSpannableFactory = Spannable.Factory.getInstance();
@@ -1267,6 +1269,8 @@
                 case com.android.internal.R.styleable.TextView_lineHeight:
                     lineHeight = a.getDimensionPixelSize(attr, -1);
                     break;
+                case com.android.internal.R.styleable.TextView_accessibilityHeading:
+                    mIsAccessibilityHeading = a.getBoolean(attr, false);
             }
         }
 
@@ -5128,6 +5132,31 @@
     }
 
     /**
+     * Gets whether this view is a heading for accessibility purposes.
+     *
+     * @return {@code true} if the view is a heading, {@code false} otherwise.
+     *
+     * @attr ref android.R.styleable#TextView_accessibilityHeading
+     */
+    public boolean isAccessibilityHeading() {
+        return mIsAccessibilityHeading;
+    }
+
+    /**
+     * Set if view is a heading for a section of content for accessibility purposes.
+     *
+     * @param isHeading {@code true} if the view is a heading, {@code false} otherwise.
+     *
+     * @attr ref android.R.styleable#TextView_accessibilityHeading
+     */
+    public void setAccessibilityHeading(boolean isHeading) {
+        if (isHeading != mIsAccessibilityHeading) {
+            mIsAccessibilityHeading = isHeading;
+            notifyAccessibilityStateChanged(AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
+        }
+    }
+
+    /**
      * Convenience method to append the specified text to the TextView's
      * display buffer, upgrading it to {@link android.widget.TextView.BufferType#EDITABLE}
      * if it was not already editable.
@@ -10677,6 +10706,7 @@
         info.setText(getTextForAccessibility());
         info.setHintText(mHint);
         info.setShowingHintText(isShowingHint());
+        info.setHeading(mIsAccessibilityHeading);
 
         if (mBufferType == BufferType.EDITABLE) {
             info.setEditable(true);
diff --git a/core/java/android/widget/VideoView2.java b/core/java/android/widget/VideoView2.java
index 310a7bb..955f053 100644
--- a/core/java/android/widget/VideoView2.java
+++ b/core/java/android/widget/VideoView2.java
@@ -20,9 +20,8 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
-import android.graphics.Canvas;
 import android.media.AudioAttributes;
-import android.media.MediaPlayer;
+import android.media.AudioManager;
 import android.media.update.ApiLoader;
 import android.media.update.VideoView2Provider;
 import android.media.update.ViewProvider;
@@ -80,7 +79,8 @@
             int defStyleAttr, int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
 
-        mProvider = ApiLoader.getProvider(context).createVideoView2(this, new SuperProvider());
+        mProvider = ApiLoader.getProvider(context).createVideoView2(this, new SuperProvider(),
+                attrs, defStyleAttr, defStyleRes);
     }
 
     /**
@@ -93,6 +93,20 @@
     /**
      * @hide
      */
+    public void setMediaControlView2(MediaControlView2 mediaControlView) {
+        mProvider.setMediaControlView2_impl(mediaControlView);
+    }
+
+    /**
+     * @hide
+     */
+    public MediaControlView2 getMediaControlView2() {
+        return mProvider.getMediaControlView2_impl();
+    }
+
+    /**
+     * @hide
+     */
     public void start() {
         mProvider.start_impl();
     }
@@ -161,6 +175,45 @@
     }
 
     /**
+     * Sets playback speed.
+     *
+     * It is expressed as a multiplicative factor, where normal speed is 1.0f. If it is less than
+     * or equal to zero, it will be just ignored and nothing will be changed. If it exceeds the
+     * maximum speed that internal engine supports, system will determine best handling or it will
+     * be reset to the normal speed 1.0f.
+     * TODO: This should be revised after integration with MediaPlayer2.
+     * @param speed the playback speed. It should be positive.
+     * @hide
+     */
+    public void setSpeed(float speed) {
+        mProvider.setSpeed_impl(speed);
+    }
+
+    /**
+     * Returns current speed setting.
+     *
+     * If setSpeed() has never been called, returns the default value 1.0f.
+     * @return current speed setting
+     * @hide
+     */
+    public float getSpeed() {
+        return mProvider.getSpeed_impl();
+    }
+
+    /**
+     * Sets which type of audio focus will be requested during the playback, or configures playback
+     * to not request audio focus. Valid values for focus requests are
+     * {@link AudioManager#AUDIOFOCUS_GAIN}, {@link AudioManager#AUDIOFOCUS_GAIN_TRANSIENT},
+     * {@link AudioManager#AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK}, and
+     * {@link AudioManager#AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE}. Or use
+     * {@link AudioManager#AUDIOFOCUS_NONE} to express that audio focus should not be
+     * requested when playback starts. You can for instance use this when playing a silent animation
+     * through this class, and you don't want to affect other audio applications playing in the
+     * background.
+     *
+     * @param focusGain the type of audio focus gain that will be requested, or
+     *     {@link AudioManager#AUDIOFOCUS_NONE} to disable the use audio focus during playback.
+     *
      * @hide
      */
     public void setAudioFocusRequest(int focusGain) {
@@ -168,6 +221,10 @@
     }
 
     /**
+     * Sets the {@link AudioAttributes} to be used during the playback of the video.
+     *
+     * @param attributes non-null <code>AudioAttributes</code>.
+     *
      * @hide
      */
     public void setAudioAttributes(@NonNull AudioAttributes attributes) {
@@ -175,6 +232,9 @@
     }
 
     /**
+     * Sets video path.
+     *
+     * @param path the path of the video.
      * @hide
      */
     public void setVideoPath(String path) {
@@ -198,13 +258,6 @@
     /**
      * @hide
      */
-    public void setMediaController2(MediaController2 controllerView) {
-        mProvider.setMediaController2_impl(controllerView);
-    }
-
-    /**
-     * @hide
-     */
     public void setViewType(@ViewType int viewType) {
         mProvider.setViewType_impl(viewType);
     }
@@ -227,28 +280,28 @@
     /**
      * @hide
      */
-    public void setOnPreparedListener(MediaPlayer.OnPreparedListener l) {
+    public void setOnPreparedListener(OnPreparedListener l) {
         mProvider.setOnPreparedListener_impl(l);
     }
 
     /**
      * @hide
      */
-    public void setOnCompletionListener(MediaPlayer.OnCompletionListener l) {
+    public void setOnCompletionListener(OnCompletionListener l) {
         mProvider.setOnCompletionListener_impl(l);
     }
 
     /**
      * @hide
      */
-    public void setOnErrorListener(MediaPlayer.OnErrorListener l) {
+    public void setOnErrorListener(OnErrorListener l) {
         mProvider.setOnErrorListener_impl(l);
     }
 
     /**
      * @hide
      */
-    public void setOnInfoListener(MediaPlayer.OnInfoListener l) {
+    public void setOnInfoListener(OnInfoListener l) {
         mProvider.setOnInfoListener_impl(l);
     }
 
@@ -260,15 +313,61 @@
     }
 
     /**
+     * Interface definition of a callback to be invoked when the viw type has been changed.
      * @hide
      */
     public interface OnViewTypeChangedListener {
         /**
-         * @hide
+         * Called when the view type has been changed.
+         * @see VideoView2#setViewType(int)
          */
         void onViewTypeChanged(@ViewType int viewType);
     }
 
+    /**
+     * @hide
+     */
+    public interface OnPreparedListener {
+        /**
+         * Called when the media file is ready for playback.
+         */
+        void onPrepared();
+    }
+
+    /**
+     * @hide
+     */
+    public interface OnCompletionListener {
+        /**
+         * Called when the end of a media source is reached during playback.
+         */
+        void onCompletion();
+    }
+
+    /**
+     * @hide
+     */
+    public interface OnErrorListener {
+        /**
+         * Called to indicate an error.
+         */
+        boolean onError(int what, int extra);
+    }
+
+    /**
+     * @hide
+     */
+    public interface OnInfoListener {
+        /**
+         * Called to indicate an info or a warning.
+         * @see MediaPlayer#OnInfoListener
+         *
+         * @param what the type of info or warning.
+         * @param extra an extra code, specific to the info.
+         */
+        void onInfo(int what, int extra);
+    }
+
     @Override
     public CharSequence getAccessibilityClassName() {
         return mProvider.getAccessibilityClassName_impl();
@@ -306,26 +405,6 @@
 
     private class SuperProvider implements ViewProvider {
         @Override
-        public void onAttachedToWindow_impl() {
-            VideoView2.super.onAttachedToWindow();
-        }
-
-        @Override
-        public void onDetachedFromWindow_impl() {
-            VideoView2.super.onDetachedFromWindow();
-        }
-
-        @Override
-        public void onLayout_impl(boolean changed, int left, int top, int right, int bottom) {
-            VideoView2.super.onLayout(changed, left, top, right, bottom);
-        }
-
-        @Override
-        public void draw_impl(Canvas canvas) {
-            VideoView2.super.draw(canvas);
-        }
-
-        @Override
         public CharSequence getAccessibilityClassName_impl() {
             return VideoView2.super.getAccessibilityClassName();
         }
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index 388180d..e2d1ad5 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -23,6 +23,7 @@
 import android.os.ParcelFileDescriptor;
 import android.os.WorkSource;
 import android.os.connectivity.CellularBatteryStats;
+import android.os.connectivity.GpsBatteryStats;
 import android.os.health.HealthStatsParceler;
 import android.telephony.DataConnectionRealTimeInfo;
 import android.telephony.ModemActivityInfo;
@@ -91,6 +92,7 @@
     void noteVibratorOff(int uid);
     void noteStartGps(int uid);
     void noteStopGps(int uid);
+    void noteGpsSignalQuality(int signalLevel);
     void noteScreenState(int state);
     void noteScreenBrightness(int brightness);
     void noteUserActivity(int uid, int event);
@@ -140,6 +142,9 @@
     /** {@hide} */
     CellularBatteryStats getCellularBatteryStats();
 
+    /** {@hide} */
+    GpsBatteryStats getGpsBatteryStats();
+
     HealthStatsParceler takeUidSnapshot(int uid);
     HealthStatsParceler[] takeUidSnapshots(in int[] uid);
 
diff --git a/core/java/com/android/internal/content/PackageHelper.java b/core/java/com/android/internal/content/PackageHelper.java
index e765ab1..8a456d1 100644
--- a/core/java/com/android/internal/content/PackageHelper.java
+++ b/core/java/com/android/internal/content/PackageHelper.java
@@ -25,6 +25,7 @@
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.PackageParser.PackageLite;
+import android.content.pm.dex.DexMetadataHelper;
 import android.os.Environment;
 import android.os.IBinder;
 import android.os.RemoteException;
@@ -415,6 +416,9 @@
             sizeBytes += codeFile.length();
         }
 
+        // Include raw dex metadata files
+        sizeBytes += DexMetadataHelper.getPackageDexMetadataSize(pkg);
+
         // Include all relevant native code
         sizeBytes += NativeLibraryHelper.sumNativeBinariesWithOverride(handle, abiOverride);
 
diff --git a/core/java/com/android/internal/net/NetworkStatsFactory.java b/core/java/com/android/internal/net/NetworkStatsFactory.java
index 5eda81b..02cd09f 100644
--- a/core/java/com/android/internal/net/NetworkStatsFactory.java
+++ b/core/java/com/android/internal/net/NetworkStatsFactory.java
@@ -219,7 +219,7 @@
             }
 
             NetworkStats.Entry adjust =
-                    new NetworkStats.Entry(baseIface, 0, 0, 0, 0L, 0L, 0L, 0L, 0L);
+                    new NetworkStats.Entry(baseIface, 0, 0, 0, 0, 0, 0, 0L, 0L, 0L, 0L, 0L);
             // Subtract any 464lat traffic seen for the root UID on the current base interface.
             adjust.rxBytes -= (entry.rxBytes + entry.rxPackets * IPV4V6_HEADER_DELTA);
             adjust.txBytes -= (entry.txBytes + entry.txPackets * IPV4V6_HEADER_DELTA);
diff --git a/core/java/com/android/internal/os/BatteryStatsHelper.java b/core/java/com/android/internal/os/BatteryStatsHelper.java
index 15dc6f5..5a59e70 100644
--- a/core/java/com/android/internal/os/BatteryStatsHelper.java
+++ b/core/java/com/android/internal/os/BatteryStatsHelper.java
@@ -665,14 +665,14 @@
 
     /**
      * Calculate the baseline power usage for the device when it is in suspend and idle.
-     * The device is drawing POWER_CPU_IDLE power at its lowest power state.
-     * The device is drawing POWER_CPU_IDLE + POWER_CPU_AWAKE power when a wakelock is held.
+     * The device is drawing POWER_CPU_SUSPEND power at its lowest power state.
+     * The device is drawing POWER_CPU_SUSPEND + POWER_CPU_IDLE power when a wakelock is held.
      */
     private void addIdleUsage() {
         final double suspendPowerMaMs = (mTypeBatteryRealtimeUs / 1000) *
-                mPowerProfile.getAveragePower(PowerProfile.POWER_CPU_IDLE);
+                mPowerProfile.getAveragePower(PowerProfile.POWER_CPU_SUSPEND);
         final double idlePowerMaMs = (mTypeBatteryUptimeUs / 1000) *
-                mPowerProfile.getAveragePower(PowerProfile.POWER_CPU_AWAKE);
+                mPowerProfile.getAveragePower(PowerProfile.POWER_CPU_IDLE);
         final double totalPowerMah = (suspendPowerMaMs + idlePowerMaMs) / (60 * 60 * 1000);
         if (DEBUG && totalPowerMah != 0) {
             Log.d(TAG, "Suspend: time=" + (mTypeBatteryRealtimeUs / 1000)
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index ac5dbc4..799e3e8 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -34,6 +34,7 @@
 import android.os.BatteryStats;
 import android.os.Build;
 import android.os.connectivity.CellularBatteryStats;
+import android.os.connectivity.GpsBatteryStats;
 import android.os.FileUtils;
 import android.os.Handler;
 import android.os.IBatteryPropertiesRegistrar;
@@ -78,6 +79,7 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.location.gnssmetrics.GnssMetrics;
 import com.android.internal.net.NetworkStatsFactory;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.FastPrintWriter;
@@ -153,11 +155,11 @@
             MAX_HISTORY_BUFFER = 96*1024;  // 96KB
             MAX_MAX_HISTORY_BUFFER = 128*1024; // 128KB
         } else {
-            MAX_HISTORY_ITEMS = 2000;
-            MAX_MAX_HISTORY_ITEMS = 3000;
-            MAX_WAKELOCKS_PER_UID = 100;
-            MAX_HISTORY_BUFFER = 256*1024;  // 256KB
-            MAX_MAX_HISTORY_BUFFER = 320*1024;  // 256KB
+            MAX_HISTORY_ITEMS = 4000;
+            MAX_MAX_HISTORY_ITEMS = 6000;
+            MAX_WAKELOCKS_PER_UID = 200;
+            MAX_HISTORY_BUFFER = 512*1024;  // 512KB
+            MAX_MAX_HISTORY_BUFFER = 640*1024;  // 640KB
         }
     }
 
@@ -198,6 +200,12 @@
     protected KernelUidCpuFreqTimeReader mKernelUidCpuFreqTimeReader =
             new KernelUidCpuFreqTimeReader();
     @VisibleForTesting
+    protected KernelUidCpuActiveTimeReader mKernelUidCpuActiveTimeReader =
+            new KernelUidCpuActiveTimeReader();
+    @VisibleForTesting
+    protected KernelUidCpuClusterTimeReader mKernelUidCpuClusterTimeReader =
+            new KernelUidCpuClusterTimeReader();
+    @VisibleForTesting
     protected KernelSingleUidTimeReader mKernelSingleUidTimeReader;
 
     private final KernelMemoryBandwidthStats mKernelMemoryBandwidthStats
@@ -666,6 +674,10 @@
     int mCameraOnNesting;
     StopwatchTimer mCameraOnTimer;
 
+    int mGpsSignalQualityBin = -1;
+    final StopwatchTimer[] mGpsSignalQualityTimer =
+        new StopwatchTimer[GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS];
+
     int mPhoneSignalStrengthBin = -1;
     int mPhoneSignalStrengthBinRaw = -1;
     final StopwatchTimer[] mPhoneSignalStrengthsTimer =
@@ -3880,6 +3892,8 @@
         }
         mKernelUidCpuTimeReader.removeUid(isolatedUid);
         mKernelUidCpuFreqTimeReader.removeUid(isolatedUid);
+        mKernelUidCpuActiveTimeReader.removeUid(isolatedUid);
+        mKernelUidCpuClusterTimeReader.removeUid(isolatedUid);
     }
 
     public int mapUid(int uid) {
@@ -4575,10 +4589,37 @@
             if (DEBUG_HISTORY) Slog.v(TAG, "Stop GPS to: "
                     + Integer.toHexString(mHistoryCur.states));
             addHistoryRecordLocked(elapsedRealtime, uptime);
+            stopAllGpsSignalQualityTimersLocked(-1);
+            mGpsSignalQualityBin = -1;
         }
         getUidStatsLocked(uid).noteStopGps(elapsedRealtime);
     }
 
+    public void noteGpsSignalQualityLocked(int signalLevel) {
+        if (mGpsNesting == 0) {
+            return;
+        }
+        if (signalLevel < 0 || signalLevel >= GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS) {
+            stopAllGpsSignalQualityTimersLocked(-1);
+            return;
+        }
+        final long elapsedRealtime = mClocks.elapsedRealtime();
+        final long uptime = mClocks.uptimeMillis();
+        if (mGpsSignalQualityBin != signalLevel) {
+            if (mGpsSignalQualityBin >= 0) {
+                mGpsSignalQualityTimer[mGpsSignalQualityBin].stopRunningLocked(elapsedRealtime);
+            }
+            if(!mGpsSignalQualityTimer[signalLevel].isRunningLocked()) {
+                mGpsSignalQualityTimer[signalLevel].startRunningLocked(elapsedRealtime);
+            }
+            mHistoryCur.states2 = (mHistoryCur.states2&~HistoryItem.STATE2_GPS_SIGNAL_QUALITY_MASK)
+                    | (signalLevel << HistoryItem.STATE2_GPS_SIGNAL_QUALITY_SHIFT);
+            addHistoryRecordLocked(elapsedRealtime, uptime);
+            mGpsSignalQualityBin = signalLevel;
+        }
+        return;
+    }
+
     public void noteScreenStateLocked(int state) {
         state = mPretendScreenOff ? Display.STATE_OFF : state;
 
@@ -4912,6 +4953,18 @@
         mDailyPackageChanges.add(pc);
     }
 
+    void stopAllGpsSignalQualityTimersLocked(int except) {
+        final long elapsedRealtime = mClocks.elapsedRealtime();
+        for (int i = 0; i < GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
+            if (i == except) {
+                continue;
+            }
+            while (mGpsSignalQualityTimer[i].isRunningLocked()) {
+                mGpsSignalQualityTimer[i].stopRunningLocked(elapsedRealtime);
+            }
+        }
+    }
+
     public void notePhoneOnLocked() {
         if (!mPhoneOn) {
             final long elapsedRealtime = mClocks.elapsedRealtime();
@@ -6123,6 +6176,20 @@
         return val;
     }
 
+    @Override public long getGpsSignalQualityTime(int strengthBin,
+        long elapsedRealtimeUs, int which) {
+        if (strengthBin < 0 || strengthBin >= GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS) {
+            return 0;
+        }
+        return mGpsSignalQualityTimer[strengthBin].getTotalTimeLocked(
+            elapsedRealtimeUs, which);
+    }
+
+    @Override public long getGpsBatteryDrainMaMs() {
+        //TODO: Add GPS power computation (b/67213967)
+        return 0;
+    }
+
     @Override public long getPhoneOnTime(long elapsedRealtimeUs, int which) {
         return mPhoneOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
     }
@@ -6479,9 +6546,11 @@
         LongSamplingCounter mUserCpuTime;
         LongSamplingCounter mSystemCpuTime;
         LongSamplingCounter[][] mCpuClusterSpeedTimesUs;
+        LongSamplingCounter mCpuActiveTimeMs;
 
         LongSamplingCounterArray mCpuFreqTimeMs;
         LongSamplingCounterArray mScreenOffCpuFreqTimeMs;
+        LongSamplingCounterArray mCpuClusterTimesMs;
 
         LongSamplingCounterArray[] mProcStateTimeMs;
         LongSamplingCounterArray[] mProcStateScreenOffTimeMs;
@@ -6551,6 +6620,8 @@
 
             mUserCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
             mSystemCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
+            mCpuActiveTimeMs = new LongSamplingCounter(mBsi.mOnBatteryTimeBase);
+            mCpuClusterTimesMs = new LongSamplingCounterArray(mBsi.mOnBatteryTimeBase);
 
             mWakelockStats = mBsi.new OverflowArrayMap<Wakelock>(uid) {
                 @Override public Wakelock instantiateObject() {
@@ -6598,6 +6669,17 @@
         }
 
         @Override
+        public long getCpuActiveTime() {
+            return mCpuActiveTimeMs.getCountLocked(STATS_SINCE_CHARGED);
+        }
+
+        @Override
+        public long[] getCpuClusterTimes() {
+            return nullIfAllZeros(mCpuClusterTimesMs, STATS_SINCE_CHARGED);
+        }
+
+
+        @Override
         public long[] getCpuFreqTimes(int which, int procState) {
             if (which < 0 || which >= NUM_PROCESS_STATE) {
                 return null;
@@ -7660,6 +7742,9 @@
                 mScreenOffCpuFreqTimeMs.reset(false);
             }
 
+            mCpuActiveTimeMs.reset(false);
+            mCpuClusterTimesMs.reset(false);
+
             if (mProcStateTimeMs != null) {
                 for (LongSamplingCounterArray counters : mProcStateTimeMs) {
                     if (counters != null) {
@@ -7864,6 +7949,8 @@
                 if (mScreenOffCpuFreqTimeMs != null) {
                     mScreenOffCpuFreqTimeMs.detach();
                 }
+                mCpuActiveTimeMs.detach();
+                mCpuClusterTimesMs.detach();
 
                 if (mProcStateTimeMs != null) {
                     for (LongSamplingCounterArray counters : mProcStateTimeMs) {
@@ -8139,6 +8226,10 @@
 
             LongSamplingCounterArray.writeToParcel(out, mCpuFreqTimeMs);
             LongSamplingCounterArray.writeToParcel(out, mScreenOffCpuFreqTimeMs);
+
+            mCpuActiveTimeMs.writeToParcel(out);
+            mCpuClusterTimesMs.writeToParcel(out);
+
             if (mProcStateTimeMs != null) {
                 out.writeInt(mProcStateTimeMs.length);
                 for (LongSamplingCounterArray counters : mProcStateTimeMs) {
@@ -8456,6 +8547,9 @@
             mScreenOffCpuFreqTimeMs = LongSamplingCounterArray.readFromParcel(
                     in, mBsi.mOnBatteryScreenOffTimeBase);
 
+            mCpuActiveTimeMs = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
+            mCpuClusterTimesMs = new LongSamplingCounterArray(mBsi.mOnBatteryTimeBase, in);
+
             int length = in.readInt();
             if (length == NUM_PROCESS_STATE) {
                 mProcStateTimeMs = new LongSamplingCounterArray[length];
@@ -9822,6 +9916,10 @@
             mWifiSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -800-i, null,
                     mOnBatteryTimeBase);
         }
+        for (int i=0; i< GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
+            mGpsSignalQualityTimer[i] = new StopwatchTimer(mClocks, null, -1000-i, null,
+                mOnBatteryTimeBase);
+        }
         mAudioOnTimer = new StopwatchTimer(mClocks, null, -7, null, mOnBatteryTimeBase);
         mVideoOnTimer = new StopwatchTimer(mClocks, null, -8, null, mOnBatteryTimeBase);
         mFlashlightOnTimer = new StopwatchTimer(mClocks, null, -9, null, mOnBatteryTimeBase);
@@ -10511,6 +10609,9 @@
             mWifiSignalStrengthsTimer[i].reset(false);
         }
         mWifiMulticastWakelockTimer.reset(false);
+        for (int i=0; i< GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
+            mGpsSignalQualityTimer[i].reset(false);
+        }
         mWifiActivity.reset(false);
         mBluetoothActivity.reset(false);
         mModemActivity.reset(false);
@@ -11437,6 +11538,8 @@
         if (!mOnBatteryInternal) {
             mKernelUidCpuTimeReader.readDelta(null);
             mKernelUidCpuFreqTimeReader.readDelta(null);
+            mKernelUidCpuActiveTimeReader.readDelta(null);
+            mKernelUidCpuClusterTimeReader.readDelta(null);
             for (int cluster = mKernelCpuSpeedReaders.length - 1; cluster >= 0; --cluster) {
                 mKernelCpuSpeedReaders[cluster].readDelta();
             }
@@ -11453,6 +11556,8 @@
             updateClusterSpeedTimes(updatedUids);
         }
         readKernelUidCpuFreqTimesLocked(partialTimersToConsider);
+        readKernelUidCpuActiveTimesLocked();
+        readKernelUidCpuClusterTimesLocked();
     }
 
     /**
@@ -11764,6 +11869,64 @@
         }
     }
 
+    /**
+     * Take a snapshot of the cpu active times spent by each uid and update the corresponding
+     * counters.
+     */
+    @VisibleForTesting
+    public void readKernelUidCpuActiveTimesLocked() {
+        final long startTimeMs = mClocks.uptimeMillis();
+        mKernelUidCpuActiveTimeReader.readDelta((uid, cpuActiveTimesUs) -> {
+            uid = mapUid(uid);
+            if (Process.isIsolated(uid)) {
+                mKernelUidCpuActiveTimeReader.removeUid(uid);
+                Slog.w(TAG, "Got active times for an isolated uid with no mapping: " + uid);
+                return;
+            }
+            if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
+                Slog.w(TAG, "Got active times for an invalid user's uid " + uid);
+                mKernelUidCpuActiveTimeReader.removeUid(uid);
+                return;
+            }
+            final Uid u = getUidStatsLocked(uid);
+            u.mCpuActiveTimeMs.addCountLocked(cpuActiveTimesUs);
+        });
+
+        final long elapsedTimeMs = mClocks.uptimeMillis() - startTimeMs;
+        if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
+            Slog.d(TAG, "Reading cpu active times took " + elapsedTimeMs + "ms");
+        }
+    }
+
+    /**
+     * Take a snapshot of the cpu cluster times spent by each uid and update the corresponding
+     * counters.
+     */
+    @VisibleForTesting
+    public void readKernelUidCpuClusterTimesLocked() {
+        final long startTimeMs = mClocks.uptimeMillis();
+        mKernelUidCpuClusterTimeReader.readDelta((uid, cpuClusterTimesUs) -> {
+            uid = mapUid(uid);
+            if (Process.isIsolated(uid)) {
+                mKernelUidCpuClusterTimeReader.removeUid(uid);
+                Slog.w(TAG, "Got cluster times for an isolated uid with no mapping: " + uid);
+                return;
+            }
+            if (!mUserInfoProvider.exists(UserHandle.getUserId(uid))) {
+                Slog.w(TAG, "Got cluster times for an invalid user's uid " + uid);
+                mKernelUidCpuClusterTimeReader.removeUid(uid);
+                return;
+            }
+            final Uid u = getUidStatsLocked(uid);
+            u.mCpuClusterTimesMs.addCountLocked(cpuClusterTimesUs);
+        });
+
+        final long elapsedTimeMs = mClocks.uptimeMillis() - startTimeMs;
+        if (DEBUG_ENERGY_CPU || elapsedTimeMs >= 100) {
+            Slog.d(TAG, "Reading cpu cluster times took " + elapsedTimeMs + "ms");
+        }
+    }
+
     boolean setChargingLocked(boolean charging) {
         if (mCharging != charging) {
             mCharging = charging;
@@ -12367,6 +12530,21 @@
         return s;
     }
 
+    /*@hide */
+    public GpsBatteryStats getGpsBatteryStats() {
+        GpsBatteryStats s = new GpsBatteryStats();
+        final int which = STATS_SINCE_CHARGED;
+        final long rawRealTime = SystemClock.elapsedRealtime() * 1000;
+        s.setLoggingDurationMs(computeBatteryRealtime(rawRealTime, which) / 1000);
+        s.setEnergyConsumedMaMs(getGpsBatteryDrainMaMs());
+        long[] time = new long[GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS];
+        for (int i=0; i<time.length; i++) {
+            time[i] = getGpsSignalQualityTime(i, rawRealTime, which) / 1000;
+        }
+        s.setTimeInGpsSignalQualityLevel(time);
+        return s;
+    }
+
     @Override
     public LevelStepTracker getChargeLevelStepTracker() {
         return mChargeStepTracker;
@@ -13044,6 +13222,9 @@
         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
             mWifiSignalStrengthsTimer[i].readSummaryFromParcelLocked(in);
         }
+        for (int i=0; i<GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
+            mGpsSignalQualityTimer[i].readSummaryFromParcelLocked(in);
+        }
         mWifiActivity.readSummaryFromParcel(in);
         mBluetoothActivity.readSummaryFromParcel(in);
         mModemActivity.readSummaryFromParcel(in);
@@ -13249,6 +13430,10 @@
                     in, mOnBatteryTimeBase);
             u.mScreenOffCpuFreqTimeMs = LongSamplingCounterArray.readSummaryFromParcelLocked(
                     in, mOnBatteryScreenOffTimeBase);
+
+            u.mCpuActiveTimeMs.readSummaryFromParcelLocked(in);
+            u.mCpuClusterTimesMs.readSummaryFromParcelLocked(in);
+
             int length = in.readInt();
             if (length == Uid.NUM_PROCESS_STATE) {
                 u.mProcStateTimeMs = new LongSamplingCounterArray[length];
@@ -13482,6 +13667,9 @@
         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
             mWifiSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
         }
+        for (int i=0; i< GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
+            mGpsSignalQualityTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
+        }
         mWifiActivity.writeSummaryToParcel(out);
         mBluetoothActivity.writeSummaryToParcel(out);
         mModemActivity.writeSummaryToParcel(out);
@@ -13725,6 +13913,9 @@
             LongSamplingCounterArray.writeSummaryToParcelLocked(out, u.mCpuFreqTimeMs);
             LongSamplingCounterArray.writeSummaryToParcelLocked(out, u.mScreenOffCpuFreqTimeMs);
 
+            u.mCpuActiveTimeMs.writeSummaryFromParcelLocked(out);
+            u.mCpuClusterTimesMs.writeSummaryToParcelLocked(out);
+
             if (u.mProcStateTimeMs != null) {
                 out.writeInt(u.mProcStateTimeMs.length);
                 for (LongSamplingCounterArray counters : u.mProcStateTimeMs) {
@@ -13954,7 +14145,10 @@
             mWifiSignalStrengthsTimer[i] = new StopwatchTimer(mClocks, null, -800-i,
                     null, mOnBatteryTimeBase, in);
         }
-
+        for (int i=0; i<GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
+            mGpsSignalQualityTimer[i] = new StopwatchTimer(mClocks, null, -1000-i,
+                null, mOnBatteryTimeBase, in);
+        }
         mWifiActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
                 NUM_WIFI_TX_LEVELS, in);
         mBluetoothActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
@@ -14154,6 +14348,9 @@
         for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) {
             mWifiSignalStrengthsTimer[i].writeToParcel(out, uSecRealtime);
         }
+        for (int i=0; i< GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
+            mGpsSignalQualityTimer[i].writeToParcel(out, uSecRealtime);
+        }
         mWifiActivity.writeToParcel(out, 0);
         mBluetoothActivity.writeToParcel(out, 0);
         mModemActivity.writeToParcel(out, 0);
@@ -14348,6 +14545,10 @@
                 pr.println("*** Wifi signal strength #" + i + ":");
                 mWifiSignalStrengthsTimer[i].logState(pr, "  ");
             }
+            for (int i=0; i<GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
+                pr.println("*** GPS signal quality #" + i + ":");
+                mGpsSignalQualityTimer[i].logState(pr, "  ");
+            }
             pr.println("*** Flashlight timer:");
             mFlashlightOnTimer.logState(pr, "  ");
             pr.println("*** Camera timer:");
diff --git a/core/java/com/android/internal/os/CpuPowerCalculator.java b/core/java/com/android/internal/os/CpuPowerCalculator.java
index bb743c1..a34e7f5 100644
--- a/core/java/com/android/internal/os/CpuPowerCalculator.java
+++ b/core/java/com/android/internal/os/CpuPowerCalculator.java
@@ -31,8 +31,7 @@
 
     @Override
     public void calculateApp(BatterySipper app, BatteryStats.Uid u, long rawRealtimeUs,
-                             long rawUptimeUs, int statsType) {
-
+            long rawUptimeUs, int statsType) {
         app.cpuTimeMs = (u.getUserCpuTimeUs(statsType) + u.getSystemCpuTimeUs(statsType)) / 1000;
         final int numClusters = mProfile.getNumCpuClusters();
 
@@ -42,7 +41,7 @@
             for (int speed = 0; speed < speedsForCluster; speed++) {
                 final long timeUs = u.getTimeAtCpuSpeed(cluster, speed, statsType);
                 final double cpuSpeedStepPower = timeUs *
-                        mProfile.getAveragePowerForCpu(cluster, speed);
+                        mProfile.getAveragePowerForCpuCore(cluster, speed);
                 if (DEBUG) {
                     Log.d(TAG, "UID " + u.getUid() + ": CPU cluster #" + cluster + " step #"
                             + speed + " timeUs=" + timeUs + " power="
@@ -51,6 +50,25 @@
                 cpuPowerMaUs += cpuSpeedStepPower;
             }
         }
+        cpuPowerMaUs += u.getCpuActiveTime() * mProfile.getAveragePower(
+                PowerProfile.POWER_CPU_ACTIVE);
+        long[] cpuClusterTimes = u.getCpuClusterTimes();
+        if (cpuClusterTimes != null) {
+            if (cpuClusterTimes.length == numClusters) {
+                for (int i = 0; i < numClusters; i++) {
+                    double power = cpuClusterTimes[i] * mProfile.getAveragePowerForCpuCluster(i);
+                    cpuPowerMaUs += power;
+                    if (DEBUG) {
+                        Log.d(TAG, "UID " + u.getUid() + ": CPU cluster #" + i + " clusterTimeUs="
+                                + cpuClusterTimes[i] + " power="
+                                + BatteryStatsHelper.makemAh(power / MICROSEC_IN_HR));
+                    }
+                }
+            } else {
+                Log.w(TAG, "UID " + u.getUid() + " CPU cluster # mismatch: Power Profile # "
+                        + numClusters + " actual # " + cpuClusterTimes.length);
+            }
+        }
         app.cpuPowerMah = cpuPowerMaUs / MICROSEC_IN_HR;
 
         if (DEBUG && (app.cpuTimeMs != 0 || app.cpuPowerMah != 0)) {
diff --git a/core/java/com/android/internal/os/KernelUidCpuActiveTimeReader.java b/core/java/com/android/internal/os/KernelUidCpuActiveTimeReader.java
new file mode 100644
index 0000000..cb96c5c
--- /dev/null
+++ b/core/java/com/android/internal/os/KernelUidCpuActiveTimeReader.java
@@ -0,0 +1,146 @@
+/*
+ * 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.internal.os;
+
+import android.annotation.Nullable;
+import android.os.StrictMode;
+import android.os.SystemClock;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.util.TimeUtils;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.IOException;
+
+/**
+ * Reads /proc/uid_concurrent_active_time which has the format:
+ * active: X (X is # cores)
+ * [uid0]: [time-0] [time-1] [time-2] ... (# entries = # cores)
+ * [uid1]: [time-0] [time-1] [time-2] ... ...
+ * ...
+ * Time-N means the CPU time a UID spent running concurrently with N other processes.
+ * The file contains a monotonically increasing count of time for a single boot. This class
+ * maintains the previous results of a call to {@link #readDelta} in order to provide a
+ * proper delta.
+ */
+public class KernelUidCpuActiveTimeReader {
+    private static final boolean DEBUG = false;
+    private static final String TAG = "KernelUidCpuActiveTimeReader";
+    private static final String UID_TIMES_PROC_FILE = "/proc/uid_concurrent_active_time";
+
+    private int mCoreCount;
+    private long mLastTimeReadMs;
+    private long mNowTimeMs;
+    private SparseArray<long[]> mLastUidCpuActiveTimeMs = new SparseArray<>();
+
+    public interface Callback {
+        void onUidCpuActiveTime(int uid, long cpuActiveTimeMs);
+    }
+
+    public void readDelta(@Nullable Callback cb) {
+        final int oldMask = StrictMode.allowThreadDiskReadsMask();
+        try (BufferedReader reader = new BufferedReader(new FileReader(UID_TIMES_PROC_FILE))) {
+            mNowTimeMs = SystemClock.elapsedRealtime();
+            readDeltaInternal(reader, cb);
+            mLastTimeReadMs = mNowTimeMs;
+        } catch (IOException e) {
+            Slog.e(TAG, "Failed to read " + UID_TIMES_PROC_FILE + ": " + e);
+        } finally {
+            StrictMode.setThreadPolicyMask(oldMask);
+        }
+    }
+
+    public void removeUid(int uid) {
+        mLastUidCpuActiveTimeMs.delete(uid);
+    }
+
+    public void removeUidsInRange(int startUid, int endUid) {
+        if (endUid < startUid) {
+            Slog.w(TAG, "End UID " + endUid + " is smaller than start UID " + startUid);
+            return;
+        }
+        mLastUidCpuActiveTimeMs.put(startUid, null);
+        mLastUidCpuActiveTimeMs.put(endUid, null);
+        final int firstIndex = mLastUidCpuActiveTimeMs.indexOfKey(startUid);
+        final int lastIndex = mLastUidCpuActiveTimeMs.indexOfKey(endUid);
+        mLastUidCpuActiveTimeMs.removeAtRange(firstIndex, lastIndex - firstIndex + 1);
+    }
+
+    @VisibleForTesting
+    public void readDeltaInternal(BufferedReader reader, @Nullable Callback cb) throws IOException {
+        String line = reader.readLine();
+        if (line == null || !line.startsWith("active:")) {
+            Slog.e(TAG, String.format("Malformed proc file: %s ", UID_TIMES_PROC_FILE));
+            return;
+        }
+        if (mCoreCount == 0) {
+            mCoreCount = Integer.parseInt(line.substring(line.indexOf(' ')+1));
+        }
+        while ((line = reader.readLine()) != null) {
+            final int index = line.indexOf(' ');
+            final int uid = Integer.parseInt(line.substring(0, index - 1), 10);
+            readTimesForUid(uid, line.substring(index + 1), cb);
+        }
+    }
+
+    private void readTimesForUid(int uid, String line, @Nullable Callback cb) {
+        long[] lastActiveTime = mLastUidCpuActiveTimeMs.get(uid);
+        if (lastActiveTime == null) {
+            lastActiveTime = new long[mCoreCount];
+            mLastUidCpuActiveTimeMs.put(uid, lastActiveTime);
+        }
+        final String[] timesStr = line.split(" ");
+        if (timesStr.length != mCoreCount) {
+            Slog.e(TAG, String.format("# readings don't match # cores, readings: %d, CPU cores: %d",
+                    timesStr.length, mCoreCount));
+            return;
+        }
+        long sumDeltas = 0;
+        final long[] curActiveTime = new long[mCoreCount];
+        boolean notify = false;
+        for (int i = 0; i < mCoreCount; i++) {
+            // Times read will be in units of 10ms
+            curActiveTime[i] = Long.parseLong(timesStr[i], 10) * 10;
+            long delta = curActiveTime[i] - lastActiveTime[i];
+            if (delta < 0 || curActiveTime[i] < 0) {
+                if (DEBUG) {
+                    final StringBuilder sb = new StringBuilder();
+                    sb.append(String.format("Malformed cpu active time for UID=%d\n", uid));
+                    sb.append(String.format("data=(%d,%d)\n", lastActiveTime[i], curActiveTime[i]));
+                    sb.append("times=(");
+                    TimeUtils.formatDuration(mLastTimeReadMs, sb);
+                    sb.append(",");
+                    TimeUtils.formatDuration(mNowTimeMs, sb);
+                    sb.append(")");
+                    Slog.e(TAG, sb.toString());
+                }
+                return;
+            }
+            notify |= delta > 0;
+            sumDeltas += delta / (i + 1);
+        }
+        if (notify) {
+            System.arraycopy(curActiveTime, 0, lastActiveTime, 0, mCoreCount);
+            if (cb != null) {
+                cb.onUidCpuActiveTime(uid, sumDeltas);
+            }
+        }
+    }
+}
diff --git a/core/java/com/android/internal/os/KernelUidCpuClusterTimeReader.java b/core/java/com/android/internal/os/KernelUidCpuClusterTimeReader.java
new file mode 100644
index 0000000..85153bc
--- /dev/null
+++ b/core/java/com/android/internal/os/KernelUidCpuClusterTimeReader.java
@@ -0,0 +1,178 @@
+/*
+ * 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.internal.os;
+
+import android.annotation.Nullable;
+import android.os.StrictMode;
+import android.os.SystemClock;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.util.TimeUtils;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Reads /proc/uid_concurrent_policy_time which has the format:
+ * policy0: X policy4: Y (there are X cores on policy0, Y cores on policy4)
+ * [uid0]: [time-0-0] [time-0-1] ... [time-1-0] [time-1-1] ...
+ * [uid1]: [time-0-0] [time-0-1] ... [time-1-0] [time-1-1] ...
+ * ...
+ * Time-X-Y means the time a UID spent on clusterX running concurrently with Y other processes.
+ * The file contains a monotonically increasing count of time for a single boot. This class
+ * maintains the previous results of a call to {@link #readDelta} in order to provide a proper
+ * delta.
+ */
+public class KernelUidCpuClusterTimeReader {
+
+    private static final boolean DEBUG = false;
+    private static final String TAG = "KernelUidCpuClusterTimeReader";
+    private static final String UID_TIMES_PROC_FILE = "/proc/uid_concurrent_policy_time";
+
+    // mCoreOnCluster[i] is the # of cores on cluster i
+    private int[] mCoreOnCluster;
+    private int mCores;
+    private long mLastTimeReadMs;
+    private long mNowTimeMs;
+    private SparseArray<long[]> mLastUidPolicyTimeMs = new SparseArray<>();
+
+    public interface Callback {
+        /**
+         * @param uid
+         * @param cpuActiveTimeMs the first dimension is cluster, the second dimension is the # of
+         *                        processes running concurrently with this uid.
+         */
+        void onUidCpuPolicyTime(int uid, long[] cpuActiveTimeMs);
+    }
+
+    public void readDelta(@Nullable Callback cb) {
+        final int oldMask = StrictMode.allowThreadDiskReadsMask();
+        try (BufferedReader reader = new BufferedReader(new FileReader(UID_TIMES_PROC_FILE))) {
+            mNowTimeMs = SystemClock.elapsedRealtime();
+            readDeltaInternal(reader, cb);
+            mLastTimeReadMs = mNowTimeMs;
+        } catch (IOException e) {
+            Slog.e(TAG, "Failed to read " + UID_TIMES_PROC_FILE + ": " + e);
+        } finally {
+            StrictMode.setThreadPolicyMask(oldMask);
+        }
+    }
+
+    public void removeUid(int uid) {
+        mLastUidPolicyTimeMs.delete(uid);
+    }
+
+    public void removeUidsInRange(int startUid, int endUid) {
+        if (endUid < startUid) {
+            Slog.w(TAG, "End UID " + endUid + " is smaller than start UID " + startUid);
+            return;
+        }
+        mLastUidPolicyTimeMs.put(startUid, null);
+        mLastUidPolicyTimeMs.put(endUid, null);
+        final int firstIndex = mLastUidPolicyTimeMs.indexOfKey(startUid);
+        final int lastIndex = mLastUidPolicyTimeMs.indexOfKey(endUid);
+        mLastUidPolicyTimeMs.removeAtRange(firstIndex, lastIndex - firstIndex + 1);
+    }
+
+    @VisibleForTesting
+    public void readDeltaInternal(BufferedReader reader, @Nullable Callback cb) throws IOException {
+        String line = reader.readLine();
+        if (line == null || !line.startsWith("policy")) {
+            Slog.e(TAG, String.format("Malformed proc file: %s ", UID_TIMES_PROC_FILE));
+            return;
+        }
+        if (mCoreOnCluster == null) {
+            List<Integer> list = new ArrayList<>();
+            String[] policies = line.split(" ");
+
+            if (policies.length == 0 || policies.length % 2 != 0) {
+                Slog.e(TAG, String.format("Malformed proc file: %s ", UID_TIMES_PROC_FILE));
+                return;
+            }
+
+            for (int i = 0; i < policies.length; i+=2) {
+                list.add(Integer.parseInt(policies[i+1]));
+            }
+
+            mCoreOnCluster = new int[list.size()];
+            for(int i=0;i<list.size();i++){
+                mCoreOnCluster[i] = list.get(i);
+                mCores += mCoreOnCluster[i];
+            }
+        }
+        while ((line = reader.readLine()) != null) {
+            final int index = line.indexOf(' ');
+            final int uid = Integer.parseInt(line.substring(0, index - 1), 10);
+            readTimesForUid(uid, line.substring(index + 1), cb);
+        }
+    }
+
+    private void readTimesForUid(int uid, String line, @Nullable Callback cb) {
+        long[] lastPolicyTime = mLastUidPolicyTimeMs.get(uid);
+        if (lastPolicyTime == null) {
+            lastPolicyTime = new long[mCores];
+            mLastUidPolicyTimeMs.put(uid, lastPolicyTime);
+        }
+        final String[] timeStr = line.split(" ");
+        if (timeStr.length != mCores) {
+            Slog.e(TAG, String.format("# readings don't match # cores, readings: %d, # CPU cores: %d",
+                    timeStr.length, mCores));
+            return;
+        }
+        final long[] deltaPolicyTime = new long[mCores];
+        final long[] currPolicyTime = new long[mCores];
+        boolean notify = false;
+        for (int i = 0; i < mCores; i++) {
+            // Times read will be in units of 10ms
+            currPolicyTime[i] = Long.parseLong(timeStr[i], 10) * 10;
+            deltaPolicyTime[i] = currPolicyTime[i] - lastPolicyTime[i];
+            if (deltaPolicyTime[i] < 0 || currPolicyTime[i] < 0) {
+                if (DEBUG) {
+                    final StringBuilder sb = new StringBuilder();
+                    sb.append(String.format("Malformed cpu policy time for UID=%d\n", uid));
+                    sb.append(String.format("data=(%d,%d)\n", lastPolicyTime[i], currPolicyTime[i]));
+                    sb.append("times=(");
+                    TimeUtils.formatDuration(mLastTimeReadMs, sb);
+                    sb.append(",");
+                    TimeUtils.formatDuration(mNowTimeMs, sb);
+                    sb.append(")");
+                    Slog.e(TAG, sb.toString());
+                }
+                return;
+            }
+            notify |= deltaPolicyTime[i] > 0;
+        }
+        if (notify) {
+            System.arraycopy(currPolicyTime, 0, lastPolicyTime, 0, mCores);
+            if (cb != null) {
+                final long[] times = new long[mCoreOnCluster.length];
+                int core = 0;
+                for (int i = 0; i < mCoreOnCluster.length; i++) {
+                    for (int j = 0; j < mCoreOnCluster[i]; j++) {
+                        times[i] += deltaPolicyTime[core++] / (j+1);
+                    }
+                }
+                cb.onUidCpuPolicyTime(uid, times);
+            }
+        }
+    }
+}
diff --git a/core/java/com/android/internal/os/PowerProfile.java b/core/java/com/android/internal/os/PowerProfile.java
index 872b465..fcbbcd0 100644
--- a/core/java/com/android/internal/os/PowerProfile.java
+++ b/core/java/com/android/internal/os/PowerProfile.java
@@ -21,6 +21,7 @@
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.XmlUtils;
 
 import org.xmlpull.v1.XmlPullParser;
@@ -43,23 +44,25 @@
     public static final String POWER_NONE = "none";
 
     /**
-     * Power consumption when CPU is in power collapse mode.
+     * POWER_CPU_SUSPEND: Power consumption when CPU is in power collapse mode.
+     * POWER_CPU_IDLE: Power consumption when CPU is awake (when a wake lock is held). This should
+     *                 be zero on devices that can go into full CPU power collapse even when a wake
+     *                 lock is held. Otherwise, this is the power consumption in addition to
+     *                 POWER_CPU_SUSPEND due to a wake lock being held but with no CPU activity.
+     * POWER_CPU_ACTIVE: Power consumption when CPU is running, excluding power consumed by clusters
+     *                   and cores.
+     *
+     * CPU Power Equation (assume two clusters):
+     * Total power = POWER_CPU_SUSPEND  (always added)
+     *               + POWER_CPU_IDLE   (skip this and below if in power collapse mode)
+     *               + POWER_CPU_ACTIVE (skip this and below if CPU is not running, but a wakelock
+     *                                   is held)
+     *               + cluster_power.cluster0 + cluster_power.cluster1 (skip cluster not running)
+     *               + core_power.cluster0 * num running cores in cluster 0
+     *               + core_power.cluster1 * num running cores in cluster 1
      */
+    public static final String POWER_CPU_SUSPEND = "cpu.suspend";
     public static final String POWER_CPU_IDLE = "cpu.idle";
-
-    /**
-     * Power consumption when CPU is awake (when a wake lock is held).  This
-     * should be 0 on devices that can go into full CPU power collapse even
-     * when a wake lock is held.  Otherwise, this is the power consumption in
-     * addition to POWER_CPU_IDLE due to a wake lock being held but with no
-     * CPU activity.
-     */
-    public static final String POWER_CPU_AWAKE = "cpu.awake";
-
-    /**
-     * Power consumption when CPU is in power collapse mode.
-     */
-    @Deprecated
     public static final String POWER_CPU_ACTIVE = "cpu.active";
 
     /**
@@ -182,9 +185,6 @@
      */
     public static final String POWER_CAMERA = "camera.avg";
 
-    @Deprecated
-    public static final String POWER_CPU_SPEEDS = "cpu.speeds";
-
     /**
      * Power consumed by wif batched scaning.  Broken down into bins by
      * Channels Scanned per Hour.  May do 1-720 scans per hour of 1-100 channels
@@ -197,7 +197,15 @@
      */
     public static final String POWER_BATTERY_CAPACITY = "battery.capacity";
 
-    static final HashMap<String, Object> sPowerMap = new HashMap<>();
+    /**
+     * A map from Power Use Item to its power consumption.
+     */
+    static final HashMap<String, Double> sPowerItemMap = new HashMap<>();
+    /**
+     * A map from Power Use Item to an array of its power consumption
+     * (for items with variable power e.g. CPU).
+     */
+    static final HashMap<String, Double[]> sPowerArrayMap = new HashMap<>();
 
     private static final String TAG_DEVICE = "device";
     private static final String TAG_ITEM = "item";
@@ -207,23 +215,32 @@
 
     private static final Object sLock = new Object();
 
+    @VisibleForTesting
     public PowerProfile(Context context) {
-        // Read the XML file for the given profile (normally only one per
-        // device)
+        this(context, false);
+    }
+
+    /**
+     * For PowerProfileTest
+     */
+    @VisibleForTesting
+    public PowerProfile(Context context, boolean forTest) {
+        // Read the XML file for the given profile (normally only one per device)
         synchronized (sLock) {
-            if (sPowerMap.size() == 0) {
-                readPowerValuesFromXml(context);
+            if (sPowerItemMap.size() == 0 && sPowerArrayMap.size() == 0) {
+                readPowerValuesFromXml(context, forTest);
             }
             initCpuClusters();
         }
     }
 
-    private void readPowerValuesFromXml(Context context) {
-        int id = com.android.internal.R.xml.power_profile;
+    private void readPowerValuesFromXml(Context context, boolean forTest) {
+        final int id = forTest ? com.android.internal.R.xml.power_profile_test :
+                com.android.internal.R.xml.power_profile;
         final Resources resources = context.getResources();
         XmlResourceParser parser = resources.getXml(id);
         boolean parsingArray = false;
-        ArrayList<Double> array = new ArrayList<Double>();
+        ArrayList<Double> array = new ArrayList<>();
         String arrayName = null;
 
         try {
@@ -237,7 +254,7 @@
 
                 if (parsingArray && !element.equals(TAG_ARRAYITEM)) {
                     // Finish array
-                    sPowerMap.put(arrayName, array.toArray(new Double[array.size()]));
+                    sPowerArrayMap.put(arrayName, array.toArray(new Double[array.size()]));
                     parsingArray = false;
                 }
                 if (element.equals(TAG_ARRAY)) {
@@ -255,7 +272,7 @@
                         } catch (NumberFormatException nfe) {
                         }
                         if (element.equals(TAG_ITEM)) {
-                            sPowerMap.put(name, value);
+                            sPowerItemMap.put(name, value);
                         } else if (parsingArray) {
                             array.add(value);
                         }
@@ -263,7 +280,7 @@
                 }
             }
             if (parsingArray) {
-                sPowerMap.put(arrayName, array.toArray(new Double[array.size()]));
+                sPowerArrayMap.put(arrayName, array.toArray(new Double[array.size()]));
             }
         } catch (XmlPullParserException e) {
             throw new RuntimeException(e);
@@ -300,52 +317,56 @@
             String key = configResIdKeys[i];
             // if we already have some of these parameters in power_profile.xml, ignore the
             // value in config.xml
-            if ((sPowerMap.containsKey(key) && (Double) sPowerMap.get(key) > 0)) {
+            if ((sPowerItemMap.containsKey(key) && sPowerItemMap.get(key) > 0)) {
                 continue;
             }
             int value = resources.getInteger(configResIds[i]);
             if (value > 0) {
-                sPowerMap.put(key, (double) value);
+                sPowerItemMap.put(key, (double) value);
             }
         }
     }
 
     private CpuClusterKey[] mCpuClusters;
 
-    private static final String POWER_CPU_CLUSTER_CORE_COUNT = "cpu.clusters.cores";
-    private static final String POWER_CPU_CLUSTER_SPEED_PREFIX = "cpu.speeds.cluster";
-    private static final String POWER_CPU_CLUSTER_ACTIVE_PREFIX = "cpu.active.cluster";
+    private static final String CPU_PER_CLUSTER_CORE_COUNT = "cpu.clusters.cores";
+    private static final String CPU_CLUSTER_POWER_COUNT = "cpu.cluster_power.cluster";
+    private static final String CPU_CORE_SPEED_PREFIX = "cpu.core_speeds.cluster";
+    private static final String CPU_CORE_POWER_PREFIX = "cpu.core_power.cluster";
 
-    @SuppressWarnings("deprecation")
     private void initCpuClusters() {
-        // Figure out how many CPU clusters we're dealing with
-        final Object obj = sPowerMap.get(POWER_CPU_CLUSTER_CORE_COUNT);
-        if (obj == null || !(obj instanceof Double[])) {
+        if (sPowerArrayMap.containsKey(CPU_PER_CLUSTER_CORE_COUNT)) {
+            final Double[] data = sPowerArrayMap.get(CPU_PER_CLUSTER_CORE_COUNT);
+            mCpuClusters = new CpuClusterKey[data.length];
+            for (int cluster = 0; cluster < data.length; cluster++) {
+                int numCpusInCluster = (int) Math.round(data[cluster]);
+                mCpuClusters[cluster] = new CpuClusterKey(
+                        CPU_CORE_SPEED_PREFIX + cluster, CPU_CLUSTER_POWER_COUNT + cluster,
+                        CPU_CORE_POWER_PREFIX + cluster, numCpusInCluster);
+            }
+        } else {
             // Default to single.
             mCpuClusters = new CpuClusterKey[1];
-            mCpuClusters[0] = new CpuClusterKey(POWER_CPU_SPEEDS, POWER_CPU_ACTIVE, 1);
-
-        } else {
-            final Double[] array = (Double[]) obj;
-            mCpuClusters = new CpuClusterKey[array.length];
-            for (int cluster = 0; cluster < array.length; cluster++) {
-                int numCpusInCluster = (int) Math.round(array[cluster]);
-                mCpuClusters[cluster] = new CpuClusterKey(
-                        POWER_CPU_CLUSTER_SPEED_PREFIX + cluster,
-                        POWER_CPU_CLUSTER_ACTIVE_PREFIX + cluster,
-                        numCpusInCluster);
+            int numCpus = 1;
+            if (sPowerItemMap.containsKey(CPU_PER_CLUSTER_CORE_COUNT)) {
+                numCpus = (int) Math.round(sPowerItemMap.get(CPU_PER_CLUSTER_CORE_COUNT));
             }
+            mCpuClusters[0] = new CpuClusterKey(CPU_CORE_SPEED_PREFIX + 0,
+                    CPU_CLUSTER_POWER_COUNT + 0, CPU_CORE_POWER_PREFIX + 0, numCpus);
         }
     }
 
     public static class CpuClusterKey {
-        private final String timeKey;
-        private final String powerKey;
+        private final String freqKey;
+        private final String clusterPowerKey;
+        private final String corePowerKey;
         private final int numCpus;
 
-        private CpuClusterKey(String timeKey, String powerKey, int numCpus) {
-            this.timeKey = timeKey;
-            this.powerKey = powerKey;
+        private CpuClusterKey(String freqKey, String clusterPowerKey,
+                String corePowerKey, int numCpus) {
+            this.freqKey = freqKey;
+            this.clusterPowerKey = clusterPowerKey;
+            this.corePowerKey = corePowerKey;
             this.numCpus = numCpus;
         }
     }
@@ -354,21 +375,30 @@
         return mCpuClusters.length;
     }
 
-    public int getNumCoresInCpuCluster(int index) {
-        return mCpuClusters[index].numCpus;
+    public int getNumCoresInCpuCluster(int cluster) {
+        return mCpuClusters[cluster].numCpus;
     }
 
-    public int getNumSpeedStepsInCpuCluster(int index) {
-        Object value = sPowerMap.get(mCpuClusters[index].timeKey);
-        if (value != null && value instanceof Double[]) {
-            return ((Double[])value).length;
+    public int getNumSpeedStepsInCpuCluster(int cluster) {
+        if (cluster < 0 || cluster >= mCpuClusters.length) {
+            return 0; // index out of bound
+        }
+        if (sPowerArrayMap.containsKey(mCpuClusters[cluster].freqKey)) {
+            return sPowerArrayMap.get(mCpuClusters[cluster].freqKey).length;
         }
         return 1; // Only one speed
     }
 
-    public double getAveragePowerForCpu(int cluster, int step) {
+    public double getAveragePowerForCpuCluster(int cluster) {
         if (cluster >= 0 && cluster < mCpuClusters.length) {
-            return getAveragePower(mCpuClusters[cluster].powerKey, step);
+            return getAveragePower(mCpuClusters[cluster].clusterPowerKey);
+        }
+        return 0;
+    }
+
+    public double getAveragePowerForCpuCore(int cluster, int step) {
+        if (cluster >= 0 && cluster < mCpuClusters.length) {
+            return getAveragePower(mCpuClusters[cluster].corePowerKey, step);
         }
         return 0;
     }
@@ -379,14 +409,10 @@
      * @return the number of memory bandwidth buckets.
      */
     public int getNumElements(String key) {
-        if (sPowerMap.containsKey(key)) {
-            Object data = sPowerMap.get(key);
-            if (data instanceof Double[]) {
-                final Double[] values = (Double[]) data;
-                return values.length;
-            } else {
-                return 1;
-            }
+        if (sPowerItemMap.containsKey(key)) {
+            return 1;
+        } else if (sPowerArrayMap.containsKey(key)) {
+            return sPowerArrayMap.get(key).length;
         }
         return 0;
     }
@@ -399,13 +425,10 @@
      * @return the average current in milliAmps.
      */
     public double getAveragePowerOrDefault(String type, double defaultValue) {
-        if (sPowerMap.containsKey(type)) {
-            Object data = sPowerMap.get(type);
-            if (data instanceof Double[]) {
-                return ((Double[])data)[0];
-            } else {
-                return (Double) sPowerMap.get(type);
-            }
+        if (sPowerItemMap.containsKey(type)) {
+            return sPowerItemMap.get(type);
+        } else if (sPowerArrayMap.containsKey(type)) {
+            return sPowerArrayMap.get(type)[0];
         } else {
             return defaultValue;
         }
@@ -429,19 +452,16 @@
      * @return the average current in milliAmps.
      */
     public double getAveragePower(String type, int level) {
-        if (sPowerMap.containsKey(type)) {
-            Object data = sPowerMap.get(type);
-            if (data instanceof Double[]) {
-                final Double[] values = (Double[]) data;
-                if (values.length > level && level >= 0) {
-                    return values[level];
-                } else if (level < 0 || values.length == 0) {
-                    return 0;
-                } else {
-                    return values[values.length - 1];
-                }
+        if (sPowerItemMap.containsKey(type)) {
+            return sPowerItemMap.get(type);
+        } else if (sPowerArrayMap.containsKey(type)) {
+            final Double[] values = sPowerArrayMap.get(type);
+            if (values.length > level && level >= 0) {
+                return values[level];
+            } else if (level < 0 || values.length == 0) {
+                return 0;
             } else {
-                return (Double) data;
+                return values[values.length - 1];
             }
         } else {
             return 0;
diff --git a/core/java/com/android/internal/os/WakelockPowerCalculator.java b/core/java/com/android/internal/os/WakelockPowerCalculator.java
index c7897b2..486b584 100644
--- a/core/java/com/android/internal/os/WakelockPowerCalculator.java
+++ b/core/java/com/android/internal/os/WakelockPowerCalculator.java
@@ -26,7 +26,7 @@
     private long mTotalAppWakelockTimeMs = 0;
 
     public WakelockPowerCalculator(PowerProfile profile) {
-        mPowerWakelock = profile.getAveragePower(PowerProfile.POWER_CPU_AWAKE);
+        mPowerWakelock = profile.getAveragePower(PowerProfile.POWER_CPU_IDLE);
     }
 
     @Override
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index 5ec9094..85655a5 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -55,7 +55,7 @@
             boolean showImeSwitcher);
     void setWindowState(int window, int state);
 
-    void showRecentApps(boolean triggeredFromAltTab, boolean fromHome);
+    void showRecentApps(boolean triggeredFromAltTab);
     void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey);
     void toggleRecentApps();
     void toggleSplitScreen();
diff --git a/core/java/com/android/internal/util/ArrayUtils.java b/core/java/com/android/internal/util/ArrayUtils.java
index 7b023f4..621619c 100644
--- a/core/java/com/android/internal/util/ArrayUtils.java
+++ b/core/java/com/android/internal/util/ArrayUtils.java
@@ -619,6 +619,10 @@
         return size - leftIdx;
     }
 
+    public static @NonNull int[] defeatNullable(@Nullable int[] val) {
+        return (val != null) ? val : EmptyArray.INT;
+    }
+
     public static @NonNull String[] defeatNullable(@Nullable String[] val) {
         return (val != null) ? val : EmptyArray.STRING;
     }
diff --git a/core/java/com/android/internal/util/DumpUtils.java b/core/java/com/android/internal/util/DumpUtils.java
index 66b777e..2b51033 100644
--- a/core/java/com/android/internal/util/DumpUtils.java
+++ b/core/java/com/android/internal/util/DumpUtils.java
@@ -102,6 +102,7 @@
             case android.os.Process.ROOT_UID:
             case android.os.Process.SYSTEM_UID:
             case android.os.Process.SHELL_UID:
+            case android.os.Process.INCIDENTD_UID:
                 return true;
         }
 
diff --git a/core/java/com/android/internal/util/ScreenshotHelper.java b/core/java/com/android/internal/util/ScreenshotHelper.java
index f7ea787..7fd94c6 100644
--- a/core/java/com/android/internal/util/ScreenshotHelper.java
+++ b/core/java/com/android/internal/util/ScreenshotHelper.java
@@ -1,5 +1,6 @@
 package com.android.internal.util;
 
+import android.annotation.NonNull;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -32,8 +33,18 @@
         mContext = context;
     }
 
+    /**
+     * Request a screenshot be taken.
+     *
+     * @param screenshotType The type of screenshot, for example either
+     *                       {@link android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN}
+     *                       or {@link android.view.WindowManager.TAKE_SCREENSHOT_SELECTED_REGION}
+     * @param hasStatus {@code true} if the status bar is currently showing. {@code false} if not.
+     * @param hasNav {@code true} if the navigation bar is currently showing. {@code false} if not.
+     * @param handler A handler used in case the screenshot times out
+     */
     public void takeScreenshot(final int screenshotType, final boolean hasStatus,
-            final boolean hasNav, Handler handler) {
+            final boolean hasNav, @NonNull Handler handler) {
         synchronized (mScreenshotLock) {
             if (mScreenshotConnection != null) {
                 return;
diff --git a/core/java/com/android/internal/widget/ILockSettings.aidl b/core/java/com/android/internal/widget/ILockSettings.aidl
index 274239b..e3f1f47 100644
--- a/core/java/com/android/internal/widget/ILockSettings.aidl
+++ b/core/java/com/android/internal/widget/ILockSettings.aidl
@@ -60,7 +60,7 @@
             in byte[] token, int requestedQuality, int userId);
     void unlockUserWithToken(long tokenHandle, in byte[] token, int userId);
 
-    // Keystore RecoveryManager methods.
+    // Keystore RecoveryController methods.
     // {@code ServiceSpecificException} may be thrown to signal an error, which caller can
     // convert to  {@code RecoveryManagerException}.
     void initRecoveryService(in String rootCertificateAlias, in byte[] signedPublicKeyList);
diff --git a/core/jni/android/graphics/ImageDecoder.cpp b/core/jni/android/graphics/ImageDecoder.cpp
index ed9d0e9..1c2528f 100644
--- a/core/jni/android/graphics/ImageDecoder.cpp
+++ b/core/jni/android/graphics/ImageDecoder.cpp
@@ -393,7 +393,7 @@
         canvas.drawBitmap(bm, 0.0f, 0.0f, &paint);
 
         bm.swap(scaledBm);
-        nativeBitmap = scaledPixelRef;
+        nativeBitmap = std::move(scaledPixelRef);
     }
 
     if (jpostProcess) {
diff --git a/core/jni/android_os_HwParcel.cpp b/core/jni/android_os_HwParcel.cpp
index 9494fb8..061349a 100644
--- a/core/jni/android_os_HwParcel.cpp
+++ b/core/jni/android_os_HwParcel.cpp
@@ -391,6 +391,10 @@
     Status status;
     status_t err = ::android::hardware::readFromParcel(&status, *parcel);
     signalExceptionForError(env, err);
+
+    if (!status.isOk()) {
+        signalExceptionForError(env, UNKNOWN_ERROR, true /* canThrowRemoteException */);
+    }
 }
 
 static void JHwParcel_native_release(
diff --git a/core/jni/android_text_MeasuredParagraph.cpp b/core/jni/android_text_MeasuredParagraph.cpp
index bdae0b2..58c05b4 100644
--- a/core/jni/android_text_MeasuredParagraph.cpp
+++ b/core/jni/android_text_MeasuredParagraph.cpp
@@ -85,12 +85,12 @@
 
 // Regular JNI
 static jlong nBuildNativeMeasuredParagraph(JNIEnv* env, jclass /* unused */, jlong builderPtr,
-                                      jcharArray javaText) {
+                                      jcharArray javaText, jboolean computeHyphenation) {
     ScopedCharArrayRO text(env, javaText);
     const minikin::U16StringPiece textBuffer(text.get(), text.size());
 
     // Pass the ownership to Java.
-    return toJLong(toBuilder(builderPtr)->build(textBuffer).release());
+    return toJLong(toBuilder(builderPtr)->build(textBuffer, computeHyphenation).release());
 }
 
 // Regular JNI
@@ -108,7 +108,7 @@
     {"nInitBuilder", "()J", (void*) nInitBuilder},
     {"nAddStyleRun", "(JJIIZ)V", (void*) nAddStyleRun},
     {"nAddReplacementRun", "(JJIIF)V", (void*) nAddReplacementRun},
-    {"nBuildNativeMeasuredParagraph", "(J[C)J", (void*) nBuildNativeMeasuredParagraph},
+    {"nBuildNativeMeasuredParagraph", "(J[CZ)J", (void*) nBuildNativeMeasuredParagraph},
     {"nFreeBuilder", "(J)V", (void*) nFreeBuilder},
 
     // MeasuredParagraph native functions.
diff --git a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp
index 0cb6935..d254de6 100644
--- a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp
+++ b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp
@@ -45,6 +45,7 @@
     jfieldID tag;
     jfieldID metered;
     jfieldID roaming;
+    jfieldID defaultNetwork;
     jfieldID rxBytes;
     jfieldID rxPackets;
     jfieldID txBytes;
@@ -246,6 +247,9 @@
     ScopedIntArrayRW roaming(env, get_int_array(env, stats,
             gNetworkStatsClassInfo.roaming, size, grow));
     if (roaming.get() == NULL) return -1;
+    ScopedIntArrayRW defaultNetwork(env, get_int_array(env, stats,
+            gNetworkStatsClassInfo.defaultNetwork, size, grow));
+    if (defaultNetwork.get() == NULL) return -1;
     ScopedLongArrayRW rxBytes(env, get_long_array(env, stats,
             gNetworkStatsClassInfo.rxBytes, size, grow));
     if (rxBytes.get() == NULL) return -1;
@@ -269,7 +273,7 @@
         uid[i] = lines[i].uid;
         set[i] = lines[i].set;
         tag[i] = lines[i].tag;
-        // Metered and Roaming are populated in Java-land by inspecting the iface properties.
+        // Metered, roaming and defaultNetwork are populated in Java-land.
         rxBytes[i] = lines[i].rxBytes;
         rxPackets[i] = lines[i].rxPackets;
         txBytes[i] = lines[i].txBytes;
@@ -285,6 +289,8 @@
         env->SetObjectField(stats, gNetworkStatsClassInfo.tag, tag.getJavaArray());
         env->SetObjectField(stats, gNetworkStatsClassInfo.metered, metered.getJavaArray());
         env->SetObjectField(stats, gNetworkStatsClassInfo.roaming, roaming.getJavaArray());
+        env->SetObjectField(stats, gNetworkStatsClassInfo.defaultNetwork,
+                defaultNetwork.getJavaArray());
         env->SetObjectField(stats, gNetworkStatsClassInfo.rxBytes, rxBytes.getJavaArray());
         env->SetObjectField(stats, gNetworkStatsClassInfo.rxPackets, rxPackets.getJavaArray());
         env->SetObjectField(stats, gNetworkStatsClassInfo.txBytes, txBytes.getJavaArray());
@@ -318,6 +324,7 @@
     gNetworkStatsClassInfo.tag = GetFieldIDOrDie(env, clazz, "tag", "[I");
     gNetworkStatsClassInfo.metered = GetFieldIDOrDie(env, clazz, "metered", "[I");
     gNetworkStatsClassInfo.roaming = GetFieldIDOrDie(env, clazz, "roaming", "[I");
+    gNetworkStatsClassInfo.defaultNetwork = GetFieldIDOrDie(env, clazz, "defaultNetwork", "[I");
     gNetworkStatsClassInfo.rxBytes = GetFieldIDOrDie(env, clazz, "rxBytes", "[J");
     gNetworkStatsClassInfo.rxPackets = GetFieldIDOrDie(env, clazz, "rxPackets", "[J");
     gNetworkStatsClassInfo.txBytes = GetFieldIDOrDie(env, clazz, "txBytes", "[J");
diff --git a/core/proto/android/server/forceappstandbytracker.proto b/core/proto/android/server/forceappstandbytracker.proto
index c9f7d52..8753bf7 100644
--- a/core/proto/android/server/forceappstandbytracker.proto
+++ b/core/proto/android/server/forceappstandbytracker.proto
@@ -41,13 +41,4 @@
 
   // Packages that are disallowed OP_RUN_ANY_IN_BACKGROUND.
   repeated RunAnyInBackgroundRestrictedPackages run_any_in_background_restricted_packages = 5;
-
-  // Whether device is a small battery device
-  optional bool is_small_battery_device = 6;
-
-  // Whether force app standby for small battery device setting is enabled
-  optional bool force_all_apps_standby_for_small_battery = 7;
-
-  // Whether device is charging
-  optional bool is_charging = 8;
 }
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index d2a22d0..e4e46f6 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -554,8 +554,6 @@
     <protected-broadcast android:name="android.intent.action.DEVICE_LOCKED_CHANGED" />
 
     <!-- Added in O -->
-    <!-- TODO: temporary broadcast used by AutoFillManagerServiceImpl; will be removed -->
-    <protected-broadcast android:name="com.android.internal.autofill.action.REQUEST_AUTOFILL" />
     <protected-broadcast android:name="android.app.action.APPLICATION_DELEGATION_SCOPES_CHANGED" />
     <protected-broadcast android:name="com.android.server.wm.ACTION_REVOKE_SYSTEM_ALERT_WINDOW_PERMISSION" />
     <protected-broadcast android:name="android.media.tv.action.PARENTAL_CONTROLS_ENABLED_CHANGED" />
@@ -1749,6 +1747,12 @@
     <permission android:name="android.permission.SEND_EMBMS_INTENTS"
         android:protectionLevel="signature|privileged" />
 
+
+    <!-- Allows internal management of the sensor framework
+         @hide -->
+    <permission android:name="android.permission.MANAGE_SENSORS"
+        android:protectionLevel="signature" />
+
     <!-- Must be required by an ImsService to ensure that only the
          system can bind to it.
          <p>Protection level: signature|privileged
@@ -2684,6 +2688,13 @@
     <permission android:name="android.permission.BIND_AUTOFILL_SERVICE"
         android:protectionLevel="signature" />
 
+    <!-- Must be required by an {@link android.service.autofill.AutofillFieldClassificationService}
+         to ensure that only the system can bind to it.
+         @hide This is not a third-party API (intended for OEMs and system apps).
+    -->
+    <permission android:name="android.permission.BIND_AUTOFILL_FIELD_CLASSIFICATION_SERVICE"
+                android:protectionLevel="signature" />
+
     <!-- Must be required by hotword enrollment application,
          to ensure that only the system can interact with it.
          @hide <p>Not for use by third-party applications.</p> -->
@@ -3687,6 +3698,10 @@
     <permission android:name="android.permission.READ_RUNTIME_PROFILES"
                 android:protectionLevel="signature|privileged" />
 
+    <!-- @hide Allows audio policy management. -->
+    <permission android:name="android.permission.MANAGE_AUDIO_POLICY"
+        android:protectionLevel="signature" />
+
     <!-- @SystemApi Allows an application to turn on / off quiet mode.
          @hide <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.MODIFY_QUIET_MODE"
diff --git a/core/res/res/values-watch/themes_device_defaults.xml b/core/res/res/values-watch/themes_device_defaults.xml
index f6752c2..a7736e7c 100644
--- a/core/res/res/values-watch/themes_device_defaults.xml
+++ b/core/res/res/values-watch/themes_device_defaults.xml
@@ -10,7 +10,7 @@
      Unless required by applicable law or agreed to in writing, software
      distributed under the License is distributed on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
+     See the License for the specific language gning permissions and
      limitations under the License.
 -->
 
@@ -147,6 +147,7 @@
     an activity that looks like a Dialog.-->
     <style name="Theme.DeviceDefault.Dialog" parent="Theme.Material.Dialog" >
         <item name="windowIsFloating">false</item>
+        <item name="windowElevation">0dp</item>
         <item name="windowTitleStyle">@style/DialogWindowTitle.DeviceDefault</item>
         <item name="windowAnimationStyle">@style/Animation.DeviceDefault.Dialog</item>
 
@@ -183,6 +184,7 @@
 
     <style name="Theme.DeviceDefault.Settings.Dialog.Alert" parent="Theme.Material.Dialog.Alert">
         <item name="windowIsFloating">false</item>
+        <item name="windowElevation">0dp</item>
         <!-- Color palette Dark -->
         <item name="colorPrimary">@color/primary_device_default_dark</item>
         <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
@@ -200,6 +202,7 @@
 
     <style name="Theme.DeviceDefault.Settings.CompactMenu" parent="Theme.Material.CompactMenu">
         <item name="windowIsFloating">false</item>
+        <item name="windowElevation">0dp</item>
         <!-- Color palette Dark -->
         <item name="colorPrimary">@color/primary_device_default_dark</item>
         <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
@@ -219,6 +222,7 @@
     regular dialog. -->
     <style name="Theme.DeviceDefault.Dialog.MinWidth" parent="Theme.Material.Dialog.MinWidth">
         <item name="windowIsFloating">false</item>
+        <item name="windowElevation">0dp</item>
         <!-- Color palette Dark -->
         <item name="colorPrimary">@color/primary_device_default_dark</item>
         <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
@@ -237,6 +241,7 @@
     <!-- Variant of {@link #Theme_DeviceDefault_Dialog} without an action bar -->
     <style name="Theme.DeviceDefault.Dialog.NoActionBar" parent="Theme.Material.Dialog.NoActionBar">
         <item name="windowIsFloating">false</item>
+        <item name="windowElevation">0dp</item>
         <!-- Color palette Dark -->
         <item name="colorPrimary">@color/primary_device_default_dark</item>
         <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
@@ -256,6 +261,7 @@
     for a regular dialog. -->
     <style name="Theme.DeviceDefault.Dialog.NoActionBar.MinWidth" parent="Theme.Material.Dialog.NoActionBar.MinWidth">
         <item name="windowIsFloating">false</item>
+        <item name="windowElevation">0dp</item>
         <!-- Color palette Dark -->
         <item name="colorPrimary">@color/primary_device_default_dark</item>
         <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
@@ -434,6 +440,7 @@
 
     <style name="Theme.DeviceDefault.Dialog.NoFrame" parent="Theme.Material.Dialog.NoFrame">
         <item name="windowIsFloating">false</item>
+        <item name="windowElevation">0dp</item>
         <!-- Color palette Dialog -->
         <item name="colorPrimary">@color/primary_device_default_dark</item>
         <item name="colorPrimaryDark">@color/primary_dark_device_default_dark</item>
diff --git a/core/res/res/values-watch/themes_material.xml b/core/res/res/values-watch/themes_material.xml
index 0cf398b..40a249a 100644
--- a/core/res/res/values-watch/themes_material.xml
+++ b/core/res/res/values-watch/themes_material.xml
@@ -43,6 +43,7 @@
     <!-- Override behaviour to set the theme colours for dialogs, keep them the same. -->
     <style name="ThemeOverlay.Material.Dialog" parent="ThemeOverlay.Material.BaseDialog">
         <item name="windowIsFloating">false</item>
+        <item name="windowElevation">0dp</item>
     </style>
 
     <!-- Force the background and floating colours to be the default colours. -->
@@ -51,6 +52,7 @@
         <item name="colorBackgroundFloating">@color/background_floating_material_dark</item>
         <item name="colorBackgroundCacheHint">@color/background_cache_hint_selector_material_dark</item>
         <item name="windowIsFloating">false</item>
+        <item name="windowElevation">0dp</item>
     </style>
 
     <!-- Force the background and floating colours to be the default colours. -->
@@ -59,6 +61,7 @@
         <item name="colorBackgroundFloating">@color/background_floating_material_light</item>
         <item name="colorBackgroundCacheHint">@color/background_cache_hint_selector_material_light</item>
         <item name="windowIsFloating">false</item>
+        <item name="windowElevation">0dp</item>
     </style>
 
     <!-- Force all settings themes to use normal Material theme. -->
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index fd33dc9..4eaf93d 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -4876,6 +4876,8 @@
             <!-- Justification by stretching word spacing. -->
             <enum name="inter_word" value = "1" />
         </attr>
+        <!-- Whether or not this view is a heading for accessibility purposes. -->
+        <attr name="accessibilityHeading" format="boolean"/>
     </declare-styleable>
     <declare-styleable name="TextViewAppearance">
         <!-- Base text color, typeface, size, and style. -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 3b02a96..7005e28 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -640,6 +640,12 @@
     <!-- Wifi driver supports batched scan -->
     <bool translatable="false" name="config_wifi_batched_scan_supported">false</bool>
 
+    <!-- Wifi driver supports Automatic channel selection (ACS) for softap -->
+    <bool translatable="false" name="config_wifi_softap_acs_supported">false</bool>
+
+    <!-- Wifi driver supports IEEE80211AC for softap -->
+    <bool translatable="false" name="config_wifi_softap_ieee80211ac_supported">false</bool>
+
     <!-- Idle Receive current for wifi radio. 0 by default-->
     <integer translatable="false" name="config_wifi_idle_receive_cur_ma">0</integer>
 
@@ -2780,8 +2786,22 @@
     <!-- The bounding path of the cutout region of the main built-in display.
          Must either be empty if there is no cutout region, or a string that is parsable by
          {@link android.util.PathParser}.
+
          The path is assumed to be specified in display coordinates with pixel units and in
-         the display's native orientation. -->
+         the display's native orientation, with the origin of the coordinate system at the
+         center top of the display.
+
+         To facilitate writing device-independent emulation overlays, the marker `@dp` can be
+         appended after the path string to interpret coordinates in dp instead of px units.
+         Note that a physical cutout should be configured in pixels for the best results.
+
+         Example for a 10px x 10px square top-center cutout:
+                <string ...>M -5,0 L -5,10 L 5,10 L 5,0 Z</string>
+         Example for a 10dp x 10dp square top-center cutout:
+                <string ...>M -5,0 L -5,10 L 5,10 L 5,0 Z @dp</string>
+
+         @see https://www.w3.org/TR/SVG/paths.html#PathData
+         -->
     <string translatable="false" name="config_mainBuiltInDisplayCutout"></string>
 
     <!-- Whether the display cutout region of the main built-in display should be forced to
@@ -3252,4 +3272,6 @@
 
     <!-- Package name that should be granted Notification Assistant access -->
     <string name="config_defaultAssistantAccessPackage" translatable="false">android.ext.services</string>
+
+    <bool name="config_supportBluetoothPersistedState">true</bool>
 </resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 656add6..9cdf553 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2865,6 +2865,7 @@
       <public name="firstBaselineToTopHeight" />
       <public name="lastBaselineToBottomHeight" />
       <public name="lineHeight" />
+      <public name="accessibilityHeading" />
     </public-group>
 
     <public-group type="style" first-id="0x010302e0">
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index b2fa294..2cfe919 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -379,6 +379,9 @@
     <string name="factory_reset_message">The admin app can\'t be used. Your device will now be
         erased.\n\nIf you have questions, contact your organization's admin.</string>
 
+    <!-- A toast message displayed when printing is attempted but disabled by policy. -->
+    <string name="printing_disabled_by">Printing disabled by <xliff:g id="owner_app">%s</xliff:g>.</string>
+
     <!-- Display name for any time a piece of data refers to the owner of the phone. For example, this could be used in place of the phone's phone number. -->
     <string name="me">Me</string>
 
@@ -3754,6 +3757,11 @@
     <!-- Notification body when background data usage is limited. -->
     <string name="data_usage_restricted_body">Tap to remove restriction.</string>
 
+    <!-- Notification title when there has been recent excessive data usage. [CHAR LIMIT=32] -->
+    <string name="data_usage_rapid_title">Large data usage</string>
+    <!-- Notification body when there has been recent excessive data usage. [CHAR LIMIT=128] -->
+    <string name="data_usage_rapid_body">Your data usage over the last few days is larger than normal. Tap to view usage and settings.</string>
+
     <!-- SSL Certificate dialogs -->
     <!-- Title for an SSL Certificate dialog -->
     <string name="ssl_certificate">Security certificate</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 6e33648..5309115 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -309,6 +309,8 @@
   <java-symbol type="bool" name="config_useFixedVolume" />
   <java-symbol type="bool" name="config_forceDefaultOrientation" />
   <java-symbol type="bool" name="config_wifi_batched_scan_supported" />
+  <java-symbol type="bool" name="config_wifi_softap_acs_supported" />
+  <java-symbol type="bool" name="config_wifi_softap_ieee80211ac_supported" />
   <java-symbol type="bool" name="config_enableMultiUserUI"/>
   <java-symbol type="bool" name="config_disableUsbPermissionDialogs"/>
   <java-symbol type="bool" name="config_hasRecents" />
@@ -878,6 +880,7 @@
   <java-symbol type="string" name="preposition_for_time" />
   <java-symbol type="string" name="print_service_installed_title" />
   <java-symbol type="string" name="print_service_installed_message" />
+  <java-symbol type="string" name="printing_disabled_by" />
   <java-symbol type="string" name="progress_erasing" />
   <java-symbol type="string" name="mobile_provisioning_apn" />
   <java-symbol type="string" name="mobile_provisioning_url" />
@@ -1507,6 +1510,7 @@
   <java-symbol type="xml" name="password_kbd_symbols" />
   <java-symbol type="xml" name="password_kbd_symbols_shift" />
   <java-symbol type="xml" name="power_profile" />
+  <java-symbol type="xml" name="power_profile_test" />
   <java-symbol type="xml" name="sms_short_codes" />
   <java-symbol type="xml" name="audio_assets" />
   <java-symbol type="xml" name="global_keys" />
@@ -1973,6 +1977,8 @@
   <java-symbol type="string" name="data_usage_warning_title" />
   <java-symbol type="string" name="data_usage_wifi_limit_snoozed_title" />
   <java-symbol type="string" name="data_usage_wifi_limit_title" />
+  <java-symbol type="string" name="data_usage_rapid_title" />
+  <java-symbol type="string" name="data_usage_rapid_body" />
   <java-symbol type="string" name="default_wallpaper_component" />
   <java-symbol type="string" name="device_storage_monitor_notification_channel" />
   <java-symbol type="string" name="dlg_ok" />
@@ -3219,4 +3225,6 @@
   <java-symbol type="string" name="harmful_app_warning_title" />
 
   <java-symbol type="string" name="config_defaultAssistantAccessPackage" />
+
+  <java-symbol type="bool" name="config_supportBluetoothPersistedState" />
 </resources>
diff --git a/core/res/res/xml/power_profile_test.xml b/core/res/res/xml/power_profile_test.xml
new file mode 100644
index 0000000..cdb7134
--- /dev/null
+++ b/core/res/res/xml/power_profile_test.xml
@@ -0,0 +1,116 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 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.
+*/
+-->
+<device name="Android">
+    <!-- All values are in mAh except as noted.
+         This file is for PowerProfileTest.java. Changes must be synced between these two. Since
+         power_profile.xml may be overridden by actual device's power_profile.xml at compile time,
+         this test config ensures we have something constant to test against. Values below are
+         sample values, not meant to reflect any real device.
+    -->
+
+    <!-- Nothing -->
+    <item name="none">0</item>
+
+    <!-- This is the battery capacity in mAh -->
+    <item name="battery.capacity">3000</item>
+
+    <!-- Number of cores each CPU cluster contains -->
+    <array name="cpu.clusters.cores">
+        <value>4</value> <!-- Cluster 0 has 4 cores (cpu0, cpu1, cpu2, cpu3) -->
+        <value>4</value> <!-- Cluster 1 has 4 cores (cpu4, cpu5, cpu5, cpu7) -->
+    </array>
+
+    <!-- Power consumption when CPU is suspended -->
+    <item name="cpu.suspend">5</item>
+    <!-- Additional power consumption when CPU is in a kernel idle loop -->
+    <item name="cpu.idle">1.11</item>
+    <!-- Additional power consumption by CPU excluding cluster and core when  running -->
+    <item name="cpu.active">2.55</item>
+
+    <!-- Additional power consumption by CPU cluster0 itself when running excluding cores in it -->
+    <item name="cpu.cluster_power.cluster0">2.11</item>
+    <!-- Additional power consumption by CPU cluster1 itself when running excluding cores in it -->
+    <item name="cpu.cluster_power.cluster1">2.22</item>
+
+    <!-- Different CPU speeds as reported in
+         /sys/devices/system/cpu/cpu0/cpufreq/stats/scaling_available_frequencies -->
+    <array name="cpu.core_speeds.cluster0">
+        <value>300000</value> <!-- 300 MHz CPU speed -->
+        <value>1000000</value> <!-- 1000 MHz CPU speed -->
+        <value>2000000</value> <!-- 2000 MHz CPU speed -->
+    </array>
+    <!-- Different CPU speeds as reported in
+         /sys/devices/system/cpu/cpu4/cpufreq/stats/scaling_available_frequencies -->
+    <array name="cpu.core_speeds.cluster1">
+        <value>300000</value> <!-- 300 MHz CPU speed -->
+        <value>1000000</value> <!-- 1000 MHz CPU speed -->
+        <value>2500000</value> <!-- 2500 MHz CPU speed -->
+        <value>3000000</value> <!-- 3000 MHz CPU speed -->
+    </array>
+
+    <!-- Additional power used by a CPU from cluster 0 when running at different
+         speeds. Currently this measurement also includes cluster cost. -->
+    <array name="cpu.core_power.cluster0">
+        <value>10</value> <!-- 300 MHz CPU speed -->
+        <value>20</value> <!-- 1000 MHz CPU speed -->
+        <value>30</value> <!-- 1900 MHz CPU speed -->
+    </array>
+    <!-- Additional power used by a CPU from cluster 1 when running at different
+         speeds. Currently this measurement also includes cluster cost. -->
+    <array name="cpu.core_power.cluster1">
+        <value>25</value> <!-- 300 MHz CPU speed -->
+        <value>35</value> <!-- 1000 MHz CPU speed -->
+        <value>50</value> <!-- 2500 MHz CPU speed -->
+        <value>60</value> <!-- 3000 MHz CPU speed -->
+    </array>
+
+    <!-- Additional power used when screen is turned on at minimum brightness -->
+    <item name="screen.on">100</item>
+    <!-- Additional power used when screen is at maximum brightness, compared to
+         screen at minimum brightness -->
+    <item name="screen.full">800</item>
+
+    <!-- Average power used by the camera flash module when on -->
+    <item name="camera.flashlight">500</item>
+    <!-- Average power use by the camera subsystem for a typical camera
+         application. Intended as a rough estimate for an application running a
+         preview and capturing approximately 10 full-resolution pictures per
+         minute. -->
+    <item name="camera.avg">600</item>
+
+    <!-- Additional power used when audio decoding/encoding via DSP -->
+    <item name="dsp.audio">100</item>
+
+    <!-- Additional power used when GPS is acquiring a signal -->
+    <item name="gps.on">10</item>
+
+    <!-- Additional power used when cellular radio is transmitting/receiving -->
+    <item name="radio.active">60</item>
+    <!-- Additional power used when cellular radio is paging the tower -->
+    <item name="radio.scanning">3</item>
+    <!-- Additional power used when the cellular radio is on. Multi-value entry,
+         one per signal strength (no signal, weak, moderate, strong) -->
+    <array name="radio.on"> <!-- Strength 0 to BINS-1 -->
+        <value>6</value>       <!-- none -->
+        <value>5</value>       <!-- poor -->
+        <value>4</value>       <!-- moderate -->
+        <value>3</value>       <!-- good -->
+        <value>3</value>       <!-- great -->
+    </array>
+</device>
diff --git a/core/tests/coretests/apks/install-split-base/Android.mk b/core/tests/coretests/apks/install-split-base/Android.mk
new file mode 100644
index 0000000..5b60e31
--- /dev/null
+++ b/core/tests/coretests/apks/install-split-base/Android.mk
@@ -0,0 +1,10 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := install_split_base
+
+include $(FrameworkCoreTests_BUILD_PACKAGE)
\ No newline at end of file
diff --git a/core/tests/coretests/apks/install-split-base/AndroidManifest.xml b/core/tests/coretests/apks/install-split-base/AndroidManifest.xml
new file mode 100644
index 0000000..c2bfedd
--- /dev/null
+++ b/core/tests/coretests/apks/install-split-base/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.frameworks.coretests.install_split"
+        android:isolatedSplits="true">
+
+    <application android:label="ClassloaderSplitApp">
+        <activity android:name=".BaseActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/core/tests/coretests/apks/install-split-base/src/com/google/android/dexapis/splitapp/BaseActivity.java b/core/tests/coretests/apks/install-split-base/src/com/google/android/dexapis/splitapp/BaseActivity.java
new file mode 100644
index 0000000..cb5760ce
--- /dev/null
+++ b/core/tests/coretests/apks/install-split-base/src/com/google/android/dexapis/splitapp/BaseActivity.java
@@ -0,0 +1,23 @@
+/**
+ * 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.
+ */
+
+package com.google.android.dexapis.splitapp;
+
+import android.app.Activity;
+
+/** Main activity */
+public class BaseActivity extends Activity {
+}
diff --git a/core/tests/coretests/apks/install-split-feature-a/Android.mk b/core/tests/coretests/apks/install-split-feature-a/Android.mk
new file mode 100644
index 0000000..0f37d16
--- /dev/null
+++ b/core/tests/coretests/apks/install-split-feature-a/Android.mk
@@ -0,0 +1,14 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := install_split_feature_a
+
+LOCAL_USE_AAPT2 := true
+LOCAL_AAPT_FLAGS += --custom-package com.google.android.dexapis.splitapp.feature_a
+LOCAL_AAPT_FLAGS += --package-id 0x80
+
+include $(FrameworkCoreTests_BUILD_PACKAGE)
\ No newline at end of file
diff --git a/core/tests/coretests/apks/install-split-feature-a/AndroidManifest.xml b/core/tests/coretests/apks/install-split-feature-a/AndroidManifest.xml
new file mode 100644
index 0000000..3221c75
--- /dev/null
+++ b/core/tests/coretests/apks/install-split-feature-a/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.frameworks.coretests.install_split"
+        featureSplit="feature_a">
+
+    <application>
+        <activity android:name=".feature_a.FeatureAActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/core/tests/coretests/apks/install-split-feature-a/src/com/google/android/dexapis/splitapp/feature_a/FeatureAActivity.java b/core/tests/coretests/apks/install-split-feature-a/src/com/google/android/dexapis/splitapp/feature_a/FeatureAActivity.java
new file mode 100644
index 0000000..0af5f89
--- /dev/null
+++ b/core/tests/coretests/apks/install-split-feature-a/src/com/google/android/dexapis/splitapp/feature_a/FeatureAActivity.java
@@ -0,0 +1,23 @@
+/**
+ * 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.
+ */
+
+package com.google.android.dexapis.splitapp.feature_a;
+
+import android.app.Activity;
+
+/** Main activity */
+public class FeatureAActivity extends Activity {
+}
diff --git a/core/tests/coretests/src/android/content/pm/crossprofile/CrossProfileAppsTest.java b/core/tests/coretests/src/android/content/pm/CrossProfileAppsTest.java
similarity index 92%
rename from core/tests/coretests/src/android/content/pm/crossprofile/CrossProfileAppsTest.java
rename to core/tests/coretests/src/android/content/pm/CrossProfileAppsTest.java
index 80e4c02..0cfcd8f8 100644
--- a/core/tests/coretests/src/android/content/pm/crossprofile/CrossProfileAppsTest.java
+++ b/core/tests/coretests/src/android/content/pm/CrossProfileAppsTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.content.pm.crossprofile;
+package android.content.pm;
 
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.nullable;
@@ -42,7 +42,7 @@
 
 /**
  * Build/Install/Run:
- * bit FrameworksCoreTests:android.content.pm.crossprofile.CrossProfileAppsTest
+ * atest frameworks/base/core/tests/coretests/src/android/content/pm/CrossProfileAppsTest.java
  */
 @Presubmit
 @RunWith(MockitoJUnitRunner.class)
@@ -118,7 +118,7 @@
     public void getProfileSwitchingIcon_managedProfile() {
         setValidTargetProfile(MANAGED_PROFILE);
 
-        mCrossProfileApps.getProfileSwitchingIcon(MANAGED_PROFILE);
+        mCrossProfileApps.getProfileSwitchingIconDrawable(MANAGED_PROFILE);
         verify(mResources).getDrawable(R.drawable.ic_corp_badge, null);
     }
 
@@ -126,13 +126,13 @@
     public void getProfileSwitchingIcon_personalProfile() {
         setValidTargetProfile(PERSONAL_PROFILE);
 
-        mCrossProfileApps.getProfileSwitchingIcon(PERSONAL_PROFILE);
+        mCrossProfileApps.getProfileSwitchingIconDrawable(PERSONAL_PROFILE);
         verify(mResources).getDrawable(R.drawable.ic_account_circle, null);
     }
 
     @Test(expected = SecurityException.class)
     public void getProfileSwitchingIcon_securityException() {
-        mCrossProfileApps.getProfileSwitchingIcon(PERSONAL_PROFILE);
+        mCrossProfileApps.getProfileSwitchingIconDrawable(PERSONAL_PROFILE);
     }
 
     private void setValidTargetProfile(UserHandle userHandle) {
diff --git a/core/tests/coretests/src/android/content/pm/dex/DexMetadataHelperTest.java b/core/tests/coretests/src/android/content/pm/dex/DexMetadataHelperTest.java
new file mode 100644
index 0000000..4b84429
--- /dev/null
+++ b/core/tests/coretests/src/android/content/pm/dex/DexMetadataHelperTest.java
@@ -0,0 +1,208 @@
+/**
+ * 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.content.pm.dex;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageParser;
+import android.content.pm.PackageParser.Package;
+import android.content.pm.PackageParser.PackageParserException;
+import android.os.FileUtils;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.frameworks.coretests.R;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.util.Map;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+import libcore.io.IoUtils;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class DexMetadataHelperTest {
+    private static final String APK_FILE_EXTENSION = ".apk";
+    private static final String DEX_METADATA_FILE_EXTENSION = ".dm";
+
+    private File mTmpDir = null;
+
+    @Before
+    public void setUp() {
+        mTmpDir = IoUtils.createTemporaryDirectory("DexMetadataHelperTest");
+    }
+
+    @After
+    public void tearDown() {
+        if (mTmpDir != null) {
+            File[] files = mTmpDir.listFiles();
+            for (File f : files) {
+                f.delete();
+            }
+        }
+    }
+
+    private File createDexMetadataFile(String apkFileName) throws IOException {
+        File dmFile = new File(mTmpDir, apkFileName.replace(APK_FILE_EXTENSION,
+                DEX_METADATA_FILE_EXTENSION));
+        try (FileOutputStream fos = new FileOutputStream(dmFile)) {
+            try (ZipOutputStream zipOs = new ZipOutputStream(fos)) {
+                zipOs.putNextEntry(new ZipEntry("primary.prof"));
+                zipOs.closeEntry();
+            }
+        }
+        return dmFile;
+    }
+
+    private File copyApkToToTmpDir(String apkFileName, int apkResourceId) throws IOException {
+        Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
+        File outFile = new File(mTmpDir, apkFileName);
+        try (InputStream is = context.getResources().openRawResource(apkResourceId)) {
+            FileUtils.copyToFileOrThrow(is, outFile);
+        }
+        return outFile;
+    }
+
+    @Test
+    public void testParsePackageWithDmFileValid() throws IOException, PackageParserException {
+        copyApkToToTmpDir("install_split_base.apk", R.raw.install_split_base);
+        createDexMetadataFile("install_split_base.apk");
+        Package pkg = new PackageParser().parsePackage(mTmpDir, 0 /* flags */);
+
+        Map<String, String> packageDexMetadata = DexMetadataHelper.getPackageDexMetadata(pkg);
+        assertEquals(1, packageDexMetadata.size());
+        String baseDexMetadata = packageDexMetadata.get(pkg.baseCodePath);
+        assertNotNull(baseDexMetadata);
+        assertTrue(isDexMetadataForApk(baseDexMetadata, pkg.baseCodePath));
+    }
+
+    @Test
+    public void testParsePackageSplitsWithDmFileValid()
+            throws IOException, PackageParserException {
+        copyApkToToTmpDir("install_split_base.apk", R.raw.install_split_base);
+        copyApkToToTmpDir("install_split_feature_a.apk", R.raw.install_split_feature_a);
+        createDexMetadataFile("install_split_base.apk");
+        createDexMetadataFile("install_split_feature_a.apk");
+        Package pkg = new PackageParser().parsePackage(mTmpDir, 0 /* flags */);
+
+        Map<String, String> packageDexMetadata = DexMetadataHelper.getPackageDexMetadata(pkg);
+        assertEquals(2, packageDexMetadata.size());
+        String baseDexMetadata = packageDexMetadata.get(pkg.baseCodePath);
+        assertNotNull(baseDexMetadata);
+        assertTrue(isDexMetadataForApk(baseDexMetadata, pkg.baseCodePath));
+
+        String splitDexMetadata = packageDexMetadata.get(pkg.splitCodePaths[0]);
+        assertNotNull(splitDexMetadata);
+        assertTrue(isDexMetadataForApk(splitDexMetadata, pkg.splitCodePaths[0]));
+    }
+
+    @Test
+    public void testParsePackageSplitsNoBaseWithDmFileValid()
+            throws IOException, PackageParserException {
+        copyApkToToTmpDir("install_split_base.apk", R.raw.install_split_base);
+        copyApkToToTmpDir("install_split_feature_a.apk", R.raw.install_split_feature_a);
+        createDexMetadataFile("install_split_feature_a.apk");
+        Package pkg = new PackageParser().parsePackage(mTmpDir, 0 /* flags */);
+
+        Map<String, String> packageDexMetadata = DexMetadataHelper.getPackageDexMetadata(pkg);
+        assertEquals(1, packageDexMetadata.size());
+
+        String splitDexMetadata = packageDexMetadata.get(pkg.splitCodePaths[0]);
+        assertNotNull(splitDexMetadata);
+        assertTrue(isDexMetadataForApk(splitDexMetadata, pkg.splitCodePaths[0]));
+    }
+
+    @Test
+    public void testParsePackageWithDmFileInvalid() throws IOException {
+        copyApkToToTmpDir("install_split_base.apk", R.raw.install_split_base);
+        File invalidDmFile = new File(mTmpDir, "install_split_base.dm");
+        Files.createFile(invalidDmFile.toPath());
+        try {
+            PackageParser.Package pkg = new PackageParser().parsePackage(mTmpDir, 0 /* flags */);
+            DexMetadataHelper.validatePackageDexMetadata(pkg);
+        } catch (PackageParserException e) {
+            assertEquals(e.error, PackageManager.INSTALL_FAILED_BAD_DEX_METADATA);
+        }
+    }
+
+    @Test
+    public void testParsePackageSplitsWithDmFileInvalid()
+            throws IOException, PackageParserException {
+        copyApkToToTmpDir("install_split_base.apk", R.raw.install_split_base);
+        copyApkToToTmpDir("install_split_feature_a.apk", R.raw.install_split_feature_a);
+        createDexMetadataFile("install_split_base.apk");
+        File invalidDmFile = new File(mTmpDir, "install_split_feature_a.dm");
+        Files.createFile(invalidDmFile.toPath());
+
+        try {
+            PackageParser.Package pkg = new PackageParser().parsePackage(mTmpDir, 0 /* flags */);
+            DexMetadataHelper.validatePackageDexMetadata(pkg);
+        } catch (PackageParserException e) {
+            assertEquals(e.error, PackageManager.INSTALL_FAILED_BAD_DEX_METADATA);
+        }
+    }
+
+    @Test
+    public void testPackageWithDmFileNoMatch() throws IOException {
+        copyApkToToTmpDir("install_split_base.apk", R.raw.install_split_base);
+        createDexMetadataFile("non_existent.apk");
+
+        try {
+            DexMetadataHelper.validateDexPaths(mTmpDir.list());
+            fail("Should fail validation");
+        } catch (IllegalStateException e) {
+            // expected.
+        }
+    }
+
+    @Test
+    public void testPackageSplitsWithDmFileNoMatch()
+            throws IOException, PackageParserException {
+        copyApkToToTmpDir("install_split_base.apk", R.raw.install_split_base);
+        copyApkToToTmpDir("install_split_feature_a.apk", R.raw.install_split_feature_a);
+        createDexMetadataFile("install_split_base.apk");
+        createDexMetadataFile("install_split_feature_a.mistake.apk");
+
+        try {
+            DexMetadataHelper.validateDexPaths(mTmpDir.list());
+            fail("Should fail validation");
+        } catch (IllegalStateException e) {
+            // expected.
+        }
+    }
+
+    private static boolean isDexMetadataForApk(String dmaPath, String apkPath) {
+        return apkPath.substring(0, apkPath.length() - APK_FILE_EXTENSION.length()).equals(
+                dmaPath.substring(0, dmaPath.length() - DEX_METADATA_FILE_EXTENSION.length()));
+    }
+}
diff --git a/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java b/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java
index 417faf2..eaabdc8 100644
--- a/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java
+++ b/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java
@@ -505,4 +505,84 @@
         assertEquals(GLYPH_3EM_WIDTH, paint.measureText("b"), 0.0f);
         assertEquals(GLYPH_1EM_WIDTH, paint.measureText("c"), 0.0f);
     }
+
+    @Test
+    public void testBuildSystemFallback_ElegantFallback_customFallback_missingFile() {
+        final String xml = "<?xml version='1.0' encoding='UTF-8'?>"
+                + "<familyset>"
+                + "  <family name='sans-serif'>"
+                + "    <font weight='400' style='normal'>no_coverage.ttf</font>"
+                + "  </family>"
+                + "  <family name='serif'>"
+                + "    <font weight='400' style='normal'>no_coverage.ttf</font>"
+                + "  </family>"
+                + "  <family>"
+                + "    <font weight='400' style='normal'>a3em.ttf</font>"
+                + "    <font weight='400' style='normal' fallbackFor='serif'>NoSuchFont.ttf</font>"
+                + "  </family>"
+                + "  <family>"
+                + "    <font weight='400' style='normal'>b3em.ttf</font>"
+                + "  </family>"
+                + "</familyset>";
+        final ArrayMap<String, Typeface> fontMap = new ArrayMap<>();
+        final ArrayMap<String, FontFamily[]> fallbackMap = new ArrayMap<>();
+
+        buildSystemFallback(xml, fontMap, fallbackMap);
+
+        final Paint paint = new Paint();
+
+        Typeface testTypeface = fontMap.get("serif");
+        assertNotNull(testTypeface);
+        paint.setTypeface(testTypeface);
+        assertEquals(GLYPH_3EM_WIDTH, paint.measureText("a"), 0.0f);
+        assertEquals(GLYPH_1EM_WIDTH, paint.measureText("b"), 0.0f);
+        assertEquals(GLYPH_1EM_WIDTH, paint.measureText("c"), 0.0f);
+
+        testTypeface = fontMap.get("sans-serif");
+        assertNotNull(testTypeface);
+        paint.setTypeface(testTypeface);
+        assertEquals(GLYPH_3EM_WIDTH, paint.measureText("a"), 0.0f);
+        assertEquals(GLYPH_1EM_WIDTH, paint.measureText("b"), 0.0f);
+        assertEquals(GLYPH_1EM_WIDTH, paint.measureText("c"), 0.0f);
+    }
+
+    @Test
+    public void testBuildSystemFallback_ElegantFallback_customFallback_missingFile2() {
+        final String xml = "<?xml version='1.0' encoding='UTF-8'?>"
+                + "<familyset>"
+                + "  <family name='sans-serif'>"
+                + "    <font weight='400' style='normal'>no_coverage.ttf</font>"
+                + "  </family>"
+                + "  <family name='serif'>"
+                + "    <font weight='400' style='normal'>no_coverage.ttf</font>"
+                + "  </family>"
+                + "  <family>"
+                + "    <font weight='400' style='normal' fallbackFor='serif'>NoSuchFont.ttf</font>"
+                + "  </family>"
+                + "  <family>"
+                + "    <font weight='400' style='normal'>a3em.ttf</font>"
+                + "  </family>"
+                + "</familyset>";
+        final ArrayMap<String, Typeface> fontMap = new ArrayMap<>();
+        final ArrayMap<String, FontFamily[]> fallbackMap = new ArrayMap<>();
+
+        buildSystemFallback(xml, fontMap, fallbackMap);
+
+        final Paint paint = new Paint();
+
+        Typeface testTypeface = fontMap.get("serif");
+        assertNotNull(testTypeface);
+        paint.setTypeface(testTypeface);
+        assertEquals(GLYPH_3EM_WIDTH, paint.measureText("a"), 0.0f);
+        assertEquals(GLYPH_1EM_WIDTH, paint.measureText("b"), 0.0f);
+        assertEquals(GLYPH_1EM_WIDTH, paint.measureText("c"), 0.0f);
+
+        testTypeface = fontMap.get("sans-serif");
+        assertNotNull(testTypeface);
+        paint.setTypeface(testTypeface);
+        assertEquals(GLYPH_3EM_WIDTH, paint.measureText("a"), 0.0f);
+        assertEquals(GLYPH_1EM_WIDTH, paint.measureText("b"), 0.0f);
+        assertEquals(GLYPH_1EM_WIDTH, paint.measureText("c"), 0.0f);
+    }
+
 }
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index c2ae776..ec3a6ce 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -213,7 +213,6 @@
                     Settings.Global.FANCY_IME_ANIMATIONS,
                     Settings.Global.FORCE_ALLOW_ON_EXTERNAL,
                     Settings.Global.FORCED_APP_STANDBY_ENABLED,
-                    Settings.Global.FORCED_APP_STANDBY_FOR_SMALL_BATTERY_ENABLED,
                     Settings.Global.FSTRIM_MANDATORY_INTERVAL,
                     Settings.Global.GLOBAL_HTTP_PROXY_EXCLUSION_LIST,
                     Settings.Global.GLOBAL_HTTP_PROXY_HOST,
@@ -354,6 +353,7 @@
                     Settings.Global.SYS_STORAGE_THRESHOLD_MAX_BYTES,
                     Settings.Global.SYS_STORAGE_THRESHOLD_PERCENTAGE,
                     Settings.Global.SYS_VDSO,
+                    Settings.Global.FPS_DEVISOR,
                     Settings.Global.TCP_DEFAULT_INIT_RWND,
                     Settings.Global.TETHER_DUN_APN,
                     Settings.Global.TETHER_DUN_REQUIRED,
@@ -534,7 +534,9 @@
                  Settings.Secure.VOICE_RECOGNITION_SERVICE,
                  Settings.Secure.INSTANT_APPS_ENABLED,
                  Settings.Secure.BACKUP_MANAGER_CONSTANTS,
-                 Settings.Secure.KEYGUARD_SLICE_URI);
+                 Settings.Secure.KEYGUARD_SLICE_URI,
+                 Settings.Secure.PARENTAL_CONTROL_ENABLED,
+                 Settings.Secure.PARENTAL_CONTROL_REDIRECT_URL);
 
     @Test
     public void systemSettingsBackedUpOrBlacklisted() {
diff --git a/core/tests/coretests/src/android/provider/SettingsValidatorsTest.java b/core/tests/coretests/src/android/provider/SettingsValidatorsTest.java
new file mode 100644
index 0000000..4c4aeaf
--- /dev/null
+++ b/core/tests/coretests/src/android/provider/SettingsValidatorsTest.java
@@ -0,0 +1,89 @@
+/*
+ * 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.provider;
+
+import static org.junit.Assert.fail;
+
+import android.platform.test.annotations.Presubmit;
+import android.provider.SettingsValidators.Validator;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Map;
+
+/** Tests that ensure all backed up settings have non-null validators. */
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class SettingsValidatorsTest {
+
+    @Test
+    public void ensureAllBackedUpSystemSettingsHaveValidators() {
+        String offenders = getOffenders(concat(Settings.System.SETTINGS_TO_BACKUP,
+                Settings.System.LEGACY_RESTORE_SETTINGS), Settings.System.VALIDATORS);
+
+        failIfOffendersPresent(offenders, "Settings.System");
+    }
+
+    @Test
+    public void ensureAllBackedUpGlobalSettingsHaveValidators() {
+        String offenders = getOffenders(concat(Settings.Global.SETTINGS_TO_BACKUP,
+                Settings.Global.LEGACY_RESTORE_SETTINGS), Settings.Global.VALIDATORS);
+
+        failIfOffendersPresent(offenders, "Settings.Global");
+    }
+
+    @Test
+    public void ensureAllBackedUpSecureSettingsHaveValidators() {
+        String offenders = getOffenders(concat(Settings.Secure.SETTINGS_TO_BACKUP,
+                Settings.Secure.LEGACY_RESTORE_SETTINGS), Settings.Secure.VALIDATORS);
+
+        failIfOffendersPresent(offenders, "Settings.Secure");
+    }
+
+    private void failIfOffendersPresent(String offenders, String settingsType) {
+        if (offenders.length() > 0) {
+            fail("All " + settingsType + " settings that are backed up have to have a non-null"
+                    + " validator, but those don't: " + offenders);
+        }
+    }
+
+    private String getOffenders(String[] settingsToBackup, Map<String, Validator> validators) {
+        StringBuilder offenders = new StringBuilder();
+        for (String setting : settingsToBackup) {
+            if (validators.get(setting) == null) {
+                offenders.append(setting).append(" ");
+            }
+        }
+        return offenders.toString();
+    }
+
+    private String[] concat(String[] first, String[] second) {
+        if (second == null || second.length == 0) {
+            return first;
+        }
+        final int firstLen = first.length;
+        final int secondLen = second.length;
+        String[] both = new String[firstLen + secondLen];
+        System.arraycopy(first, 0, both, 0, firstLen);
+        System.arraycopy(second, 0, both, firstLen, secondLen);
+        return both;
+    }
+}
diff --git a/core/tests/coretests/src/android/text/MeasuredParagraphTest.java b/core/tests/coretests/src/android/text/MeasuredParagraphTest.java
index 5d33397..f6300ee 100644
--- a/core/tests/coretests/src/android/text/MeasuredParagraphTest.java
+++ b/core/tests/coretests/src/android/text/MeasuredParagraphTest.java
@@ -132,7 +132,7 @@
     public void buildForStaticLayout() {
         MeasuredParagraph mt = null;
 
-        mt = MeasuredParagraph.buildForStaticLayout(PAINT, "XXX", 0, 3, LTR, null);
+        mt = MeasuredParagraph.buildForStaticLayout(PAINT, "XXX", 0, 3, LTR, false, null);
         assertNotNull(mt);
         assertNotNull(mt.getChars());
         assertEquals("XXX", charsToString(mt.getChars()));
@@ -147,7 +147,7 @@
 
         // Recycle it
         MeasuredParagraph mt2 =
-                MeasuredParagraph.buildForStaticLayout(PAINT, "_VVV_", 1, 4, RTL, mt);
+                MeasuredParagraph.buildForStaticLayout(PAINT, "_VVV_", 1, 4, RTL, false, mt);
         assertEquals(mt2, mt);
         assertNotNull(mt2.getChars());
         assertEquals("VVV", charsToString(mt.getChars()));
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsCpuTimesTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsCpuTimesTest.java
index b5a7bec..32053e3 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsCpuTimesTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsCpuTimesTest.java
@@ -62,9 +62,9 @@
  *
  * Build: m FrameworksCoreTests
  * Install: adb install -r \
- *     ${ANDROID_PRODUCT_OUT}/data/app/FrameworksCoreTests/FrameworksCoreTests.apk
+ * ${ANDROID_PRODUCT_OUT}/data/app/FrameworksCoreTests/FrameworksCoreTests.apk
  * Run: adb shell am instrument -e class com.android.internal.os.BatteryStatsCpuTimesTest -w \
- *     com.android.frameworks.coretests/android.support.test.runner.AndroidJUnitRunner
+ * com.android.frameworks.coretests/android.support.test.runner.AndroidJUnitRunner
  *
  * or
  *
@@ -73,10 +73,18 @@
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class BatteryStatsCpuTimesTest {
-    @Mock KernelUidCpuTimeReader mKernelUidCpuTimeReader;
-    @Mock KernelUidCpuFreqTimeReader mKernelUidCpuFreqTimeReader;
-    @Mock BatteryStatsImpl.UserInfoProvider mUserInfoProvider;
-    @Mock PowerProfile mPowerProfile;
+    @Mock
+    KernelUidCpuTimeReader mKernelUidCpuTimeReader;
+    @Mock
+    KernelUidCpuFreqTimeReader mKernelUidCpuFreqTimeReader;
+    @Mock
+    KernelUidCpuActiveTimeReader mKernelUidCpuActiveTimeReader;
+    @Mock
+    KernelUidCpuClusterTimeReader mKernelUidCpuClusterTimeReader;
+    @Mock
+    BatteryStatsImpl.UserInfoProvider mUserInfoProvider;
+    @Mock
+    PowerProfile mPowerProfile;
 
     private MockClocks mClocks;
     private MockBatteryStatsImpl mBatteryStatsImpl;
@@ -90,6 +98,8 @@
         mBatteryStatsImpl = new MockBatteryStatsImpl(mClocks)
                 .setKernelUidCpuTimeReader(mKernelUidCpuTimeReader)
                 .setKernelUidCpuFreqTimeReader(mKernelUidCpuFreqTimeReader)
+                .setKernelUidCpuActiveTimeReader(mKernelUidCpuActiveTimeReader)
+                .setKernelUidCpuClusterTimeReader(mKernelUidCpuClusterTimeReader)
                 .setUserInfoProvider(mUserInfoProvider);
     }
 
@@ -134,6 +144,10 @@
         verify(mKernelUidCpuFreqTimeReader, times(2)).perClusterTimesAvailable();
         verify(mKernelUidCpuFreqTimeReader).readDelta(
                 any(KernelUidCpuFreqTimeReader.Callback.class));
+        verify(mKernelUidCpuActiveTimeReader).readDelta(
+                any(KernelUidCpuActiveTimeReader.Callback.class));
+        verify(mKernelUidCpuClusterTimeReader).readDelta(
+                any(KernelUidCpuClusterTimeReader.Callback.class));
         verifyNoMoreInteractions(mKernelUidCpuFreqTimeReader);
         for (int i = 0; i < numClusters; ++i) {
             verify(mKernelCpuSpeedReaders[i]).readDelta();
@@ -228,7 +242,7 @@
         updateTimeBasesLocked(true, Display.STATE_ON, 0, 0);
         final int testUserId = 11;
         when(mUserInfoProvider.exists(testUserId)).thenReturn(true);
-        final int[] testUids = getUids(testUserId, new int[] {
+        final int[] testUids = getUids(testUserId, new int[]{
                 FIRST_APPLICATION_UID + 22,
                 FIRST_APPLICATION_UID + 27,
                 FIRST_APPLICATION_UID + 33
@@ -301,7 +315,7 @@
         when(mUserInfoProvider.exists(testUserId)).thenReturn(true);
         final int isolatedAppId = FIRST_ISOLATED_UID + 27;
         final int isolatedUid = UserHandle.getUid(testUserId, isolatedAppId);
-        final int[] testUids = getUids(testUserId, new int[] {
+        final int[] testUids = getUids(testUserId, new int[]{
                 FIRST_APPLICATION_UID + 22,
                 isolatedAppId,
                 FIRST_APPLICATION_UID + 33
@@ -389,7 +403,7 @@
         final int invalidUid = UserHandle.getUid(invalidUserId, FIRST_APPLICATION_UID + 99);
         when(mUserInfoProvider.exists(testUserId)).thenReturn(true);
         when(mUserInfoProvider.exists(invalidUserId)).thenReturn(false);
-        final int[] testUids = getUids(testUserId, new int[] {
+        final int[] testUids = getUids(testUserId, new int[]{
                 FIRST_APPLICATION_UID + 22,
                 FIRST_APPLICATION_UID + 27,
                 FIRST_APPLICATION_UID + 33
@@ -431,7 +445,7 @@
         updateTimeBasesLocked(true, Display.STATE_ON, 0, 0);
         final int testUserId = 11;
         when(mUserInfoProvider.exists(testUserId)).thenReturn(true);
-        final int[] testUids = getUids(testUserId, new int[] {
+        final int[] testUids = getUids(testUserId, new int[]{
                 FIRST_APPLICATION_UID + 22,
                 FIRST_APPLICATION_UID + 27,
                 FIRST_APPLICATION_UID + 33
@@ -514,10 +528,10 @@
 
         final int testUserId = 11;
         when(mUserInfoProvider.exists(testUserId)).thenReturn(true);
-        final int[] testUids = getUids(testUserId, new int[] {
-            FIRST_APPLICATION_UID + 22,
-            FIRST_APPLICATION_UID + 27,
-            FIRST_APPLICATION_UID + 33
+        final int[] testUids = getUids(testUserId, new int[]{
+                FIRST_APPLICATION_UID + 22,
+                FIRST_APPLICATION_UID + 27,
+                FIRST_APPLICATION_UID + 33
         });
         final long[][] uidTimesMs = {
                 {4, 10, 5, 9, 4},
@@ -589,7 +603,7 @@
 
         final int testUserId = 11;
         when(mUserInfoProvider.exists(testUserId)).thenReturn(true);
-        final int[] testUids = getUids(testUserId, new int[] {
+        final int[] testUids = getUids(testUserId, new int[]{
                 FIRST_APPLICATION_UID + 22,
                 FIRST_APPLICATION_UID + 27,
                 FIRST_APPLICATION_UID + 33
@@ -693,7 +707,7 @@
 
         final int testUserId = 11;
         when(mUserInfoProvider.exists(testUserId)).thenReturn(true);
-        final int[] testUids = getUids(testUserId, new int[] {
+        final int[] testUids = getUids(testUserId, new int[]{
                 FIRST_APPLICATION_UID + 22,
                 FIRST_APPLICATION_UID + 27,
                 FIRST_APPLICATION_UID + 33
@@ -782,7 +796,7 @@
             }
         }
         for (int cluster = 0; cluster < clusterFreqs.length; ++cluster) {
-            for (int speed = 0 ; speed < clusterFreqs[cluster]; ++speed) {
+            for (int speed = 0; speed < clusterFreqs[cluster]; ++speed) {
                 assertEquals("There shouldn't be any left-overs: "
                                 + Arrays.deepToString(expectedWakeLockUidTimesUs),
                         0, expectedWakeLockUidTimesUs[cluster][speed]);
@@ -797,7 +811,7 @@
 
         final int testUserId = 11;
         when(mUserInfoProvider.exists(testUserId)).thenReturn(true);
-        final int[] testUids = getUids(testUserId, new int[] {
+        final int[] testUids = getUids(testUserId, new int[]{
                 FIRST_APPLICATION_UID + 22,
                 FIRST_APPLICATION_UID + 27,
                 FIRST_APPLICATION_UID + 33
@@ -874,7 +888,7 @@
         when(mUserInfoProvider.exists(testUserId)).thenReturn(true);
         final int isolatedAppId = FIRST_ISOLATED_UID + 27;
         final int isolatedUid = UserHandle.getUid(testUserId, isolatedAppId);
-        final int[] testUids = getUids(testUserId, new int[] {
+        final int[] testUids = getUids(testUserId, new int[]{
                 FIRST_APPLICATION_UID + 22,
                 isolatedAppId,
                 FIRST_APPLICATION_UID + 33
@@ -969,7 +983,7 @@
         final int invalidUid = UserHandle.getUid(invalidUserId, FIRST_APPLICATION_UID + 99);
         when(mUserInfoProvider.exists(testUserId)).thenReturn(true);
         when(mUserInfoProvider.exists(invalidUserId)).thenReturn(false);
-        final int[] testUids = getUids(testUserId, new int[] {
+        final int[] testUids = getUids(testUserId, new int[]{
                 FIRST_APPLICATION_UID + 22,
                 FIRST_APPLICATION_UID + 27,
                 FIRST_APPLICATION_UID + 33
@@ -986,7 +1000,7 @@
                 callback.onUidCpuFreqTime(testUids[i], uidTimesMs[i]);
             }
             // And one for the invalid uid
-            callback.onUidCpuFreqTime(invalidUid, new long[] {12, 839, 32, 34, 21});
+            callback.onUidCpuFreqTime(invalidUid, new long[]{12, 839, 32, 34, 21});
             return null;
         }).when(mKernelUidCpuFreqTimeReader).readDelta(
                 any(KernelUidCpuFreqTimeReader.Callback.class));
@@ -1009,6 +1023,136 @@
         verify(mKernelUidCpuFreqTimeReader).removeUid(invalidUid);
     }
 
+    @Test
+    public void testReadKernelUidCpuActiveTimesLocked() {
+        // PRECONDITIONS
+        updateTimeBasesLocked(true, Display.STATE_ON, 0, 0);
+
+        final int testUserId = 11;
+        when(mUserInfoProvider.exists(testUserId)).thenReturn(true);
+        final int[] testUids = getUids(testUserId, new int[]{
+                FIRST_APPLICATION_UID + 22,
+                FIRST_APPLICATION_UID + 27,
+                FIRST_APPLICATION_UID + 33
+        });
+        final long[] uidTimesMs = {8000, 25000, 3000, 0, 42000};
+        doAnswer(invocation -> {
+            final KernelUidCpuActiveTimeReader.Callback callback =
+                    (KernelUidCpuActiveTimeReader.Callback) invocation.getArguments()[0];
+            for (int i = 0; i < testUids.length; ++i) {
+                callback.onUidCpuActiveTime(testUids[i], uidTimesMs[i]);
+            }
+            return null;
+        }).when(mKernelUidCpuActiveTimeReader).readDelta(
+                any(KernelUidCpuActiveTimeReader.Callback.class));
+
+        // RUN
+        mBatteryStatsImpl.readKernelUidCpuActiveTimesLocked();
+
+        // VERIFY
+        for (int i = 0; i < testUids.length; ++i) {
+            final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
+            assertNotNull("No entry for uid=" + testUids[i], u);
+            assertEquals("Unexpected cpu active time for uid=" + testUids[i], uidTimesMs[i],
+                    u.getCpuActiveTime());
+        }
+
+        // Repeat the test when the screen is off.
+
+        // PRECONDITIONS
+        updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
+        final long[] deltasMs = {43000, 3345000, 2143000, 123000, 4554000};
+        doAnswer(invocation -> {
+            final KernelUidCpuActiveTimeReader.Callback callback =
+                    (KernelUidCpuActiveTimeReader.Callback) invocation.getArguments()[0];
+            for (int i = 0; i < testUids.length; ++i) {
+                callback.onUidCpuActiveTime(testUids[i], deltasMs[i]);
+            }
+            return null;
+        }).when(mKernelUidCpuActiveTimeReader).readDelta(
+                any(KernelUidCpuActiveTimeReader.Callback.class));
+
+        // RUN
+        mBatteryStatsImpl.readKernelUidCpuActiveTimesLocked();
+
+        // VERIFY
+        for (int i = 0; i < testUids.length; ++i) {
+            final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
+            assertNotNull("No entry for uid=" + testUids[i], u);
+            assertEquals("Unexpected cpu active time for uid=" + testUids[i],
+                    uidTimesMs[i] + deltasMs[i], u.getCpuActiveTime());
+        }
+    }
+
+    @Test
+    public void testReadKernelUidCpuClusterTimesLocked() {
+        // PRECONDITIONS
+        updateTimeBasesLocked(true, Display.STATE_ON, 0, 0);
+
+        final int testUserId = 11;
+        when(mUserInfoProvider.exists(testUserId)).thenReturn(true);
+        final int[] testUids = getUids(testUserId, new int[]{
+                FIRST_APPLICATION_UID + 22,
+                FIRST_APPLICATION_UID + 27,
+                FIRST_APPLICATION_UID + 33
+        });
+        final long[][] uidTimesMs = {
+                {4000, 10000},
+                {5000, 1000},
+                {8000, 0}
+        };
+        doAnswer(invocation -> {
+            final KernelUidCpuClusterTimeReader.Callback callback =
+                    (KernelUidCpuClusterTimeReader.Callback) invocation.getArguments()[0];
+            for (int i = 0; i < testUids.length; ++i) {
+                callback.onUidCpuPolicyTime(testUids[i], uidTimesMs[i]);
+            }
+            return null;
+        }).when(mKernelUidCpuClusterTimeReader).readDelta(
+                any(KernelUidCpuClusterTimeReader.Callback.class));
+
+        // RUN
+        mBatteryStatsImpl.readKernelUidCpuClusterTimesLocked();
+
+        // VERIFY
+        for (int i = 0; i < testUids.length; ++i) {
+            final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
+            assertNotNull("No entry for uid=" + testUids[i], u);
+            assertArrayEquals("Unexpected cpu cluster time for uid=" + testUids[i], uidTimesMs[i],
+                    u.getCpuClusterTimes());
+        }
+
+        // Repeat the test when the screen is off.
+
+        // PRECONDITIONS
+        updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0);
+        final long[][] deltasMs = {
+                {3000, 12000},
+                {3248327490475L, 0},
+                {43000, 3345000}
+        };
+        doAnswer(invocation -> {
+            final KernelUidCpuClusterTimeReader.Callback callback =
+                    (KernelUidCpuClusterTimeReader.Callback) invocation.getArguments()[0];
+            for (int i = 0; i < testUids.length; ++i) {
+                callback.onUidCpuPolicyTime(testUids[i], deltasMs[i]);
+            }
+            return null;
+        }).when(mKernelUidCpuClusterTimeReader).readDelta(
+                any(KernelUidCpuClusterTimeReader.Callback.class));
+
+        // RUN
+        mBatteryStatsImpl.readKernelUidCpuClusterTimesLocked();
+
+        // VERIFY
+        for (int i = 0; i < testUids.length; ++i) {
+            final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
+            assertNotNull("No entry for uid=" + testUids[i], u);
+            assertArrayEquals("Unexpected cpu cluster time for uid=" + testUids[i], sum(uidTimesMs[i], deltasMs[i]),
+                    u.getCpuClusterTimes());
+        }
+    }
+
     private void updateTimeBasesLocked(boolean unplugged, int screenState,
             long upTime, long realTime) {
         // Set PowerProfile=null before calling updateTimeBasesLocked to avoid execution of
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java
index e8f2456..702f4b8 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java
@@ -39,8 +39,11 @@
         KernelMemoryBandwidthStatsTest.class,
         KernelSingleUidTimeReaderTest.class,
         KernelUidCpuFreqTimeReaderTest.class,
+        KernelUidCpuActiveTimeReaderTest.class,
+        KernelUidCpuClusterTimeReaderTest.class,
         KernelWakelockReaderTest.class,
-        LongSamplingCounterArrayTest.class
+        LongSamplingCounterArrayTest.class,
+        PowerProfileTest.class
     })
 public class BatteryStatsTests {
 }
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelUidCpuActiveTimeReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelUidCpuActiveTimeReaderTest.java
new file mode 100644
index 0000000..1ac82bd
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/os/KernelUidCpuActiveTimeReaderTest.java
@@ -0,0 +1,240 @@
+/*
+ * 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.internal.os;
+
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+import java.io.BufferedReader;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Random;
+
+/**
+ * Test class for {@link KernelUidCpuActiveTimeReader}.
+ *
+ * To run it:
+ * bit FrameworksCoreTests:com.android.internal.os.KernelUidCpuActiveTimeReaderTest
+ *
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class KernelUidCpuActiveTimeReaderTest {
+    @Mock private BufferedReader mBufferedReader;
+    @Mock private KernelUidCpuActiveTimeReader.Callback mCallback;
+
+    private KernelUidCpuActiveTimeReader mReader;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mReader = new KernelUidCpuActiveTimeReader();
+    }
+
+    public class Temp {
+
+        public void method() {
+            method1(new long[][]{{1,2,3}, {2,3,4}});
+            method1(new long[][]{{2,2,3}, {2,3,4}});
+        }
+        public int method1(long[][] array) {
+            return array.length * array[0].length;
+        }
+    }
+
+    @Test
+    public void testReadDelta() throws Exception {
+        final int cores = 8;
+        final String info = "active: 8";
+        final int[] uids = {1, 22, 333, 4444, 5555};
+
+        final long[][] times = increaseTime(new long[uids.length][cores]);
+        when(mBufferedReader.readLine()).thenReturn(info, formatTime(uids, times));
+        mReader.readDeltaInternal(mBufferedReader, mCallback);
+        for(int i=0;i<uids.length;i++){
+            verify(mCallback).onUidCpuActiveTime(uids[i], getTotal(times[i]));
+        }
+        verifyNoMoreInteractions(mCallback);
+
+        // Verify that a second call will only return deltas.
+        Mockito.reset(mCallback, mBufferedReader);
+        final long[][] times1 = increaseTime(times);
+        when(mBufferedReader.readLine()).thenReturn(info, formatTime(uids, times1));
+        mReader.readDeltaInternal(mBufferedReader, mCallback);
+        for(int i=0;i<uids.length;i++){
+            verify(mCallback).onUidCpuActiveTime(uids[i], getTotal(subtract(times1[i], times[i])));
+        }
+        verifyNoMoreInteractions(mCallback);
+
+        // Verify that there won't be a callback if the proc file values didn't change.
+        Mockito.reset(mCallback, mBufferedReader);
+        when(mBufferedReader.readLine()).thenReturn(info, formatTime(uids, times1));
+        mReader.readDeltaInternal(mBufferedReader, mCallback);
+        verifyNoMoreInteractions(mCallback);
+
+        // Verify that calling with a null callback doesn't result in any crashes
+        Mockito.reset(mCallback, mBufferedReader);
+        final long[][] times2 = increaseTime(times1);
+        when(mBufferedReader.readLine()).thenReturn(info, formatTime(uids, times2));
+        mReader.readDeltaInternal(mBufferedReader, null);
+
+        // Verify that the readDelta call will only return deltas when
+        // the previous call had null callback.
+        Mockito.reset(mCallback, mBufferedReader);
+        final long[][] times3 = increaseTime(times2);
+        when(mBufferedReader.readLine()).thenReturn(info, formatTime(uids, times3));
+        mReader.readDeltaInternal(mBufferedReader, mCallback);
+        for (int i = 0; i < uids.length; ++i) {
+            verify(mCallback).onUidCpuActiveTime(uids[i], getTotal(subtract(times3[i], times2[i])));
+        }
+        verifyNoMoreInteractions(mCallback);
+    }
+
+    @Test
+    public void testReadDelta_malformedData() throws Exception {
+        final int cores = 8;
+        final String info = "active: 8";
+        final int[] uids = {1, 22, 333, 4444, 5555};
+        final long[][] times = increaseTime(new long[uids.length][cores]);
+        when(mBufferedReader.readLine()).thenReturn(info, formatTime(uids, times));
+        mReader.readDeltaInternal(mBufferedReader, mCallback);
+        for(int i=0;i<uids.length;i++){
+            verify(mCallback).onUidCpuActiveTime(uids[i], getTotal(times[i]));
+        }
+        verifyNoMoreInteractions(mCallback);
+
+        // Verify that there is no callback if subsequent call provides wrong # of entries.
+        Mockito.reset(mCallback, mBufferedReader);
+        final long[][] temp = increaseTime(times);
+        final long[][] times1 = new long[uids.length][];
+        for(int i=0;i<temp.length;i++){
+            times1[i] = Arrays.copyOfRange(temp[i], 0, 6);
+        }
+        when(mBufferedReader.readLine()).thenReturn(info, formatTime(uids, times1));
+        mReader.readDeltaInternal(mBufferedReader, mCallback);
+        verifyNoMoreInteractions(mCallback);
+
+        // Verify that the internal state was not modified if the given core count does not match
+        // the following # of entries.
+        Mockito.reset(mCallback, mBufferedReader);
+        final long[][] times2 = increaseTime(times);
+        when(mBufferedReader.readLine()).thenReturn(info, formatTime(uids, times2));
+        mReader.readDeltaInternal(mBufferedReader, mCallback);
+        for(int i=0;i<uids.length;i++){
+            verify(mCallback).onUidCpuActiveTime(uids[i], getTotal(subtract(times2[i], times[i])));
+        }
+        verifyNoMoreInteractions(mCallback);
+
+        // Verify that there is no callback if any value in the proc file is -ve.
+        Mockito.reset(mCallback, mBufferedReader);
+        final long[][] times3 = increaseTime(times2);
+        times3[uids.length - 1][cores - 1] *= -1;
+        when(mBufferedReader.readLine()).thenReturn(info, formatTime(uids, times3));
+        mReader.readDeltaInternal(mBufferedReader, mCallback);
+        for (int i = 0; i < uids.length - 1; ++i) {
+            verify(mCallback).onUidCpuActiveTime(uids[i], getTotal(subtract(times3[i], times2[i])));
+        }
+        verifyNoMoreInteractions(mCallback);
+
+        // Verify that the internal state was not modified when the proc file had -ve value.
+        Mockito.reset(mCallback, mBufferedReader);
+        for (int i = 0; i < cores; i++) {
+            times3[uids.length - 1][i] = times2[uids.length - 1][i] + uids[uids.length - 1] * 1000;
+        }
+        when(mBufferedReader.readLine()).thenReturn(info, formatTime(uids, times3));
+        mReader.readDeltaInternal(mBufferedReader, mCallback);
+        verify(mCallback).onUidCpuActiveTime(uids[uids.length - 1], getTotal(subtract(times3[uids.length - 1], times2[uids.length - 1])));
+        verifyNoMoreInteractions(mCallback);
+
+        // Verify that there is no callback if the values in the proc file are decreased.
+        Mockito.reset(mCallback, mBufferedReader);
+        final long[][] times4 = increaseTime(times3);
+        times4[uids.length - 1][cores - 1] = times3[uids.length - 1][cores - 1] - 1;
+        when(mBufferedReader.readLine()).thenReturn(info, formatTime(uids, times4));
+        mReader.readDeltaInternal(mBufferedReader, mCallback);
+        for (int i = 0; i < uids.length - 1; ++i) {
+            verify(mCallback).onUidCpuActiveTime(uids[i], getTotal(subtract(times4[i], times3[i])));
+        }
+        verifyNoMoreInteractions(mCallback);
+
+        // Verify that the internal state was not modified when the proc file had decreased values.
+        Mockito.reset(mCallback, mBufferedReader);
+        for (int i = 0; i < cores; i++) {
+            times4[uids.length - 1][i] = times3[uids.length - 1][i] + uids[uids.length - 1] * 1000;
+        }
+        when(mBufferedReader.readLine()).thenReturn(info, formatTime(uids, times4));
+        mReader.readDeltaInternal(mBufferedReader, mCallback);
+        verify(mCallback).onUidCpuActiveTime(uids[uids.length - 1], getTotal(subtract(times4[uids.length - 1], times3[uids.length - 1])));
+        verifyNoMoreInteractions(mCallback);
+    }
+
+    private long[] subtract(long[] a1, long[] a2) {
+        long[] val = new long[a1.length];
+        for (int i = 0; i < val.length; ++i) {
+            val[i] = a1[i] - a2[i];
+        }
+        return val;
+    }
+
+    private String[] formatTime(int[] uids, long[][] times) {
+        String[] lines = new String[uids.length + 1];
+        for (int i=0;i<uids.length;i++){
+            StringBuilder sb = new StringBuilder();
+            sb.append(uids[i]).append(':');
+            for(int j=0;j<times[i].length;j++){
+                sb.append(' ').append(times[i][j]);
+            }
+            lines[i] = sb.toString();
+        }
+        lines[uids.length] = null;
+        return lines;
+    }
+
+    private long[][] increaseTime(long[][] original) {
+        long[][] newTime = new long[original.length][original[0].length];
+        Random rand = new Random();
+        for(int i = 0;i<original.length;i++){
+            for(int j=0;j<original[0].length;j++){
+                newTime[i][j] = original[i][j] + rand.nextInt(1000_000) + 10000;
+            }
+        }
+        return newTime;
+    }
+
+    private long getTotal(long[] times) {
+        long sum = 0;
+        for(int i=0;i<times.length;i++){
+            sum+=times[i] * 10 / (i+1);
+        }
+        return sum;
+    }
+}
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelUidCpuClusterTimeReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelUidCpuClusterTimeReaderTest.java
new file mode 100644
index 0000000..0d1f852
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/os/KernelUidCpuClusterTimeReaderTest.java
@@ -0,0 +1,245 @@
+/*
+ * 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.internal.os;
+
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import static org.junit.Assert.*;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+import java.io.BufferedReader;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Random;
+
+/**
+ * Test class for {@link KernelUidCpuClusterTimeReader}.
+ *
+ * To run it:
+ * bit FrameworksCoreTests:com.android.internal.os.KernelUidCpuClusterTimeReaderTest
+ *
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class KernelUidCpuClusterTimeReaderTest {
+    @Mock private BufferedReader mBufferedReader;
+    @Mock private KernelUidCpuClusterTimeReader.Callback mCallback;
+
+    private KernelUidCpuClusterTimeReader mReader;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mReader = new KernelUidCpuClusterTimeReader();
+    }
+
+    @Test
+    public void testReadDelta() throws Exception {
+        final String info = "policy0: 2 policy4: 4";
+        final int cores = 6;
+        final int[] cluster = {2, 4};
+        final int[] uids = {1, 22, 333, 4444, 5555};
+
+        // Verify initial call
+        final long[][] times = increaseTime(new long[uids.length][cores]);
+        when(mBufferedReader.readLine()).thenReturn(info, formatTime(uids, times));
+        mReader.readDeltaInternal(mBufferedReader, mCallback);
+        for (int i=0;i<uids.length;i++){
+            verify(mCallback).onUidCpuPolicyTime(uids[i], getTotal(cluster, times[i]));
+        }
+
+        // Verify that a second call will only return deltas.
+        Mockito.reset(mCallback, mBufferedReader);
+        final long[][] times1 = increaseTime(times);
+        when(mBufferedReader.readLine()).thenReturn(info, formatTime(uids, times1));
+        mReader.readDeltaInternal(mBufferedReader, mCallback);
+        for (int i=0;i<uids.length;i++){
+            verify(mCallback).onUidCpuPolicyTime(uids[i], getTotal(cluster, subtract(times1[i], times[i])));
+        }
+
+        // Verify that there won't be a callback if the proc file values didn't change.
+        Mockito.reset(mCallback, mBufferedReader);
+        when(mBufferedReader.readLine()).thenReturn(info, formatTime(uids, times1));
+        mReader.readDeltaInternal(mBufferedReader, mCallback);
+        verifyNoMoreInteractions(mCallback);
+
+        // Verify that calling with a null callback doesn't result in any crashes
+        Mockito.reset(mCallback, mBufferedReader);
+        final long[][] times2 = increaseTime(times1);
+        when(mBufferedReader.readLine()).thenReturn(info, formatTime(uids, times2));
+        mReader.readDeltaInternal(mBufferedReader, null);
+
+        // Verify that the readDelta call will only return deltas when
+        // the previous call had null callback.
+        Mockito.reset(mCallback, mBufferedReader);
+        final long[][] times3 = increaseTime(times2);
+        when(mBufferedReader.readLine()).thenReturn(info, formatTime(uids, times3));
+        mReader.readDeltaInternal(mBufferedReader, mCallback);
+        for (int i=0;i<uids.length;i++){
+            verify(mCallback).onUidCpuPolicyTime(uids[i], getTotal(cluster, subtract(times3[i], times2[i])));
+        }
+
+    }
+
+    @Test
+    public void testReadDelta_malformedData() throws Exception {
+        final String info = "policy0: 2 policy4: 4";
+        final int cores = 6;
+        final int[] cluster = {2, 4};
+        final int[] uids = {1, 22, 333, 4444, 5555};
+
+        // Verify initial call
+        final long[][] times = increaseTime(new long[uids.length][cores]);
+        when(mBufferedReader.readLine()).thenReturn(info, formatTime(uids, times));
+        mReader.readDeltaInternal(mBufferedReader, mCallback);
+        for (int i=0;i<uids.length;i++){
+            verify(mCallback).onUidCpuPolicyTime(uids[i], getTotal(cluster, times[i]));
+        }
+
+        // Verify that there is no callback if subsequent call provides wrong # of entries.
+        Mockito.reset(mCallback, mBufferedReader);
+        final long[][] temp = increaseTime(times);
+        final long[][] times1 = new long[uids.length][];
+        for(int i=0;i<temp.length;i++){
+            times1[i] = Arrays.copyOfRange(temp[i], 0, 4);
+        }
+        when(mBufferedReader.readLine()).thenReturn(info, formatTime(uids, times1));
+        mReader.readDeltaInternal(mBufferedReader, mCallback);
+        verifyNoMoreInteractions(mCallback);
+
+        // Verify that the internal state was not modified if the given core count does not match
+        // the following # of entries.
+        Mockito.reset(mCallback, mBufferedReader);
+        final long[][] times2 = increaseTime(times);
+        when(mBufferedReader.readLine()).thenReturn(info, formatTime(uids, times2));
+        mReader.readDeltaInternal(mBufferedReader, mCallback);
+        for (int i=0;i<uids.length;i++){
+            verify(mCallback).onUidCpuPolicyTime(uids[i], getTotal(cluster, subtract(times2[i], times[i])));
+        }
+
+        // Verify that there is no callback if any value in the proc file is -ve.
+        Mockito.reset(mCallback, mBufferedReader);
+        final long[][] times3 = increaseTime(times2);
+        times3[uids.length - 1][cores - 1] *= -1;
+        when(mBufferedReader.readLine()).thenReturn(info, formatTime(uids, times3));
+        mReader.readDeltaInternal(mBufferedReader, mCallback);
+        for (int i=0;i<uids.length-1;i++){
+            verify(mCallback).onUidCpuPolicyTime(uids[i], getTotal(cluster, subtract(times3[i], times2[i])));
+        }
+        verifyNoMoreInteractions(mCallback);
+
+        // Verify that the internal state was not modified when the proc file had -ve value.
+        Mockito.reset(mCallback, mBufferedReader);
+        for(int i=0;i<cores;i++){
+            times3[uids.length -1][i] = times2[uids.length -1][i] + uids[uids.length -1]*1000;
+        }
+        when(mBufferedReader.readLine()).thenReturn(info, formatTime(uids, times3));
+        mReader.readDeltaInternal(mBufferedReader, mCallback);
+        verify(mCallback, times(1)).onUidCpuPolicyTime(uids[uids.length-1], getTotal(cluster, subtract(times3[uids.length -1], times2[uids.length -1])));
+
+        // // Verify that there is no callback if the values in the proc file are decreased.
+        Mockito.reset(mCallback, mBufferedReader);
+        final long[][] times4 = increaseTime(times3);
+        times4[uids.length - 1][cores - 1] = times3[uids.length - 1][cores - 1] - 1;
+        when(mBufferedReader.readLine()).thenReturn(info, formatTime(uids, times4));
+        mReader.readDeltaInternal(mBufferedReader, mCallback);
+        for (int i=0;i<uids.length-1;i++){
+            verify(mCallback).onUidCpuPolicyTime(uids[i], getTotal(cluster, subtract(times4[i], times3[i])));
+        }
+        verifyNoMoreInteractions(mCallback);
+
+        // Verify that the internal state was not modified when the proc file had decreased values.
+        Mockito.reset(mCallback, mBufferedReader);
+        for(int i=0;i<cores;i++){
+            times4[uids.length -1][i] = times3[uids.length -1][i] + uids[uids.length -1]*1000;
+        }
+        when(mBufferedReader.readLine()).thenReturn(info, formatTime(uids, times4));
+        mReader.readDeltaInternal(mBufferedReader, mCallback);
+        verify(mCallback, times(1))
+                .onUidCpuPolicyTime(uids[uids.length-1], getTotal(cluster, subtract(times3[uids.length -1], times2[uids.length -1])));
+
+    }
+
+
+    private long[] subtract(long[] a1, long[] a2) {
+        long[] val = new long[a1.length];
+        for (int i = 0; i < val.length; ++i) {
+            val[i] = a1[i] - a2[i];
+        }
+        return val;
+    }
+
+    private String[] formatTime(int[] uids, long[][] times) {
+        String[] lines = new String[uids.length + 1];
+        for (int i=0;i<uids.length;i++){
+            StringBuilder sb = new StringBuilder();
+            sb.append(uids[i]).append(':');
+            for(int j=0;j<times[i].length;j++){
+                sb.append(' ').append(times[i][j]);
+            }
+            lines[i] = sb.toString();
+        }
+        lines[uids.length] = null;
+        return lines;
+    }
+
+    private long[][] increaseTime(long[][] original) {
+        long[][] newTime = new long[original.length][original[0].length];
+        Random rand = new Random();
+        for(int i = 0;i<original.length;i++){
+            for(int j=0;j<original[0].length;j++){
+                newTime[i][j] = original[i][j] + rand.nextInt(1000_000) + 10000;
+            }
+        }
+        return newTime;
+    }
+
+    // Format an array of cluster times according to the algorithm in KernelUidCpuClusterTimeReader
+    private long[] getTotal(int[] cluster, long[] times) {
+        int core = 0;
+        long[] sum = new long[cluster.length];
+        for(int i=0;i<cluster.length;i++){
+            for(int j=0;j<cluster[i];j++){
+                sum[i] += times[core++] * 10 / (j+1);
+            }
+        }
+        return sum;
+    }
+
+    // Compare array1 against flattened 2d array array2 element by element
+    private boolean testEqual(long[] array1, long[][] array2) {
+        int k=0;
+        for(int i=0;i<array2.length;i++){
+            for(int j=0;j<array2[i].length;j++){
+                if (k >= array1.length || array1[k++]!=array2[i][j])return false;
+            }
+        }
+        return k == array1.length;
+    }
+}
diff --git a/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java b/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java
index 6c5a2aa..660c744 100644
--- a/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java
+++ b/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java
@@ -88,6 +88,16 @@
         return this;
     }
 
+    public MockBatteryStatsImpl setKernelUidCpuActiveTimeReader(KernelUidCpuActiveTimeReader reader) {
+        mKernelUidCpuActiveTimeReader = reader;
+        return this;
+    }
+
+    public MockBatteryStatsImpl setKernelUidCpuClusterTimeReader(KernelUidCpuClusterTimeReader reader) {
+        mKernelUidCpuClusterTimeReader = reader;
+        return this;
+    }
+
     public MockBatteryStatsImpl setKernelUidCpuTimeReader(KernelUidCpuTimeReader reader) {
         mKernelUidCpuTimeReader = reader;
         return this;
diff --git a/core/tests/coretests/src/com/android/internal/os/PowerProfileTest.java b/core/tests/coretests/src/com/android/internal/os/PowerProfileTest.java
new file mode 100644
index 0000000..eb7da9c
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/os/PowerProfileTest.java
@@ -0,0 +1,58 @@
+/*
+ * 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.internal.os;
+
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+
+import junit.framework.TestCase;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/*
+ * Keep this file in sync with frameworks/base/core/res/res/xml/power_profile_test.xml
+ */
+@SmallTest
+public class PowerProfileTest extends TestCase {
+
+    private PowerProfile mProfile;
+
+    @Before
+    public void setUp() {
+        mProfile = new PowerProfile(InstrumentationRegistry.getContext(), true);
+    }
+
+    @Test
+    public void testPowerProfile() {
+        assertEquals(2, mProfile.getNumCpuClusters());
+        assertEquals(4, mProfile.getNumCoresInCpuCluster(0));
+        assertEquals(4, mProfile.getNumCoresInCpuCluster(1));
+        assertEquals(5.0, mProfile.getAveragePower(PowerProfile.POWER_CPU_SUSPEND));
+        assertEquals(1.11, mProfile.getAveragePower(PowerProfile.POWER_CPU_IDLE));
+        assertEquals(2.55, mProfile.getAveragePower(PowerProfile.POWER_CPU_ACTIVE));
+        assertEquals(2.11, mProfile.getAveragePowerForCpuCluster(0));
+        assertEquals(2.22, mProfile.getAveragePowerForCpuCluster(1));
+        assertEquals(3, mProfile.getNumSpeedStepsInCpuCluster(0));
+        assertEquals(30.0, mProfile.getAveragePowerForCpuCore(0, 2));
+        assertEquals(4, mProfile.getNumSpeedStepsInCpuCluster(1));
+        assertEquals(60.0, mProfile.getAveragePowerForCpuCore(1, 3));
+        assertEquals(3000.0, mProfile.getBatteryCapacity());
+    }
+
+}
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index 993bae1..c0633cb 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -165,6 +165,9 @@
 
     <assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="graphics" />
 
+    <assign-permission name="android.permission.DUMP" uid="incidentd" />
+    <assign-permission name="android.permission.PACKAGE_USAGE_STATS" uid="incidentd" />
+
     <assign-permission name="android.permission.ACCESS_LOWPAN_STATE" uid="lowpan" />
     <assign-permission name="android.permission.MANAGE_LOWPAN_INTERFACES" uid="lowpan" />
 
diff --git a/docs/html/reference/images/text/style/backgroundcolorspan.png b/docs/html/reference/images/text/style/backgroundcolorspan.png
new file mode 100644
index 0000000..e7e7271
--- /dev/null
+++ b/docs/html/reference/images/text/style/backgroundcolorspan.png
Binary files differ
diff --git a/docs/html/reference/images/text/style/foregroundcolorspan.png b/docs/html/reference/images/text/style/foregroundcolorspan.png
new file mode 100644
index 0000000..f60db6c
--- /dev/null
+++ b/docs/html/reference/images/text/style/foregroundcolorspan.png
Binary files differ
diff --git a/graphics/java/android/graphics/ImageDecoder.java b/graphics/java/android/graphics/ImageDecoder.java
index 05dadc9..4d715d1 100644
--- a/graphics/java/android/graphics/ImageDecoder.java
+++ b/graphics/java/android/graphics/ImageDecoder.java
@@ -33,6 +33,8 @@
 import android.net.Uri;
 import android.system.ErrnoException;
 import android.system.Os;
+import android.util.DisplayMetrics;
+import android.util.TypedValue;
 
 import libcore.io.IoUtils;
 import dalvik.system.CloseGuard;
@@ -64,6 +66,19 @@
         Resources getResources() { return null; }
 
         /* @hide */
+        int getDensity() { return Bitmap.DENSITY_NONE; }
+
+        /* @hide */
+        int computeDstDensity() {
+            Resources res = getResources();
+            if (res == null) {
+                return Bitmap.getDefaultDensity();
+            }
+
+            return res.getDisplayMetrics().densityDpi;
+        }
+
+        /* @hide */
         abstract ImageDecoder createImageDecoder() throws IOException;
     };
 
@@ -170,26 +185,73 @@
         return decoder;
     }
 
+    private static class InputStreamSource extends Source {
+        InputStreamSource(Resources res, InputStream is, int inputDensity) {
+            if (is == null) {
+                throw new IllegalArgumentException("The InputStream cannot be null");
+            }
+            mResources = res;
+            mInputStream = is;
+            mInputDensity = res != null ? inputDensity : Bitmap.DENSITY_NONE;
+        }
+
+        final Resources mResources;
+        InputStream mInputStream;
+        final int mInputDensity;
+
+        @Override
+        public Resources getResources() { return mResources; }
+
+        @Override
+        public int getDensity() { return mInputDensity; }
+
+        @Override
+        public ImageDecoder createImageDecoder() throws IOException {
+
+            synchronized (this) {
+                if (mInputStream == null) {
+                    throw new IOException("Cannot reuse InputStreamSource");
+                }
+                InputStream is = mInputStream;
+                mInputStream = null;
+                return createFromStream(is);
+            }
+        }
+    }
+
     private static class ResourceSource extends Source {
         ResourceSource(Resources res, int resId) {
             mResources = res;
             mResId = resId;
+            mResDensity = Bitmap.DENSITY_NONE;
         }
 
         final Resources mResources;
         final int       mResId;
+        int             mResDensity;
 
         @Override
         public Resources getResources() { return mResources; }
 
         @Override
+        public int getDensity() { return mResDensity; }
+
+        @Override
         public ImageDecoder createImageDecoder() throws IOException {
             // This is just used in order to access the underlying Asset and
             // keep it alive. FIXME: Can we skip creating this object?
             InputStream is = null;
             ImageDecoder decoder = null;
+            TypedValue value = new TypedValue();
             try {
-                is = mResources.openRawResource(mResId);
+                is = mResources.openRawResource(mResId, value);
+
+                if (value.density == TypedValue.DENSITY_DEFAULT) {
+                    mResDensity = DisplayMetrics.DENSITY_DEFAULT;
+                } else if (value.density != TypedValue.DENSITY_NONE) {
+                    mResDensity = value.density;
+                }
+
                 if (!(is instanceof AssetManager.AssetInputStream)) {
                     // This should never happen.
                     throw new RuntimeException("Resource is not an asset?");
@@ -421,6 +483,22 @@
     }
 
     /**
+     * Internal API used to generate bitmaps for use by Drawables (i.e. BitmapDrawable)
+     * @hide
+     */
+    public static Source createSource(Resources res, InputStream is) {
+        return new InputStreamSource(res, is, Bitmap.getDefaultDensity());
+    }
+
+    /**
+     * Internal API used to generate bitmaps for use by Drawables (i.e. BitmapDrawable)
+     * @hide
+     */
+    public static Source createSource(Resources res, InputStream is, int density) {
+        return new InputStreamSource(res, is, density);
+    }
+
+    /**
      *  Return the width and height of a given sample size.
      *
      *  This takes an input that functions like
@@ -476,6 +554,10 @@
         this.resize(dimensions.x, dimensions.y);
     }
 
+    private boolean requestedResize() {
+        return mWidth != mDesiredWidth || mHeight != mDesiredHeight;
+    }
+
     // These need to stay in sync with ImageDecoder.cpp's Allocator enum.
     /**
      *  Use the default allocation for the pixel memory.
@@ -730,6 +812,9 @@
                                                 "Drawable!");
             }
 
+            // this call potentially manipulates the decoder so it must be performed prior to
+            // decoding the bitmap and after decode set the density on the resulting bitmap
+            final int srcDensity = computeDensity(src, decoder);
             if (decoder.mAnimated) {
                 // AnimatedImageDrawable calls postProcessAndRelease only if
                 // mPostProcess exists.
@@ -737,7 +822,8 @@
                         null : decoder;
                 Drawable d = new AnimatedImageDrawable(decoder.mNativePtr,
                         postProcessPtr, decoder.mDesiredWidth,
-                        decoder.mDesiredHeight, decoder.mCropRect,
+                        decoder.mDesiredHeight, srcDensity,
+                        src.computeDstDensity(), decoder.mCropRect,
                         decoder.mInputStream, decoder.mAssetFd);
                 // d has taken ownership of these objects.
                 decoder.mInputStream = null;
@@ -746,13 +832,15 @@
             }
 
             Bitmap bm = decoder.decodeBitmap();
-            Resources res = src.getResources();
-            if (res == null) {
-                bm.setDensity(Bitmap.DENSITY_NONE);
-            }
+            bm.setDensity(srcDensity);
 
+            Resources res = src.getResources();
             byte[] np = bm.getNinePatchChunk();
             if (np != null && NinePatch.isNinePatchChunk(np)) {
+                if (res != null) {
+                    bm.setDensity(res.getDisplayMetrics().densityDpi);
+                }
+
                 Rect opticalInsets = new Rect();
                 bm.getOpticalInsets(opticalInsets);
                 Rect padding = new Rect();
@@ -799,10 +887,48 @@
                 }
             }
 
-            return decoder.decodeBitmap();
+            // this call potentially manipulates the decoder so it must be performed prior to
+            // decoding the bitmap
+            final int srcDensity = computeDensity(src, decoder);
+            Bitmap bm = decoder.decodeBitmap();
+            bm.setDensity(srcDensity);
+            return bm;
         }
     }
 
+    // This method may modify the decoder so it must be called prior to performing the decode
+    private static int computeDensity(@NonNull Source src, @NonNull ImageDecoder decoder) {
+        // if the caller changed the size then we treat the density as unknown
+        if (decoder.requestedResize()) {
+            return Bitmap.DENSITY_NONE;
+        }
+
+        // Special stuff for compatibility mode: if the target density is not
+        // the same as the display density, but the resource -is- the same as
+        // the display density, then don't scale it down to the target density.
+        // This allows us to load the system's density-correct resources into
+        // an application in compatibility mode, without scaling those down
+        // to the compatibility density only to have them scaled back up when
+        // drawn to the screen.
+        Resources res = src.getResources();
+        final int srcDensity = src.getDensity();
+        if (res != null && res.getDisplayMetrics().noncompatDensityDpi == srcDensity) {
+            return srcDensity;
+        }
+
+        // downscale the bitmap if the asset has a higher density than the default
+        final int dstDensity = src.computeDstDensity();
+        if (srcDensity != Bitmap.DENSITY_NONE && srcDensity > dstDensity) {
+            float scale = (float) dstDensity / srcDensity;
+            int scaledWidth = (int) (decoder.mWidth * scale + 0.5f);
+            int scaledHeight = (int) (decoder.mHeight * scale + 0.5f);
+            decoder.resize(scaledWidth, scaledHeight);
+            return dstDensity;
+        }
+
+        return srcDensity;
+    }
+
     private String getMimeType() {
         return nGetMimeType(mNativePtr);
     }
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index 68b7ac2..ef41507 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -1025,6 +1025,10 @@
                         xmlFamily.getName(), fallback, languageTags, variant, cache, fontDir);
                 if (family != null) {
                     fallbackMap.valueAt(i).add(family);
+                } else if (defaultFamily != null) {
+                    fallbackMap.valueAt(i).add(defaultFamily);
+                } else {
+                    // There is no valid for for default fallback. Ignore.
                 }
             }
         }
diff --git a/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java b/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java
index ce3bd9a..da170c0 100644
--- a/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedImageDrawable.java
@@ -20,12 +20,14 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.res.AssetFileDescriptor;
+import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.ColorFilter;
 import android.graphics.ImageDecoder;
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
 import android.os.SystemClock;
+import android.util.DisplayMetrics;
 
 import libcore.io.IoUtils;
 import libcore.util.NativeAllocationRegistry;
@@ -59,22 +61,31 @@
      * decoder is only non-null if it has a PostProcess
      */
     public AnimatedImageDrawable(long nativeImageDecoder,
-            @Nullable ImageDecoder decoder, int width, int height, Rect cropRect,
+            @Nullable ImageDecoder decoder, int width, int height,
+            int srcDensity, int dstDensity, Rect cropRect,
             InputStream inputStream, AssetFileDescriptor afd)
             throws IOException {
-        mNativePtr = nCreate(nativeImageDecoder, decoder, width, height, cropRect);
-        mInputStream = inputStream;
-        mAssetFd = afd;
+        width = Bitmap.scaleFromDensity(width, srcDensity, dstDensity);
+        height = Bitmap.scaleFromDensity(height, srcDensity, dstDensity);
 
         if (cropRect == null) {
             mIntrinsicWidth  = width;
             mIntrinsicHeight = height;
         } else {
+            cropRect.set(Bitmap.scaleFromDensity(cropRect.left, srcDensity, dstDensity),
+                    Bitmap.scaleFromDensity(cropRect.top, srcDensity, dstDensity),
+                    Bitmap.scaleFromDensity(cropRect.right, srcDensity, dstDensity),
+                    Bitmap.scaleFromDensity(cropRect.bottom, srcDensity, dstDensity));
             mIntrinsicWidth  = cropRect.width();
             mIntrinsicHeight = cropRect.height();
         }
 
-        long nativeSize = nNativeByteSize(mNativePtr);
+        mNativePtr = nCreate(nativeImageDecoder, decoder, width, height, cropRect);
+        mInputStream = inputStream;
+        mAssetFd = afd;
+
+        // FIXME: Use the right size for the native allocation.
+        long nativeSize = 200;
         NativeAllocationRegistry registry = new NativeAllocationRegistry(
                 AnimatedImageDrawable.class.getClassLoader(), nGetNativeFinalizer(), nativeSize);
         registry.registerNativeAllocation(this, mNativePtr);
diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java
index e3740e3..f74c39d 100644
--- a/graphics/java/android/graphics/drawable/BitmapDrawable.java
+++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java
@@ -27,6 +27,7 @@
 import android.graphics.BitmapShader;
 import android.graphics.Canvas;
 import android.graphics.ColorFilter;
+import android.graphics.ImageDecoder;
 import android.graphics.Insets;
 import android.graphics.Matrix;
 import android.graphics.Outline;
@@ -49,6 +50,7 @@
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
+import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 
@@ -111,7 +113,7 @@
      */
     @Deprecated
     public BitmapDrawable() {
-        mBitmapState = new BitmapState((Bitmap) null);
+        init(new BitmapState((Bitmap) null), null);
     }
 
     /**
@@ -124,8 +126,7 @@
     @SuppressWarnings("unused")
     @Deprecated
     public BitmapDrawable(Resources res) {
-        mBitmapState = new BitmapState((Bitmap) null);
-        mBitmapState.mTargetDensity = mTargetDensity;
+        init(new BitmapState((Bitmap) null), res);
     }
 
     /**
@@ -135,7 +136,7 @@
      */
     @Deprecated
     public BitmapDrawable(Bitmap bitmap) {
-        this(new BitmapState(bitmap), null);
+        init(new BitmapState(bitmap), null);
     }
 
     /**
@@ -143,8 +144,7 @@
      * the display metrics of the resources.
      */
     public BitmapDrawable(Resources res, Bitmap bitmap) {
-        this(new BitmapState(bitmap), res);
-        mBitmapState.mTargetDensity = mTargetDensity;
+        init(new BitmapState(bitmap), res);
     }
 
     /**
@@ -154,10 +154,7 @@
      */
     @Deprecated
     public BitmapDrawable(String filepath) {
-        this(new BitmapState(BitmapFactory.decodeFile(filepath)), null);
-        if (mBitmapState.mBitmap == null) {
-            android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + filepath);
-        }
+        this(null, filepath);
     }
 
     /**
@@ -165,10 +162,21 @@
      */
     @SuppressWarnings("unused")
     public BitmapDrawable(Resources res, String filepath) {
-        this(new BitmapState(BitmapFactory.decodeFile(filepath)), null);
-        mBitmapState.mTargetDensity = mTargetDensity;
-        if (mBitmapState.mBitmap == null) {
-            android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + filepath);
+        Bitmap bitmap = null;
+        try (FileInputStream stream = new FileInputStream(filepath)) {
+            bitmap = ImageDecoder.decodeBitmap(ImageDecoder.createSource(res, stream),
+                    (info, decoder) -> {
+                decoder.setAllocator(ImageDecoder.SOFTWARE_ALLOCATOR);
+            });
+        } catch (Exception e) {
+            /*  do nothing. This matches the behavior of BitmapFactory.decodeFile()
+                If the exception happened on decode, mBitmapState.mBitmap will be null.
+            */
+        } finally {
+            init(new BitmapState(bitmap), res);
+            if (mBitmapState.mBitmap == null) {
+                android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + filepath);
+            }
         }
     }
 
@@ -179,10 +187,7 @@
      */
     @Deprecated
     public BitmapDrawable(java.io.InputStream is) {
-        this(new BitmapState(BitmapFactory.decodeStream(is)), null);
-        if (mBitmapState.mBitmap == null) {
-            android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + is);
-        }
+        this(null, is);
     }
 
     /**
@@ -190,10 +195,21 @@
      */
     @SuppressWarnings("unused")
     public BitmapDrawable(Resources res, java.io.InputStream is) {
-        this(new BitmapState(BitmapFactory.decodeStream(is)), null);
-        mBitmapState.mTargetDensity = mTargetDensity;
-        if (mBitmapState.mBitmap == null) {
-            android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + is);
+        Bitmap bitmap = null;
+        try {
+            bitmap = ImageDecoder.decodeBitmap(ImageDecoder.createSource(res, is),
+                    (info, decoder) -> {
+                decoder.setAllocator(ImageDecoder.SOFTWARE_ALLOCATOR);
+            });
+        } catch (Exception e) {
+            /*  do nothing. This matches the behavior of BitmapFactory.decodeStream()
+                If the exception happened on decode, mBitmapState.mBitmap will be null.
+            */
+        } finally {
+            init(new BitmapState(bitmap), res);
+            if (mBitmapState.mBitmap == null) {
+                android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + is);
+            }
         }
     }
 
@@ -812,9 +828,19 @@
                 }
             }
 
+            int density = Bitmap.DENSITY_NONE;
+            if (value.density == TypedValue.DENSITY_DEFAULT) {
+                density = DisplayMetrics.DENSITY_DEFAULT;
+            } else if (value.density != TypedValue.DENSITY_NONE) {
+                density = value.density;
+            }
+
             Bitmap bitmap = null;
             try (InputStream is = r.openRawResource(srcResId, value)) {
-                bitmap = BitmapFactory.decodeResourceStream(r, value, is, null, null);
+                ImageDecoder.Source source = ImageDecoder.createSource(r, is, density);
+                bitmap = ImageDecoder.decodeBitmap(source, (info, decoder) -> {
+                    decoder.setAllocator(ImageDecoder.SOFTWARE_ALLOCATOR);
+                });
             } catch (Exception e) {
                 // Do nothing and pick up the error below.
             }
@@ -1013,14 +1039,21 @@
         }
     }
 
+    private BitmapDrawable(BitmapState state, Resources res) {
+        init(state, res);
+    }
+
     /**
-     * The one constructor to rule them all. This is called by all public
+     * The one helper to rule them all. This is called by all public & private
      * constructors to set the state and initialize local properties.
      */
-    private BitmapDrawable(BitmapState state, Resources res) {
+    private void init(BitmapState state, Resources res) {
         mBitmapState = state;
-
         updateLocalState(res);
+
+        if (mBitmapState != null && res != null) {
+            mBitmapState.mTargetDensity = mTargetDensity;
+        }
     }
 
     /**
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index f17cd76..291b0a0 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -37,6 +37,7 @@
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.ColorFilter;
+import android.graphics.ImageDecoder;
 import android.graphics.Insets;
 import android.graphics.NinePatch;
 import android.graphics.Outline;
@@ -50,11 +51,13 @@
 import android.os.Trace;
 import android.util.AttributeSet;
 import android.util.DisplayMetrics;
+import android.util.Log;
 import android.util.StateSet;
 import android.util.TypedValue;
 import android.util.Xml;
 import android.view.View;
 
+import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.lang.ref.WeakReference;
@@ -1175,6 +1178,10 @@
             return null;
         }
 
+        if (opts == null) {
+            return getBitmapDrawable(res, value, is);
+        }
+
         /*  ugh. The decodeStream contract is that we have already allocated
             the pad rect, but if the bitmap does not had a ninepatch chunk,
             then the pad will be ignored. If we could change this to lazily
@@ -1207,6 +1214,33 @@
         return null;
     }
 
+    private static Drawable getBitmapDrawable(Resources res, TypedValue value, InputStream is) {
+        try {
+            ImageDecoder.Source source = null;
+            if (value != null) {
+                int density = Bitmap.DENSITY_NONE;
+                if (value.density == TypedValue.DENSITY_DEFAULT) {
+                    density = DisplayMetrics.DENSITY_DEFAULT;
+                } else if (value.density != TypedValue.DENSITY_NONE) {
+                    density = value.density;
+                }
+                source = ImageDecoder.createSource(res, is, density);
+            } else {
+                source = ImageDecoder.createSource(res, is);
+            }
+
+            return ImageDecoder.decodeDrawable(source, (info, decoder) -> {
+                decoder.setAllocator(ImageDecoder.SOFTWARE_ALLOCATOR);
+            });
+        } catch (IOException e) {
+            /*  do nothing.
+                If the exception happened on decode, the drawable will be null.
+            */
+            Log.e("Drawable", "Unable to decode stream: " + e);
+        }
+        return null;
+    }
+
     /**
      * Create a drawable from an XML document. For more information on how to
      * create resources in XML, see
@@ -1306,11 +1340,10 @@
         }
 
         Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, pathName);
-        try {
-            Bitmap bm = BitmapFactory.decodeFile(pathName);
-            if (bm != null) {
-                return drawableFromBitmap(null, bm, null, null, null, pathName);
-            }
+        try (FileInputStream stream = new FileInputStream(pathName)) {
+            return getBitmapDrawable(null, null, stream);
+        } catch(IOException e) {
+            // Do nothing; we will just return null if the FileInputStream had an error
         } finally {
             Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
         }
diff --git a/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java b/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java
index 833376c..603926f 100644
--- a/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java
+++ b/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java
@@ -19,10 +19,12 @@
 import android.os.SystemClock;
 
 import android.util.Base64;
+import android.util.Log;
 import android.util.TimeUtils;
 
 import java.util.Arrays;
 
+import com.android.internal.app.IBatteryStats;
 import com.android.internal.location.nano.GnssLogsProto.GnssLog;
 
 /**
@@ -31,14 +33,29 @@
  */
 public class GnssMetrics {
 
+  private static final String TAG = GnssMetrics.class.getSimpleName();
+
+  /* Constant which indicates GPS signal quality is poor */
+  public static final int GPS_SIGNAL_QUALITY_POOR = 0;
+
+  /* Constant which indicates GPS signal quality is good */
+  public static final int GPS_SIGNAL_QUALITY_GOOD = 1;
+
+  /* Number of GPS signal quality levels */
+  public static final int NUM_GPS_SIGNAL_QUALITY_LEVELS = GPS_SIGNAL_QUALITY_GOOD + 1;
+
   /** Default time between location fixes (in millisecs) */
   private static final int DEFAULT_TIME_BETWEEN_FIXES_MILLISECS = 1000;
 
   /* The time since boot when logging started */
   private String logStartInElapsedRealTime;
 
+  /* GNSS power metrics */
+  private GnssPowerMetrics mGnssPowerMetrics;
+
   /** Constructor */
-  public GnssMetrics() {
+  public GnssMetrics(IBatteryStats stats) {
+    mGnssPowerMetrics = new GnssPowerMetrics(stats);
     locationFailureStatistics = new Statistics();
     timeToFirstFixSecStatistics = new Statistics();
     positionAccuracyMeterStatistics = new Statistics();
@@ -103,11 +120,18 @@
   *
   */
   public void logCn0(float[] cn0s, int numSv) {
-    if (numSv < 4) {
+    if (numSv == 0 || cn0s == null || cn0s.length == 0 || cn0s.length < numSv) {
+      if (numSv == 0) {
+         mGnssPowerMetrics.reportSignalQuality(null, 0);
+      }
       return;
     }
     float[] cn0Array = Arrays.copyOf(cn0s, numSv);
     Arrays.sort(cn0Array);
+    mGnssPowerMetrics.reportSignalQuality(cn0Array, numSv);
+    if (numSv < 4) {
+      return;
+    }
     if (cn0Array[numSv - 4] > 0.0) {
       double top4AvgCn0 = 0.0;
       for (int i = numSv - 4; i < numSv; i++) {
@@ -265,4 +289,62 @@
     topFourAverageCn0Statistics.reset();
     return;
   }
+
+  /* Class for handling GNSS power related metrics */
+  private class GnssPowerMetrics {
+
+    /* Threshold for Top Four Average CN0 below which GNSS signal quality is declared poor */
+    private static final double POOR_TOP_FOUR_AVG_CN0_THRESHOLD_DB_HZ = 20.0;
+
+    /* Minimum change in Top Four Average CN0 needed to trigger a report */
+    private static final double REPORTING_THRESHOLD_DB_HZ = 1.0;
+
+    /* BatteryStats API */
+    private final IBatteryStats mBatteryStats;
+
+    /* Last reported Top Four Average CN0 */
+    private double mLastAverageCn0;
+
+    public GnssPowerMetrics(IBatteryStats stats) {
+      mBatteryStats = stats;
+      // Used to initialize the variable to a very small value (unachievable in practice) so that
+      // the first CNO report will trigger an update to BatteryStats
+      mLastAverageCn0 = -100.0;
+    }
+
+    /**
+     * Reports signal quality to BatteryStats. Signal quality is based on Top four average CN0. If
+     * the number of SVs seen is less than 4, then signal quality is the average CN0.
+     * Changes are reported only if the average CN0 changes by more than REPORTING_THRESHOLD_DB_HZ.
+     */
+    public void reportSignalQuality(float[] ascendingCN0Array, int numSv) {
+      double avgCn0 = 0.0;
+      if (numSv > 0) {
+        for (int i = Math.max(0, numSv - 4); i < numSv; i++) {
+          avgCn0 += (double) ascendingCN0Array[i];
+        }
+        avgCn0 /= Math.min(numSv, 4);
+      }
+      if (Math.abs(avgCn0 - mLastAverageCn0) < REPORTING_THRESHOLD_DB_HZ) {
+        return;
+      }
+      try {
+        mBatteryStats.noteGpsSignalQuality(getSignalLevel(avgCn0));
+        mLastAverageCn0 = avgCn0;
+      } catch (Exception e) {
+        Log.w(TAG, "Exception", e);
+      }
+      return;
+    }
+
+    /**
+     * Obtains signal level based on CN0
+     */
+    private int getSignalLevel(double cn0) {
+      if (cn0 > POOR_TOP_FOUR_AVG_CN0_THRESHOLD_DB_HZ) {
+        return GnssMetrics.GPS_SIGNAL_QUALITY_GOOD;
+      }
+      return GnssMetrics.GPS_SIGNAL_QUALITY_POOR;
+    }
+  }
 }
\ No newline at end of file
diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index e0289f0..d7861e3 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -180,6 +180,7 @@
     /**
      * IMPORTANT: when adding new usage types, add them to SDK_USAGES and update SUPPRESSIBLE_USAGES
      *            if applicable, as well as audioattributes.proto.
+     *            Also consider adding them to <aaudio/AAudio.h> for the NDK.
      */
 
     /**
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index e56944d..2cd764d 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -914,7 +914,8 @@
             (1 << STREAM_MUSIC) |
             (1 << STREAM_RING) |
             (1 << STREAM_NOTIFICATION) |
-            (1 << STREAM_SYSTEM);
+            (1 << STREAM_SYSTEM) |
+            (1 << STREAM_VOICE_CALL);
 
     /**
      * Event posted by AudioTrack and AudioRecord JNI (JNIDeviceCallback) when routing changes.
diff --git a/media/java/android/media/update/ApiLoader.java b/media/java/android/media/update/ApiLoader.java
index 07483f6..b928e93 100644
--- a/media/java/android/media/update/ApiLoader.java
+++ b/media/java/android/media/update/ApiLoader.java
@@ -16,8 +16,10 @@
 
 package android.media.update;
 
+import android.content.res.Resources;
 import android.content.Context;
-import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.PackageManager;
+import android.os.Build;
 
 /**
  * @hide
@@ -34,23 +36,25 @@
     public static StaticProvider getProvider(Context context) {
         try {
             return (StaticProvider) getMediaLibraryImpl(context);
-        } catch (NameNotFoundException | ReflectiveOperationException e) {
+        } catch (PackageManager.NameNotFoundException | ReflectiveOperationException e) {
             throw new RuntimeException(e);
         }
     }
 
     // TODO This method may do I/O; Ensure it does not violate (emit warnings in) strict mode.
-    private static synchronized Object getMediaLibraryImpl(Context appContext)
-            throws NameNotFoundException, ReflectiveOperationException {
+    private static synchronized Object getMediaLibraryImpl(Context context)
+            throws PackageManager.NameNotFoundException, ReflectiveOperationException {
         if (sMediaLibrary != null) return sMediaLibrary;
 
-        // TODO Dynamically find the package name
-        Context libContext = appContext.createPackageContext(UPDATE_PACKAGE,
+        // TODO Figure out when to use which package (query media update service)
+        int flags = Build.IS_DEBUGGABLE ? 0 : PackageManager.MATCH_FACTORY_ONLY;
+        Context libContext = context.createApplicationContext(
+                context.getPackageManager().getPackageInfo(UPDATE_PACKAGE, flags).applicationInfo,
                 Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
         sMediaLibrary = libContext.getClassLoader()
                 .loadClass(UPDATE_CLASS)
-                .getMethod(UPDATE_METHOD, Context.class, Context.class)
-                .invoke(null, appContext, libContext);
+                .getMethod(UPDATE_METHOD, Resources.class, Resources.Theme.class)
+                .invoke(null, libContext.getResources(), libContext.getTheme());
         return sMediaLibrary;
     }
 }
diff --git a/media/java/android/media/update/MediaController2Provider.java b/media/java/android/media/update/MediaControlView2Provider.java
similarity index 82%
rename from media/java/android/media/update/MediaController2Provider.java
rename to media/java/android/media/update/MediaControlView2Provider.java
index 71fbd08..83763b4 100644
--- a/media/java/android/media/update/MediaController2Provider.java
+++ b/media/java/android/media/update/MediaControlView2Provider.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright 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.
@@ -19,7 +19,6 @@
 import android.annotation.SystemApi;
 import android.media.session.MediaController;
 import android.view.View;
-import android.view.View.OnClickListener;
 
 /**
  * Interface for connecting the public API to an updatable implementation.
@@ -30,19 +29,17 @@
  *
  * All methods behave as per their namesake in the public API.
  *
- * @see android.widget.MediaController2
+ * @see android.widget.MediaControlView2
  *
  * @hide
  */
 // TODO @SystemApi
-public interface MediaController2Provider extends ViewProvider {
+public interface MediaControlView2Provider extends ViewProvider {
     void setController_impl(MediaController controller);
-    void setAnchorView_impl(View view);
     void show_impl();
     void show_impl(int timeout);
     boolean isShowing_impl();
     void hide_impl();
-    void setPrevNextListeners_impl(OnClickListener next, OnClickListener prev);
     void showCCButton_impl();
     boolean isPlaying_impl();
     int getCurrentPosition_impl();
diff --git a/media/java/android/media/update/StaticProvider.java b/media/java/android/media/update/StaticProvider.java
index a1e2404..1a0df52 100644
--- a/media/java/android/media/update/StaticProvider.java
+++ b/media/java/android/media/update/StaticProvider.java
@@ -16,8 +16,10 @@
 
 package android.media.update;
 
+import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.widget.MediaController2;
+import android.util.AttributeSet;
+import android.widget.MediaControlView2;
 import android.widget.VideoView2;
 
 /**
@@ -30,7 +32,9 @@
  */
 // TODO @SystemApi
 public interface StaticProvider {
-    MediaController2Provider createMediaController2(
-            MediaController2 instance, ViewProvider superProvider);
-    VideoView2Provider createVideoView2(VideoView2 instance, ViewProvider superProvider);
+    MediaControlView2Provider createMediaControlView2(
+            MediaControlView2 instance, ViewProvider superProvider);
+    VideoView2Provider createVideoView2(
+            VideoView2 instance, ViewProvider superProvider,
+            @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes);
 }
diff --git a/media/java/android/media/update/VideoView2Provider.java b/media/java/android/media/update/VideoView2Provider.java
index 6fc9bdc..b7a24e5 100644
--- a/media/java/android/media/update/VideoView2Provider.java
+++ b/media/java/android/media/update/VideoView2Provider.java
@@ -17,9 +17,8 @@
 package android.media.update;
 
 import android.media.AudioAttributes;
-import android.media.MediaPlayer;
 import android.net.Uri;
-import android.widget.MediaController2;
+import android.widget.MediaControlView2;
 import android.widget.VideoView2;
 
 import java.util.Map;
@@ -39,6 +38,8 @@
  */
 // TODO @SystemApi
 public interface VideoView2Provider extends ViewProvider {
+    void setMediaControlView2_impl(MediaControlView2 mediaControlView);
+    MediaControlView2 getMediaControlView2_impl();
     void start_impl();
     void pause_impl();
     int getDuration_impl();
@@ -49,18 +50,19 @@
     int getAudioSessionId_impl();
     void showSubtitle_impl();
     void hideSubtitle_impl();
+    void setSpeed_impl(float speed);
+    float getSpeed_impl();
     void setAudioFocusRequest_impl(int focusGain);
     void setAudioAttributes_impl(AudioAttributes attributes);
     void setVideoPath_impl(String path);
     void setVideoURI_impl(Uri uri);
     void setVideoURI_impl(Uri uri, Map<String, String> headers);
-    void setMediaController2_impl(MediaController2 controllerView);
     void setViewType_impl(int viewType);
     int getViewType_impl();
     void stopPlayback_impl();
-    void setOnPreparedListener_impl(MediaPlayer.OnPreparedListener l);
-    void setOnCompletionListener_impl(MediaPlayer.OnCompletionListener l);
-    void setOnErrorListener_impl(MediaPlayer.OnErrorListener l);
-    void setOnInfoListener_impl(MediaPlayer.OnInfoListener l);
+    void setOnPreparedListener_impl(VideoView2.OnPreparedListener l);
+    void setOnCompletionListener_impl(VideoView2.OnCompletionListener l);
+    void setOnErrorListener_impl(VideoView2.OnErrorListener l);
+    void setOnInfoListener_impl(VideoView2.OnInfoListener l);
     void setOnViewTypeChangedListener_impl(VideoView2.OnViewTypeChangedListener l);
 }
diff --git a/media/java/android/media/update/ViewProvider.java b/media/java/android/media/update/ViewProvider.java
index bc8f203..e542404 100644
--- a/media/java/android/media/update/ViewProvider.java
+++ b/media/java/android/media/update/ViewProvider.java
@@ -37,10 +37,6 @@
 // TODO @SystemApi
 public interface ViewProvider {
     // TODO Add more (all?) methods from View
-    void onAttachedToWindow_impl();
-    void onDetachedFromWindow_impl();
-    void onLayout_impl(boolean changed, int left, int top, int right, int bottom);
-    void draw_impl(Canvas canvas);
     CharSequence getAccessibilityClassName_impl();
     boolean onTouchEvent_impl(MotionEvent ev);
     boolean onTrackballEvent_impl(MotionEvent ev);
diff --git a/native/graphics/jni/Android.bp b/native/graphics/jni/Android.bp
index 61164e0..0704e35 100644
--- a/native/graphics/jni/Android.bp
+++ b/native/graphics/jni/Android.bp
@@ -29,6 +29,13 @@
     shared_libs: [
         "libandroid_runtime",
     ],
+
+    arch: {
+        arm: {
+            // TODO: This is to work around b/24465209. Remove after root cause is fixed
+            ldflags: ["-Wl,--hash-style=both"],
+        },
+    },
 }
 
 // The headers module is in frameworks/native/Android.bp.
diff --git a/packages/ExtServices/AndroidManifest.xml b/packages/ExtServices/AndroidManifest.xml
index 291009e..45e557c 100644
--- a/packages/ExtServices/AndroidManifest.xml
+++ b/packages/ExtServices/AndroidManifest.xml
@@ -51,6 +51,19 @@
             </intent-filter>
         </service>
 
+        <service android:name=".autofill.AutofillFieldClassificationServiceImpl"
+             android:permission="android.permission.BIND_AUTOFILL_FIELD_CLASSIFICATION_SERVICE">
+            <intent-filter>
+                <action android:name="android.service.autofill.AutofillFieldClassificationService" />
+            </intent-filter>
+            <meta-data
+                android:name="android.autofill.field_classification.default_algorithm"
+                android:resource="@string/autofill_field_classification_default_algorithm" />
+            <meta-data
+                android:name="android.autofill.field_classification.available_algorithms"
+                android:resource="@array/autofill_field_classification_available_algorithms" />
+        </service>
+
         <library android:name="android.ext.services"/>
     </application>
 
diff --git a/packages/ExtServices/res/values/strings.xml b/packages/ExtServices/res/values/strings.xml
index a2e65bc..72647ab 100644
--- a/packages/ExtServices/res/values/strings.xml
+++ b/packages/ExtServices/res/values/strings.xml
@@ -19,4 +19,9 @@
 
     <string name="notification_assistant">Notification Assistant</string>
     <string name="prompt_block_reason">Too many dismissals:views</string>
+
+    <string name="autofill_field_classification_default_algorithm">EDIT_DISTANCE</string>
+    <string-array name="autofill_field_classification_available_algorithms">
+        <item>EDIT_DISTANCE</item>
+    </string-array>
 </resources>
diff --git a/packages/ExtServices/src/android/ext/services/autofill/AutofillFieldClassificationServiceImpl.java b/packages/ExtServices/src/android/ext/services/autofill/AutofillFieldClassificationServiceImpl.java
new file mode 100644
index 0000000..4709d35
--- /dev/null
+++ b/packages/ExtServices/src/android/ext/services/autofill/AutofillFieldClassificationServiceImpl.java
@@ -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.
+ */
+package android.ext.services.autofill;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Bundle;
+import android.service.autofill.AutofillFieldClassificationService;
+import android.util.Log;
+import android.view.autofill.AutofillValue;
+
+import com.android.internal.util.ArrayUtils;
+
+import java.util.List;
+
+public class AutofillFieldClassificationServiceImpl extends AutofillFieldClassificationService {
+
+    private static final String TAG = "AutofillFieldClassificationServiceImpl";
+    // TODO(b/70291841): set to false before launching
+    private static final boolean DEBUG = true;
+
+    @Nullable
+    @Override
+    public float[][] onGetScores(@Nullable String algorithmName,
+            @Nullable Bundle algorithmArgs, @NonNull List<AutofillValue> actualValues,
+            @NonNull List<String> userDataValues) {
+        if (ArrayUtils.isEmpty(actualValues) || ArrayUtils.isEmpty(userDataValues)) {
+            Log.w(TAG, "getScores(): empty currentvalues (" + actualValues + ") or userValues ("
+                    + userDataValues + ")");
+            // TODO(b/70939974): add unit test
+            return null;
+        }
+        if (algorithmName != null && !algorithmName.equals(EditDistanceScorer.NAME)) {
+            Log.w(TAG, "Ignoring invalid algorithm (" + algorithmName + ") and using "
+                    + EditDistanceScorer.NAME + " instead");
+        }
+
+        final String actualAlgorithmName = EditDistanceScorer.NAME;
+        final int actualValuesSize = actualValues.size();
+        final int userDataValuesSize = userDataValues.size();
+        if (DEBUG) {
+            Log.d(TAG, "getScores() will return a " + actualValuesSize + "x"
+                    + userDataValuesSize + " matrix for " + actualAlgorithmName);
+        }
+        final float[][] scores = new float[actualValuesSize][userDataValuesSize];
+
+        final EditDistanceScorer algorithm = EditDistanceScorer.getInstance();
+        for (int i = 0; i < actualValuesSize; i++) {
+            for (int j = 0; j < userDataValuesSize; j++) {
+                final float score = algorithm.getScore(actualValues.get(i), userDataValues.get(j));
+                scores[i][j] = score;
+            }
+        }
+        return scores;
+    }
+}
diff --git a/core/java/android/service/autofill/EditDistanceScorer.java b/packages/ExtServices/src/android/ext/services/autofill/EditDistanceScorer.java
similarity index 91%
rename from core/java/android/service/autofill/EditDistanceScorer.java
rename to packages/ExtServices/src/android/ext/services/autofill/EditDistanceScorer.java
index 97a3868..d2e804a 100644
--- a/core/java/android/service/autofill/EditDistanceScorer.java
+++ b/packages/ExtServices/src/android/ext/services/autofill/EditDistanceScorer.java
@@ -13,10 +13,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.service.autofill;
+package android.ext.services.autofill;
 
 import android.annotation.NonNull;
-import android.annotation.TestApi;
 import android.view.autofill.AutofillValue;
 
 /**
@@ -24,20 +23,15 @@
  * by the user and the expected value predicted by an autofill service.
  */
 // TODO(b/70291841): explain algorithm once it's fully implemented
-/** @hide */
-@TestApi
-public final class EditDistanceScorer {
+final class EditDistanceScorer {
 
     private static final EditDistanceScorer sInstance = new EditDistanceScorer();
 
-    /** @hide */
     public static final String NAME = "EDIT_DISTANCE";
 
     /**
      * Gets the singleton instance.
      */
-    @TestApi
-    /** @hide */
     public static EditDistanceScorer getInstance() {
         return sInstance;
     }
@@ -52,9 +46,7 @@
      * <p>A full-match is {@code 1.0} (representing 100%), a full mismatch is {@code 0.0} and
      * partial mathces are something in between, typically using edit-distance algorithms.
      *
-     * @hide
      */
-    @TestApi
     public float getScore(@NonNull AutofillValue actualValue, @NonNull String userDataValue) {
         if (actualValue == null || !actualValue.isText() || userDataValue == null) return 0;
         // TODO(b/70291841): implement edit distance - currently it's returning either 0, 100%, or
diff --git a/packages/ExtServices/tests/src/android/ext/services/autofill/EditDistanceScorerTest.java b/packages/ExtServices/tests/src/android/ext/services/autofill/EditDistanceScorerTest.java
new file mode 100644
index 0000000..cc15719
--- /dev/null
+++ b/packages/ExtServices/tests/src/android/ext/services/autofill/EditDistanceScorerTest.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.ext.services.autofill;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.support.test.runner.AndroidJUnit4;
+import android.view.autofill.AutofillValue;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class EditDistanceScorerTest {
+
+    private final EditDistanceScorer mScorer = EditDistanceScorer.getInstance();
+
+    @Test
+    public void testGetScore_nullValue() {
+        assertFloat(mScorer.getScore(null, "D'OH!"), 0);
+    }
+
+    @Test
+    public void testGetScore_nonTextValue() {
+        assertFloat(mScorer.getScore(AutofillValue.forToggle(true), "D'OH!"), 0);
+    }
+
+    @Test
+    public void testGetScore_nullUserData() {
+        assertFloat(mScorer.getScore(AutofillValue.forText("D'OH!"), null), 0);
+    }
+
+    @Test
+    public void testGetScore_fullMatch() {
+        assertFloat(mScorer.getScore(AutofillValue.forText("D'OH!"), "D'OH!"), 1);
+    }
+
+    @Test
+    public void testGetScore_fullMatchMixedCase() {
+        assertFloat(mScorer.getScore(AutofillValue.forText("D'OH!"), "D'oH!"), 1);
+    }
+
+    // TODO(b/70291841): might need to change it once it supports different sizes
+    @Test
+    public void testGetScore_mismatchDifferentSizes() {
+        assertFloat(mScorer.getScore(AutofillValue.forText("One"), "MoreThanOne"), 0);
+        assertFloat(mScorer.getScore(AutofillValue.forText("MoreThanOne"), "One"), 0);
+    }
+
+    @Test
+    public void testGetScore_partialMatch() {
+        assertFloat(mScorer.getScore(AutofillValue.forText("Dude"), "Dxxx"), 0.25F);
+        assertFloat(mScorer.getScore(AutofillValue.forText("Dude"), "DUxx"), 0.50F);
+        assertFloat(mScorer.getScore(AutofillValue.forText("Dude"), "DUDx"), 0.75F);
+        assertFloat(mScorer.getScore(AutofillValue.forText("Dxxx"), "Dude"), 0.25F);
+        assertFloat(mScorer.getScore(AutofillValue.forText("DUxx"), "Dude"), 0.50F);
+        assertFloat(mScorer.getScore(AutofillValue.forText("DUDx"), "Dude"), 0.75F);
+    }
+
+    public static void assertFloat(float actualValue, float expectedValue) {
+        assertThat(actualValue).isWithin(1.0e-10f).of(expectedValue);
+    }
+}
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index d130a61..b13de2e 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -498,8 +498,6 @@
     <string name="wifi_display_certification">Wireless display certification</string>
     <!-- Setting Checkbox title whether to enable WiFi Verbose Logging. [CHAR LIMIT=40] -->
     <string name="wifi_verbose_logging">Enable Wi\u2011Fi Verbose Logging</string>
-    <!-- Setting Checkbox title whether to enable WiFi Scanning in the presence of traffic. [CHAR LIMIT=80] -->
-    <string name="wifi_allow_scan_with_traffic">Always allow Wi\u2011Fi Roam Scans</string>
     <!-- Setting Checkbox title whether to always keep mobile data active. [CHAR LIMIT=80] -->
     <string name="mobile_data_always_on">Mobile data always active</string>
     <!-- Setting Checkbox title whether to enable hardware acceleration for tethering. [CHAR LIMIT=80] -->
@@ -554,8 +552,6 @@
     <string name="wifi_display_certification_summary">Show options for wireless display certification</string>
     <!-- Setting Checkbox summary whether to enable Wifi verbose Logging [CHAR LIMIT=80] -->
     <string name="wifi_verbose_logging_summary">Increase Wi\u2011Fi logging level, show per SSID RSSI in Wi\u2011Fi Picker</string>
-    <!-- Setting Checkbox summary whether to always allow WiFi Roam Scans [CHAR LIMIT=130] -->
-    <string name="wifi_allow_scan_with_traffic_summary">Allow/Disallow Wi\u2011Fi Roam Scans based on the amount of data traffic present at the interface</string>
     <!-- UI debug setting: limit size of Android logger buffers -->
     <string name="select_logd_size_title">Logger buffer sizes</string>
     <!-- UI debug setting: limit size of Android logger buffers [CHAR LIMIT=59] -->
diff --git a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/EventLogWriter.java b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/EventLogWriter.java
new file mode 100644
index 0000000..7227304
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/EventLogWriter.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.core.instrumentation;
+
+import android.content.Context;
+import android.metrics.LogMaker;
+import android.util.Log;
+import android.util.Pair;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto;
+
+/**
+ * {@link LogWriter} that writes data to eventlog.
+ */
+public class EventLogWriter implements LogWriter {
+
+    private final MetricsLogger mMetricsLogger = new MetricsLogger();
+
+    public void visible(Context context, int source, int category) {
+        final LogMaker logMaker = new LogMaker(category)
+                .setType(MetricsProto.MetricsEvent.TYPE_OPEN)
+                .addTaggedData(MetricsProto.MetricsEvent.FIELD_CONTEXT, source);
+        MetricsLogger.action(logMaker);
+    }
+
+    public void hidden(Context context, int category) {
+        MetricsLogger.hidden(context, category);
+    }
+
+    public void action(int category, int value, Pair<Integer, Object>... taggedData) {
+        if (taggedData == null || taggedData.length == 0) {
+            mMetricsLogger.action(category, value);
+        } else {
+            final LogMaker logMaker = new LogMaker(category)
+                    .setType(MetricsProto.MetricsEvent.TYPE_ACTION)
+                    .setSubtype(value);
+            for (Pair<Integer, Object> pair : taggedData) {
+                logMaker.addTaggedData(pair.first, pair.second);
+            }
+            mMetricsLogger.write(logMaker);
+        }
+    }
+
+    public void action(int category, boolean value, Pair<Integer, Object>... taggedData) {
+        action(category, value ? 1 : 0, taggedData);
+    }
+
+    public void action(Context context, int category, Pair<Integer, Object>... taggedData) {
+        action(context, category, "", taggedData);
+    }
+
+    public void actionWithSource(Context context, int source, int category) {
+        final LogMaker logMaker = new LogMaker(category)
+                .setType(MetricsProto.MetricsEvent.TYPE_ACTION);
+        if (source != MetricsProto.MetricsEvent.VIEW_UNKNOWN) {
+            logMaker.addTaggedData(MetricsProto.MetricsEvent.FIELD_CONTEXT, source);
+        }
+        MetricsLogger.action(logMaker);
+    }
+
+    /** @deprecated use {@link #action(int, int, Pair[])} */
+    @Deprecated
+    public void action(Context context, int category, int value) {
+        MetricsLogger.action(context, category, value);
+    }
+
+    /** @deprecated use {@link #action(int, boolean, Pair[])} */
+    @Deprecated
+    public void action(Context context, int category, boolean value) {
+        MetricsLogger.action(context, category, value);
+    }
+
+    public void action(Context context, int category, String pkg,
+            Pair<Integer, Object>... taggedData) {
+        if (taggedData == null || taggedData.length == 0) {
+            MetricsLogger.action(context, category, pkg);
+        } else {
+            final LogMaker logMaker = new LogMaker(category)
+                    .setType(MetricsProto.MetricsEvent.TYPE_ACTION)
+                    .setPackageName(pkg);
+            for (Pair<Integer, Object> pair : taggedData) {
+                logMaker.addTaggedData(pair.first, pair.second);
+            }
+            MetricsLogger.action(logMaker);
+        }
+    }
+
+    public void count(Context context, String name, int value) {
+        MetricsLogger.count(context, name, value);
+    }
+
+    public void histogram(Context context, String name, int bucket) {
+        MetricsLogger.histogram(context, name, bucket);
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/Instrumentable.java b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/Instrumentable.java
new file mode 100644
index 0000000..dbc61c2
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/Instrumentable.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.core.instrumentation;
+
+public interface Instrumentable {
+
+    int METRICS_CATEGORY_UNKNOWN = 0;
+
+    /**
+     * Instrumented name for a view as defined in
+     * {@link com.android.internal.logging.nano.MetricsProto.MetricsEvent}.
+     */
+    int getMetricsCategory();
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/LogWriter.java b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/LogWriter.java
new file mode 100644
index 0000000..4b9f572
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/LogWriter.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settingslib.core.instrumentation;
+
+import android.content.Context;
+import android.util.Pair;
+
+/**
+ * Generic log writer interface.
+ */
+public interface LogWriter {
+
+    /**
+     * Logs a visibility event when view becomes visible.
+     */
+    void visible(Context context, int source, int category);
+
+    /**
+     * Logs a visibility event when view becomes hidden.
+     */
+    void hidden(Context context, int category);
+
+    /**
+     * Logs a user action.
+     */
+    void action(int category, int value, Pair<Integer, Object>... taggedData);
+
+    /**
+     * Logs a user action.
+     */
+    void action(int category, boolean value, Pair<Integer, Object>... taggedData);
+
+    /**
+     * Logs an user action.
+     */
+    void action(Context context, int category, Pair<Integer, Object>... taggedData);
+
+    /**
+     * Logs an user action.
+     */
+    void actionWithSource(Context context, int source, int category);
+
+    /**
+     * Logs an user action.
+     * @deprecated use {@link #action(int, int, Pair[])}
+     */
+    @Deprecated
+    void action(Context context, int category, int value);
+
+    /**
+     * Logs an user action.
+     * @deprecated use {@link #action(int, boolean, Pair[])}
+     */
+    @Deprecated
+    void action(Context context, int category, boolean value);
+
+    /**
+     * Logs an user action.
+     */
+    void action(Context context, int category, String pkg, Pair<Integer, Object>... taggedData);
+
+    /**
+     * Logs a count.
+     */
+    void count(Context context, String name, int value);
+
+    /**
+     * Logs a histogram event.
+     */
+    void histogram(Context context, String name, int bucket);
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/MetricsFeatureProvider.java b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/MetricsFeatureProvider.java
new file mode 100644
index 0000000..1e5b378
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/MetricsFeatureProvider.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settingslib.core.instrumentation;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.text.TextUtils;
+import android.util.Pair;
+
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * FeatureProvider for metrics.
+ */
+public class MetricsFeatureProvider {
+    private List<LogWriter> mLoggerWriters;
+
+    public MetricsFeatureProvider() {
+        mLoggerWriters = new ArrayList<>();
+        installLogWriters();
+    }
+
+    protected void installLogWriters() {
+        mLoggerWriters.add(new EventLogWriter());
+    }
+
+    public void visible(Context context, int source, int category) {
+        for (LogWriter writer : mLoggerWriters) {
+            writer.visible(context, source, category);
+        }
+    }
+
+    public void hidden(Context context, int category) {
+        for (LogWriter writer : mLoggerWriters) {
+            writer.hidden(context, category);
+        }
+    }
+
+    public void actionWithSource(Context context, int source, int category) {
+        for (LogWriter writer : mLoggerWriters) {
+            writer.actionWithSource(context, source, category);
+        }
+    }
+
+    /**
+     * Logs a user action. Includes the elapsed time since the containing
+     * fragment has been visible.
+     */
+    public void action(VisibilityLoggerMixin visibilityLogger, int category, int value) {
+        for (LogWriter writer : mLoggerWriters) {
+            writer.action(category, value,
+                    sinceVisibleTaggedData(visibilityLogger.elapsedTimeSinceVisible()));
+        }
+    }
+
+    /**
+     * Logs a user action. Includes the elapsed time since the containing
+     * fragment has been visible.
+     */
+    public void action(VisibilityLoggerMixin visibilityLogger, int category, boolean value) {
+        for (LogWriter writer : mLoggerWriters) {
+            writer.action(category, value,
+                    sinceVisibleTaggedData(visibilityLogger.elapsedTimeSinceVisible()));
+        }
+    }
+
+    public void action(Context context, int category, Pair<Integer, Object>... taggedData) {
+        for (LogWriter writer : mLoggerWriters) {
+            writer.action(context, category, taggedData);
+        }
+    }
+
+    /** @deprecated use {@link #action(VisibilityLoggerMixin, int, int)} */
+    @Deprecated
+    public void action(Context context, int category, int value) {
+        for (LogWriter writer : mLoggerWriters) {
+            writer.action(context, category, value);
+        }
+    }
+
+    /** @deprecated use {@link #action(VisibilityLoggerMixin, int, boolean)} */
+    @Deprecated
+    public void action(Context context, int category, boolean value) {
+        for (LogWriter writer : mLoggerWriters) {
+            writer.action(context, category, value);
+        }
+    }
+
+    public void action(Context context, int category, String pkg,
+            Pair<Integer, Object>... taggedData) {
+        for (LogWriter writer : mLoggerWriters) {
+            writer.action(context, category, pkg, taggedData);
+        }
+    }
+
+    public void count(Context context, String name, int value) {
+        for (LogWriter writer : mLoggerWriters) {
+            writer.count(context, name, value);
+        }
+    }
+
+    public void histogram(Context context, String name, int bucket) {
+        for (LogWriter writer : mLoggerWriters) {
+            writer.histogram(context, name, bucket);
+        }
+    }
+
+    public int getMetricsCategory(Object object) {
+        if (object == null || !(object instanceof Instrumentable)) {
+            return MetricsEvent.VIEW_UNKNOWN;
+        }
+        return ((Instrumentable) object).getMetricsCategory();
+    }
+
+    public void logDashboardStartIntent(Context context, Intent intent,
+            int sourceMetricsCategory) {
+        if (intent == null) {
+            return;
+        }
+        final ComponentName cn = intent.getComponent();
+        if (cn == null) {
+            final String action = intent.getAction();
+            if (TextUtils.isEmpty(action)) {
+                // Not loggable
+                return;
+            }
+            action(context, MetricsEvent.ACTION_SETTINGS_TILE_CLICK, action,
+                    Pair.create(MetricsEvent.FIELD_CONTEXT, sourceMetricsCategory));
+            return;
+        } else if (TextUtils.equals(cn.getPackageName(), context.getPackageName())) {
+            // Going to a Setting internal page, skip click logging in favor of page's own
+            // visibility logging.
+            return;
+        }
+        action(context, MetricsEvent.ACTION_SETTINGS_TILE_CLICK, cn.flattenToString(),
+                Pair.create(MetricsEvent.FIELD_CONTEXT, sourceMetricsCategory));
+    }
+
+    private Pair<Integer, Object> sinceVisibleTaggedData(long timestamp) {
+        return Pair.create(MetricsEvent.NOTIFICATION_SINCE_VISIBLE_MILLIS, timestamp);
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/SharedPreferencesLogger.java b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/SharedPreferencesLogger.java
new file mode 100644
index 0000000..facce4e
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/SharedPreferencesLogger.java
@@ -0,0 +1,259 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.settingslib.core.instrumentation;
+
+import android.annotation.Nullable;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
+import android.os.AsyncTask;
+import android.support.annotation.VisibleForTesting;
+import android.text.TextUtils;
+import android.util.Log;
+import android.util.Pair;
+
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentSkipListSet;
+
+public class SharedPreferencesLogger implements SharedPreferences {
+
+    private static final String LOG_TAG = "SharedPreferencesLogger";
+
+    private final String mTag;
+    private final Context mContext;
+    private final MetricsFeatureProvider mMetricsFeature;
+    private final Set<String> mPreferenceKeySet;
+
+    public SharedPreferencesLogger(Context context, String tag,
+            MetricsFeatureProvider metricsFeature) {
+        mContext = context;
+        mTag = tag;
+        mMetricsFeature = metricsFeature;
+        mPreferenceKeySet = new ConcurrentSkipListSet<>();
+    }
+
+    @Override
+    public Map<String, ?> getAll() {
+        return null;
+    }
+
+    @Override
+    public String getString(String key, @Nullable String defValue) {
+        return defValue;
+    }
+
+    @Override
+    public Set<String> getStringSet(String key, @Nullable Set<String> defValues) {
+        return defValues;
+    }
+
+    @Override
+    public int getInt(String key, int defValue) {
+        return defValue;
+    }
+
+    @Override
+    public long getLong(String key, long defValue) {
+        return defValue;
+    }
+
+    @Override
+    public float getFloat(String key, float defValue) {
+        return defValue;
+    }
+
+    @Override
+    public boolean getBoolean(String key, boolean defValue) {
+        return defValue;
+    }
+
+    @Override
+    public boolean contains(String key) {
+        return false;
+    }
+
+    @Override
+    public Editor edit() {
+        return new EditorLogger();
+    }
+
+    @Override
+    public void registerOnSharedPreferenceChangeListener(
+            OnSharedPreferenceChangeListener listener) {
+    }
+
+    @Override
+    public void unregisterOnSharedPreferenceChangeListener(
+            OnSharedPreferenceChangeListener listener) {
+    }
+
+    private void logValue(String key, Object value) {
+        logValue(key, value, false /* forceLog */);
+    }
+
+    private void logValue(String key, Object value, boolean forceLog) {
+        final String prefKey = buildPrefKey(mTag, key);
+        if (!forceLog && !mPreferenceKeySet.contains(prefKey)) {
+            // Pref key doesn't exist in set, this is initial display so we skip metrics but
+            // keeps track of this key.
+            mPreferenceKeySet.add(prefKey);
+            return;
+        }
+        // TODO: Remove count logging to save some resource.
+        mMetricsFeature.count(mContext, buildCountName(prefKey, value), 1);
+
+        final Pair<Integer, Object> valueData;
+        if (value instanceof Long) {
+            final Long longVal = (Long) value;
+            final int intVal;
+            if (longVal > Integer.MAX_VALUE) {
+                intVal = Integer.MAX_VALUE;
+            } else if (longVal < Integer.MIN_VALUE) {
+                intVal = Integer.MIN_VALUE;
+            } else {
+                intVal = longVal.intValue();
+            }
+            valueData = Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE,
+                    intVal);
+        } else if (value instanceof Integer) {
+            valueData = Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE,
+                    value);
+        } else if (value instanceof Boolean) {
+            valueData = Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE,
+                    (Boolean) value ? 1 : 0);
+        } else if (value instanceof Float) {
+            valueData = Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_FLOAT_VALUE,
+                    value);
+        } else if (value instanceof String) {
+            Log.d(LOG_TAG, "Tried to log string preference " + prefKey + " = " + value);
+            valueData = null;
+        } else {
+            Log.w(LOG_TAG, "Tried to log unloggable object" + value);
+            valueData = null;
+        }
+        if (valueData != null) {
+            // Pref key exists in set, log it's change in metrics.
+            mMetricsFeature.action(mContext, MetricsEvent.ACTION_SETTINGS_PREFERENCE_CHANGE,
+                    Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_NAME, prefKey),
+                    valueData);
+        }
+    }
+
+    @VisibleForTesting
+    void logPackageName(String key, String value) {
+        final String prefKey = mTag + "/" + key;
+        mMetricsFeature.action(mContext, MetricsEvent.ACTION_SETTINGS_PREFERENCE_CHANGE, value,
+                Pair.create(MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_NAME, prefKey));
+    }
+
+    private void safeLogValue(String key, String value) {
+        new AsyncPackageCheck().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, key, value);
+    }
+
+    public static String buildCountName(String prefKey, Object value) {
+        return prefKey + "|" + value;
+    }
+
+    public static String buildPrefKey(String tag, String key) {
+        return tag + "/" + key;
+    }
+
+    private class AsyncPackageCheck extends AsyncTask<String, Void, Void> {
+        @Override
+        protected Void doInBackground(String... params) {
+            String key = params[0];
+            String value = params[1];
+            PackageManager pm = mContext.getPackageManager();
+            try {
+                // Check if this might be a component.
+                ComponentName name = ComponentName.unflattenFromString(value);
+                if (value != null) {
+                    value = name.getPackageName();
+                }
+            } catch (Exception e) {
+            }
+            try {
+                pm.getPackageInfo(value, PackageManager.MATCH_ANY_USER);
+                logPackageName(key, value);
+            } catch (PackageManager.NameNotFoundException e) {
+                // Clearly not a package, and it's unlikely this preference is in prefSet, so
+                // lets force log it.
+                logValue(key, value, true /* forceLog */);
+            }
+            return null;
+        }
+    }
+
+    public class EditorLogger implements Editor {
+        @Override
+        public Editor putString(String key, @Nullable String value) {
+            safeLogValue(key, value);
+            return this;
+        }
+
+        @Override
+        public Editor putStringSet(String key, @Nullable Set<String> values) {
+            safeLogValue(key, TextUtils.join(",", values));
+            return this;
+        }
+
+        @Override
+        public Editor putInt(String key, int value) {
+            logValue(key, value);
+            return this;
+        }
+
+        @Override
+        public Editor putLong(String key, long value) {
+            logValue(key, value);
+            return this;
+        }
+
+        @Override
+        public Editor putFloat(String key, float value) {
+            logValue(key, value);
+            return this;
+        }
+
+        @Override
+        public Editor putBoolean(String key, boolean value) {
+            logValue(key, value);
+            return this;
+        }
+
+        @Override
+        public Editor remove(String key) {
+            return this;
+        }
+
+        @Override
+        public Editor clear() {
+            return this;
+        }
+
+        @Override
+        public boolean commit() {
+            return true;
+        }
+
+        @Override
+        public void apply() {
+        }
+    }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/VisibilityLoggerMixin.java b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/VisibilityLoggerMixin.java
new file mode 100644
index 0000000..7983896
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/core/instrumentation/VisibilityLoggerMixin.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.core.instrumentation;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+
+import android.os.SystemClock;
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.settingslib.core.lifecycle.LifecycleObserver;
+import com.android.settingslib.core.lifecycle.events.OnPause;
+import com.android.settingslib.core.lifecycle.events.OnResume;
+
+import static com.android.settingslib.core.instrumentation.Instrumentable.METRICS_CATEGORY_UNKNOWN;
+
+/**
+ * Logs visibility change of a fragment.
+ */
+public class VisibilityLoggerMixin implements LifecycleObserver, OnResume, OnPause {
+
+    private static final String TAG = "VisibilityLoggerMixin";
+
+    private final int mMetricsCategory;
+
+    private MetricsFeatureProvider mMetricsFeature;
+    private int mSourceMetricsCategory = MetricsProto.MetricsEvent.VIEW_UNKNOWN;
+    private long mVisibleTimestamp;
+
+    /**
+     * The metrics category constant for logging source when a setting fragment is opened.
+     */
+    public static final String EXTRA_SOURCE_METRICS_CATEGORY = ":settings:source_metrics";
+
+    private VisibilityLoggerMixin() {
+        mMetricsCategory = METRICS_CATEGORY_UNKNOWN;
+    }
+
+    public VisibilityLoggerMixin(int metricsCategory, MetricsFeatureProvider metricsFeature) {
+        mMetricsCategory = metricsCategory;
+        mMetricsFeature = metricsFeature;
+    }
+
+    @Override
+    public void onResume() {
+        mVisibleTimestamp = SystemClock.elapsedRealtime();
+        if (mMetricsFeature != null && mMetricsCategory != METRICS_CATEGORY_UNKNOWN) {
+            mMetricsFeature.visible(null /* context */, mSourceMetricsCategory, mMetricsCategory);
+        }
+    }
+
+    @Override
+    public void onPause() {
+        mVisibleTimestamp = 0;
+        if (mMetricsFeature != null && mMetricsCategory != METRICS_CATEGORY_UNKNOWN) {
+            mMetricsFeature.hidden(null /* context */, mMetricsCategory);
+        }
+    }
+
+    /**
+     * Sets source metrics category for this logger. Source is the caller that opened this UI.
+     */
+    public void setSourceMetricsCategory(Activity activity) {
+        if (mSourceMetricsCategory != MetricsProto.MetricsEvent.VIEW_UNKNOWN || activity == null) {
+            return;
+        }
+        final Intent intent = activity.getIntent();
+        if (intent == null) {
+            return;
+        }
+        mSourceMetricsCategory = intent.getIntExtra(EXTRA_SOURCE_METRICS_CATEGORY,
+                MetricsProto.MetricsEvent.VIEW_UNKNOWN);
+    }
+
+    /** Returns elapsed time since onResume() */
+    public long elapsedTimeSinceVisible() {
+        if (mVisibleTimestamp == 0) {
+            return 0;
+        }
+        return SystemClock.elapsedRealtime() - mVisibleTimestamp;
+    }
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/MetricsFeatureProviderTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/MetricsFeatureProviderTest.java
new file mode 100644
index 0000000..8bea51d
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/MetricsFeatureProviderTest.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settingslib.core.instrumentation;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.util.Pair;
+
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.settingslib.TestConfig;
+import com.android.settingslib.SettingsLibRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.util.ReflectionHelpers;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@RunWith(SettingsLibRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class MetricsFeatureProviderTest {
+    private static int CATEGORY = 10;
+    private static boolean SUBTYPE_BOOLEAN = true;
+    private static int SUBTYPE_INTEGER = 1;
+    private static long ELAPSED_TIME = 1000;
+
+    @Mock private LogWriter mockLogWriter;
+    @Mock private VisibilityLoggerMixin mockVisibilityLogger;
+
+    private Context mContext;
+    private MetricsFeatureProvider mProvider;
+
+    @Captor
+    private ArgumentCaptor<Pair> mPairCaptor;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext = RuntimeEnvironment.application;
+        mProvider = new MetricsFeatureProvider();
+        List<LogWriter> writers = new ArrayList<>();
+        writers.add(mockLogWriter);
+        ReflectionHelpers.setField(mProvider, "mLoggerWriters", writers);
+
+        when(mockVisibilityLogger.elapsedTimeSinceVisible()).thenReturn(ELAPSED_TIME);
+    }
+
+    @Test
+    public void logDashboardStartIntent_intentEmpty_shouldNotLog() {
+        mProvider.logDashboardStartIntent(mContext, null /* intent */,
+                MetricsEvent.SETTINGS_GESTURES);
+
+        verifyNoMoreInteractions(mockLogWriter);
+    }
+
+    @Test
+    public void logDashboardStartIntent_intentHasNoComponent_shouldLog() {
+        final Intent intent = new Intent(Intent.ACTION_ASSIST);
+
+        mProvider.logDashboardStartIntent(mContext, intent, MetricsEvent.SETTINGS_GESTURES);
+
+        verify(mockLogWriter).action(
+                eq(mContext),
+                eq(MetricsEvent.ACTION_SETTINGS_TILE_CLICK),
+                anyString(),
+                eq(Pair.create(MetricsEvent.FIELD_CONTEXT, MetricsEvent.SETTINGS_GESTURES)));
+    }
+
+    @Test
+    public void logDashboardStartIntent_intentIsExternal_shouldLog() {
+        final Intent intent = new Intent().setComponent(new ComponentName("pkg", "cls"));
+
+        mProvider.logDashboardStartIntent(mContext, intent, MetricsEvent.SETTINGS_GESTURES);
+
+        verify(mockLogWriter).action(
+                eq(mContext),
+                eq(MetricsEvent.ACTION_SETTINGS_TILE_CLICK),
+                anyString(),
+                eq(Pair.create(MetricsEvent.FIELD_CONTEXT, MetricsEvent.SETTINGS_GESTURES)));
+    }
+
+    @Test
+    public void action_BooleanLogsElapsedTime() {
+        mProvider.action(mockVisibilityLogger, CATEGORY, SUBTYPE_BOOLEAN);
+        verify(mockLogWriter).action(eq(CATEGORY), eq(SUBTYPE_BOOLEAN), mPairCaptor.capture());
+
+        Pair value = mPairCaptor.getValue();
+        assertThat(value.first instanceof Integer).isTrue();
+        assertThat((int) value.first).isEqualTo(MetricsEvent.NOTIFICATION_SINCE_VISIBLE_MILLIS);
+        assertThat(value.second).isEqualTo(ELAPSED_TIME);
+    }
+
+    @Test
+    public void action_IntegerLogsElapsedTime() {
+        mProvider.action(mockVisibilityLogger, CATEGORY, SUBTYPE_INTEGER);
+        verify(mockLogWriter).action(eq(CATEGORY), eq(SUBTYPE_INTEGER), mPairCaptor.capture());
+
+        Pair value = mPairCaptor.getValue();
+        assertThat(value.first instanceof Integer).isTrue();
+        assertThat((int) value.first).isEqualTo(MetricsEvent.NOTIFICATION_SINCE_VISIBLE_MILLIS);
+        assertThat(value.second).isEqualTo(ELAPSED_TIME);
+    }
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/SharedPreferenceLoggerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/SharedPreferenceLoggerTest.java
new file mode 100644
index 0000000..d558a64
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/SharedPreferenceLoggerTest.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settingslib.core.instrumentation;
+
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_SETTINGS_PREFERENCE_CHANGE;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_FLOAT_VALUE;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_SETTINGS_PREFERENCE_CHANGE_NAME;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.argThat;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.util.Pair;
+
+import com.android.settingslib.TestConfig;
+import com.android.settingslib.SettingsLibRobolectricTestRunner;
+
+import com.google.common.truth.Platform;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Answers;
+import org.mockito.ArgumentMatcher;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsLibRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class SharedPreferenceLoggerTest {
+
+    private static final String TEST_TAG = "tag";
+    private static final String TEST_KEY = "key";
+
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+    private Context mContext;
+
+    private ArgumentMatcher<Pair<Integer, Object>> mNamePairMatcher;
+    @Mock
+    private MetricsFeatureProvider mMetricsFeature;
+    private SharedPreferencesLogger mSharedPrefLogger;
+
+    @Before
+    public void init() {
+        MockitoAnnotations.initMocks(this);
+        mSharedPrefLogger = new SharedPreferencesLogger(mContext, TEST_TAG, mMetricsFeature);
+        mNamePairMatcher = pairMatches(FIELD_SETTINGS_PREFERENCE_CHANGE_NAME, String.class);
+    }
+
+    @Test
+    public void putInt_shouldNotLogInitialPut() {
+        final SharedPreferences.Editor editor = mSharedPrefLogger.edit();
+        editor.putInt(TEST_KEY, 1);
+        editor.putInt(TEST_KEY, 1);
+        editor.putInt(TEST_KEY, 1);
+        editor.putInt(TEST_KEY, 2);
+        editor.putInt(TEST_KEY, 2);
+        editor.putInt(TEST_KEY, 2);
+        editor.putInt(TEST_KEY, 2);
+
+        verify(mMetricsFeature, times(6)).action(any(Context.class), anyInt(),
+                argThat(mNamePairMatcher),
+                argThat(pairMatches(FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE, Integer.class)));
+    }
+
+    @Test
+    public void putBoolean_shouldNotLogInitialPut() {
+        final SharedPreferences.Editor editor = mSharedPrefLogger.edit();
+        editor.putBoolean(TEST_KEY, true);
+        editor.putBoolean(TEST_KEY, true);
+        editor.putBoolean(TEST_KEY, false);
+        editor.putBoolean(TEST_KEY, false);
+        editor.putBoolean(TEST_KEY, false);
+
+
+        verify(mMetricsFeature).action(any(Context.class), anyInt(),
+                argThat(mNamePairMatcher),
+                argThat(pairMatches(FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE, true)));
+        verify(mMetricsFeature, times(3)).action(any(Context.class), anyInt(),
+                argThat(mNamePairMatcher),
+                argThat(pairMatches(FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE, false)));
+    }
+
+    @Test
+    public void putLong_shouldNotLogInitialPut() {
+        final SharedPreferences.Editor editor = mSharedPrefLogger.edit();
+        editor.putLong(TEST_KEY, 1);
+        editor.putLong(TEST_KEY, 1);
+        editor.putLong(TEST_KEY, 1);
+        editor.putLong(TEST_KEY, 1);
+        editor.putLong(TEST_KEY, 2);
+
+        verify(mMetricsFeature, times(4)).action(any(Context.class), anyInt(),
+                argThat(mNamePairMatcher),
+                argThat(pairMatches(FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE, Integer.class)));
+    }
+
+    @Test
+    public void putLong_biggerThanIntMax_shouldLogIntMax() {
+        final SharedPreferences.Editor editor = mSharedPrefLogger.edit();
+        final long veryBigNumber = 500L + Integer.MAX_VALUE;
+        editor.putLong(TEST_KEY, 1);
+        editor.putLong(TEST_KEY, veryBigNumber);
+
+        verify(mMetricsFeature).action(any(Context.class), anyInt(),
+                argThat(mNamePairMatcher),
+                argThat(pairMatches(
+                        FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE, Integer.MAX_VALUE)));
+    }
+
+    @Test
+    public void putLong_smallerThanIntMin_shouldLogIntMin() {
+        final SharedPreferences.Editor editor = mSharedPrefLogger.edit();
+        final long veryNegativeNumber = -500L + Integer.MIN_VALUE;
+        editor.putLong(TEST_KEY, 1);
+        editor.putLong(TEST_KEY, veryNegativeNumber);
+
+        verify(mMetricsFeature).action(any(Context.class), anyInt(),
+                argThat(mNamePairMatcher),
+                argThat(pairMatches(
+                        FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE, Integer.MIN_VALUE)));
+    }
+
+    @Test
+    public void putFloat_shouldNotLogInitialPut() {
+        final SharedPreferences.Editor editor = mSharedPrefLogger.edit();
+        editor.putFloat(TEST_KEY, 1);
+        editor.putFloat(TEST_KEY, 1);
+        editor.putFloat(TEST_KEY, 1);
+        editor.putFloat(TEST_KEY, 1);
+        editor.putFloat(TEST_KEY, 2);
+
+        verify(mMetricsFeature, times(4)).action(any(Context.class), anyInt(),
+                argThat(mNamePairMatcher),
+                argThat(pairMatches(FIELD_SETTINGS_PREFERENCE_CHANGE_FLOAT_VALUE, Float.class)));
+    }
+
+    @Test
+    public void logPackage_shouldUseLogPackageApi() {
+        mSharedPrefLogger.logPackageName("key", "com.android.settings");
+        verify(mMetricsFeature).action(any(Context.class),
+                eq(ACTION_SETTINGS_PREFERENCE_CHANGE),
+                eq("com.android.settings"),
+                any(Pair.class));
+    }
+
+    private ArgumentMatcher<Pair<Integer, Object>> pairMatches(int tag, Class clazz) {
+        return pair -> pair.first == tag && Platform.isInstanceOfType(pair.second, clazz);
+    }
+
+    private ArgumentMatcher<Pair<Integer, Object>> pairMatches(int tag, boolean bool) {
+        return pair -> pair.first == tag
+                && Platform.isInstanceOfType(pair.second, Integer.class)
+                && pair.second.equals((bool ? 1 : 0));
+    }
+
+    private ArgumentMatcher<Pair<Integer, Object>> pairMatches(int tag, int val) {
+        return pair -> pair.first == tag
+                && Platform.isInstanceOfType(pair.second, Integer.class)
+                && pair.second.equals(val);
+    }
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/VisibilityLoggerMixinTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/VisibilityLoggerMixinTest.java
new file mode 100644
index 0000000..a264886
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/core/instrumentation/VisibilityLoggerMixinTest.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settingslib.core.instrumentation;
+
+import static com.android.settingslib.core.instrumentation.Instrumentable.METRICS_CATEGORY_UNKNOWN;
+
+import static org.mockito.ArgumentMatchers.nullable;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.settingslib.SettingsLibRobolectricTestRunner;
+import com.android.settingslib.TestConfig;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.Config;
+
+
+@RunWith(SettingsLibRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class VisibilityLoggerMixinTest {
+
+    @Mock
+    private MetricsFeatureProvider mMetricsFeature;
+
+    private VisibilityLoggerMixin mMixin;
+
+    @Before
+    public void init() {
+        MockitoAnnotations.initMocks(this);
+        mMixin = new VisibilityLoggerMixin(TestInstrumentable.TEST_METRIC, mMetricsFeature);
+    }
+
+    @Test
+    public void shouldLogVisibleOnResume() {
+        mMixin.onResume();
+
+        verify(mMetricsFeature, times(1))
+                .visible(nullable(Context.class), eq(MetricsProto.MetricsEvent.VIEW_UNKNOWN),
+                        eq(TestInstrumentable.TEST_METRIC));
+    }
+
+    @Test
+    public void shouldLogVisibleWithSource() {
+        final Intent sourceIntent = new Intent()
+                .putExtra(VisibilityLoggerMixin.EXTRA_SOURCE_METRICS_CATEGORY,
+                        MetricsProto.MetricsEvent.SETTINGS_GESTURES);
+        final Activity activity = mock(Activity.class);
+        when(activity.getIntent()).thenReturn(sourceIntent);
+        mMixin.setSourceMetricsCategory(activity);
+        mMixin.onResume();
+
+        verify(mMetricsFeature, times(1))
+                .visible(nullable(Context.class), eq(MetricsProto.MetricsEvent.SETTINGS_GESTURES),
+                        eq(TestInstrumentable.TEST_METRIC));
+    }
+
+    @Test
+    public void shouldLogHideOnPause() {
+        mMixin.onPause();
+
+        verify(mMetricsFeature, times(1))
+                .hidden(nullable(Context.class), eq(TestInstrumentable.TEST_METRIC));
+    }
+
+    @Test
+    public void shouldNotLogIfMetricsFeatureIsNull() {
+        mMixin = new VisibilityLoggerMixin(TestInstrumentable.TEST_METRIC, null);
+        mMixin.onResume();
+        mMixin.onPause();
+
+        verify(mMetricsFeature, never())
+                .hidden(nullable(Context.class), anyInt());
+    }
+
+    @Test
+    public void shouldNotLogIfMetricsCategoryIsUnknown() {
+        mMixin = new VisibilityLoggerMixin(METRICS_CATEGORY_UNKNOWN, mMetricsFeature);
+
+        mMixin.onResume();
+        mMixin.onPause();
+
+        verify(mMetricsFeature, never())
+                .hidden(nullable(Context.class), anyInt());
+    }
+
+    private final class TestInstrumentable implements Instrumentable {
+
+        public static final int TEST_METRIC = 12345;
+
+        @Override
+        public int getMetricsCategory() {
+            return TEST_METRIC;
+        }
+    }
+}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 175cff6..2a697b8 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -60,6 +60,7 @@
 import android.os.UserManager;
 import android.os.UserManagerInternal;
 import android.provider.Settings;
+import android.provider.SettingsValidators;
 import android.provider.Settings.Global;
 import android.provider.Settings.Secure;
 import android.text.TextUtils;
@@ -297,6 +298,12 @@
     @Override
     public boolean onCreate() {
         Settings.setInSystemServer();
+
+        // fail to boot if there're any backed up settings that don't have a non-null validator
+        ensureAllBackedUpSystemSettingsHaveValidators();
+        ensureAllBackedUpGlobalSettingsHaveValidators();
+        ensureAllBackedUpSecureSettingsHaveValidators();
+
         synchronized (mLock) {
             mUserManager = UserManager.get(getContext());
             mPackageManager = AppGlobals.getPackageManager();
@@ -314,6 +321,57 @@
         return true;
     }
 
+    private void ensureAllBackedUpSystemSettingsHaveValidators() {
+        String offenders = getOffenders(concat(Settings.System.SETTINGS_TO_BACKUP,
+                Settings.System.LEGACY_RESTORE_SETTINGS), Settings.System.VALIDATORS);
+
+        failToBootIfOffendersPresent(offenders, "Settings.System");
+    }
+
+    private void ensureAllBackedUpGlobalSettingsHaveValidators() {
+        String offenders = getOffenders(concat(Settings.Global.SETTINGS_TO_BACKUP,
+                Settings.Global.LEGACY_RESTORE_SETTINGS), Settings.Global.VALIDATORS);
+
+        failToBootIfOffendersPresent(offenders, "Settings.Global");
+    }
+
+    private void ensureAllBackedUpSecureSettingsHaveValidators() {
+        String offenders = getOffenders(concat(Settings.Secure.SETTINGS_TO_BACKUP,
+                Settings.Secure.LEGACY_RESTORE_SETTINGS), Settings.Secure.VALIDATORS);
+
+        failToBootIfOffendersPresent(offenders, "Settings.Secure");
+    }
+
+    private void failToBootIfOffendersPresent(String offenders, String settingsType) {
+        if (offenders.length() > 0) {
+            throw new RuntimeException("All " + settingsType + " settings that are backed up"
+                    + " have to have a non-null validator, but those don't: " + offenders);
+        }
+    }
+
+    private String getOffenders(String[] settingsToBackup, Map<String,
+            SettingsValidators.Validator> validators) {
+        StringBuilder offenders = new StringBuilder();
+        for (String setting : settingsToBackup) {
+            if (validators.get(setting) == null) {
+                offenders.append(setting).append(" ");
+            }
+        }
+        return offenders.toString();
+    }
+
+    private final String[] concat(String[] first, String[] second) {
+        if (second == null || second.length == 0) {
+            return first;
+        }
+        final int firstLen = first.length;
+        final int secondLen = second.length;
+        String[] both = new String[firstLen + secondLen];
+        System.arraycopy(first, 0, both, 0, firstLen);
+        System.arraycopy(second, 0, both, firstLen, secondLen);
+        return both;
+    }
+
     @Override
     public Bundle call(String method, String name, Bundle args) {
         final int requestingUserId = getRequestingUserId(args);
@@ -1472,7 +1530,7 @@
     }
 
     private void validateSystemSettingValue(String name, String value) {
-        Settings.System.Validator validator = Settings.System.VALIDATORS.get(name);
+        SettingsValidators.Validator validator = Settings.System.VALIDATORS.get(name);
         if (validator != null && !validator.validate(value)) {
             throw new IllegalArgumentException("Invalid value: " + value
                     + " for setting: " + name);
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 0f43db0..2a6d55c 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -135,6 +135,9 @@
     <uses-permission android:name="android.permission.RESTRICTED_VR_ACCESS" />
     <uses-permission android:name="android.permission.MANAGE_BIND_INSTANT_SERVICE" />
     <uses-permission android:name="android.permission.SET_HARMFUL_APP_WARNINGS" />
+    <uses-permission android:name="android.permission.MANAGE_SENSORS" />
+
+    <uses-permission android:name="android.permission.MANAGE_AUDIO_POLICY" />
 
     <application android:label="@string/app_label"
                  android:defaultToDeviceProtectedStorage="true"
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml
index 631cc0d..41dd0b3 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml
@@ -67,7 +67,7 @@
                     android:paddingTop="8dip"
                     android:paddingBottom="8dip"
                     android:paddingRight="0dp"
-                    android:paddingLeft="24dp"
+                    android:paddingLeft="0dp"
                     android:background="@drawable/ripple_drawable"
                     android:contentDescription="@string/keyboardview_keycode_delete"
                     android:layout_alignEnd="@+id/pinEntry"
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml
index 947f27d..33f7e75 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml
@@ -81,7 +81,7 @@
                     android:paddingTop="8dip"
                     android:paddingBottom="8dip"
                     android:paddingRight="0dp"
-                    android:paddingLeft="24dp"
+                    android:paddingLeft="0dp"
                     android:background="@drawable/ripple_drawable"
                     android:contentDescription="@string/keyboardview_keycode_delete"
                     android:layout_alignEnd="@+id/pinEntry"
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml
index 6f270b4..4b385fc 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml
@@ -82,7 +82,7 @@
                     android:paddingTop="8dip"
                     android:paddingBottom="8dip"
                     android:paddingRight="0dp"
-                    android:paddingLeft="24dp"
+                    android:paddingLeft="0dp"
                     android:background="@drawable/ripple_drawable"
                     android:contentDescription="@string/keyboardview_keycode_delete"
                     android:layout_alignEnd="@+id/pinEntry"
diff --git a/packages/SystemUI/res/drawable/ic_landscape_from_auto_rotate_animation.xml b/packages/SystemUI/res/drawable/ic_landscape_from_auto_rotate_animation.xml
deleted file mode 100644
index 00bcaf6..0000000
--- a/packages/SystemUI/res/drawable/ic_landscape_from_auto_rotate_animation.xml
+++ /dev/null
@@ -1,32 +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.
--->
-<animated-vector
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:drawable="@drawable/ic_landscape_from_auto_rotate" >
-    <target
-        android:name="landscape"
-        android:animation="@anim/ic_rotate_to_landscape_landscape_animation" />
-    <target
-        android:name="arrows"
-        android:animation="@anim/ic_rotate_to_landscape_arrows_animation" />
-    <target
-        android:name="arrows_0"
-        android:animation="@anim/ic_rotate_to_landscape_arrows_0_animation" />
-    <target
-        android:name="bottom_merged"
-        android:animation="@anim/ic_rotate_to_landscape_bottom_merged_animation" />
-</animated-vector>
diff --git a/packages/SystemUI/res/drawable/ic_landscape_to_auto_rotate.xml b/packages/SystemUI/res/drawable/ic_landscape_to_auto_rotate.xml
deleted file mode 100644
index cde6797..0000000
--- a/packages/SystemUI/res/drawable/ic_landscape_to_auto_rotate.xml
+++ /dev/null
@@ -1,65 +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.
--->
-<vector
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:name="ic_landscape_to_rotate"
-    android:height="48dp"
-    android:width="48dp"
-    android:viewportHeight="48"
-    android:viewportWidth="48"
-    android:tint="?android:attr/colorControlNormal" >
-    <group
-        android:name="device"
-        android:translateX="24"
-        android:translateY="24" >
-        <group
-            android:name="device_pivot"
-            android:translateX="-24.15"
-            android:translateY="-24.25" >
-            <group
-                android:name="landscape"
-                android:translateX="24"
-                android:translateY="24" >
-                <path
-                    android:name="device_merged"
-                    android:pathData="M -21.9799957275,-10.0 c 0.0,0.0 -0.0200042724609,20.0 -0.0200042724609,20.0 c 0.0,2.19999694824 1.80000305176,4.0 4.0,4.0 c 0.0,0.0 36.0,0.0 36.0,0.0 c 2.19999694824,0.0 4.0,-1.80000305176 4.0,-4.0 c 0.0,0.0 0.0,-20.0 0.0,-20.0 c 0.0,-2.19999694824 -1.80000305176,-4.0 -4.0,-4.0 c 0.0,0.0 -36.0,0.0 -36.0,0.0 c -2.19999694824,0.0 -3.97999572754,1.80000305176 -3.97999572754,4.0 Z M 14.0,10.0 c 0.0,0.0 -28.0,0.0 -28.0,0.0 c 0.0,0.0 0.0,-20.0 0.0,-20.0 c 0.0,0.0 28.0,0.0 28.0,0.0 c 0.0,0.0 0.0,20.0 0.0,20.0 Z"
-                    android:fillColor="#FFFFFFFF" />
-            </group>
-        </group>
-    </group>
-    <group
-        android:name="arrows"
-        android:translateX="24"
-        android:translateY="24"
-        android:rotation="-90" >
-        <group
-            android:name="arrows_pivot"
-            android:translateX="-24.0798"
-            android:translateY="-24.23" >
-            <group
-                android:name="arrows_0"
-                android:translateX="12.2505"
-                android:translateY="37.2145" >
-                <path
-                    android:name="bottom_merged"
-                    android:pathData="M 20.7395019531,-31.9844970703 c 6.23999023438,2.83999633789 10.6999969482,8.7200012207 11.8399963379,15.7799987793 c 0.119995117188,0.699996948242 0.740005493164,1.2200012207 1.46099853516,1.2200012207 c 0.919998168945,0.0 1.6190032959,-0.84001159668 1.47900390625,-1.74000549316 c -1.75900268555,-10.3800048828 -9.75900268555,-19.1199951172 -22.5800018311,-20.1600036621 c -0.919998168945,-0.0800018310547 -1.43899536133,1.04000854492 -0.800003051758,1.70001220703 c 0.0,0.0 5.12100219727,5.11999511719 5.12100219727,5.11999511719 c 0.378997802734,0.380004882812 0.97900390625,0.380004882812 1.37899780273,0.020004272461 c 0.0,0.0 2.10000610352,-1.94000244141 2.10000610352,-1.94000244141 Z M 2.73950195312,6.01550292969 c -6.26000976562,-2.83999633789 -10.7200012207,-8.76000976562 -11.8399963379,-15.8600006104 c -0.118011474609,-0.667007446289 -0.702011108398,-1.15100097656 -1.38000488281,-1.13999938965 c -0.860000610352,0.0 -1.52000427246,0.759994506836 -1.38000488281,1.61999511719 c 1.54000854492,10.4000091553 9.5,19.2200012207 22.4199981689,20.2799987793 c 0.920013427734,0.0800018310547 1.44100952148,-1.03999328613 0.800003051758,-1.69999694824 c 0.0,0.0 -5.11999511719,-5.11999511719 -5.11999511719,-5.11999511719 c -0.380004882812,-0.376007080078 -0.988998413086,-0.385009765625 -1.38000488281,-0.0200042724609 c 0.0,0.0 -2.11999511719,1.94000244141 -2.11999511719,1.94000244141 Z"
-                    android:fillColor="#FFFFFFFF"
-                    android:fillAlpha="0" />
-            </group>
-        </group>
-    </group>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_landscape_to_auto_rotate_animation.xml b/packages/SystemUI/res/drawable/ic_landscape_to_auto_rotate_animation.xml
deleted file mode 100644
index 86dc6ce..0000000
--- a/packages/SystemUI/res/drawable/ic_landscape_to_auto_rotate_animation.xml
+++ /dev/null
@@ -1,29 +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.
--->
-<animated-vector
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:drawable="@drawable/ic_landscape_to_auto_rotate" >
-    <target
-        android:name="landscape"
-        android:animation="@anim/ic_landscape_to_rotate_landscape_animation" />
-    <target
-        android:name="arrows"
-        android:animation="@anim/ic_landscape_to_rotate_arrows_animation" />
-    <target
-        android:name="bottom_merged"
-        android:animation="@anim/ic_landscape_to_rotate_bottom_merged_animation" />
-</animated-vector>
diff --git a/packages/SystemUI/res/drawable/ic_portrait_from_auto_rotate_animation.xml b/packages/SystemUI/res/drawable/ic_portrait_from_auto_rotate_animation.xml
deleted file mode 100644
index b8465f4..0000000
--- a/packages/SystemUI/res/drawable/ic_portrait_from_auto_rotate_animation.xml
+++ /dev/null
@@ -1,35 +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.
--->
-<animated-vector
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:drawable="@drawable/ic_portrait_to_auto_rotate" >
-    <target
-        android:name="device_0"
-        android:animation="@anim/ic_portrait_to_rotate_device_0_animation" />
-    <target
-        android:name="device_merged"
-        android:animation="@anim/ic_portrait_to_rotate_device_merged_animation" />
-    <target
-        android:name="arrows"
-        android:animation="@anim/ic_portrait_to_rotate_arrows_animation" />
-    <target
-        android:name="arrows_0"
-        android:animation="@anim/ic_portrait_to_rotate_arrows_0_animation" />
-    <target
-        android:name="bottom_merged"
-        android:animation="@anim/ic_portrait_to_rotate_bottom_merged_animation" />
-</animated-vector>
diff --git a/packages/SystemUI/res/drawable/ic_portrait_to_auto_rotate.xml b/packages/SystemUI/res/drawable/ic_portrait_to_auto_rotate.xml
deleted file mode 100644
index 0ef15f0..0000000
--- a/packages/SystemUI/res/drawable/ic_portrait_to_auto_rotate.xml
+++ /dev/null
@@ -1,68 +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.
--->
-<vector
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:name="ic_rotate_to_portrait"
-    android:height="48dp"
-    android:width="48dp"
-    android:viewportHeight="48"
-    android:viewportWidth="48"
-    android:tint="?android:attr/colorControlNormal" >
-    <group
-        android:name="device"
-        android:translateX="24"
-        android:translateY="24" >
-        <group
-            android:name="device_pivot"
-            android:translateX="-24.15"
-            android:translateY="-24.25" >
-            <group
-                android:name="device_0"
-                android:translateX="24.14999"
-                android:translateY="24.25"
-                android:rotation="-135" >
-                <path
-                    android:name="device_merged"
-                    android:pathData="M -3.34053039551,-22.9980926514 c -1.3207244873,-1.3207244873 -3.46876525879,-1.26383972168 -4.74829101563,0.125762939453 c 0.0,0.0 -14.8512420654,14.7411804199 -14.8512420654,14.7411804199 c -1.39259338379,1.392578125 -1.44947814941,3.54061889648 -0.125762939453,4.74827575684 c 0.0,0.0 26.4143981934,26.4144134521 26.4143981934,26.4144134521 c 1.3207244873,1.3207244873 3.46876525879,1.26382446289 4.74829101562,-0.125762939453 c 0.0,0.0 14.7381896973,-14.7381896973 14.7381896973,-14.7381896973 c 1.392578125,-1.39259338379 1.44947814941,-3.54061889648 0.125762939453,-4.74829101562 c 0.0,0.0 -26.3013458252,-26.417388916 -26.3013458252,-26.417388916 Z M 2.87156677246,16.9857940674 c 0.0,0.0 -19.7573547363,-19.7573699951 -19.7573547363,-19.7573699951 c 0.0,0.0 14.0142059326,-14.2142181396 14.0142059326,-14.2142181396 c 0.0,0.0 19.7573699951,19.7573699951 19.7573699951,19.7573699951 c 0.0,0.0 -14.0142211914,14.2142181396 -14.0142211914,14.2142181396 Z"
-                    android:fillColor="#FFFFFFFF" />
-            </group>
-        </group>
-    </group>
-    <group
-        android:name="arrows"
-        android:translateX="24"
-        android:translateY="24"
-        android:rotation="-221" >
-        <group
-            android:name="arrows_pivot"
-            android:translateX="-24.0798"
-            android:translateY="-24.23" >
-            <group
-                android:name="arrows_0"
-                android:translateX="12.2505"
-                android:translateY="37.2145"
-                android:scaleX="0.9"
-                android:scaleY="0.9" >
-                <path
-                    android:name="bottom_merged"
-                    android:pathData="M 20.7395019531,-31.9844970703 c 6.23999023438,2.83999633789 10.6999969482,8.7200012207 11.8399963379,15.7799987793 c 0.119995117188,0.699996948242 0.740005493164,1.2200012207 1.46099853516,1.2200012207 c 0.919998168945,0.0 1.6190032959,-0.84001159668 1.47900390625,-1.74000549316 c -1.75900268555,-10.3800048828 -9.75900268555,-19.1199951172 -22.5800018311,-20.1600036621 c -0.919998168945,-0.0800018310547 -1.43899536133,1.04000854492 -0.800003051758,1.70001220703 c 0.0,0.0 5.12100219727,5.11999511719 5.12100219727,5.11999511719 c 0.378997802734,0.380004882812 0.97900390625,0.380004882812 1.37899780273,0.020004272461 c 0.0,0.0 2.10000610352,-1.94000244141 2.10000610352,-1.94000244141 Z M 2.73950195312,6.01550292969 c -6.26000976562,-2.83999633789 -10.7200012207,-8.76000976562 -11.8399963379,-15.8600006104 c -0.118011474609,-0.667007446289 -0.702011108398,-1.15100097656 -1.38000488281,-1.13999938965 c -0.860000610352,0.0 -1.52000427246,0.759994506836 -1.38000488281,1.61999511719 c 1.54000854492,10.4000091553 9.5,19.2200012207 22.4199981689,20.2799987793 c 0.920013427734,0.0800018310547 1.44100952148,-1.03999328613 0.800003051758,-1.69999694824 c 0.0,0.0 -5.11999511719,-5.11999511719 -5.11999511719,-5.11999511719 c -0.380004882812,-0.376007080078 -0.988998413086,-0.385009765625 -1.38000488281,-0.0200042724609 c 0.0,0.0 -2.11999511719,1.94000244141 -2.11999511719,1.94000244141 Z"
-                    android:fillColor="#FFFFFFFF"
-                    android:fillAlpha="0" />
-            </group>
-        </group>
-    </group>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_portrait_to_auto_rotate_animation.xml b/packages/SystemUI/res/drawable/ic_portrait_to_auto_rotate_animation.xml
deleted file mode 100644
index 6d3fd37..0000000
--- a/packages/SystemUI/res/drawable/ic_portrait_to_auto_rotate_animation.xml
+++ /dev/null
@@ -1,35 +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.
--->
-<animated-vector
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:drawable="@drawable/ic_portrait_from_auto_rotate" >
-    <target
-        android:name="device_0"
-        android:animation="@anim/ic_rotate_to_portrait_device_0_animation" />
-    <target
-        android:name="device_merged"
-        android:animation="@anim/ic_rotate_to_portrait_device_merged_animation" />
-    <target
-        android:name="arrows"
-        android:animation="@anim/ic_rotate_to_portrait_arrows_animation" />
-    <target
-        android:name="arrows_0"
-        android:animation="@anim/ic_rotate_to_portrait_arrows_0_animation" />
-    <target
-        android:name="bottom_merged"
-        android:animation="@anim/ic_rotate_to_portrait_bottom_merged_animation" />
-</animated-vector>
diff --git a/packages/SystemUI/res/drawable/ic_portrait_from_auto_rotate.xml b/packages/SystemUI/res/drawable/ic_qs_auto_rotate.xml
similarity index 95%
rename from packages/SystemUI/res/drawable/ic_portrait_from_auto_rotate.xml
rename to packages/SystemUI/res/drawable/ic_qs_auto_rotate.xml
index bce494c..fba45d1 100644
--- a/packages/SystemUI/res/drawable/ic_portrait_from_auto_rotate.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_auto_rotate.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
-     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.
@@ -16,12 +16,10 @@
 -->
 <vector
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:name="ic_portrait_to_rotate"
     android:height="48dp"
     android:width="48dp"
     android:viewportHeight="48"
-    android:viewportWidth="48"
-    android:tint="?android:attr/colorControlNormal" >
+    android:viewportWidth="48">
     <group
         android:name="device"
         android:translateX="24"
@@ -61,4 +59,3 @@
         </group>
     </group>
 </vector>
-
diff --git a/packages/SystemUI/res/layout/volume_dialog.xml b/packages/SystemUI/res/layout/volume_dialog.xml
index 748c9a5..5108f58 100644
--- a/packages/SystemUI/res/layout/volume_dialog.xml
+++ b/packages/SystemUI/res/layout/volume_dialog.xml
@@ -34,7 +34,7 @@
 
         <LinearLayout
             android:id="@+id/volume_dialog_rows"
-            android:layout_width="@dimen/volume_dialog_panel_width"
+            android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:clipChildren="false"
             android:clipToPadding="false"
@@ -56,6 +56,7 @@
             android:layout_below="@id/volume_dialog_rows"
             android:background="@drawable/rounded_bg_full"
             android:gravity="center"
+            android:layout_gravity="end"
             android:orientation="vertical" >
 
             <TextView
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index fb756e3..8b2ab81 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -33,7 +33,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Voortdurend"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Kennisgewings"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"Battery is amper pap"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"Battery is amper pap. Skakel Batterybespaarder aan"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> oor"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> oor; ongeveer <xliff:g id="TIME">%s</xliff:g> oor op grond van jou gebruik"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> oor; ongeveer <xliff:g id="TIME">%s</xliff:g> oor"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> oor. Batterybespaarder is aan."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"USB-laaiery nie ondersteun nie.\nGebruik net die laaier wat verskaf is."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"Laai met USB word nie gesteun nie."</string>
@@ -67,14 +70,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Die gebruiker wat tans by hierdie toestel aangemeld is, kan nie USB-ontfouting aanskakel nie. Skakel na die primêre gebruiker toe oor om hierdie kenmerk te gebruik."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoem om skerm te vul"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Strek om skerm te vul"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Skermkiekie"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Stoor tans skermkiekie..."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Stoor tans skermkiekie..."</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"Skermkiekie word tans gestoor."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Skermkiekie geneem."</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"Tik om jou skermkiekie te sien."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"Kon nie skermkiekie neem nie."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Kon nie skermkiekie stoor nie."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Kan weens beperkte bergingspasie nie skermkiekie stoor nie."</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"Skermkiekie word tans gestoor"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"Skermkiekie is gestoor"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"Tik om jou skermkiekie te bekyk"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"Kon nie skermkiekie neem nie"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"Kon nie skermkiekie stoor nie"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Kan weens beperkte bergingspasie nie skermkiekie stoor nie"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Die program of jou organisasie laat nie toe dat skermkiekies geneem word nie"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB-lêeroordrag-opsies"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Heg as \'n mediaspeler (MTP)"</string>
@@ -557,26 +561,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"Af"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Met kragkennisgewingkontroles kan jy \'n belangrikheidvlak van 0 tot 5 vir \'n program se kennisgewings stel. \n\n"<b>"Vlak 5"</b>" \n- Wys aan die bokant van die kennisgewinglys \n- Laat volskermonderbreking toe \n- Wys altyd opspringkennisgewings \n\n"<b>"Vlak 4"</b>" \n- Verhoed volskermonderbreking \n- Wys altyd opspringkennisgewings \n\n"<b>"Vlak 3"</b>" \n- Verhoed volskermonderbreking \n- Verhoed opspringkennisgewings \n\n"<b>"Vlak 2"</b>" \n- Verhoed volskermonderbreking \n- Verhoed opspringkennisgewings \n- Moet nooit \'n klank maak of vibreer nie \n\n"<b>"Vlak 1"</b>" \n- Verhoed volskermonderbreking \n- Verhoed opspringkennisgewings \n- Moet nooit \'n klank maak of vibreer nie \n- Versteek van sluitskerm en statusbalk \n- Wys aan die onderkant van die kennisgewinglys \n\n"<b>"Vlak 0"</b>" \n- Blokkeer alle kennisgewings van die program af"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Kennisgewings"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"Jy sal nie meer hierdie kennisgewings kry nie"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> kennisgewingkategorieë"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"Hierdie program het nie kennisgewingkategorieë nie"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"Kennisgewings van hierdie program af kan nie afgeskakel word nie"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="other">1 uit <xliff:g id="NUMBER_1">%s</xliff:g> kennisgewingkategorieë van hierdie program</item>
-      <item quantity="one">1 uit <xliff:g id="NUMBER_0">%s</xliff:g> kennisgewingkategorie van hierdie program</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> en <xliff:g id="NUMBER_5">%3$d</xliff:g> ander kanale</item>
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_0">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_1">%2$s</xliff:g> en <xliff:g id="NUMBER_2">%3$d</xliff:g> ander kanaal</item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"Jy sal nie meer hierdie kennisgewings sien nie"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"Hou aan om hierdie kennisgewings te wys?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"Stop kennisgewings"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"Hou aan wys"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"Hou aan om kennisgewings van hierdie program af te wys?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"Hierdie kennisgewings kan nie afgeskakel word nie"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"Kennisgewingkontroles vir <xliff:g id="APP_NAME">%1$s</xliff:g> is oopgemaak"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"Kennisgewingkontroles vir <xliff:g id="APP_NAME">%1$s</xliff:g> is toegemaak"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Laat kennisgewings van hierdie kanaal af toe"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"Alle kategorieë"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Meer instellings"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"Pasmaak: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"Pasmaak"</string>
     <string name="notification_done" msgid="5279426047273930175">"Klaar"</string>
+    <string name="inline_undo" msgid="558916737624706010">"Ontdoen"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"kennisgewingkontroles"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"kennisgewing-sluimeropsies"</string>
@@ -731,8 +728,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"Vou uit"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimeer"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Maak toe"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"Instellings"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Sleep af om toe te maak"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"Kieslys"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> is in beeld-in-beeld"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index e5db8de..a2a0f06 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -37,7 +37,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"مستمر"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"الإشعارات"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"البطارية منخفضة"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"طاقة البطارية منخفضة، لذا يُرجى تفعيل الوضع \"توفير شحن البطارية\"."</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"متبقي <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"طاقة البطارية المتبقية <xliff:g id="PERCENTAGE">%s</xliff:g> ويتبقى على نفادها <xliff:g id="TIME">%s</xliff:g> تقريبًا بناءً على استخدامك."</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"طاقة البطارية المتبقية <xliff:g id="PERCENTAGE">%s</xliff:g> ويتبقى على نفادها <xliff:g id="TIME">%s</xliff:g> تقريبًا."</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"يتبقى <xliff:g id="PERCENTAGE">%s</xliff:g>. تم تفعيل ميزة توفير شحن البطارية."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"‏شحن USB غير معتمد.\nاستخدم الشاحن الموفر فقط."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"‏لا يمكن إجراء الشحن عبر USB."</string>
@@ -71,14 +74,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"‏لا يمكن للمستخدم الذي يسجّل دخوله حاليًا إلى هذا الجهاز تشغيل تصحيح أخطاء USB. لاستخدام هذه الميزة، يمكنك التبديل إلى المستخدم الأساسي."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"تكبير/تصغير لملء الشاشة"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"توسيع بملء الشاشة"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"لقطة شاشة"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"جارٍ حفظ لقطة الشاشة..."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"جارٍ حفظ لقطة الشاشة..."</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"يتم حفظ لقطة."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"تم التقاط لقطة الشاشة"</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"انقر لعرض لقطة الشاشة"</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"تعذر التقاط لقطة الشاشة."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"حدثت مشكلة أثناء حفظ لقطة الشاشة."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"يتعذر حفظ لقطة الشاشة نظرًا لأن مساحة التخزين المتاحة محدودة."</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"جارٍ حفظ لقطة الشاشة."</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"تم حفظ لقطة الشاشة."</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"انقر لعرض لقطة الشاشة."</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"تعذَّر الحصول على لقطة شاشة"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"حدثت مشكلة أثناء حفظ لقطة الشاشة."</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"يتعذر حفظ لقطة الشاشة لأن مساحة التخزين المتاحة محدودة."</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"يحظر التطبيق أو تحظر مؤسستك التقاط لقطات شاشة"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"‏خيارات نقل الملفات عبر USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"‏تحميل كمشغل وسائط (MTP)"</string>
@@ -565,34 +569,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"إيقاف"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"باستخدام عناصر التحكم في إشعار التشغيل، يمكنك تعيين مستوى الأهمية من 0 إلى 5 لإشعارات التطبيق. \n\n"<b>"المستوى 5"</b>" \n- العرض أعلى قائمة الإشعارات \n- يسمح بمقاطعة ملء الشاشة \n- الظهور الخاطف دائمًا \n\n"<b>"المستوى 4"</b>" \n- منع مقاطعة ملء الشاشة \n- الظهور الخاطف دائمًا \n\n"<b>"المستوى 3"</b>" \n- منع مقاطعة ملء الشاشة \n- عدم الظهور الخاطف أبدًا \n\n"<b>"المستوى 2"</b>" \n- منع مقاطعة ملء الشاشة \n- عدم الظهور الخاطف أبدًا \n- عدم إصدار أصوات واهتزاز \n\n"<b>"المستوى 1"</b>" \n- منع مقاطعة ملء الشاشة \n- عدم الظهور الخاطف أبدًا \n- عدم إصدار أصوات أو اهتزاز أبدًا \n- الإخفاء من شاشة التأمين وشريط الحالة \n- العرض أسفل قائمة الإشعارات \n\n"<b>"المستوى 0"</b>" \n- حظر جميع الإشعارات من التطبيق"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"الإشعارات"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"لن تتلقى هذه الإشعارات بعد الآن."</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> فئة إشعار"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"لا يحتوي هذا التطبيق على فئات إشعار"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"لا يمكن إيقاف الإشعارات من هذا التطبيق"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="zero">1 من إجمالي <xliff:g id="NUMBER_1">%s</xliff:g> فئة إشعار من هذا التطبيق</item>
-      <item quantity="two">1 من إجمالي فئتي إشعار (<xliff:g id="NUMBER_1">%s</xliff:g>) من هذا التطبيق</item>
-      <item quantity="few">1 من إجمالي <xliff:g id="NUMBER_1">%s</xliff:g> فئات إشعار من هذا التطبيق</item>
-      <item quantity="many">1 من إجمالي <xliff:g id="NUMBER_1">%s</xliff:g> فئة إشعار من هذا التطبيق</item>
-      <item quantity="other">1 من إجمالي <xliff:g id="NUMBER_1">%s</xliff:g> فئة إشعار من هذا التطبيق</item>
-      <item quantity="one">1 من إجمالي <xliff:g id="NUMBER_0">%s</xliff:g> فئة إشعار من هذا التطبيق</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>، <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="zero"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g> و<xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> و<xliff:g id="NUMBER_5">%3$d</xliff:g> أيضًا</item>
-      <item quantity="two"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g> و<xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> و<xliff:g id="NUMBER_5">%3$d</xliff:g> أيضًا</item>
-      <item quantity="few"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g> و<xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> و<xliff:g id="NUMBER_5">%3$d</xliff:g> أيضًا</item>
-      <item quantity="many"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g> و<xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> و<xliff:g id="NUMBER_5">%3$d</xliff:g> أيضًا</item>
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g> و<xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> و<xliff:g id="NUMBER_5">%3$d</xliff:g> أيضًا</item>
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_0">%1$s</xliff:g> و<xliff:g id="CHANNEL_NAME_2_1">%2$s</xliff:g> و<xliff:g id="NUMBER_2">%3$d</xliff:g> أيضًا</item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"لن تتلقى هذه الإشعارات بعد الآن."</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"هل تريد الاستمرار في تلقي هذه الإشعارات؟"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"إيقاف الإشعارات"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"الاستمرار في تلقّي الإشعارات"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"هل تريد الاستمرار في تلقي إشعارات من هذا التطبيق؟"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"يتعذَّر إيقاف هذه الإشعارات."</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"تم فتح عناصر التحكم في الإشعارات لتطبيق <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"تم إغلاق عناصر التحكم في الإشعارات لتطبيق <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"السماح بالإشعارات من هذه القناة"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"كل الفئات"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"المزيد من الإعدادات"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"تخصيص: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"تخصيص"</string>
     <string name="notification_done" msgid="5279426047273930175">"تم"</string>
+    <string name="inline_undo" msgid="558916737624706010">"تراجع"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"عناصر التحكم في الإشعارات"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"خيارات تأجيل الإشعارات"</string>
@@ -755,8 +744,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"توسيع"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"تصغير"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"إغلاق"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"الإعدادات"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"اسحب لأسفل للإلغاء"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"القائمة"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> يظهر في صورة داخل صورة"</string>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index 1b2972b..e73cc86 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -33,7 +33,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Davam edir"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Bildirişlər"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"Enerji azdır"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"Batareya azdır. Batareya Qənaətini aktiv edin"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> qalır"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Qalan <xliff:g id="PERCENTAGE">%s</xliff:g>, istifadəyə əsasən təxminən <xliff:g id="TIME">%s</xliff:g> qalıb"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Qalan <xliff:g id="PERCENTAGE">%s</xliff:g>, təxminən <xliff:g id="TIME">%s</xliff:g> qalır"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> qalır. Batareya Qənaəti aktivdir."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"USB ilə elektrik doldurma dəstəklənmir.\nYalnız adapter istifadə edin."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"USB qidalandırıcı dəstəklənmir."</string>
@@ -67,14 +70,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Hazırda bu cihaza daxil olmuş istifadəçi USB sazlama prosesini aktiv edə bilməz. Bu funksiyadan istifadə etmək üçün əsas istifadəçi hesaba daxil olmalıdır."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Ekranı doldurmaq üçün yaxınlaşdır"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Ekranı doldurmaq üçün uzat"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Skrinşot"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Skrinşot yadda saxlanılır..."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Skrinşot yadda saxlanır..."</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"Skrinşot yadda saxlanır."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Skrinşot çəkildi."</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"Skrinşotunuza baxmaq üçün tıklayın."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"Skrinşot götürülə bilinmədi."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Skrinşot yadda saxlanarkən problem baş verdi."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Yaddaş ehtiyatının az olması səbəbindən skrinşotu yadda saxlamaq olmur."</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"Skrinşot yadda saxlanır"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"Skrinşot yadda saxlandı"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"Skrinşotunuza baxmaq üçün klikləyin"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"Skrinşot çəkmək alınmadı"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"Skrinşot yadda saxlanarkən problem baş verdi"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Yaddaş ehtiyatının az olması səbəbindən skrinşotu yadda saxlamaq olmur"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Skrinşot çəkməyə tətbiq və ya təşkilat tərəfindən icazə verilmir"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB fayl transferi seçimləri"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Media pleyer (MTP) kimi montaj edin"</string>
@@ -557,26 +561,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"Deaktiv"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Enerji bildiriş nəzarəti ilə, tətbiq bildirişləri üçün əhəmiyyət səviyyəsini 0-dan 5-ə kimi ayarlaya bilərsiniz. \n\n"<b>"Səviyyə 5"</b>" \n- Bildiriş siyahısının yuxarı hissəsində göstərin \n- Tam ekran kəsintisinə icazə verin \n- Hər zaman izləyin \n\n"<b>"Səviyyə 4"</b>" \n- Tam ekran kəsintisinin qarşısını alın \n- Hər zaman izləyin \n\n"<b>"Level 3"</b>" \n- Tam ekran kəsintisinin qarşısını alın \n- Heç vaxt izləməyin \n\n"<b>"Level 2"</b>" \n- Tam ekran kəsintisinin qarşısını alın \n- Heç vaxt izləməyin \n- Heç vaxt səsliyə və ya vibrasiyaya qoymayın \n\n"<b>"Səviyyə 1"</b>" \n- Prevent full screen interruption \n- Heç vaxt izləməyin \n- Heç vaxt səsliyə və ya vibrasiyaya qoymayın \n- Ekran kilidi və ya status panelindən gizlədin \n- Bildiriş siyahısının yuxarı hissəsində göstərin \n\n"<b>"Səviyyə 0"</b>" \n- Bütün bildirişləri tətbiqdən blok edin"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Bildirişlər"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"Bu bildirişlər daha sizə göndərilməyəcək"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> bildiriş kateqoriyaları"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"Bu tətbiqin bildiriş kateqoriyası yoxdur"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"Bu tətbiqin bildirişləri deaktiv edilə bilməz"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="other">Bu tətbiqin <xliff:g id="NUMBER_1">%s</xliff:g> bildiriş kateqoriyasından 1 kanal</item>
-      <item quantity="one">Bu tətbiqin <xliff:g id="NUMBER_0">%s</xliff:g> bildiriş kateqoriyasından 1 kanal</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g>, və <xliff:g id="NUMBER_5">%3$d</xliff:g> digər</item>
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_0">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_1">%2$s</xliff:g>, və <xliff:g id="NUMBER_2">%3$d</xliff:g> digər</item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"Artıq bu bildirişləri görməyəcəkəsiniz"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"Bu bildirişlər göstərilməyə davam edilsin?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"Bildirişləri dayandırın"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"Göstərməyə davam edin"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"Bu tətbiqin bildirişləri göstərilməyə davam edilsin?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"Bu bildirişlər deaktiv edilə bilməz"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"<xliff:g id="APP_NAME">%1$s</xliff:g> üçün bildiriş kontrolları açıqdır"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"<xliff:g id="APP_NAME">%1$s</xliff:g> üçün bildiriş kontrolları bağlıdır"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Bu kanaldan gələn bildirişlərə icazə verin"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"Bütün Kateqoriyalar"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Daha çox ayar"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"Fərdiləşdirin: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"Fərdiləşdirin"</string>
     <string name="notification_done" msgid="5279426047273930175">"Hazırdır"</string>
+    <string name="inline_undo" msgid="558916737624706010">"Ləğv edin"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"bildiriş nəzarəti"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"bildiriş təxirə salma seçimləri"</string>
@@ -731,8 +728,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"Genişləndirin"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Kiçildin"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Bağlayın"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"Ayarlar"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Rədd etmək üçün aşağı çəkin"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"Menyu"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> şəkil içində şəkildədir"</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index 2d3635c..3c203b1 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -34,7 +34,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Tekuće"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Obaveštenja"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"Nivo napunjenosti baterije je nizak"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"Baterija je skoro prazna. Uključite Uštedu baterije"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"Još <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Još <xliff:g id="PERCENTAGE">%s</xliff:g>, na osnovu korišćenja ostalo je oko <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Još <xliff:g id="PERCENTAGE">%s</xliff:g>, ostalo je oko <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Još <xliff:g id="PERCENTAGE">%s</xliff:g>. Ušteda baterije je uključena."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"Punjenje preko USB-a nije podržano.\nKoristite samo priloženi punjač."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"Punjenje preko USB-a nije podržano."</string>
@@ -68,14 +71,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Korisnik koji je trenutno prijavljen na ovaj uređaj ne može da uključi otklanjanje grešaka na USB-u. Da biste koristili ovu funkciju, prebacite na primarnog korisnika."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zumiraj na celom ekranu"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Razvuci na ceo ekran"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Snimak ekrana"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Čuvanje snimka ekrana..."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Čuvanje snimka ekrana..."</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"Snimak ekrana se čuva."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Snimak ekrana je napravljen."</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"Dodirnite da biste videli snimak ekrana."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"Nije moguće napraviti snimak ekrana."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Došlo je do problema pri čuvanju snimka ekrana."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Čuvanje snimka ekrana nije uspelo zbog ograničenog memorijskog prostora."</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"Snimak ekrana se čuva"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"Snimak ekrana je sačuvan"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"Dodirnite da biste videli snimak ekrana"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"Ne možete da napravite snimak ekrana"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"Došlo je do problema pri čuvanju snimka ekrana"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Čuvanje snimka ekrana nije uspelo zbog ograničenog memorijskog prostora"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Aplikacija ili organizacija ne dozvoljavaju pravljenje snimaka ekrana"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opcije USB prenosa datoteka"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Priključi kao medija plejer (MTP)"</string>
@@ -559,28 +563,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"Isključeno"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Pomoću naprednih kontrola za obaveštenja možete da podesite nivo važnosti od 0. do 5. za obaveštenja aplikacije. \n\n"<b>"5. nivo"</b>" \n– Prikazuju se u vrhu liste obaveštenja \n- Dozvoli prekid režima celog ekrana \n– Uvek zaviruj \n\n"<b>"4. nivo"</b>" \n– Spreči prekid režima celog ekrana \n– Uvek zaviruj \n\n"<b>"3. nivo"</b>" \n– Spreči prekid režima celog ekrana \n– Nikada ne zaviruj \n\n"<b>"2. nivo"</b>" \n– Spreči prekid režima celog ekrana \n– Nikada ne zaviruj \n– Nikada ne proizvodi zvuk ili vibraciju \n\n"<b>"1. nivo"</b>" \n– Spreči prekid režima celog ekrana \n– Nikada ne zaviruj \n– Nikada ne proizvodi zvuk ili vibraciju \n– Sakrij na zaključanom ekranu i statusnoj traci \n– Prikazuju se u dnu liste obaveštenja \n\n"<b>"0. nivo"</b>" \n– Blokiraj sva obaveštenja iz aplikacije"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Obaveštenja"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"Više nećete dobijati ova obaveštenja"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"Kategorija obaveštenja: <xliff:g id="NUMBER">%d</xliff:g>"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"Ova aplikacija nema kategorije obaveštenja"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"Obaveštenja iz ove aplikacije ne mogu da se isključe"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="one">1 od <xliff:g id="NUMBER_1">%s</xliff:g> kategorije obaveštenja za ovu aplikaciju</item>
-      <item quantity="few">1 od <xliff:g id="NUMBER_1">%s</xliff:g> kategorije obaveštenja za ovu aplikaciju</item>
-      <item quantity="other">1 od <xliff:g id="NUMBER_1">%s</xliff:g> kategorija obaveštenja za ovu aplikaciju</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> i još <xliff:g id="NUMBER_5">%3$d</xliff:g></item>
-      <item quantity="few"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> i još <xliff:g id="NUMBER_5">%3$d</xliff:g></item>
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> i još <xliff:g id="NUMBER_5">%3$d</xliff:g></item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"Više nećete videti ova obaveštenja"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"Želite li da se ova obaveštenja i dalje prikazuju?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"Prestani da prikazuješ obaveštenja"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"Nastavi da prikazuješ"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"Želite li da se obaveštenja iz ove aplikacije i dalje prikazuju?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"Ne možete da isključite ova obaveštenja"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"Kontrole obaveštenja za otvaranje aplikacije <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"Kontrole obaveštenja za zatvaranje aplikacije <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Dozvoli obaveštenja sa ovog kanala"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"Sve kategorije"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Još podešavanja"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"Prilagodite: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"Prilagodi"</string>
     <string name="notification_done" msgid="5279426047273930175">"Gotovo"</string>
+    <string name="inline_undo" msgid="558916737624706010">"Opozovi"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"kontrole obaveštenja"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"opcije za odlaganje obaveštenja"</string>
@@ -737,8 +732,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"Proširi"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Umanji"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Zatvori"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"Podešavanja"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Prevucite nadole da biste odbili"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"Meni"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> je slika u slici"</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index 27e3a7d..41ce823 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -35,7 +35,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Пастаянныя"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Апавяшчэнні"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"Нізкі ўзровень зараду акумулятара"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"Нізкі зарад акумулятара. Уключыце функцыю эканоміі зараду"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"Засталося <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Засталося <xliff:g id="PERCENTAGE">%s</xliff:g>, у вас ёсць каля <xliff:g id="TIME">%s</xliff:g> на аснове даных аб выкарыстанні вашай прылады"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Засталося <xliff:g id="PERCENTAGE">%s</xliff:g>, у вас ёсць каля <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Засталося <xliff:g id="PERCENTAGE">%s</xliff:g>. Уключана эканомія зараду."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"USB-зарадка не падтрымліваецца.\nКарыстайцеся толькі зарадкай для прылады."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"Зарадка па USB не падтрымліваецца."</string>
@@ -69,14 +72,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Карыстальнік, які зараз увайшоў у гэту прыладу, не можа ўключыць адладку USB. Каб выкарыстоўваць гэту функцыю, пераключыцеся на асноўнага карыстальніка."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Павял. на ўвесь экран"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Расцягн. на ўвесь экран"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Здымак экрана"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Захаванне скрыншота..."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Захаванне скрыншота..."</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"Скрыншот захаваны."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Скрыншот зроблены"</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"Дакраніцеся, каб прагледзець здымак экрана."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"Не атрымалася зрабiць скрыншот."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Падчас захавання скрыншота адбылася памылка."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Немагчыма захаваць здымак экрана, бо мала месца ў памяці."</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"Захаванне здымка экрана"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"Здымак экрана захаваны"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"Дакраніцеся, каб прагледзець здымак экрана"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"Не атрымалася зрабіць здымак экрана"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"Падчас захавання здымка экрана адбылася памылка"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Немагчыма захаваць здымак экрана, бо мала месца ў сховішчу"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Рабіць здымкі экрана не дазваляе праграма ці ваша арганізацыя"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Парам. перадачы файлаў па USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Падлучыць як медыяпрайгравальнік (ССП)"</string>
@@ -563,30 +567,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"Выключана"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"З дапамогай пашыранага кіравання апавяшчэннямі вы можаце задаваць узровень важнасці апавяшчэнняў праграмы ад 0 да 5. \n\n"<b>"Узровень 5"</b>" \n- Паказваць уверсе спіса апавяшчэнняў \n- Дазваляць перапыняць рэжым поўнага экрана \n- Заўсёды дазваляць кароткі паказ \n\n"<b>"Узровень 4"</b>" \n- Забараняць перапыняць рэжым поўнага экрана \n- Заўсёды дазваляць кароткі паказ \n\n"<b>"Узровень 3"</b>" \n- Забараняць перапыняць рэжым поўнага экрана \n- Ніколі не дазваляць кароткі паказ \n\n"<b>"Узровень 2"</b>" \n- Забараняць перапыняць рэжым поўнага экрана \n- Ніколі не дазваляць кароткі паказ \n- Ніколі не прайграваць гук і не вібрыраваць \n\n"<b>"Узровень 1"</b>" \n- Забараняць перапыняць рэжым поўнага экрана \n- Ніколі не дазваляць кароткі паказ \n- Ніколі не прайграваць гук і не вібрыраваць \n- Хаваць з экрана блакіроўкі і панэлі стану \n- Паказваць унізе спіса апавяшчэнняў \n\n"<b>"Узровень 0"</b>" \n- Блакіраваць усе апавяшчэнні ад праграмы"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Апавяшчэнні"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"Вы больш не будзеце атрымліваць гэтыя апавяшчэнні"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"Катэгорый апавяшчэнняў: <xliff:g id="NUMBER">%d</xliff:g>"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"У гэтай праграме няма катэгорый апавяшчэнняў"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"Апавяшчэнні ад гэтай праграмы нельга адключыць"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="one">1 з <xliff:g id="NUMBER_1">%s</xliff:g> катэгорыі апавяшчэнняў у гэтай праграме</item>
-      <item quantity="few">1 з <xliff:g id="NUMBER_1">%s</xliff:g> катэгорый апавяшчэнняў у гэтай праграме</item>
-      <item quantity="many">1 з <xliff:g id="NUMBER_1">%s</xliff:g> катэгорый апавяшчэнняў у гэтай праграме</item>
-      <item quantity="other">1 з <xliff:g id="NUMBER_1">%s</xliff:g> катэгорыі апавяшчэнняў у гэтай праграме</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> і яшчэ <xliff:g id="NUMBER_5">%3$d</xliff:g></item>
-      <item quantity="few"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> і яшчэ <xliff:g id="NUMBER_5">%3$d</xliff:g></item>
-      <item quantity="many"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> і яшчэ <xliff:g id="NUMBER_5">%3$d</xliff:g></item>
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> і яшчэ <xliff:g id="NUMBER_5">%3$d</xliff:g></item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"Вы больш не будзеце бачыць гэты апавяшчэнні"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"Працягваць паказваць гэтыя апавяшчэнні?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"Спыніць апавяшчэнні"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"Працягваць паказваць"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"Працягваць паказваць апавяшчэнні гэтай праграмы?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"Немагчыма адключыць гэты апавяшчэнні"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"Кіраванне апавяшчэннямі для <xliff:g id="APP_NAME">%1$s</xliff:g> адкрыта"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"Кіраванне апавяшчэннямі для <xliff:g id="APP_NAME">%1$s</xliff:g> закрыта"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Дазволіць апавяшчэнні з гэтага канала"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"Усе катэгорыі"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Дадатковыя налады"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"Персаналізаваць: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"Наладзіць"</string>
     <string name="notification_done" msgid="5279426047273930175">"Гатова"</string>
+    <string name="inline_undo" msgid="558916737624706010">"Адрабіць"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"кіраванне апавяшчэннямі"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"параметры адкладвання апавяшчэнняў"</string>
@@ -745,8 +738,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"Разгарнуць"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Згарнуць"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Закрыць"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"Налады"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Перацягніце ўніз, каб адхіліць"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"Меню"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> з’яўляецца відарысам у відарысе"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 6a93d9e..fbdf93c 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -33,7 +33,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"В момента"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Известия"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"Батерията е изтощена"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"Батерията е изтощена – включете режима за запазването й"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"Остава/т <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Остава/т <xliff:g id="PERCENTAGE">%s</xliff:g> – още около <xliff:g id="TIME">%s</xliff:g> въз основа на използването"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Остава/т <xliff:g id="PERCENTAGE">%s</xliff:g> – още около <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Остава/т <xliff:g id="PERCENTAGE">%s</xliff:g>. Режимът за запазване на батерията е включен."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"Не се поддържа зареждане през USB.\nИзползвайте само доставеното зарядно устройство."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"Зареждането през USB не се поддържа."</string>
@@ -67,14 +70,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Потребителят, който понастоящем е влязъл в това устройство, не може да включи функцията за отстраняване на грешки през USB. За да я използвате, превключете към основния потребител."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Мащаб – запълва екрана"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Разпъване – запълва екрана"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Екранна снимка"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Екранната снимка се запазва..."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Екранната снимка се запазва..."</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"Екранната снимка се запазва."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Екранната снимка е заснета."</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"Докоснете, за да видите екранната снимка."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"Екранната снимка не можа да бъде заснета."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"При запазването на екранната снимка възникна проблем."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Екранната снимка не може да се запази поради ограничено място в хранилището."</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"Екранната снимка се запазва"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"Екранната снимка е запазена"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"Докоснете, за да видите екранната снимка"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"Екранната снимка не можа да бъде направена"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"При запазването на екранната снимка възникна проблем"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Екранната снимка не може да се запази поради ограничено място в хранилището"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Правенето на екранни снимки не е разрешено от приложението или организацията ви"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Опции за пренос на файлове чрез USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Свързване като медиен плейър (MTP)"</string>
@@ -557,26 +561,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"Изкл."</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"С помощта на контролите за известията можете да зададете ниво на важност от 0 до 5 за известията от дадено приложение. \n\n"<b>"Ниво 5"</b>" \n– Показване най-горе в списъка с известия. \n– Разрешаване на прекъсването на цял екран. \n– Известията винаги се показват мимолетно. \n\n"<b>"Ниво 4"</b>" \n– Предотвратяване на прекъсването на цял екран. \n– Известията винаги се показват мимолетно. \n\n"<b>"Ниво 3"</b>" \n– Предотвратяване на прекъсването на цял екран. \n– Известията никога не се показват мимолетно. \n\n"<b>"Ниво 2"</b>" \n– Предотвратяване на прекъсването на цял екран. \n– Известията никога не се показват мимолетно. \n– Без издаване на звуков сигнал и вибриране. \n\n"<b>"Ниво 1"</b>" \n– Предотвратяване на прекъсването на цял екран. \n– Известията никога не се показват мимолетно. \n– Без издаване на звуков сигнал и вибриране. \n– Скриване от заключения екран и лентата на състоянието. \n– Показване най-долу в списъка с известия. \n\n"<b>"Ниво 0"</b>" \n– Блокиране на всички известия от приложението."</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Известия"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"Вече няма да получавате тези известия"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> категории известия"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"За това приложение няма категории на известията"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"Известията от това приложение не могат да бъдат изключени"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="other">1 от <xliff:g id="NUMBER_1">%s</xliff:g> категории известия от това приложение</item>
-      <item quantity="one">1 от <xliff:g id="NUMBER_0">%s</xliff:g> категория известия от това приложение</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"„<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>“, „<xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>“"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="other">„<xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>“, „<xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g>“ и още <xliff:g id="NUMBER_5">%3$d</xliff:g></item>
-      <item quantity="one">„<xliff:g id="CHANNEL_NAME_1_0">%1$s</xliff:g>“, „<xliff:g id="CHANNEL_NAME_2_1">%2$s</xliff:g>“ и още <xliff:g id="NUMBER_2">%3$d</xliff:g></item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"Вече няма да виждате тези известия"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"Тези известия да продължат ли да се показват?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"Спиране на известията"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"Да продължат да се показват"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"Да продължат ли да се показват известията от това приложение?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"Тези известия не могат да бъдат изключени"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"Контролите за известията за <xliff:g id="APP_NAME">%1$s</xliff:g> са оттворени"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"Контролите за известията за <xliff:g id="APP_NAME">%1$s</xliff:g> са затворени"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Разрешаване на известия от този канал"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"Всички категории"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Още настройки"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"Персонализиране: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"Персонализиране"</string>
     <string name="notification_done" msgid="5279426047273930175">"Готово"</string>
+    <string name="inline_undo" msgid="558916737624706010">"Отмяна"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g> от <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"контроли за известията"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"опции за отлагане на известията"</string>
@@ -731,8 +728,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"Разгъване"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Намаляване"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Затваряне"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"Настройки"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Преместете надолу с плъзгане, за да отхвърлите"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"Меню"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> е в режима „Картина в картината“"</string>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 4b163ec..a8e0c2b 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -33,7 +33,13 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"চলতে-থাকা"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"বিজ্ঞপ্তিগুলি"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"ব্যাটারি কম"</string>
+    <!-- no translation found for battery_low_title_hybrid (6268991275887381595) -->
+    <skip />
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> অবশিষ্ট আছে"</string>
+    <!-- no translation found for battery_low_percent_format_hybrid (6838677459286775617) -->
+    <skip />
+    <!-- no translation found for battery_low_percent_format_hybrid_short (9025795469949145586) -->
+    <skip />
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> অবশিষ্ট আছে। ব্যাটারি সেভার চালু আছে।"</string>
     <string name="invalid_charger" msgid="4549105996740522523">"USB চার্জিং সমর্থিত নয়৷\nকেবলমাত্র সরবহারকৃত চার্জার ব্যবহার করুন৷"</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"USB চার্জিং সমর্থিত নয়।"</string>
@@ -67,14 +73,22 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"ব্যবহারকারী এখন এই ডিভাইসে সাইন-ইন করেছেন তাই USB ডিবাগিং চালু করা যাবে না। এই বৈশিষ্ট্যটি ব্যবহার করতে, প্রাথমিক ব্যবহারকারীতে পাল্টে নিন।"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"স্ক্রীণ পূরণ করতে জুম করুন"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"ফুল স্ক্রিন করুন"</string>
+    <!-- no translation found for global_action_screenshot (8329831278085426283) -->
+    <skip />
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"স্ক্রিনশট সেভ করা হচ্ছে..."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"স্ক্রিনশট সেভ করা হচ্ছে..."</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"স্ক্রিনশট সেভ করা হচ্ছে৷"</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"স্ক্রিনশট নেওয়া হযেছে৷"</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"আপনার স্ক্রিনশট দেখতে আলতো চাপ দিন৷"</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"স্ক্রিনশট নেওয়া যায়নি৷"</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"স্ক্রিনশট সেভের সময়ে সমস্যা হয়েছে৷"</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"স্টোরেজ সীমিত থাকায় স্ক্রিনশটটি সেভ করা যাবে না৷"</string>
+    <!-- no translation found for screenshot_saving_text (2545047868936087248) -->
+    <skip />
+    <!-- no translation found for screenshot_saved_title (5637073968117370753) -->
+    <skip />
+    <!-- no translation found for screenshot_saved_text (7574667448002050363) -->
+    <skip />
+    <!-- no translation found for screenshot_failed_title (9096484883063264803) -->
+    <skip />
+    <!-- no translation found for screenshot_failed_to_save_unknown_text (8844781948876286488) -->
+    <skip />
+    <!-- no translation found for screenshot_failed_to_save_text (3041612585107107310) -->
+    <skip />
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"এই অ্যাপ বা আপনার প্রতিষ্ঠান স্ক্রিনশট নেওয়ার অনুমতি দেয়নি"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB ফাইল স্থানান্তরের বিকল্পগুলি"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"একটি মিডিয়া প্লেয়ার হিসেবে মাউন্ট করুন (MTP)"</string>
@@ -557,26 +571,27 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"বন্ধ আছে"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"পাওয়ার বিজ্ঞপ্তির নিয়ন্ত্রণগুলি ব্যহবার করে, আপনি কোনও অ্যাপ্লিকেশনের বিজ্ঞপ্তির জন্য ০ থেকে ৫ পর্যন্ত একটি গুরুত্বের লেভেলকে সেট করতে পারবেন৷ \n\n"<b>"লেভেল ৫"</b>" \n- বিজ্ঞপ্তি তালিকার শীর্ষে দেখায় \n- পূর্ণ স্ক্রিনের বাধাকে অনুমতি দেয় \n- সর্বদা স্ক্রিনে উপস্থিত হয় \n\n"<b>"লেভেল ৪"</b>" \n- পূর্ণ স্ক্রিনের বাধাকে আটকায় \n- সর্বদা স্ক্রিনে উপস্থিত হয় \n\n"<b>"লেভেল ৩"</b>" \n- পূর্ণ স্ক্রিনের বাধাকে আটকায় \n- কখনওই স্ক্রিনে উপস্থিত হয় না \n\n"<b>"লেভেল ২"</b>" \n- পূর্ণ স্ক্রিনের বাধাকে আটকায় \n- কখনওই স্ক্রিনে উপস্থিত হয় না \n- কখনওই শব্দ এবং কম্পন করে না \n\n"<b>"লেভেল ১"</b>" \n- পূর্ণ স্ক্রিনের বাধাকে আটকায় \n- কখনওই স্ক্রিনে উপস্থিত হয় না \n- কখনওই শব্দ এবং কম্পন করে না \n- লক স্ক্রিন এবং স্ট্যাটাস বার থেকে লুকায় \n- বিজ্ঞপ্তি তালিকার নীচের দিকে দেখায় \n\n"<b>"লেভেল ০"</b>" \n- অ্যাপ্লিকেশন থেকে সমস্ত বিজ্ঞপ্তিকে অবরূদ্ধ করে"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"বিজ্ঞপ্তি"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"আপনি এই বিজ্ঞপ্তিগুলি আর পাবেন না"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> বিজ্ঞপ্তির বিভাগগুলি"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"এই অ্যাপটিতে বিজ্ঞপ্তির বিভাগ নেই"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"এই অ্যাপ থেকে আসা বিজ্ঞপ্তি বন্ধ করা যাবে না"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="one">এই অ্যাপের <xliff:g id="NUMBER_1">%s</xliff:g>টি বিজ্ঞপ্তির বিভাগের মধ্যে ১টি</item>
-      <item quantity="other">এই অ্যাপের <xliff:g id="NUMBER_1">%s</xliff:g>টি বিজ্ঞপ্তির বিভাগের মধ্যে ১টি</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g>, এবং আরও <xliff:g id="NUMBER_5">%3$d</xliff:g>টি</item>
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g>, এবং আরও <xliff:g id="NUMBER_5">%3$d</xliff:g>টি</item>
-    </plurals>
+    <!-- no translation found for notification_channel_disabled (344536703863700565) -->
+    <skip />
+    <!-- no translation found for inline_keep_showing (8945102997083836858) -->
+    <skip />
+    <!-- no translation found for inline_stop_button (4172980096860941033) -->
+    <skip />
+    <!-- no translation found for inline_keep_button (6665940297019018232) -->
+    <skip />
+    <!-- no translation found for inline_keep_showing_app (1723113469580031041) -->
+    <skip />
+    <!-- no translation found for notification_unblockable_desc (1037434112919403708) -->
+    <skip />
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"<xliff:g id="APP_NAME">%1$s</xliff:g> খোলা থাকলে বিজ্ঞপ্তি নিয়ন্ত্রণ"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"<xliff:g id="APP_NAME">%1$s</xliff:g> বন্ধ থাকলে বিজ্ঞপ্তি নিয়ন্ত্রণ"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"এই চ্যানেল থেকে বিজ্ঞপ্তি আসতে দেয়"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"সকল বিভাগ"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"আরও সেটিংস"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"কাস্টমাইজ করুন: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <!-- no translation found for notification_app_settings (420348114670768449) -->
+    <skip />
     <string name="notification_done" msgid="5279426047273930175">"সম্পন্ন"</string>
+    <!-- no translation found for inline_undo (558916737624706010) -->
+    <skip />
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"বিজ্ঞপ্তির নিয়ন্ত্রণগুলি"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"বিজ্ঞপ্তি মনে করিয়ে দেওয়ার বিকল্পগুলি"</string>
@@ -731,8 +746,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"বড় করুন"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"ছোটো করুন"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"বন্ধ করুন"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"সেটিংস"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"খারিজ করতে নিচের দিকে টেনে আনুন"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"মেনু"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"ছবির-মধ্যে-ছবি তে <xliff:g id="NAME">%s</xliff:g> আছেন"</string>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index fc246c4..69b8fbe 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -34,7 +34,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"U toku"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Obavještenja"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"Baterija je skoro prazna"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"Baterija je skoro prazna. Uključite Uštedu baterije"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"Preostalo <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Još <xliff:g id="PERCENTAGE">%s</xliff:g>. Preostalo je oko <xliff:g id="TIME">%s</xliff:g>, na osnovu vašeg korištenja"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Još <xliff:g id="PERCENTAGE">%s</xliff:g>. Preostalo je oko <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Preostalo <xliff:g id="PERCENTAGE">%s</xliff:g>. Uključena je Ušteda baterije."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"USB punjenje nije podržano.\nKoristite samo priloženi punjač."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"Punjenje pomoću USB-a nije podržano."</string>
@@ -68,14 +71,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Korisnik koji je trenutno prijavljen na ovaj uređaj ne može uključiti opciju za otklanjanje grešaka koristeći USB. Da koristite tu funkciju, prebacite se na primarnog korisnika."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Uvećaj prikaz na ekran"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Razvuci prikaz na ekran"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Snimak ekrana"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Spašavanje snimka ekrana..."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Spašavanje snimka ekrana..."</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"Spašavanje snimka ekrana u toku."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Ekran snimljen."</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"Dodirnite za prikaz snimka ekrana."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"Došlo je do greške prilikom snimanja ekrana."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Došlo je do problema prilikom spašavanja snimka ekrana."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Snimak ekrana se ne može sačuvati zbog manjka prostora za pohranu."</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"Snimak ekrana se čuva"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"Snimak ekrana je sačuvan"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"Dodirnite za prikaz snimka ekrana"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"Pravljenje snimka ekrana nije uspjelo"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"Došlo je do problema prilikom čuvanja snimka ekrana"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Snimak ekrana se ne može sačuvati zbog manjka prostora za pohranu"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Ova aplikacija ili vaša organizacija ne dozvoljavaju snimanje ekrana"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opcije USB prijenosa fajlova"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Reproduciranje medijskih sadržaja (MTP)"</string>
@@ -561,28 +565,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"Isključeno"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Uz kontrolu obavještenja o napajanju, možete postaviti nivo značaja obavještenja iz aplikacije, i to od nivoa 0 do 5. \n\n"<b>"Nivo 5"</b>" \n- Prikaži na vrhu liste obavještenja \n- Dopusti prekid prikaza cijelog ekrana \n- Uvijek izviruj \n\n"<b>"Nvio 4"</b>" \n- Spriječi prekid prikaza cijelog ekrana \n- Uvijek izviruj \n\n"<b>"Nivo 3"</b>" \n- Spriječi prekid prikaza cijelog ekrana \n- Nikad ne izviruj \n\n"<b>"Nivo 2"</b>" \n- Spriječi prekid prikaza cijelog ekrana \n- Nikad ne izviruj \n- Nikada ne puštaj zvuk ili vibraciju \n\n"<b>"Nivo 1"</b>" \n- Spriječi prekid prikaza cijelog ekrana \n- Nikada ne izviruj \n- Nikada ne puštaj zvuk ili vibraciju \n- Sakrij sa ekrana za zaključavanje i statusne trake \n- Prikaži na dnu liste obavještenja \n\n"<b>"Nivo 0"</b>" \n- Blokiraj sva obavještenja iz aplikacije"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Obavještenja"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"Nećete više primati ova obavještenja"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"Kategorije obavještenja: <xliff:g id="NUMBER">%d</xliff:g>"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"Ova aplikacija nema kategorije obavještenja"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"Obavještenja iz ove aplikacije nije moguće isključiti"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="one">1 od <xliff:g id="NUMBER_1">%s</xliff:g> kategorije obavještenja iz ove aplikacije</item>
-      <item quantity="few">1 od <xliff:g id="NUMBER_1">%s</xliff:g> kategorije obavještenja iz ove aplikacije</item>
-      <item quantity="other">1 od <xliff:g id="NUMBER_1">%s</xliff:g> kategorija obavještenja iz ove aplikacije</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g>, i još <xliff:g id="NUMBER_5">%3$d</xliff:g></item>
-      <item quantity="few"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g>, i još <xliff:g id="NUMBER_5">%3$d</xliff:g></item>
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g>, i još <xliff:g id="NUMBER_5">%3$d</xliff:g></item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"Nećete više vidjeti ova obavještenja"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"Nastaviti prikazivanje ovih obavještenja?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"Zaustavi obavještenja"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"Nastavi prikazivanje"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"Nastaviti prikazivanje obavještenja iz ove aplikacije?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"Ova obavještenja nije moguće isključiti"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"Otvorene su kontrole obavještenja za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"Zatvorene su kontrole obavještenja za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Dozvoli obavještenja s ovog kanala"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"Sve kategorije"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Više postavki"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"Prilagodite: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"Prilagodi"</string>
     <string name="notification_done" msgid="5279426047273930175">"Gotovo"</string>
+    <string name="inline_undo" msgid="558916737624706010">"Opozovi"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"kontrole obavještenja"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"opcije za odgodu obavještenja"</string>
@@ -739,8 +734,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"Proširi"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Umanji"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Zatvori"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"Postavke"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Povucite prema dolje da odbacite"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"Meni"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> je u načinu priakza Slika u slici"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 4ff8e2c..d61d15e 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -33,7 +33,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Continu"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notificacions"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"Queda poca bateria"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"Queda poca bateria. Activa el mode Estalvi de bateria."</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"Queda un <xliff:g id="PERCENTAGE">%s</xliff:g>."</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Queda un <xliff:g id="PERCENTAGE">%s</xliff:g>; temps restant aproximat segons l\'ús que en fas: <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Queda un <xliff:g id="PERCENTAGE">%s</xliff:g>; temps restant aproximat: <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Queda un <xliff:g id="PERCENTAGE">%s</xliff:g>. La funció Estalvi de bateria està activada."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"Pujada d\'USB no admesa.\nUtilitza només el carregador proporcionat."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"La pujada per USB no és compatible."</string>
@@ -67,14 +70,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"L\'usuari que té iniciada la sessió al dispositiu en aquest moment no pot activar la depuració per USB. Per utilitzar aquesta funció, cal canviar a l\'usuari principal."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoom per omplir pantalla"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Estira per omplir pant."</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Captura de pantalla"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"S\'està desant captura de pantalla..."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"S\'està desant la captura de pantalla..."</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"La captura de pantalla s\'ha desat."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"S\'ha fet una captura de pantalla."</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"Toca la notificació per veure la captura de pantalla."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"No s\'ha pogut fer una captura de pantalla."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"S\'ha trobat un problema en desar la captura de pantalla."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"La captura de pantalla no es pot desar perquè no hi ha prou espai d\'emmagatzematge."</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"S\'està desant la captura de pantalla"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"S\'ha desat la captura de pantalla"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"Toca per veure la captura de pantalla"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"No s\'ha pogut fer la captura de pantalla"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"S\'ha trobat un problema en desar la captura de pantalla"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"La captura de pantalla no es pot desar perquè no hi ha prou espai d\'emmagatzematge"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"L\'aplicació o la teva organització no permeten fer captures de pantalla"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opcions transf. fitxers USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Munta com a reproductor multimèdia (MTP)"</string>
@@ -557,26 +561,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"Desactivat"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Amb els controls de notificació millorats, pots establir un nivell d\'importància d\'entre 0 i 5 per a les notificacions d\'una aplicació. \n\n"<b>"Nivell 5"</b>" \n- Mostra les notificacions a la part superior de la llista \n- Permet la interrupció de la pantalla completa \n- Permet sempre la previsualització \n\n"<b>"Nivell 4"</b>" \n- No permet la interrupció de la pantalla completa \n- Permet sempre la previsualització \n\n"<b>"Nivell 3"</b>" \n- No permet la interrupció de la pantalla completa \n- No permet mai la previsualització \n\n"<b>"Nivell 2"</b>" \n- No permet la interrupció de la pantalla completa \n- No permet mai la previsualització \n- Les notificacions no poden emetre sons ni vibracions \n\n"<b>"Nivell 1"</b>" \n- No permet la interrupció de la pantalla completa \n- No permet mai la previsualització \n- No activa mai el so ni la vibració \n- Amaga les notificacions de la pantalla de bloqueig i de la barra d\'estat \n- Mostra les notificacions a la part inferior de la llista \n\n"<b>"Nivell 0"</b>" \n- Bloqueja totes les notificacions de l\'aplicació"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Notificacions"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"Ja no rebràs aquestes notificacions"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> categories de notificació"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"Aquesta aplicació no té categories de notificació"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"Les notificacions d\'aquesta aplicació no es poden desactivar"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="other">1 de <xliff:g id="NUMBER_1">%s</xliff:g> categories de notificació d\'aquesta aplicació</item>
-      <item quantity="one">1 de <xliff:g id="NUMBER_0">%s</xliff:g> categoria de notificació d\'aquesta aplicació</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> i <xliff:g id="NUMBER_5">%3$d</xliff:g> més</item>
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_0">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_1">%2$s</xliff:g> i <xliff:g id="NUMBER_2">%3$d</xliff:g> més</item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"Ja no veuràs aquestes notificacions"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"Vols continuar rebent aquestes notificacions?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"Deixa d\'enviar notificacions"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"Continua rebent"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"Vols continuar rebent notificacions d\'aquesta aplicació?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"Aquestes notificacions no es poden desactivar"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"S\'han obert els controls de notificació per a <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"S\'han tancat els controls de notificació per a <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Permet les notificacions d\'aquest canal"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"Totes les categories"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Més opcions"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"Personalitza: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"Personalitza"</string>
     <string name="notification_done" msgid="5279426047273930175">"Fet"</string>
+    <string name="inline_undo" msgid="558916737624706010">"Desfés"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"controls de notificació"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"opcions per posposar la notificació"</string>
@@ -731,8 +728,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"Desplega"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimitza"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Tanca"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"Configuració"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Arrossega cap avall per ignorar-ho"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"Menú"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> està en pantalla en pantalla"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 5438434..e2ff065 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -33,7 +33,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"I gang"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Underretninger"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"Batteriniveauet er lavt"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"Batteriniveauet er lavt – aktivér Batterisparefunktion"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> tilbage"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Der er <xliff:g id="PERCENTAGE">%s</xliff:g> tilbage eller ca. <xliff:g id="TIME">%s</xliff:g>, alt efter hvordan du bruger enheden"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> tilbage eller ca. <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> tilbage. Batterisparefunktion er aktiveret."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"Opladning via USB understøttes ikke.\nBrug kun den medfølgende oplader."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"USB-opladning understøttes ikke."</string>
@@ -67,14 +70,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Den bruger, der i øjeblikket er logget ind på denne enhed, kan ikke aktivere USB-fejlretning. Skift til den primære bruger for at bruge denne funktion."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoom til fuld skærm"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Stræk til fuld skærm"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Screenshot"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Gemmer screenshot..."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Gemmer screenshot..."</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"Screenshottet gemmes."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Screenshottet er gemt."</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"Tryk for at se dit screenshot."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"Screenshottet kunne ikke tages."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Der opstod et problem ved lagringen af screenshottet."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Screenshottet kan ikke gemmes pga. begrænset lagerplads."</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"Screenshottet gemmes"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"Screenshottet blev gemt"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"Tryk for at se dit screenshot"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"Screenshottet kunne ikke tages"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"Der opstod et problem, da screenshottet skulle gemmes"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Screenshottet kan ikke gemmes, fordi der er begrænset lagerplads"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Appen eller din organisation tillader ikke, at du tager screenshots"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Muligheder for USB-filoverførsel"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Isæt som en medieafspiller (MTP)"</string>
@@ -557,26 +561,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"Fra"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Med kontrolelementer til underretninger om strøm kan du konfigurere et vigtighedsniveau fra 0 til 5 for en apps underretninger. \n\n"<b>"Niveau 5"</b>\n"- Vis øverst på listen over underretninger \n- Tillad afbrydelse af fuld skærm \n- Se altid smugkig \n\n"<b>"Niveau 4"</b>\n"- Ingen afbrydelse af fuld skærm \n- Se altid smugkig \n\n"<b>"Niveau 3"</b>\n"- Ingen afbrydelse af fuld skærm \n- Se aldrig smugkig \n\n"<b>"Niveau 2"</b>\n"- Ingen afbrydelse af fuld skærm \n Se aldrig smugkig \n- Ingen lyd og vibration \n\n"<b>"Niveau 1"</b>\n"- Ingen afbrydelse af fuld skærm \n- Se aldrig smugkig \n- Ingen lyd eller vibration \n- Skjul fra låseskærm og statusbjælke \n- Vis nederst på listen over underretninger \n\n"<b>"Niveau 0"</b>\n"- Bloker alle underretninger fra appen."</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Underretninger"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"Du modtager ikke længere disse underretninger"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> underretningskategorier"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"Denne app har ingen underretningskategorier"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"Underretninger fra denne app kan ikke deaktiveres"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="one">1 ud af <xliff:g id="NUMBER_1">%s</xliff:g> underretningskategori fra denne app</item>
-      <item quantity="other">1 ud af <xliff:g id="NUMBER_1">%s</xliff:g> underretningskategorier fra denne app</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> og <xliff:g id="NUMBER_5">%3$d</xliff:g> anden</item>
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> og <xliff:g id="NUMBER_5">%3$d</xliff:g> andre</item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"Du får ikke længere vist disse underretninger"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"Vil du fortsætte med at se disse underretninger?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"Stop underretninger"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"Fortsæt med at vise underretninger"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"Vil du fortsætte med at se underretninger fra denne app?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"Disse underretninger kan ikke deaktiveres"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"Styring af underretninger for <xliff:g id="APP_NAME">%1$s</xliff:g> blev åbnet"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"Styring af underretninger for <xliff:g id="APP_NAME">%1$s</xliff:g> blev lukket"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Tillad underretninger fra denne kanal"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"Alle kategorier"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Flere indstillinger"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"Tilpas: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"Tilpas"</string>
     <string name="notification_done" msgid="5279426047273930175">"Udfør"</string>
+    <string name="inline_undo" msgid="558916737624706010">"Fortryd"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"kontrolelementer til underretninger"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"Indstillinger for udsættelse"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 77a666d..53bf7d8 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -33,13 +33,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Aktuell"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Benachrichtigungen"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"Akku ist schwach"</string>
-    <!-- no translation found for battery_low_title_hybrid (6268991275887381595) -->
-    <skip />
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"Akku ist schwach. Energiesparmodus aktivieren."</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> verbleibend"</string>
-    <!-- no translation found for battery_low_percent_format_hybrid (6838677459286775617) -->
-    <skip />
-    <!-- no translation found for battery_low_percent_format_hybrid_short (9025795469949145586) -->
-    <skip />
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> ausstehend; noch ca. <xliff:g id="TIME">%s</xliff:g>, basierend auf deiner Nutzung"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> ausstehend; noch ca. <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Noch <xliff:g id="PERCENTAGE">%s</xliff:g>. Der Energiesparmodus ist aktiviert."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"USB-Aufladung wird nicht unterstützt.\nVerwende das mitgelieferte Aufladegerät."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"Laden per USB wird nicht unterstützt."</string>
@@ -73,22 +70,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Der momentan auf diesem Gerät angemeldete Nutzer kann das USB-Debugging nicht aktivieren. Um diese Funktion verwenden zu können, wechsle zum primären Nutzer."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoom auf Bildschirmgröße"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Auf Bildschirmgröße anpassen"</string>
-    <!-- no translation found for global_action_screenshot (8329831278085426283) -->
-    <skip />
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Screenshot"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Screenshot wird gespeichert..."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Screenshot wird gespeichert..."</string>
-    <!-- no translation found for screenshot_saving_text (2545047868936087248) -->
-    <skip />
-    <!-- no translation found for screenshot_saved_title (5637073968117370753) -->
-    <skip />
-    <!-- no translation found for screenshot_saved_text (7574667448002050363) -->
-    <skip />
-    <!-- no translation found for screenshot_failed_title (9096484883063264803) -->
-    <skip />
-    <!-- no translation found for screenshot_failed_to_save_unknown_text (8844781948876286488) -->
-    <skip />
-    <!-- no translation found for screenshot_failed_to_save_text (3041612585107107310) -->
-    <skip />
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"Screenshot wird gespeichert"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"Screenshot gespeichert"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"Tippe, um deinen Screenshot anzusehen"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"Screenshot konnte nicht aufgenommen werden"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"Beim Speichern des Screenshots ist ein Problem aufgetreten"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Speichern des Screenshots aufgrund von zu wenig Speicher nicht möglich"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Die App oder deine Organisation lässt das Erstellen von Screenshots nicht zu"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB-Dateiübertragungsoptionen"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Als Medienplayer (MTP) bereitstellen"</string>
@@ -575,27 +565,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"Aus"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Mit den erweiterten Benachrichtigungseinstellungen kannst du für App-Benachrichtigungen eine Wichtigkeitsstufe von 0 bis 5 festlegen. \n\n"<b>"Stufe 5"</b>" \n- Auf der Benachrichtigungsleiste ganz oben anzeigen \n- Vollbildunterbrechung zulassen \n- Immer kurz einblenden \n\n"<b>"Stufe 4"</b>" \n- Keine Vollbildunterbrechung \n- Immer kurz einblenden \n\n"<b>"Stufe 3"</b>" \n- Keine Vollbildunterbrechung \n- Nie kurz einblenden \n\n"<b>"Stufe 2"</b>" \n- Keine Vollbildunterbrechung \n- Nie kurz einblenden \n- Weder Ton noch Vibration \n\n"<b>"Stufe 1"</b>" \n- Keine Vollbildunterbrechung \n- Nie kurz einblenden \n- Weder Ton noch Vibration \n- Auf Sperrbildschirm und Statusleiste verbergen \n- Auf der Benachrichtigungsleiste ganz unten anzeigen \n\n"<b>"Stufe 0"</b>" \n- Alle Benachrichtigungen der App sperren"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Benachrichtigungen"</string>
-    <!-- no translation found for notification_channel_disabled (344536703863700565) -->
-    <skip />
-    <!-- no translation found for inline_keep_showing (8945102997083836858) -->
-    <skip />
-    <!-- no translation found for inline_stop_button (4172980096860941033) -->
-    <skip />
-    <!-- no translation found for inline_keep_button (6665940297019018232) -->
-    <skip />
-    <!-- no translation found for inline_keep_showing_app (1723113469580031041) -->
-    <skip />
-    <!-- no translation found for notification_unblockable_desc (1037434112919403708) -->
-    <skip />
+    <string name="notification_channel_disabled" msgid="344536703863700565">"Du erhältst diese Benachrichtigungen nicht mehr"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"Diese Benachrichtigungen weiterhin anzeigen?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"Benachrichtigungen nicht mehr anzeigen"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"Weiterhin anzeigen"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"Benachrichtigungen dieser App weiterhin anzeigen?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"Diese Benachrichtigungen können nicht deaktiviert werden"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"Benachrichtigungseinstellungen für <xliff:g id="APP_NAME">%1$s</xliff:g> geöffnet"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"Benachrichtigungseinstellungen für <xliff:g id="APP_NAME">%1$s</xliff:g> geschlossen"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Benachrichtigungen von diesem Kanal zulassen"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Weitere Einstellungen"</string>
-    <!-- no translation found for notification_app_settings (420348114670768449) -->
-    <skip />
+    <string name="notification_app_settings" msgid="420348114670768449">"Anpassen"</string>
     <string name="notification_done" msgid="5279426047273930175">"Fertig"</string>
-    <!-- no translation found for inline_undo (558916737624706010) -->
-    <skip />
+    <string name="inline_undo" msgid="558916737624706010">"Rückgängig machen"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g> – <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"Benachrichtigungseinstellungen"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"Optionen für spätere Erinnerung bei Benachrichtigungen"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 7464d31..663191c 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -33,7 +33,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Εν εξελίξει"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Ειδοποιήσεις"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"Χαμηλή στάθμη μπαταρίας"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"Χαμηλή στάθμη μπαταρίας. Ενεργοποιήστε την Εξοικονόμηση μπαταρίας"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"Απομένουν <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Απομένει <xliff:g id="PERCENTAGE">%s</xliff:g>, περίπου <xliff:g id="TIME">%s</xliff:g> με βάση τη χρήση σας"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Απομένει <xliff:g id="PERCENTAGE">%s</xliff:g>, περίπου <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Απομένουν <xliff:g id="PERCENTAGE">%s</xliff:g>. Η Εξοικονόμηση μπαταρίας είναι ενεργή."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"Δεν υποστηρίζεται η φόρτιση USB.\nΧρησιμοποιείτε μόνο τον φορτιστή που παρέχεται."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"Δεν υποστηρίζεται η φόρτιση μέσω USB."</string>
@@ -67,14 +70,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Ο χρήστης που είναι συνδεδεμένος αυτήν τη στιγμή σε αυτήν τη συσκευή δεν μπορεί να ενεργοποιήσει τον εντοπισμό σφαλμάτων USB. Για να χρησιμοποιήσετε αυτήν τη λειτουργία, κάντε εναλλαγή στον κύριο χρήστη."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Ζουμ σε πλήρη οθόνη"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Προβoλή σε πλήρη οθ."</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Στιγμιότυπο οθόνης"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Αποθήκ. στιγμιότυπου οθόνης..."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Αποθήκευση στιγμιότυπου οθόνης..."</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"Γίνεται αποθήκευση του στιγμιότυπου οθόνης."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Λήφθηκε το στιγμιότυπο οθόνης ."</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"Πατήστε για να δείτε το στιγμιότυπο οθόνης που δημιουργήσατε."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"Αδύνατη η αποθήκευση του στιγμιότυπου οθόνης."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Παρουσιάστηκε πρόβλημα κατά την αποθήκευση του στιγμιότυπου οθόνης."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Δεν είναι δυνατή η αποθήκευση του στιγμιότυπου οθόνης λόγω περιορισμένου χώρου αποθήκευσης."</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"Γίνεται αποθήκευση του στιγμιότυπου οθόνης"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"Το στιγμιότυπο οθόνης αποθηκεύτηκε"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"Πατήστε για να δείτε το στιγμιότυπο οθόνης που δημιουργήσατε"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"Αδύνατη η λήψη του στιγμιότυπου οθόνης."</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"Παρουσιάστηκε πρόβλημα κατά την αποθήκευση του στιγμιότυπου οθόνης"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Αδύνατη η αποθήκευση του στιγμιότυπου οθόνης λόγω περιορισμένου αποθηκευτικού χώρου"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Η λήψη στιγμιότυπων οθόνης δεν επιτρέπεται από την εφαρμογή ή τον οργανισμό σας"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Επιλογές μεταφοράς αρχείων μέσω USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Προσάρτηση ως μονάδας αναπαραγωγής μέσων (MTP)"</string>
@@ -557,26 +561,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"Ανενεργή"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Με τα στοιχεία ελέγχου ειδοποίησης ισχύος, μπορείτε να ορίσετε ένα επίπεδο βαρύτητας από 0 έως 5 για τις ειδοποιήσεις μιας εφαρμογής. \n\n"<b>"Επίπεδο 5"</b>" \n- Εμφάνιση στην κορυφή της λίστας ειδοποιήσεων \n- Να επιτρέπεται η διακοπή πλήρους οθόνης \n- Να γίνεται πάντα σύντομη προβολή \n\n"<b>"Επίπεδο 4"</b>" \n- Αποτροπή διακοπής πλήρους οθόνης \n- Να γίνεται πάντα σύντομη προβολή \n\n"<b>"Επίπεδο 3"</b>" \n- Αποτροπή διακοπής πλήρους οθόνης \n- Να μην γίνεται ποτέ σύντομη προβολή \n\n"<b>"Επίπεδο 2"</b>" \n- Αποτροπή διακοπής πλήρους οθόνης \n- Να μην γίνεται ποτέ σύντομη προβολή \n- Να μην χρησιμοποιείται ποτέ ήχος και δόνηση \n\n"<b>"Επίπεδο 1"</b>" \n- Αποτροπή διακοπής πλήρους οθόνης \n- Να μην γίνεται ποτέ σύντομη προβολή \n- Να μην χρησιμοποιείται ποτέ ήχος και δόνηση \n- Απόκρυψη από την οθόνη κλειδώματος και τη γραμμή κατάστασης \n- Εμφάνιση στο κάτω μέρος της λίστας ειδοποιήσεων \n\n"<b>"Επίπεδο 0"</b>" \n- Αποκλεισμός όλων των ειδοποιήσεων από την εφαρμογή"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Ειδοποιήσεις"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"Δεν θα λαμβάνετε πλέον αυτές τις ειδοποιήσεις"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> κατηγορίες ειδοποιήσεων"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"Αυτή η εφαρμογή δεν διαθέτει κατηγορίες ειδοποιήσεων"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"Οι ειδοποιήσεις από αυτήν την εφαρμογή δεν μπορούν να απενεργοποιηθούν"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="other">1 από <xliff:g id="NUMBER_1">%s</xliff:g> κατηγορίες ειδοποιήσεων από αυτή την εφαρμογή</item>
-      <item quantity="one">1 από <xliff:g id="NUMBER_0">%s</xliff:g> κατηγορία ειδοποιήσεων από αυτή την εφαρμογή</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> και <xliff:g id="NUMBER_5">%3$d</xliff:g> ακόμη</item>
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_0">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_1">%2$s</xliff:g> και <xliff:g id="NUMBER_2">%3$d</xliff:g> ακόμη</item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"Δεν θα βλέπετε πλέον αυτές τις ειδοποιήσεις"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"Να συνεχίσουν να εμφανίζονται αυτές οι ειδοποιήσεις;"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"Διακοπή ειδοποιήσεων"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"Συνέχιση εμφάνισης"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"Να συνεχίσουν να εμφανίζονται ειδοποιήσεις από αυτήν την εφαρμογή;"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"Αδύνατη η απενεργοποίηση αυτών των ειδοποιήσεων"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"Τα στοιχεία ελέγχου ειδοποιήσεων για την εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> άνοιξαν"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"Τα στοιχεία ελέγχου ειδοποιήσεων για την εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> έκλεισαν"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Να επιτρέπονται οι ειδοποιήσεις από αυτό το κανάλι"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"Όλες οι κατηγορίες"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Περισσότερες ρυθμίσεις"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"Προσαρμογή: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"Προσαρμογή"</string>
     <string name="notification_done" msgid="5279426047273930175">"Τέλος"</string>
+    <string name="inline_undo" msgid="558916737624706010">"Αναίρεση"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"στοιχεία ελέγχου ειδοποιήσεων"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"επιλογές αφύπνισης ειδοποιήσεων"</string>
@@ -731,8 +728,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"Ανάπτυξη"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Ελαχιστοποίηση"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Κλείσιμο"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"Ρυθμίσεις"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Σύρετε προς τα κάτω για παράβλεψη"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"Μενού"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"Η λειτουργία picture-in-picture είναι ενεργή σε <xliff:g id="NAME">%s</xliff:g>."</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 6901686..cdb432b 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -33,7 +33,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Continuo"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notificaciones"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"Batería baja"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"Queda poca batería. Activa el Ahorro de batería"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"Queda un <xliff:g id="PERCENTAGE">%s</xliff:g> de batería."</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Batería: <xliff:g id="PERCENTAGE">%s</xliff:g> (tiempo restante aproximado según tu uso: <xliff:g id="TIME">%s</xliff:g>)"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Batería: <xliff:g id="PERCENTAGE">%s</xliff:g> (tiempo restante aproximado: <xliff:g id="TIME">%s</xliff:g>)"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Queda <xliff:g id="PERCENTAGE">%s</xliff:g> de batería. El Ahorro de batería está activado."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"No admite la carga USB.\nUsa sólo el cargador provisto."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"No se admite la carga por USB."</string>
@@ -67,14 +70,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"El usuario al que accediste en este dispositivo no puede activar la depuración por USB. Para usar esta función, debes cambiar al usuario principal."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoom para ocupar la pantalla"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Estirar p/ ocupar la pantalla"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Captura de pantalla"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Guardando captura de pantalla"</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Guardando la captura de pantalla..."</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"La captura de pantalla se está guardando."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Se guardó la captura de pantalla."</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"Presiona para ver tu captura de pantalla."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"No se pudo guardar la captura de pantalla."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Se produjo un error al guardar la captura de pantalla."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"No se puede guardar la captura de pantalla debido al almacenamiento limitado."</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"Se está guardando la captura de pantalla"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"Se guardó la captura de pantalla"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"Presiona para ver la captura de pantalla"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"No se pudo tomar la captura de pantalla"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"Se produjo un error al guardar la captura de pantalla"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"No se puede guardar la captura de pantalla debido a que no hay suficiente espacio de almacenamiento"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"La app o tu organización no permiten las capturas de pantalla"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opciones de transferencia de archivos por USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Activar como reproductor de medios (MTP)"</string>
@@ -559,26 +563,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"Desactivado"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Con los controles de activación de notificaciones, puedes establecer un nivel de importancia para las notificaciones de una app. \n\n"<b>"Nivel 5"</b>" \n- Mostrar en la parte superior de la lista de notificaciones. \n- Permitir interrupción en la pantalla completa. \n- Mostrar siempre. \n\n"<b>"Nivel 4"</b>" \n- No permitir interrupción en la pantalla completa. \n- Mostrar siempre. \n\n"<b>"Nivel 3"</b>" \n- No permitir interrupción en la pantalla completa. \n- No mostrar. \n\n"<b>"Nivel 2"</b>" \n- No permitir interrupción en la pantalla completa. \n- No mostrar. \n- No sonar ni vibrar. \n\n"<b>"Nivel 1"</b>" \n- No permitir interrupción en la pantalla completa. \n- No mostrar. \n- No sonar ni vibrar. \n- Ocultar de la pantalla bloqueada y la barra de estado. \n- Mostrar al final de la lista de notificaciones. \n\n"<b>"Nivel 0"</b>" \n- Bloquear todas las notificaciones de la app."</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Notificaciones"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"Ya no recibirás estas notificaciones"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> categorías de notificaciones"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"Esta app no tiene categorías de notificación"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"No es posible desactivar las notificaciones de esta app"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="other">1 de <xliff:g id="NUMBER_1">%s</xliff:g> categorías de notificación de esta app</item>
-      <item quantity="one">1 de <xliff:g id="NUMBER_0">%s</xliff:g> categoría de notificación de esta app</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> y <xliff:g id="NUMBER_5">%3$d</xliff:g> más</item>
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_0">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_1">%2$s</xliff:g> y <xliff:g id="NUMBER_2">%3$d</xliff:g> más</item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"Ya no verás estas notificaciones"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"¿Quieres seguir viendo estas notificaciones?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"Detener notificaciones"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"Seguir viendo"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"¿Quieres seguir viendo las notificaciones de esta app?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"No se pueden desactivar estas notificaciones"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"Se abrieron los controles de notificaciones de <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"Se cerraron los controles de notificaciones de <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Permitir las notificaciones de este canal"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"Todas las categorías"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Más opciones de configuración"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"Personalizar: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"Personalizar"</string>
     <string name="notification_done" msgid="5279426047273930175">"Listo"</string>
+    <string name="inline_undo" msgid="558916737624706010">"Deshacer"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g> de <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"controles de notificación"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"opciones para posponer notificaciones"</string>
@@ -733,8 +730,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"Expandir"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimizar"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Cerrar"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"Configuración"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Arrastra hacia abajo para descartar"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"Menú"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> está en modo de imagen en imagen"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index a5d5c44..b467b38 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -33,7 +33,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Entrante"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notificaciones"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"Nivel de batería bajo"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"Queda poca batería. Activa la función Ahorro de batería"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"Queda un <xliff:g id="PERCENTAGE">%s</xliff:g> de batería"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Queda un <xliff:g id="PERCENTAGE">%s</xliff:g> (tiempo restante aproximado según tu uso: <xliff:g id="TIME">%s</xliff:g>)"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Queda un <xliff:g id="PERCENTAGE">%s</xliff:g> (tiempo restante aproximado: <xliff:g id="TIME">%s</xliff:g>)"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Queda un <xliff:g id="PERCENTAGE">%s</xliff:g> de batería. Se ha activado la función Ahorro de energía."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"No se admite la carga por USB.\nUtiliza solo el cargador proporcionado."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"No se admite la carga por USB."</string>
@@ -67,14 +70,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"El usuario con el que se ha iniciado sesión en este dispositivo no puede activar la depuración USB. Para utilizar esta función, inicia sesión con la cuenta de usuario principal."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoom para ajustar"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Expandir para ajustar"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Captura de pantalla"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Guardando captura..."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Guardando captura..."</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"La captura de pantalla se está guardando."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Captura guardada"</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"Toca para ver la captura de pantalla."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"No se ha podido guardar la captura de pantalla."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Se ha detectado un problema al guardar la captura de pantalla."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"No se puede guardar la captura de pantalla porque no hay espacio de almacenamiento suficiente."</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"La captura de pantalla se está guardando"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"Se ha guardado la captura de pantalla"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"Toca para ver la captura de pantalla"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"No se ha podido guardar la captura de pantalla"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"No se ha podido guardar la captura de pantalla"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"No se puede guardar la captura de pantalla porque no hay espacio de almacenamiento suficiente"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"La aplicación o tu organización no permiten realizar capturas de pantalla"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opciones de transferencia de archivos por USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Activar como reproductor de medios (MTP)"</string>
@@ -559,26 +563,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"Desactivado"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Los controles de energía de las notificaciones permiten establecer un nivel de importancia de 0 a 5 para las notificaciones de las aplicaciones. \n\n"<b>"Nivel 5"</b>" \n- Mostrar en la parte superior de la lista de notificaciones \n- Permitir interrumpir en el modo de pantalla completa \n- Mostrar siempre \n\n"<b>"Nivel 4"</b>" \n- Evitar interrumpir en el modo de pantalla completa \n- Mostrar siempre \n\n"<b>"Nivel 3"</b>" \n- Evitar interrumpir en el modo de pantalla completa \n- No mostrar nunca \n\n"<b>"Nivel 2"</b>" \n- Evitar interrumpir en el modo de pantalla completa\n- No mostrar nunca \n- No emitir sonido ni vibrar nunca \n\n"<b>"Nivel 1"</b>" \n- Evitar interrumpir en el modo de pantalla completa \n- No mostrar nunca \n- No emitir sonido ni vibrar nunca \n- Ocultar de la pantalla de bloqueo y de la barra de estado \n- Mostrar en la parte inferior de la lista de notificaciones \n\n"<b>"Nivel 0"</b>" \n- Bloquear todas las notificaciones de la aplicación"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Notificaciones"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"Ya no recibirás estas notificaciones"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> categorías de notificación"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"Esta aplicación no tiene categorías de notificación"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"No se pueden desactivar las notificaciones de esta aplicación"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="other">1 de <xliff:g id="NUMBER_1">%s</xliff:g> categorías de notificación de esta aplicación</item>
-      <item quantity="one">1 de <xliff:g id="NUMBER_0">%s</xliff:g> categoría de notificación de esta aplicación</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> y <xliff:g id="NUMBER_5">%3$d</xliff:g> más</item>
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_0">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_1">%2$s</xliff:g> y <xliff:g id="NUMBER_2">%3$d</xliff:g> más</item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"No volverás a ver estas notificaciones"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"¿Quieres seguir viendo estas notificaciones?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"Detener las notificaciones"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"Seguir mostrando"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"¿Quieres seguir viendo las notificaciones de esta aplicación?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"Estas notificaciones no se pueden desactivar"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"Se han abierto los controles de las notificaciones de <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"Se han cerrado los controles de las notificaciones de <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Permite las notificaciones de este canal"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"Todas las categorías"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Más ajustes"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"Personalizar: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"Personalizar"</string>
     <string name="notification_done" msgid="5279426047273930175">"Listo"</string>
+    <string name="inline_undo" msgid="558916737624706010">"Deshacer"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g> de <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"Controles de las notificaciones"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"Opciones para posponer las notificaciones"</string>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 84cbc44..1b8ad65 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -33,7 +33,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Jätkuv"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Märguanded"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"Aku hakkab tühjaks saama"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"Aku hakkab tühjaks saama. Lülitage sisse akusäästja"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"Jäänud on <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> on alles, teie kasutuse põhjal on jäänud umbes <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> on alles, umbes <xliff:g id="TIME">%s</xliff:g> on jäänud"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Jäänud on <xliff:g id="PERCENTAGE">%s</xliff:g>. Akusäästja on sisse lülitatud."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"USB laadimist ei toetata.\nKasutage ainult tootja laadija."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"USB-ga laadimist ei toetata."</string>
@@ -67,14 +70,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Sellesse seadmesse praegu sisse logitud kasutaja ei saa USB-silumist sisse lülitada. Selle funktsiooni kasutamiseks vahetage peamisele kasutajale."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Suumi ekraani täitmiseks"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Venita ekraani täitmiseks"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Ekraanipilt"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Kuvatõmmise salvestamine ..."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Kuvatõmmise salvestamine ..."</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"Kuvatõmmist salvestatakse."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Ekraanipilt on jäädvustatud."</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"Puudutage ekraanipildi vaatamiseks."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"Kuvatõmmist ei saanud jäädvustada."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Ekraanipildi salvestamisel ilmnes probleem."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Piiratud salvestusruumi tõttu ei saa ekraanipilti salvestada."</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"Ekraanipilti salvestatakse"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"Ekraanipilt salvestati"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"Puudutage ekraanipildi vaatamiseks"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"Ekraanipilti ei saanud jäädvustada"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"Ekraanipildi salvestamisel ilmnes probleem"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Piiratud salvestusruumi tõttu ei saa ekraanipilti salvestada"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Rakendus või teie organisatsioon ei luba ekraanipilte jäädvustada"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB-failiedastuse valikud"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Paigalda meediumimängijana (MTP)"</string>
@@ -559,26 +563,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"Väljas"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Toite märguannete juhtnuppudega saate määrata rakenduse märguannete tähtsuse taseme vahemikus 0–5. \n\n"<b>"5. tase"</b>" \n- Kuva märguannete loendi ülaosas\n- Luba täisekraanil häirimine \n- Kuva alati ekraani servas \n\n"<b>"4. tase"</b>" \n- Keela täisekraanil häirimine \n- Kuva alati ekraani servas \n\n"<b>"3. tase"</b>" \n- Keela täisekraanil häirimine \n- Ära kunagi kuva ekraani servas \n\n"<b>"2. tase"</b>" \n- Keela täisekraanil häirimine \n- Ära kunagi kuva ekraani servas \n- Ära kunagi helise ega vibreeri \n\n"<b>"1. tase"</b>" \n- Keela täisekraanil häirimine \n- Ära kunagi kuva ekraani servas \n- Ära kunagi helise ega vibreeri \n- Peida lukustuskuval ja olekuribal \n- Kuva märguannete loendi allosas \n\n"<b>"Tase 0"</b>" \n- Blokeeri kõik rakenduse märguanded"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Märguanded"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"Te ei saa enam neid märguandeid"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> märguandekategooriat"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"Sellel rakendusel ei ole märguannete kategooriaid"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"Selle rakenduse märguandeid ei saa välja lülitada"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="other">1 <xliff:g id="NUMBER_1">%s</xliff:g>-st märguannete kategooriast sellelt rakenduselt</item>
-      <item quantity="one">1 <xliff:g id="NUMBER_0">%s</xliff:g>-st märguannete kategooriast sellelt rakenduselt</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> ja veel <xliff:g id="NUMBER_5">%3$d</xliff:g> kanalit</item>
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_0">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_1">%2$s</xliff:g> ja veel <xliff:g id="NUMBER_2">%3$d</xliff:g> kanal</item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"Te ei näe enam neid märguandeid"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"Kas soovite nende märguannete kuvamist jätkata?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"Peata märguanded"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"Jätka kuvamist"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"Kas jätkata selle rakenduse märguannete kuvamist?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"Neid märguandeid ei saa välja lülitada"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"Rakenduse <xliff:g id="APP_NAME">%1$s</xliff:g> märguannete juhtelemendid on avatud"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"Rakenduse <xliff:g id="APP_NAME">%1$s</xliff:g> märguannete juhtelemendid on suletud"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Lubab selle kanali märguanded"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"Kõik kategooriad"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Rohkem seadeid"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"Kohandamine: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"Kohandamine"</string>
     <string name="notification_done" msgid="5279426047273930175">"Valmis"</string>
+    <string name="inline_undo" msgid="558916737624706010">"Võta tagasi"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g>, <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"märguannete juhtnupud"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"märguannete edasilükkamise valikud"</string>
@@ -733,8 +730,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"Laiendamine"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimeeri"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Sule"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"Seaded"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Loobumiseks lohistage alla"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"Menüü"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> on režiimis Pilt pildis"</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 1e5274e..1d49b3b 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -33,13 +33,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Abian"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Jakinarazpenak"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"Bateria agortzen ari da"</string>
-    <!-- no translation found for battery_low_title_hybrid (6268991275887381595) -->
-    <skip />
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"Bateria gutxi gelditzen da. Aktibatu Bateria-aurrezlea."</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> gelditzen da"</string>
-    <!-- no translation found for battery_low_percent_format_hybrid (6838677459286775617) -->
-    <skip />
-    <!-- no translation found for battery_low_percent_format_hybrid_short (9025795469949145586) -->
-    <skip />
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> gelditzen da; <xliff:g id="TIME">%s</xliff:g> inguru gelditzen dira, erabileraren arabera"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> gelditzen da; <xliff:g id="TIME">%s</xliff:g> inguru gelditzen dira"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> gelditzen da. Bateria-aurrezlea aktibatuta dago."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"Ez da USB bidez kargatzea onartzen.\nErabili hornitu zaizun kargagailua soilik."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"Ez da USB bidez kargatzea onartzen."</string>
@@ -73,22 +70,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Gailu honetan saioa hasita duen erabiltzaileak ezin du aktibatu USB arazketa. Eginbide hori erabiltzeko, aldatu erabiltzaile nagusira."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Handiagotu pantaila betetzeko"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Luzatu pantaila betetzeko"</string>
-    <!-- no translation found for global_action_screenshot (8329831278085426283) -->
-    <skip />
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Pantaila-argazkia"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Pantaila-argazkia gordetzen…"</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Pantaila-argazkia gordetzen…"</string>
-    <!-- no translation found for screenshot_saving_text (2545047868936087248) -->
-    <skip />
-    <!-- no translation found for screenshot_saved_title (5637073968117370753) -->
-    <skip />
-    <!-- no translation found for screenshot_saved_text (7574667448002050363) -->
-    <skip />
-    <!-- no translation found for screenshot_failed_title (9096484883063264803) -->
-    <skip />
-    <!-- no translation found for screenshot_failed_to_save_unknown_text (8844781948876286488) -->
-    <skip />
-    <!-- no translation found for screenshot_failed_to_save_text (3041612585107107310) -->
-    <skip />
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"Pantaila-argazkia gordetzen ari da"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"Gorde da pantaila-argazkia"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"Sakatu pantaila-argazkia ikusteko"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"Ezin izan da atera pantaila-argazkia"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"Arazo bat izan da pantaila-argazkia gordetzean"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Ezin da atera pantaila-argazkia ez delako gelditzen tokirik"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Aplikazioak edo erakundeak ez du onartzen pantaila-argazkiak ateratzea"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB fitxategiak transferitzeko aukerak"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Muntatu multimedia-erreproduzigailu gisa (MTP)"</string>
@@ -573,27 +563,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"Desaktibatuta"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Bateria-mailaren arabera jakinarazpenak kontrolatzeko aukerekin, 0 eta 5 bitarteko garrantzi-mailetan sailka ditzakezu aplikazioen jakinarazpenak. \n\n"<b>"5. maila"</b>" \n- Erakutsi jakinarazpenen zerrendaren goialdean. \n- Baimendu etetea pantaila osoko moduan zaudenean. \n- Agerrarazi beti jakinarazpenak. \n\n"<b>"4. maila"</b>" \n- Galarazi etetea pantaila osoko moduan zaudenean. \n- Agerrarazi beti jakinarazpenak. \n\n"<b>"3. maila"</b>" \n- Galarazi etetea pantaila osoko moduan zaudenean. \n- Ez agerrarazi jakinarazpenik inoiz. \n\n"<b>"2. maila"</b>" \n- Galarazi etetea pantaila osoko moduan zaudenean. \n- Ez agerrarazi jakinarazpenik inoiz. \n- Ez egin soinurik edo dardararik inoiz. \n\n"<b>"1. maila"</b>" \n- Galarazi etetea pantaila osoko moduan zaudenean. \n- Ez agerrarazi jakinarazpenik inoiz. \n- Ez egin soinurik edo dardararik inoiz. \n- Ezkutatu pantaila blokeatutik eta egoera-barratik. \n- Erakutsi jakinarazpenen zerrendaren behealdean. \n\n"<b>"0. maila"</b>" \n- Blokeatu aplikazioaren jakinarazpen guztiak."</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Jakinarazpenak"</string>
-    <!-- no translation found for notification_channel_disabled (344536703863700565) -->
-    <skip />
-    <!-- no translation found for inline_keep_showing (8945102997083836858) -->
-    <skip />
-    <!-- no translation found for inline_stop_button (4172980096860941033) -->
-    <skip />
-    <!-- no translation found for inline_keep_button (6665940297019018232) -->
-    <skip />
-    <!-- no translation found for inline_keep_showing_app (1723113469580031041) -->
-    <skip />
-    <!-- no translation found for notification_unblockable_desc (1037434112919403708) -->
-    <skip />
+    <string name="notification_channel_disabled" msgid="344536703863700565">"Aurrerantzean ez duzu ikusiko horrelako jakinarazpenik"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"Jakinarazpenak erakusten jarraitzea nahi duzu?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"Blokeatu jakinarazpenak"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"Jarraitu erakusten"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"Aplikazio honen jakinarazpenak erakusten jarraitzea nahi duzu?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"Jakinarazpen hauek ezin dira desaktibatu"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"Ireki dira <xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioaren jakinarazpenak kontrolatzeko aukerak"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"Itxi dira <xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioaren jakinarazpenak kontrolatzeko aukerak"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Onartu kanal honen jakinarazpenak"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Ezarpen gehiago"</string>
-    <!-- no translation found for notification_app_settings (420348114670768449) -->
-    <skip />
+    <string name="notification_app_settings" msgid="420348114670768449">"Pertsonalizatu"</string>
     <string name="notification_done" msgid="5279426047273930175">"Eginda"</string>
-    <!-- no translation found for inline_undo (558916737624706010) -->
-    <skip />
+    <string name="inline_undo" msgid="558916737624706010">"Desegin"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"jakinarazpena kontrolatzeko aukerak"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"jakinarazpena atzeratzeko aukerak"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 834397d..e597569 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -33,7 +33,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"در حال انجام"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"اعلان‌ها"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"شارژ باتری کم است"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"شارژ باتری کم است. «بهینه‌سازی باتری» را روشن کنید"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> باقی مانده است"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> باقی مانده، براساس میزان مصرف شما حدود <xliff:g id="TIME">%s</xliff:g> باقی مانده است"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> باقی مانده، حدود <xliff:g id="TIME">%s</xliff:g> باقی مانده است"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> باقی مانده است. بهینه‌سازی باتری روشن است."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"‏شارژ USB پشتیبانی نمی‌شود.\nفقط از شارژر ارائه شده استفاده کنید."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"‏شارژ با USB پشتیبانی نمی‌شود."</string>
@@ -67,14 +70,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"‏کاربری که درحال حاضر در این دستگاه وارد سیستم شده است نمی‌تواند اشکال‌زدایی USB را روشن کند. برای استفاده از این قابلیت، به کاربر اصلی تغییر وضعیت دهید."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"بزرگ‌نمایی برای پر کردن صفحه"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"گسترده کردن برای پر کردن صفحه"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"عکس صفحه‌نمایش"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"در حال ذخیره عکس صفحه‌نمایش..."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"در حال ذخیره عکس صفحه‌نمایش..."</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"عکس صفحه‌نمایش ذخیره شد."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"عکس صفحه‌نمایش گرفته شد."</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"برای مشاهده عکس صفحه‌نمایشتان ضربه بزنید."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"عکس صفحه‌نمایش گرفته نشد."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"هنگام ذخیره عکس صفحه‌نمایش مشکلی رخ داد."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"به دلیل محدود بودن فضای ذخیره‌سازی نمی‌توانید عکس صفحه‌نمایش را ذخیره کنید."</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"عکس صفحه‌نمایش درحال ذخیره شدن است"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"عکس صفحه‌نمایش ذخیره شد"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"برای مشاهده عکس صفحه‌نمایشتان ضربه بزنید"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"عکس صفحه‌نمایش گرفته نشد"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"هنگام ذخیره کردن عکس صفحه‌نمایش مشکلی پیش آمد"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"به دلیل محدود بودن فضای ذخیره‌سازی نمی‌توان عکس صفحه‌نمایش را ذخیره کرد"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"برنامه یا سازمان شما اجازه نمی‌دهند عکس صفحه‌نمایش بگیرید."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"‏گزینه‌های انتقال فایل USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"‏نصب به‌عنوان دستگاه پخش رسانه (MTP)"</string>
@@ -557,26 +561,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"خاموش"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"با کنترل‌های قدرتمند اعلان می‌توانید سطح اهمیت اعلان‌های هر برنامه را از ۰ تا ۵ تعیین کنید. \n\n"<b>"سطح ۵"</b>" \n- در صدر فهرست اعلان‌ها نشان داده می‌شود \n- وقفه برای نمایش تمام‌صفحه مجاز است \n- همیشه اجمالی نشان داده می‌شود \n\n"<b>"سطح ۴"</b>" \n- وقفه برای نمایش تمام‌صفحه مجاز نیست \n- همیشه اجمالی نشان داده می‌شود \n\n"<b>"سطح ۳"</b>" \n- وقفه برای نمایش تمام‌صفحه مجاز نیست \n- هیچ‌وقت اجمالی نشان داده نمی‌شود \n\n"<b>"سطح ۲"</b>" \n- وقفه برای نمایش تمام‌صفحه مجاز نیست \n- هیچ‌وقت اجمالی نشان داده نمی‌شود \n- هیچ‌وقت صدا و لرزش ایجاد نمی‌کند \n\n"<b>"سطح ۱"</b>" \n- نمایش تمام صفحه مجاز نیست \n- هیچ‌وقت اجمالی نشان داده نمی‌شود \n- هیچ‌وقت صدا یا لرزش ایجاد نمی‌کند \n- در قفل صفحه و نوار وضعیت پنهان است \n- در پایین فهرست اعلان‌ها نشان داده می‌شود \n\n"<b>"سطح ۰"</b>" \n- همه اعلان‌های این برنامه مسدود است"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"اعلان‌ها"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"دیگر این اعلان‌ها را دریافت نخواهید کرد"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> دسته اعلان"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"این برنامه دسته اعلان ندارد"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"نمی‌توان اعلان‌های این برنامه را خاموش کرد"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="one">۱ از <xliff:g id="NUMBER_1">%s</xliff:g> دسته اعلان این برنامه</item>
-      <item quantity="other">۱ از <xliff:g id="NUMBER_1">%s</xliff:g> دسته اعلان این برنامه</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>، <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>، <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> و <xliff:g id="NUMBER_5">%3$d</xliff:g> مورد دیگر</item>
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>، <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> و <xliff:g id="NUMBER_5">%3$d</xliff:g> مورد دیگر</item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"دیگر این اعلان‌ها را نخواهید دید"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"نمایش این اعلان‌ها ادامه یابد؟"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"توقف اعلان‌ها"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"همچنان نشان داده شود"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"نمایش اعلان از این برنامه ادامه یابد؟"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"نمی‌توان این اعلان‌ها را خاموش کرد"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"کنترل‌های اعلان برای <xliff:g id="APP_NAME">%1$s</xliff:g> باز شد"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"کنترل‌های اعلان برای <xliff:g id="APP_NAME">%1$s</xliff:g> بسته شد"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"مجاز کردن اعلان‌های این کانال"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"‏همه دسته‎ها"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"تنظیمات بیشتر"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"سفارشی کردن: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"سفارشی کردن"</string>
     <string name="notification_done" msgid="5279426047273930175">"تمام"</string>
+    <string name="inline_undo" msgid="558916737624706010">"واگرد"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"کنترل‌های اعلان"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"گزینه‌های تعویق اعلان"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 51a71de..59327c6 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -33,7 +33,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Käynnissä olevat"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Ilmoitukset"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"Akku on vähissä"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"Akku on vähissä, ota virransäästö käyttöön"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> jäljellä"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> käytettävissä, noin <xliff:g id="TIME">%s</xliff:g> jäljellä käytön perusteella"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> käytettävissä, noin <xliff:g id="TIME">%s</xliff:g> jäljellä"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> jäljellä. Virransäästö on käytössä."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"USB-latausta ei tueta.\nKäytä laitteen mukana tullutta laturia."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"USB-latausta ei tueta."</string>
@@ -67,14 +70,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Laitteelle tällä hetkellä kirjautunut käyttäjä ei voi ottaa USB-vianetsintää käyttöön. Vaihda käyttäjäksi ensisijainen käyttäjä, jotta voit käyttää tätä ominaisuutta."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoomaa koko näyttöön"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Venytä koko näyttöön"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Kuvakaappaus"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Tallennetaan kuvakaappausta..."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Tallennetaan kuvakaappausta..."</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"Kuvakaappausta tallennetaan."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Kuvakaappaus tallennettu"</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"Tarkastele kuvakaappausta napauttamalla"</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"Kuvakaappausta ei voitu tallentaa"</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Kuvakaappausta tallennettaessa tapahtui virhe."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Kuvakaappauksen tallentaminen epäonnistui, sillä tallennustilaa ei ole riittävästi."</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"Kuvakaappausta tallennetaan"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"Kuvakaappaus tallennettu"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"Napauta katsoaksesi kuvakaappausta"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"Kuvakaappauksen tallennus epäonnistui"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"Kuvakaappausta tallennettaessa tapahtui virhe"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Kuvakaappauksen tallennus epäonnistui, sillä tallennustilaa ei ole riittävästi"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Sovellus tai organisaatio ei salli kuvakaappauksien tallentamista."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB-tiedostonsiirtoasetukset"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Käytä mediasoittimena (MTP)"</string>
@@ -557,26 +561,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"Pois käytöstä"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Ilmoitusten tehohallinnan avulla voit määrittää sovelluksen ilmoituksille tärkeystason väliltä 0–5. \n\n"<b>"Taso 5"</b>" \n– Ilmoitukset näytetään ilmoitusluettelon yläosassa \n– Näkyminen koko näytön tilassa sallitaan \n– Ilmoitukset kurkistavat aina näytölle\n\n"<b>"Taso 4"</b>" \n– Näkyminen koko näytön tilassa estetään \n– Ilmoitukset kurkistavat aina näytölle \n\n"<b>"Taso 3"</b>" \n– Näkyminen koko näytön tilassa estetään \n– Ei kurkistamista \n\n"<b>"Taso 2"</b>" \n– Näkyminen koko näytön tilassa estetään \n– Ei kurkistamista \n– Ei ääniä eikä värinää \n\n"<b>"Taso 1"</b>" \n– Näkyminen koko näytön tilassa estetään \n– Ei kurkistamista \n– Ei ääniä eikä värinää \n– Ilmoitukset piilotetaan lukitusnäytöltä ja tilapalkista \n– Ilmoitukset näytetään ilmoitusluettelon alaosassa \n\n"<b>"Taso 0"</b>" \n– Kaikki sovelluksen ilmoitukset estetään"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Ilmoitukset"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"Et saa näitä ilmoituksia enää."</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> ilmoitusluokkaa"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"Tällä sovelluksella ei ole ilmoitusluokkia."</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"Tämän sovelluksen ilmoituksia ei voi poistaa käytöstä."</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="other">Tämä sovellus: 1/<xliff:g id="NUMBER_1">%s</xliff:g> ilmoitusluokkaa</item>
-      <item quantity="one">Tämä sovellus: 1/<xliff:g id="NUMBER_0">%s</xliff:g> ilmoitusluokkaa</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> ja <xliff:g id="NUMBER_5">%3$d</xliff:g> muuta</item>
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_0">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_1">%2$s</xliff:g> ja <xliff:g id="NUMBER_2">%3$d</xliff:g> toinen</item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"Et näe näitä ilmoituksia enää"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"Jatketaanko näiden ilmoitusten näyttämistä?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"Lopeta ilmoitukset"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"Jatka näyttämistä"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"Jatketaanko ilmoitusten näyttämistä tästä sovelluksesta?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"Näitä ilmoituksia ei voi poistaa käytöstä"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"Sovelluksen <xliff:g id="APP_NAME">%1$s</xliff:g> ilmoitusten hallinta on avattu."</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"Sovelluksen <xliff:g id="APP_NAME">%1$s</xliff:g> ilmoitusten hallinta on suljettu."</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Salli ilmoitukset tältä kanavalta."</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"Kaikki luokat"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Lisäasetukset"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"Muokkaa: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"Muokkaa"</string>
     <string name="notification_done" msgid="5279426047273930175">"Valmis"</string>
+    <string name="inline_undo" msgid="558916737624706010">"Kumoa"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"Ilmoitusten hallinta"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"Ilmoitusten torkkuasetukset"</string>
@@ -731,8 +728,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"Laajenna"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Pienennä"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Sulje"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"Asetukset"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Hylkää vetämällä alas."</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"Valikko"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> on kuva kuvassa ‑tilassa"</string>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 987ea59..23a22e6 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -33,7 +33,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"En curso"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notificacións"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"Queda pouca batería"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"Queda pouca batería. Activa a función Aforro de batería"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> restante"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Queda un <xliff:g id="PERCENTAGE">%s</xliff:g>, é dicir, aproximadamente <xliff:g id="TIME">%s</xliff:g> en función do uso que fas"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Queda un <xliff:g id="PERCENTAGE">%s</xliff:g>, é dicir, aproximadamente <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> restante. Está activada a función Aforro de batería."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"Non compatible coa carga por USB.\nUtiliza só o cargador proporcionado."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"Non se admite a carga mediante USB."</string>
@@ -67,14 +70,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"O usuario coa sesión iniciada actualmente neste dispositivo non pode activar a depuración por USB. Para utilizar esta función, cambia ao usuario principal."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Ampliar ata ocupar todo"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Estirar ata ocupar todo"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Captura de pantalla"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Gardando captura de pantalla…"</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Gardando captura de pantalla…"</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"Estase gardando a captura de pantalla."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Captura de pantalla gardada."</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"Toca para ver a captura de pantalla."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"Non se puido facer a captura de pantalla."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Produciuse un problema ao gardar a captura de pantalla."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Non se pode gardar a captura de pantalla porque o espazo de almacenamento é limitado."</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"Estase gardando a captura de pantalla"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"Gardouse a captura de pantalla"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"Toca para ver a captura de pantalla"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"Non se puido facer a captura de pantalla"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"Produciuse un problema ao gardar a captura de pantalla"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Non se puido gardar a captura de pantalla porque o espazo de almacenamento é limitado"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"A aplicación ou a túa organización non permite realizar capturas de pantalla"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opcións de transferencia USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Inserir como reprodutor multimedia (MTP)"</string>
@@ -559,26 +563,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"Desactivar"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Cos controis de notificacións mellorados, podes asignarlles un nivel de importancia comprendido entre 0 e 5 ás notificacións dunha aplicación determinada. \n\n"<b>"Nivel 5"</b>" \n- Mostrar na parte superior da lista de notificacións. \n- Permitir interrupcións no modo de pantalla completa. \n- Mostrar sempre. \n\n"<b>"Nivel 4"</b>" \n- Impedir interrupcións no modo de pantalla completa. \n- Mostrar sempre. \n\n"<b>"Nivel 3"</b>" \n- Impedir interrupcións no modo de pantalla completa. \n- Non mostrar nunca. \n\n"<b>"Nivel 2"</b>" \n- Impedir interrupcións no modo de pantalla completa. \n- Non mostrar nunca. \n- Non soar nin vibrar nunca. \n\n"<b>"Nivel 1"</b>" \n- Impedir interrupcións no modo de pantalla completa. \n- Non mostrar nunca. \n- Non soar nin vibrar nunca. \n- Ocultar na pantalla de bloqueo e na barra de estado. \n- Mostrar na parte inferior da lista de notificacións. \n\n"<b>"Nivel 0"</b>" \n- Bloquear todas as notificacións da aplicación."</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Notificacións"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"Deixarás de recibir estas notificacións"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> categorías de notificacións"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"Esta aplicación non ten categorías de notificacións"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"Non se poden desactivar as notificacións desta aplicación"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="other">1 de <xliff:g id="NUMBER_1">%s</xliff:g> categorías de notificacións desta aplicación</item>
-      <item quantity="one">1 de <xliff:g id="NUMBER_0">%s</xliff:g> categoría de notificación desta aplicación</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> e <xliff:g id="NUMBER_5">%3$d</xliff:g> máis</item>
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_0">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_1">%2$s</xliff:g> e <xliff:g id="NUMBER_2">%3$d</xliff:g> máis</item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"Deixarás de ver estas notificacións"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"Queres seguir mostrando estas notificacións?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"Deter notificacións"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"Continuar mostrando notificacións"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"Queres seguir mostrando as notificacións desta aplicación?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"Non se poden desactivar estas notificacións"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"Abríronse os controis de notificacións da aplicación <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"Pecháronse os controis de notificacións da aplicación <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Permitir notificacións desde esta canle"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"Todas as categorías"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Máis opcións"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"Personalizar: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"Personalizar"</string>
     <string name="notification_done" msgid="5279426047273930175">"Feito"</string>
+    <string name="inline_undo" msgid="558916737624706010">"Desfacer"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g> de <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"controis de notificacións"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"opcións para adiar notificacións"</string>
@@ -733,8 +730,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"Despregar"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimizar"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Pechar"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"Configuración"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Arrastra cara abaixo para ignorar"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"Menú"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> está na pantalla superposta"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 27ed38c..ec37855 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -33,13 +33,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"ऑनगोइंग"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"सूचनाएं"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"बैटरी कम है"</string>
-    <!-- no translation found for battery_low_title_hybrid (6268991275887381595) -->
-    <skip />
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"बैटरी कम बची है. बैटरी सेवर चालू करें"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> शेष"</string>
-    <!-- no translation found for battery_low_percent_format_hybrid (6838677459286775617) -->
-    <skip />
-    <!-- no translation found for battery_low_percent_format_hybrid_short (9025795469949145586) -->
-    <skip />
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> बची है, आपके इस्तेमाल करने के तरीके के हिसाब से बैटरी लगभग <xliff:g id="TIME">%s</xliff:g> चलेगी"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> बची है, बैटरी लगभग <xliff:g id="TIME">%s</xliff:g> चलेगी"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> बैटरी बची है. बैटरी सेवर चालू है."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"USB चार्जिंग समर्थित नहीं है.\nकेवल आपूर्ति किए गए चार्जर का उपयोग करें."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"USB चार्जिंग समर्थित नहीं है."</string>
@@ -73,22 +70,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"अभी इस डिवाइस में जिस उपयोगकर्ता ने साइन इन किया है, वो USB डीबगिंग चालू नहीं कर सकता. इस सुविधा का इस्तेमाल करने के लिए, प्राथमिक उपयोगकर्ता में बदलें."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"स्‍क्रीन भरने के लिए ज़ूम करें"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"स्‍क्रीन भरने के लिए खींचें"</string>
-    <!-- no translation found for global_action_screenshot (8329831278085426283) -->
-    <skip />
+    <string name="global_action_screenshot" msgid="8329831278085426283">"स्क्रीनशॉट"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"स्क्रीनशॉट सहेजा जा रहा है..."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"स्क्रीनशॉट सहेजा जा रहा है..."</string>
-    <!-- no translation found for screenshot_saving_text (2545047868936087248) -->
-    <skip />
-    <!-- no translation found for screenshot_saved_title (5637073968117370753) -->
-    <skip />
-    <!-- no translation found for screenshot_saved_text (7574667448002050363) -->
-    <skip />
-    <!-- no translation found for screenshot_failed_title (9096484883063264803) -->
-    <skip />
-    <!-- no translation found for screenshot_failed_to_save_unknown_text (8844781948876286488) -->
-    <skip />
-    <!-- no translation found for screenshot_failed_to_save_text (3041612585107107310) -->
-    <skip />
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"स्क्रीनशॉट सेव किया जा रहा है"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"स्क्रीनशॉट सेव किया गया"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"अपना स्क्रीनशॉट देखने के लिए टैप करें"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"स्क्रीनशॉट नहीं लिया जा सका"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"स्क्रीनशॉट सेव करते समय एक समस्या आई"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"मेमोरी कम होने की वजह से स्क्रीनशॉट सेव नहीं किया जा सका"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"ऐप्लिकेशन या आपका संगठन स्क्रीनशॉट लेने की अनुमति नहीं देता"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB फ़ाइल स्थानांतरण विकल्प"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"मीडिया प्लेयर के रूप में माउंट करें (MTP)"</string>
@@ -571,27 +561,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"बंद"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"पावर सूचना नियंत्रण के ज़रिये, आप किसी ऐप की सूचना को उसकी अहमियत के हिसाब से 0 से 5 के लेवल पर सेट कर सकते हैं.\n\n"<b>"लेवल 5"</b>" \n- सूचना सूची में सबसे ऊपर दिखाएं \n- पूरे स्क्रीन को ढंकने की अनुमति दें \n- लगातार देखते रहें \n\n"<b>" लेवल 4"</b>" \n- पूरे स्क्रीन को ढंकें \n- लगातार देखते रहें \n\n"<b>"लेवल 3"</b>" \n- पूरे स्क्रीन को ढंकने से रोकें \n-कभी भी न देखें \n\n"<b>"लेवल 2"</b>" \n- पूरे स्क्रीन को ढंकने से रोकें \n- कभी भी देखें \n- कभी भी आवाज़ या कंपन (वाइब्रेशन) न करें \n\n"<b>"लेवल 1"</b>" \n- पूरे स्क्रीन को ढंकने से रोकें \n- कभी भी न देखें \n- कभी भी आवाज़ या कंपन (वाइब्रेशन) न करें \n- लॉक स्क्रीन और स्टेटस बार से छिपाएं \n- सूचना सूची के नीचे दिखाएं \n\n"<b>"लेवल 0"</b>" \n- ऐप्लिकेशन की सभी सूचनाएं रोक दें"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"सूचना"</string>
-    <!-- no translation found for notification_channel_disabled (344536703863700565) -->
-    <skip />
-    <!-- no translation found for inline_keep_showing (8945102997083836858) -->
-    <skip />
-    <!-- no translation found for inline_stop_button (4172980096860941033) -->
-    <skip />
-    <!-- no translation found for inline_keep_button (6665940297019018232) -->
-    <skip />
-    <!-- no translation found for inline_keep_showing_app (1723113469580031041) -->
-    <skip />
-    <!-- no translation found for notification_unblockable_desc (1037434112919403708) -->
-    <skip />
+    <string name="notification_channel_disabled" msgid="344536703863700565">"अब आपको ये सूचनाएं दिखाई नहीं देंगी"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"ये सूचनाएं दिखाना जारी रखें?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"सूचनाएं दिखाना बंद करें"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"दिखाना जारी रखें"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"इस ऐप्लिकेशन से जुड़ी सूचनाएं दिखाना जारी रखें?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"ये सूचनाएं दिखाया जाना बंद नहीं किया जा सकता"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"<xliff:g id="APP_NAME">%1$s</xliff:g> के लिए सूचना नियंत्रण चालू हैं"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"<xliff:g id="APP_NAME">%1$s</xliff:g> के लिए सूचना नियंत्रण बंद हैं"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"इस चैनल से सूचना की पाने की मंज़ूरी दें"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"और सेटिंग"</string>
-    <!-- no translation found for notification_app_settings (420348114670768449) -->
-    <skip />
+    <string name="notification_app_settings" msgid="420348114670768449">"पसंद के मुताबिक बनाएं"</string>
     <string name="notification_done" msgid="5279426047273930175">"हो गया"</string>
-    <!-- no translation found for inline_undo (558916737624706010) -->
-    <skip />
+    <string name="inline_undo" msgid="558916737624706010">"पहले जैसा करें"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"सूचना नियंत्रण"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"सूचना को स्नूज़ (थोड़ी देर के लिए चुप करना) करने के विकल्प"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 7395b66..cb62834 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -34,7 +34,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"U tijeku"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Obavijesti"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"Niska razina baterije"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"Baterija je skoro prazna. Uključite Štednju baterije"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"Preostalo <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Preostalo je <xliff:g id="PERCENTAGE">%s</xliff:g>, još otprilike <xliff:g id="TIME">%s</xliff:g> na temelju vaše upotrebe"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Preostalo je <xliff:g id="PERCENTAGE">%s</xliff:g>, još otprilike <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Preostalo <xliff:g id="PERCENTAGE">%s</xliff:g>. Uključena je Štednja baterije."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"USB punjenje nije podržano.\nUpotrijebite samo priloženi punjač."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"Punjenje putem USB-a nije podržano."</string>
@@ -68,14 +71,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Korisnik koji je trenutačno prijavljen na ovaj uređaj ne može uključiti otklanjanje pogrešaka putem USB-a. Da biste upotrebljavali tu značajku, prijeđite na primarnog korisnika."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zumiraj i ispuni zaslon"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Rastegni i ispuni zaslon"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Snimka zaslona"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Spremanje snimke zaslona..."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Spremanje snimke zaslona..."</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"Spremanje snimke zaslona."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Zaslon je snimljen."</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"Dodirnite da biste vidjeli snimku zaslona."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"Nije bilo moguće snimiti zaslon."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Prilikom spremanja snimke zaslona pojavio se problem."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Zaslon nije snimljen zbog ograničenog prostora za pohranu."</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"Spremanje snimke zaslona"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"Snimka zaslona spremljena"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"Dodirnite da biste vidjeli snimku zaslona"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"Nije bilo moguće snimiti zaslon"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"Prilikom spremanja snimke zaslona pojavio se problem"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Zaslon nije snimljen zbog ograničenog prostora za pohranu"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Aplikacija ili vaša organizacija ne dopuštaju snimanje zaslona"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opcije USB prijenosa datoteka"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Učitaj kao media player (MTP)"</string>
@@ -559,28 +563,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"Isključeno"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Napredne kontrole obavijesti omogućuju vam da postavite razinu važnosti za obavijesti aplikacije od 0 do 5. \n\n"<b>"Razina 5"</b>" \n– prikaži na vrhu popisa obavijesti \n– dopusti prekide prikaza na cijelom zaslonu \n– uvijek dopusti brzi pregled \n\n"<b>"Razina 4"</b>" \n– onemogući prekid prikaza na cijelom zaslonu \n– uvijek dopusti brzi pregled \n\n"<b>"Razina 3"</b>" \n– onemogući prekid prikaza na cijelom zaslonu \n– nikad ne dopusti brzi pregled\n\n"<b>"Razina 2"</b>" \n– onemogući prekid prikaza na cijelom zaslonu \n– nikad ne dopusti brzi pregled \n– nikad ne emitiraj zvuk ni vibraciju \n\n"<b>"Razina 1"</b>" \n– onemogući prekid prikaza na cijelom zaslonu \n– nikad ne dopusti brzi pregled \n– nikad ne emitiraj zvuk ni vibraciju \n– ne prikazuj na zaključanom zaslonu i traci statusa \n– prikaži na dnu popisa obavijesti \n\n"<b>"Razina 0"</b>" \n– blokiraj sve obavijesti aplikacije"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Obavijesti"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"Više nećete primati te obavijesti"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"Broj kategorija obavijesti: <xliff:g id="NUMBER">%d</xliff:g>"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"Ova aplikacija nema kategorije obavijesti"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"Obavijesti ove aplikacije ne mogu se isključiti"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="one">1 od <xliff:g id="NUMBER_1">%s</xliff:g> kategorije obavijesti iz ove aplikacije</item>
-      <item quantity="few">1 od <xliff:g id="NUMBER_1">%s</xliff:g> kategorije obavijesti iz ove aplikacije</item>
-      <item quantity="other">1 od <xliff:g id="NUMBER_1">%s</xliff:g> kategorija obavijesti iz ove aplikacije</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> i još <xliff:g id="NUMBER_5">%3$d</xliff:g></item>
-      <item quantity="few"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> i još <xliff:g id="NUMBER_5">%3$d</xliff:g></item>
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> i još <xliff:g id="NUMBER_5">%3$d</xliff:g></item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"Te vam se obavijesti više neće prikazivati"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"Želite li da se obavijesti nastave prikazivati?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"Zaustavi obavijesti"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"Nastavi prikazivati"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"Želite li da se obavijesti te aplikacije nastave prikazivati?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"Te se obavijesti ne mogu isključiti"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"Otvorene su kontrole obavijesti za <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"Zatvorene su kontrole obavijesti za <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Dopusti obavijesti za ovaj kanal"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"Sve kategorije"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Više postavki"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"Prilagodite: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"Prilagodi"</string>
     <string name="notification_done" msgid="5279426047273930175">"Gotovo"</string>
+    <string name="inline_undo" msgid="558916737624706010">"Poništi"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g> za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"kontrole obavijesti"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"opcije odgode obavijesti"</string>
@@ -737,8 +732,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"Proširivanje"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimiziraj"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Zatvori"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"Postavke"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Povucite prema dolje da biste odbacili"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"Izbornik"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> jest na slici u slici"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 87ca49a..2069952 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -33,7 +33,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Folyamatban van"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Értesítések"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"Alacsony az energiaszint"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"Az akkumulátor szintje alacsony. Kapcsolja be az akkumulátorkímélő módot."</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> maradt"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> maradt, körülbelül <xliff:g id="TIME">%s</xliff:g> van hátra a használat alapján"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> maradt, körülbelül <xliff:g id="TIME">%s</xliff:g> van hátra"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> maradt. Az Akkumulátorkímélő mód be van kapcsolva."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"Az USB-n keresztüli töltés nincs támogatva.\nHasználja a kapott töltőt."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"Az USB-n keresztüli töltés nem támogatott."</string>
@@ -67,14 +70,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Az eszközre jelenleg bejelentkezett felhasználó nem engedélyezheti az USB-hibakeresést. A funkció használatához váltson az elsődleges felhasználóra."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Nagyítás a kitöltéshez"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Nyújtás kitöltéshez"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Képernyőkép"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Képernyőkép mentése..."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Képernyőkép mentése..."</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"Képernyőkép mentése."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Képernyőkép rögzítve."</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"Koppintson a képernyőkép megtekintéséhez."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"Nem sikerült rögzíteni a képernyőképet."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Hiba történt a képernyőkép mentése során."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Nem menthet képernyőképet, mert kevés a tárhely."</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"Képernyőkép mentése…"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"A képernyőkép mentése sikerült"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"Koppintson a képernyőkép megtekintéséhez"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"Nem sikerült rögzíteni a képernyőképet"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"Hiba történt a képernyőkép mentése során"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Nem menthet képernyőképet, mert kevés a tárhely"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Az alkalmazás vagy az Ön szervezete nem engedélyezi képernyőkép készítését"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB-fájlátvitel beállításai"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Csatlakoztatás médialejátszóként (MTP)"</string>
@@ -557,26 +561,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"Kikapcsolva"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Az értesítési beállítások révén 0-tól 5-ig állíthatja be a fontossági szintet az alkalmazás értesítéseinél. \n\n"<b>"5. szint"</b>" \n– Megjelenítés az értesítési lista tetején \n– Teljes képernyő megszakításának engedélyezése \n– Mindig felugrik \n\n"<b>"4. szint"</b>" \n– Teljes képernyő megszakításának megakadályozása \n– Mindig felugrik \n\n"<b>"3. szint"</b>" \n– Teljes képernyő megszakításának megakadályozása \n– Soha nem ugrik fel \n\n"<b>"2. szint"</b>" \n– Teljes képernyő megszakításának megakadályozása \n– Soha nem ugrik fel \n– Soha nincs hangjelzés és rezgés \n\n"<b>"1. szint"</b>" \n– Teljes képernyő megszakításának megakadályozása \n– Soha nem ugrik fel \n– Soha nincs hangjelzés vagy rezgés \n– Elrejtés a lezárási képernyőről és az állapotsávról \n– Megjelenítés az értesítési lista alján \n\n"<b>"0. szint"</b>" \n– Az alkalmazás összes értesítésének letiltása"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Értesítések"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"Többé nem jelennek meg ezek az értesítések"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> értesítéskategória"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"Az alkalmazás nem rendelkezik értesítési kategóriákkal"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"Az alkalmazástól érkező értesítések nem kapcsolhatók ki"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g>/1 értesítési kategória az alkalmazásból</item>
-      <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g>/1 értesítési kategória az alkalmazásból</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> és <xliff:g id="NUMBER_5">%3$d</xliff:g> másik</item>
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_0">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_1">%2$s</xliff:g> és <xliff:g id="NUMBER_2">%3$d</xliff:g> másik</item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"Többé nem jelennek meg ezek az értesítések"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"Továbbra is megjelenjenek ezek az értesítések?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"Értesítések letiltása"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"Megjelenítés továbbra is"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"Továbbra is megjelenjenek az alkalmazás értesítései?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"Ezeket az értesítéseket nem lehet kikapcsolni"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> értesítésvezérlői megnyitva"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> értesítésvezérlői kikapcsolva"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Értesítések engedélyezése erről a csatornáról"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"Minden kategória"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"További beállítások"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"Személyre szabás: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"Személyre szabás"</string>
     <string name="notification_done" msgid="5279426047273930175">"Kész"</string>
+    <string name="inline_undo" msgid="558916737624706010">"Visszavonás"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> – <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"értesítésvezérlők"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"értesítések halasztási beállításai"</string>
@@ -731,8 +728,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"Kibontás"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Kis méret"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Bezárás"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"Beállítások"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Elvetéshez húzza lefelé"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"Menü"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"A(z) <xliff:g id="NAME">%s</xliff:g> kép a képben funkciót használ"</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index b6172c8..0656f0c 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -33,7 +33,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Ընթացիկ"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Ծանուցումներ"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"Մարտկոցի լիցքը սպառվում է"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"Մարտկոցի լիցքը սպառվում է։ Միացրեք մարտկոցի տնտեսումը։"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"Մնաց <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Մարտկոցի լիցքը՝ <xliff:g id="PERCENTAGE">%s</xliff:g>, մնացել է մոտ <xliff:g id="TIME">%s</xliff:g>՝ օգտագործման եղանակից կախված"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Մարտկոցի լիցքը՝ <xliff:g id="PERCENTAGE">%s</xliff:g>, մնացել է մոտ <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Մնացել է <xliff:g id="PERCENTAGE">%s</xliff:g>: Մարտկոցի տնտեսումը միացված է:"</string>
     <string name="invalid_charger" msgid="4549105996740522523">"USB լիցքավորումը չի աջակցվում:\nՕգտվեք միայն գործող լիցքավորիչից:"</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"USB լիցքավորումը չի աջակցվում:"</string>
@@ -67,14 +70,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Ընթացիկ հաշվի օգտատերը չի կարող միացնել USB վրիպազերծումը: Այս գործառույթը միացնելու համար մուտք գործեք հիմնական օգտատիրոջ հաշվով:"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Խոշորացնել` էկրանը լցնելու համար"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Ձգել` էկրանը լցնելու համար"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Էկրանի պատկեր"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Էկրանի պատկերը պահվում է…"</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Էկրանի պատկերը պահվում է..."</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"Էկրանի պատկերը պահվում է:"</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Էկրանի պատկերը լուսանկարվել է:"</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"Հպեք՝ էկրանի պատկերը տեսնելու համար:"</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"Չհաջողվեց լուսանկարել էկրանի պատկերը:"</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Էկրանի պատկերը պահելիս խնդիր առաջացավ:"</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Չհաջողվեց պահել էկրանի պատկերը սահմանափակ հիշողության պատճառով:"</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"Էկրանի պատկերը պահվում է"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"Էկրանի պատկերը պահվեց"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"Հպեք՝ էկրանի պատկերը տեսնելու համար"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"Չհաջողվեց պահել էկրանի պատկերը"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"Չհաջողվեց պահել էկրանի պատկերը"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Չհաջողվեց պահել էկրանի պատկերը անբավարար հիշողության պատճառով"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Հավելվածը կամ ձեր կազմակերպությունը չի թույլատրում էկրանի պատկերի ստացումը"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB ֆայլերի փոխանցման ընտրանքներ"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Միացնել որպես մեդիա նվագարկիչ (MTP)"</string>
@@ -557,26 +561,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"Անջատել"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Ծանուցումների ընդլայնված կառավարման օգնությամբ կարող եք յուրաքանչյուր հավելվածի ծանուցումների համար նշանակել կարևորության աստիճան՝ 0-5 սահմաններում: \n\n"<b>"5-րդ աստիճան"</b>" \n- Ցուցադրել ծանուցումների ցանկի վերևում \n- Թույլատրել լիաէկրան ընդհատումները \n- Միշտ ցուցադրել կարճ ծանուցումները \n\n"<b>"4-րդ աստիճան"</b>" \n- Արգելել լիաէկրան ընդհատումները \n- Միշտ ցուցադրել կարճ ծանուցումները \n\n"<b>"3-րդ աստիճան"</b>" \n- Արգելել լիաէկրան ընդհատումները \n- Արգելել կարճ ծանուցումների ցուցադրումը \n\n"<b>"2-րդ աստիճան"</b>" \n- Արգելել լիաէկրան ընդհատումները \n- Արգելել կարճ ծանուցումների ցուցադրումը \n- Անջատել ձայնը և թրթռումը \n\n"<b>"1-ին աստիճան"</b>" \n- Արգելել լիաէկրան ընդհատումները \n- Արգելել կարճ ծանուցումների ցուցադրումը \n- Անջատել ձայնը և թրթռումը \n- Չցուցադրել կողպէկրանում և կարգավիճակի գոտում \n- Ցուցադրել ծանուցումների ցանկի ներքևում \n\n"<b>"0-րդ աստիճան"</b>\n"- Արգելափակել հավելվածի բոլոր ծանուցումները"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Ծանուցումներ"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"Այս ծանուցումներն այլևս չեք ստանա"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> ծանուցման կատեգորիաներ"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"Այս հավելվածը ծանուցման կատեգորիաներ չունի"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"Այս հավելվածի ծանուցումները հնարավոր չէ անջատել"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="one">1 out of <xliff:g id="NUMBER_1">%s</xliff:g> notification categories from this app</item>
-      <item quantity="other">1 ալիք` այս հավելվածի <xliff:g id="NUMBER_1">%s</xliff:g> կատեգորիաներից</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g>, and <xliff:g id="NUMBER_5">%3$d</xliff:g> others</item>
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> ու <xliff:g id="NUMBER_5">%3$d</xliff:g> այլ</item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"Դուք այլևս չեք ստանա այս ծանուցումները"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"Ցուցադրե՞լ այս ծանուցումները։"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"Չցուցադրել ծանուցումներ"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"Ցուցադրել"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"Ցուցադրե՞լ ծանուցումներ այս հավելվածից։"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"Այս ծանուցումները հնարավոր չէ անջատել"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"<xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածի ծանուցումների կառավարումը բաց է"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"<xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածի ծանուցումների կառավարումը փակ է"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Թույլ տալ ծանուցումներ այս ալիքից"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"Բոլոր կատեգորիաները"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Այլ կարգավորումներ"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"Հարմարեցնել՝ <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"Կարգավորել"</string>
     <string name="notification_done" msgid="5279426047273930175">"Պատրաստ է"</string>
+    <string name="inline_undo" msgid="558916737624706010">"Հետարկել"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"ծանուցման կառավարներ"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"ծանուցման հետաձգման ընտրանքներ"</string>
@@ -731,8 +728,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"Ընդարձակել"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Ծալել"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Փակել"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"Կարգավորումներ"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Քաշեք վար՝ փակելու համար"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"Ընտրացանկ"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g>-ը «Նկար նկարի մեջ» ռեժիմում է"</string>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 35bf451..dbdb273 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -33,7 +33,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Áframhaldandi"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Tilkynningar"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"Rafhlaðan er að tæmast"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"Lítil hleðsla er á rafhlöðunni. Kveiktu á rafhlöðusparnaði"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> eftir"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> eftir, um það bil <xliff:g id="TIME">%s</xliff:g> eftir miðað við notkun"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> eftir, um það bil <xliff:g id="TIME">%s</xliff:g> eftir"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> eftir. Kveikt er á rafhlöðusparnaði."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"USB-hleðsla er ekki studd.\nNotaðu eingöngu hleðslutækið sem fylgdi."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"Ekki er stuðningur við USB-hleðslu."</string>
@@ -67,14 +70,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Notandinn sem er skráður inn í þetta tæki núna getur ekki kveikt á USB-villuleit. Til þess að nota þennan eiginleika skaltu skipta yfir í aðalnotandann."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Fylla skjá með aðdrætti"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Teygja yfir allan skjáinn"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Skjámynd"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Vistar skjámynd…"</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Vistar skjámynd…"</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"Verið er að vista skjámynd."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Skjámynd var tekin."</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"Ýttu til að sjá skjámyndina."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"Ekki tókst að taka skjámynd."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Upp kom vandamál við að vista skjámynd."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Ekki tókst að vista skjámynd vegna takmarkaðs geymslupláss."</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"Vistar skjámynd"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"Skjámynd vistuð"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"Ýttu til skoða skjámyndina"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"Ekki tókst að taka skjámynd"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"Vandamál kom upp við að vista skjámynd"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Ekki tókst að vista skjámynd vegna takmarkaðs geymslupláss"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Forritið eða fyrirtækið þitt leyfir ekki skjámyndatöku"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Valkostir USB-skráaflutnings"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Tengja sem efnisspilara (MTP)"</string>
@@ -557,26 +561,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"Slökkt"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Með orkutilkynningastýringum geturðu stillt mikilvægi frá 0 upp í 5 fyrir tilkynningar forrita. \n\n"<b>"Stig 5"</b>" \n- Sýna efst á tilkynningalista \n- Leyfa truflun þegar birt er á öllum skjánum \n- Kíkja alltaf \n\n"<b>"Stig 4"</b>" \n- Hindra truflun við birtingu á öllum skjánum \n- Kíkja alltaf \n\n"<b>"Stig 3"</b>" \n- Hindra truflun við birtingu á öllum skjánum \n- Kíkja aldrei \n\n"<b>"Stig 2"</b>" \n- Hindra truflun við birtingu á öllum skjánum \n- Kíkja aldrei \n- Slökkva á hljóði og titringi \n\n"<b>"Stig 1"</b>" \n- Hindra truflun við birtingu á öllum skjánum \n- Kíkja aldrei \n- Slökkva á hljóði og titringi \n- Fela á lásskjá og stöðustiku \n- Sýna neðst á tilkynningalista \n\n"<b>"Stig 0"</b>" \n- Setja allar tilkynningar frá forriti á bannlista"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Tilkynningar"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"Þú færð þessar tilkynningar ekki framar"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> tilkynningaflokkar"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"Þetta forrit er ekki með tilkynningaflokka"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"Ekki er hægt að slökkva á tilkynningum frá þessu forriti"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="one">1 af <xliff:g id="NUMBER_1">%s</xliff:g> tilkynningaflokki frá þessu forriti</item>
-      <item quantity="other">1 af <xliff:g id="NUMBER_1">%s</xliff:g> tilkynningaflokkum frá þessu forriti</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> og <xliff:g id="NUMBER_5">%3$d</xliff:g> í viðbót</item>
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> og <xliff:g id="NUMBER_5">%3$d</xliff:g> í viðbót</item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"Þú munt ekki sjá þessar tilkynningar aftur"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"Sýna áfram þessar tilkynningar?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"Stöðva tilkynningar"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"Sýna áfram"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"Sýna áfram tilkynningar frá þessu forriti?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"Ekki er hægt að slökkva á þessum tilkynningum"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"Opnað fyrir tilkynningastýringar <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"Lokað fyrir tilkynningastýringar <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Leyfa tilkynningar frá þessari rás"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"Allir flokkar"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Fleiri stillingar"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"Sérstilla: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"Sérsníða"</string>
     <string name="notification_done" msgid="5279426047273930175">"Lokið"</string>
+    <string name="inline_undo" msgid="558916737624706010">"Afturkalla"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"tilkynningastýringar"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"þöggunarstillingar tilkynninga"</string>
@@ -731,8 +728,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"Stækka"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Minnka"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Loka"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"Stillingar"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Draga niður til að hunsa"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"Valmynd"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> er með mynd í mynd"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 276fa33..4fd68c2 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -35,7 +35,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"מתמשך"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"הודעות"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"עוצמת הסוללה נמוכה"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"עוצמת הסוללה נמוכה. כדאי להפעיל את מצב החיסכון בסוללה"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"נותרו <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"נותרו <xliff:g id="PERCENTAGE">%s</xliff:g>, נשארו בערך <xliff:g id="TIME">%s</xliff:g> על סמך השימוש במכשיר"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"נותרו <xliff:g id="PERCENTAGE">%s</xliff:g>, נשארו בערך <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"נותרו <xliff:g id="PERCENTAGE">%s</xliff:g>. הופעלה תכונת החיסכון בסוללה."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"‏טעינה באמצעות USB אינה נתמכת.\nהשתמש אך ורק במטען שסופק."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"‏טעינה בחיבור USB אינה נתמכת."</string>
@@ -69,14 +72,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"‏למשתמש המחובר לחשבון במכשיר הזה אין אפשרות להפעיל ניפוי באגים ב-USB. כדי להשתמש בתכונה הזו יש לעבור אל המשתמש הראשי."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"הגדל תצוגה כדי למלא את המסך"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"מתח כדי למלא את המסך"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"צילום מסך"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"שומר צילום מסך..."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"שומר צילום מסך..."</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"מתבצעת שמירה של צילום המסך."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"צילום המסך בוצע."</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"הקש כדי להציג את צילום המסך שלך."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"לא ניתן לבצע צילום מסך."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"התגלתה בעיה בשמירת צילום מסך."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"לא ניתן לשמור צילום מסך עקב שטח אחסון מוגבל."</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"מתבצעת שמירה של צילום המסך"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"צילום המסך נשמר"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"אפשר להקיש כדי להציג את צילום המסך"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"לא ניתן לבצע צילום מסך"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"התגלתה בעיה בשמירת צילום המסך"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"לא ניתן לשמור צילום מסך עקב שטח אחסון מוגבל"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"האפליקציה או הארגון שלך אינם מתירים ליצור צילומי מסך"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"‏אפשרויות העברת קבצים ב-USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"‏טען כנגן מדיה (MTP)"</string>
@@ -561,30 +565,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"כבוי"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"בעזרת פקדים של הודעות הפעלה, תוכל להגדיר רמת חשיבות מ-0 עד 5 להודעות אפליקציה. \n\n"<b>"רמה 5"</b>" \n- הצג בראש רשימת ההודעות \n- אפשר הפרעה במסך מלא \n- תמיד אפשר הצצה \n\n"<b>"רמה 4"</b>" \n- מנע הפרעה במסך מלא \n- תמיד אפשר הצצה \n\n"<b>"רמה 3"</b>" \n- מנע הפרעה במסך מלא \n- אף פעם אל תאפשר הצצה \n\n"<b>"רמה 2"</b>" \n- מנע הפרעה במסך מלא \n- אף פעם אל תאפשר הצצה \n- אף פעם אל תאפשר קול ורטט \n\n"<b>"רמה 1"</b>" \n- מנע הפרעה במסך מלא \n- אף פעם אל תאפשר הצצה \n- אף פעם אל תאפשר קול ורטט \n- הסתר ממסך הנעילה ומשורת הסטטוס \n- הצג בתחתית רשימת ההודעות \n\n"<b>"רמה 0"</b>" \n- חסום את כל ההודעות מהאפליקציה"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"הודעות"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"לא תקבל את ההודעות האלה יותר"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> קטגוריות של הודעות"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"האפליקציה הזו לא תומכת בקטגוריות של הודעות"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"לא ניתן לכבות הודעות של האפליקציה הזאת"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="two">קטגוריית הודעות אחת מתוך <xliff:g id="NUMBER_1">%s</xliff:g> מאפליקציה זו</item>
-      <item quantity="many">קטגוריית הודעות אחת מתוך <xliff:g id="NUMBER_1">%s</xliff:g> מאפליקציה זו</item>
-      <item quantity="other">קטגוריית הודעות אחת מתוך <xliff:g id="NUMBER_1">%s</xliff:g> מאפליקציה זו</item>
-      <item quantity="one">קטגוריית הודעות אחת מתוך <xliff:g id="NUMBER_0">%s</xliff:g> מאפליקציה זו</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="two"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>‏, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> ו-<xliff:g id="NUMBER_5">%3$d</xliff:g> אחרים</item>
-      <item quantity="many"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>‏, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> ו-,<xliff:g id="NUMBER_5">%3$d</xliff:g> אחרים</item>
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>‏, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> ו-<xliff:g id="NUMBER_5">%3$d</xliff:g> אחרים</item>
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_0">%1$s</xliff:g>‏, <xliff:g id="CHANNEL_NAME_2_1">%2$s</xliff:g> ו-<xliff:g id="NUMBER_2">%3$d</xliff:g> אחר</item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"לא תראה יותר את ההודעות האלה"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"להמשיך להציג את ההודעות האלה?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"הפסקת הודעות"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"להמשיך להציג"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"להמשיך להציג הודעות מהאפליקציה הזאת?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"לא ניתן לכבות את ההודעות האלה"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"פקדי ההודעות של <xliff:g id="APP_NAME">%1$s</xliff:g> נפתחו"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"פקדי ההודעות של <xliff:g id="APP_NAME">%1$s</xliff:g> נסגרו"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"התר הודעות מערוץ זה"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"כל הקטגוריות"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"הגדרות נוספות"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"התאמה אישית: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"התאמה אישית"</string>
     <string name="notification_done" msgid="5279426047273930175">"סיום"</string>
+    <string name="inline_undo" msgid="558916737624706010">"ביטול"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"בקרת הודעות"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"אפשרויות של דחיית הודעות לטיפול בהמשך"</string>
@@ -743,8 +736,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"הרחב"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"מזער"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"סגור"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"הגדרות"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"גרור למטה כדי לסגור"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"תפריט"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> במצב תמונה בתוך תמונה"</string>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index 870c896..09c978f 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -33,7 +33,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"მიმდინარე"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"შეტყობინებები"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"ბატარეა იწურება"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"ბატარეა იწურება. ჩართეთ ბატარეის დამზოგი"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"დარჩენილია <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"დარჩენილია <xliff:g id="PERCENTAGE">%s</xliff:g>, რაც დაახლოებით <xliff:g id="TIME">%s</xliff:g> არის, მოხმარების გათვალისწინებით"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"დარჩენილია <xliff:g id="PERCENTAGE">%s</xliff:g>, რაც დაახლოებით <xliff:g id="TIME">%s</xliff:g> არის"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"დარჩენილია <xliff:g id="PERCENTAGE">%s</xliff:g>. ბატარეის დამზოგი ჩართულია."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"USB-ით დატენვა არ არის მხარდაჭერილი.\nგამოიყენეთ მხოლოდ ელექტრო-დამტენი."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"USB დატენვა მხარდაჭერილი არ არის."</string>
@@ -67,14 +70,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"ამ მოწყობილობაზე ამჟამად შესულ მომხმარებელს არ შეუძლია USB ხარვეზების გამართვის ფუნქციის ჩართვა. ამ ფუნქციის გამოსაყენებლად, მიუერთდით მთავარ მომხმარებელს."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"მასშტაბი შეცვალეთ ეკრანის შესავსებად."</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"გაწიეთ ეკრანის შესავსებად."</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"ეკრანის ანაბეჭდი"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"სკრინშოტის შენახვა…"</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"ეკრანის სურათის შენახვა…"</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"ეკრანის სურათი შენახულია."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"სკრინშოტი გადაღებულია."</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"შეეხეთ ეკრანის ანაბეჭდის სანახავად."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"ვერ მოხერხდა ეკრანის ანაბეჭდის გადაღება."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"ეკრანის ანაბეჭდის შენახვისას წარმოიქმნა პრობლემა."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"ეკრანის ანაბეჭდის შენახვა ვერ მოხერხდა შეზღუდული მეხსიერების გამო."</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"ეკრანის ანაბეჭდი შენახულია"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"ეკრანის ანაბეჭდი შენახულია"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"შეეხეთ ეკრანის ანაბეჭდის სანახავად"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"ვერ მოხერხდა ეკრანის ანაბეჭდის გადაღება"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"ეკრანის ანაბეჭდის შენახვისას წარმოიქმნა პრობლემა"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"ეკრანის ანაბეჭდის შენახვა ვერ მოხერხდა შეზღუდული მეხსიერების გამო"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"ეკრანის ანაბეჭდების შექმნა არ არის ნებადართული აპის ან თქვენი ორგანიზაციის მიერ"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB ფაილის ტრანსფერის პარამეტრები"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"მედია-საკრავად (MTP) ჩართვა"</string>
@@ -557,26 +561,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"გამორთული"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"შეტყობინებების მართვის საშუალებების მეშვეობით, შეგიძლიათ განსაზღვროთ აპის შეტყობინებების მნიშვნელობის დონე 0-დან 5-მდე დიაპაზონში. \n\n"<b>"დონე 5"</b>" \n— შეტყობინებათა სიის თავში ჩვენება \n— სრულეკრანიანი რეჟიმის შეფერხების დაშვება \n— ეკრანზე ყოველთვის გამოჩენა \n\n"<b>"დონე 4"</b>" \n— სრულეკრანიანი რეჟიმის შეფერხების აღკვეთა \n— ეკრანზე ყოველთვის გამოჩენა \n\n"<b>"დონე 3"</b>" \n— სრულეკრანიანი რეჟიმის შეფერხების აღკვეთა \n— ეკრანზე გამოჩენის აღკვეთა \n\n"<b>"დონე 2"</b>" \n— სრულეკრანიანი რეჟიმის შეფერხების აღკვეთა \n— ეკრანზე გამოჩენის აღკვეთა \n— ხმისა და ვიბრაციის აღკვეთა \n\n"<b>"დონე 1"</b>" \n— სრულეკრანიანი რეჟიმის შეფერხების აღკვეთა \n— ეკრანზე გამოჩენის აღკვეთა \n— ხმისა და ვიბრაციის აღკვეთა \n— ჩაკეტილი ეკრანიდან და სტატუსის ზოლიდან დამალვა \n— შეტყობინებათა სიის ბოლოში ჩვენება \n\n"<b>"დონე 0"</b>" \n— აპის ყველა შეტყობინების დაბლოკვა"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"შეტყობინებები"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"ამ შეტყობინებებს აღარ მიიღებთ"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"შეტყობინებების <xliff:g id="NUMBER">%d</xliff:g> კატეგორია"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"ამ აპს შეტყობინებების კატეგორიები არ აქვს"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"ამ აპიდან შეტყობინებების გამორთვა ვერ მოხერხდება"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="other">ამ აპის შეტყობინებების <xliff:g id="NUMBER_1">%s</xliff:g> კატეგორიიდან 1</item>
-      <item quantity="one">ამ აპის შეტყობინებების <xliff:g id="NUMBER_0">%s</xliff:g> კატეგორიიდან 1</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> და <xliff:g id="NUMBER_5">%3$d</xliff:g> სხვა</item>
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_0">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_1">%2$s</xliff:g> და <xliff:g id="NUMBER_2">%3$d</xliff:g> სხვა</item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"ამ შეტყობინებებს აღარ დაინახავთ"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"გაგრძელდეს ამ შეტყობინებათა ჩვენება?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"შეტყობინებების შეწყვეტა"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"ჩვენების გაგრძელება"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"გაგრძელდეს შეტყობინებათა ჩვენება ამ აპიდან?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"ამ შეტყობინებათა გამორთვა ვერ მოხერხდება"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"შეტყობინებების მართვა „<xliff:g id="APP_NAME">%1$s</xliff:g>“-ისთვის გახსნილია"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"შეტყობინებების მართვა „<xliff:g id="APP_NAME">%1$s</xliff:g>“-ისთვის დახურულია"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"ამ არხიდან შეტყობინებების დაშვება"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"ყველა კატეგორია"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"დამატებითი პარამეტრები"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"მორგება: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"მორგება"</string>
     <string name="notification_done" msgid="5279426047273930175">"მზადაა"</string>
+    <string name="inline_undo" msgid="558916737624706010">"მოქმედების გაუქმება"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"შეტყობინებების მართვის საშუალებები"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"შეტყობინებების ჩაჩუმების ვარიანტები"</string>
@@ -731,8 +728,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"გაშლა"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"ჩაკეცვა"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"დახურვა"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"პარამეტრები"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"დასახურად ჩავლებით ჩამოიტანეთ ქვემოთ"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"მენიუ"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> იყენებს რეჟიმს „ეკრანი ეკრანში“"</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index c4ae759..061a926 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -33,7 +33,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Ағымдағы"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Хабарлар"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"Батарея заряды төмен"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"Батарея заряды аз. \"Battery Saver\" функциясын қосыңыз"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> қалды"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Пайдалану барысына байланысты <xliff:g id="PERCENTAGE">%s</xliff:g> заряд, шамамен <xliff:g id="TIME">%s</xliff:g> қалды"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> заряд, шамамен <xliff:g id="TIME">%s</xliff:g> қалды"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> қалды. Battery Saver қосулы."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"USB зарядтауды қолдау ұсынылмаған.\nЖабдықталған зарядтағыш құрылғысын ғана қолданыңыз."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"USB арқылы зарядтауға қолдау көрсетілмейді."</string>
@@ -67,14 +70,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Бұл құрылғыға жаңа кірген пайдаланушы USB түзетуін іске қосылмайды. Бұл мүмкіндікті пайдалану үшін негізгі пайдаланушыға ауысыңыз."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Экранды толтыру үшін ұлғайту"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Экранды толтыру үшін созу"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Скриншот"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Скриншотты сақтауда…"</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Скриншотты сақтауда…"</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"Скриншот сақталуда."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Скриншот сақталды."</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"Скриншотты көру үшін түртіңіз."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"Скриншот жасалмады."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Скриншотты сақтау кезінде мәселе туындады."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Жадтағы шектеулі бос орынға байланысты скриншотты сақтау мүмкін емес."</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"Скриншот сақталуда"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"Скриншот сақталды"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"Скриншотты көру үшін түртіңіз"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"Скриншот жасалмады"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"Скриншотты сақтау кезінде ақау болды"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Жадтағы шектеулі бос орынға байланысты скриншот сақталмайды"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Қолданба немесе ұйым скриншоттар түсіруге рұқсат етпейді"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB файлын жіберу опциялары"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Медиа ойнатқыш (MTP) ретінде қосыңыз"</string>
@@ -557,26 +561,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"Өшірулі"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Қуат хабарландыруының басқару элементтерімен қолданбаның хабарландырулары үшін 0-ден бастап 5-ке дейін маңыздылық деңгейін орнатуға болады. \n\n"<b>"5-деңгей"</b>" \n- Хабарландыру тізімінің ең басында көрсету \n- Толық экранға ашылуын рұқсат ету \n- Әрдайым қалқымалы хабарландыру түрінде көрсету \n\n"<b>"4-деңгей"</b>" \n- Толық экранға шығармау \n- Әрдайым қалқымалы хабарландыру түрінде көрсету \n\n"<b>"3-деңгей"</b>" \n- Толық экранға шығармау \n- Ешқашан қалқымалы хабарландыру түрінде көрсетпеу \n\n"<b>"2-деңгей"</b>" \n- Толық экранға шығармау \n- Ешқашан қалқымалы хабарландыру түрінде көрсетпеу \n- Ешқашан дыбыс және діріл шығармау \n\n"<b>"1-деңгей"</b>" \n- Толық экранға шығармау \n- Ешқашан қалқымалы хабарландыру түрінде көрсетпеу \n- Ешқашан дыбыс немесе діріл шығармау \n- Құлыпталған экраннан және күйін көрсету жолағынан жасыру \n- Хабарландыру тізімінің ең астында көрсету \n\n"<b>"0-деңгей"</b>" \n- Қолданбадағы барлық хабарландыруларға тыйым салу"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Хабарландырулар"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"Енді сізге бұл хабарландырулар жіберілмейді"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> хабарландыру санаттары"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"Бұл қолданбада хабарландыру санаттары жоқ"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"Бұл қолданбаның хабарландырулары өшірілмейді"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="other">Осы қолданбадан <xliff:g id="NUMBER_1">%s</xliff:g> ішінен 1 хабарландыру санаты</item>
-      <item quantity="one">Осы қолданбадан <xliff:g id="NUMBER_0">%s</xliff:g> ішінен 1 хабарландыру санаты</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> және тағы <xliff:g id="NUMBER_5">%3$d</xliff:g></item>
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_0">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_1">%2$s</xliff:g> және тағы <xliff:g id="NUMBER_2">%3$d</xliff:g></item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"Хабарландырулар бұдан былай көрсетілмейді"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"Хабарландырулар көрсетілсін бе?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"Хабарландыруларға тыйым салу"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"Көрсету"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"Осы қолданбаның хабарландырулары көрсетілсін бе?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"Хабарландыруларды өшіру мүмкін емес"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"<xliff:g id="APP_NAME">%1$s</xliff:g> хабарландыруларын басқару элементтері ашылды"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"<xliff:g id="APP_NAME">%1$s</xliff:g> хабарландыруларын басқару элементтері жабылды"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Осы арнадан келетін хабарландыруларға рұқсат беру"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"Барлық санаттар"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Қосымша параметрлер"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"Реттеу: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"Реттеу"</string>
     <string name="notification_done" msgid="5279426047273930175">"Дайын"</string>
+    <string name="inline_undo" msgid="558916737624706010">"Қайтару"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"хабарландыруларды басқару элементтері"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"хабарландыруды кідірту опциялары"</string>
@@ -731,8 +728,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"Жаю"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Кішірейту"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Жабу"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"Реттеулер"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Жабу үшін төмен қарай сүйреңіз"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"Mәзір"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> \"сурет ішіндегі сурет\" режимінде"</string>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index 12733f1..175e10c 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -33,7 +33,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"បន្ត"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"ការ​ជូន​ដំណឹង"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"ជិត​អស់​ថ្ម​ហើយ"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"កម្រិត​ថ្ម​នៅ​សល់​តិច។ សូមបើក​កម្មវិធីសន្សំថ្ម"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"នៅ​សល់ <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"នៅសល់ <xliff:g id="PERCENTAGE">%s</xliff:g> អាច​ប្រើ​បាន​ប្រហែល <xliff:g id="TIME">%s</xliff:g> ទៀត​ផ្អែកលើ​ការប្រើប្រាស់​របស់អ្នក"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"នៅសល់ <xliff:g id="PERCENTAGE">%s</xliff:g> អាច​ប្រើ​បាន​ប្រហែល <xliff:g id="TIME">%s</xliff:g> ទៀត"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"នៅ​សល់ <xliff:g id="PERCENTAGE">%s</xliff:g> ។ កម្មវិធី​សន្សំ​ថ្ម​បានបើក។"</string>
     <string name="invalid_charger" msgid="4549105996740522523">"មិន​គាំទ្រ​ការ​បញ្ចូល​តាម​យូអេសប៊ី។\nប្រើ​តែ​ឧបករណ៍​បញ្ចូល​ថ្ម​ដែល​បាន​ផ្ដល់។"</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"មិន​គាំទ្រ​ការ​បញ្ចូល​ថ្ម​តាម​យូអេសប៊ី​ទេ។"</string>
@@ -67,14 +70,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"អ្នកប្រើ​ដែលបច្ចុប្បន្ន​បានចូលគណនី​នៅលើឧបករណ៍នេះ​មិនអាចបើកការកែកំហុស USB បានទេ។ ដើម្បីប្រើមុខងារនេះ សូមប្តូរទៅអ្នកប្រើចម្បង។"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"ពង្រីក​​ដើម្បី​ឲ្យ​ពេញ​អេក្រង់"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"ទាញ​ដើម្បី​ឲ្យ​ពេញ​អេក្រង់"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"រូបថតអេក្រង់"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"កំពុង​រក្សាទុក​រូបថត​អេក្រង់…"</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"កំពុង​រក្សាទុក​រូបថត​អេក្រង់..."</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"រូបថត​អេក្រង់​កំពុង​ត្រូវ​បាន​រក្សាទុក។"</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"បាន​ចាប់​យក​រូបថត​អេក្រង់។​"</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"ប៉ះដើម្បីមើលរូបថតអេក្រង់របស់អ្នក"</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"មិន​អាច​ចាប់​យក​រូប​ថត​អេក្រង់​។"</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"បានជួបប្រទះបញ្ហាខណៈពេលរក្សាទុកការថតអេក្រង់"</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"មិនអាចរក្សាទុករូបថតអេក្រង់បានទេដោយសារទំហំផ្ទុកមានកម្រិត។"</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"​កំពុង​​រក្សាទុករូបថត​អេក្រង់"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"បានរក្សាទុក​រូបថតអេក្រង់"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"ចុច​ដើម្បីមើល​រូបថតអេក្រង់​របស់អ្នក"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"មិន​អាច​​ថត​រូប​អេក្រង់​​បាន​ទេ"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"បានជួប​បញ្ហា​ពេល​កំពុង​​រក្សាទុក​រូបថតអេក្រង់"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"មិនអាច​រក្សាទុក​រូបថតអេក្រង់​បានទេ ​ដោយសារ​ទំហំផ្ទុក​មានកម្រិតទាប"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"ការថត​រូបអេក្រង់​មិនត្រូវ​បាន​អនុញ្ញាត​ដោយ​កម្មវិធី​នេះ ឬ​ស្ថាប័ន​របស់អ្នក"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"ជម្រើស​ផ្ទេរ​ឯកសារ​តាម​យូអេសប៊ី"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"ភ្ជាប់​ជា​កម្មវិធី​ចាក់​មេឌៀ (MTP)"</string>
@@ -557,26 +561,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"បិទ"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"ជាមួយអង្គគ្រប់គ្រងការជូនដំណឹងថាមពល អ្នកអាចកំណត់កម្រិតសំខាន់ពី 0 ទៅ 5 សម្រាប់ការជូនដំណឹងរបស់កម្មវិធី។ \n\n"<b>"កម្រិត 5"</b>" \n- បង្ហាញនៅផ្នែកខាងលើបញ្ជីជូនដំណឹង \n- អនុញ្ញាតការរំខានលើអេក្រង់ពេញ \n- លោតឡើងជានិច្ច \n\n"<b>"កម្រិត 4"</b>" \n- រារាំងការរំខានលើអេក្រង់ពេញ \n- លោតឡើងជានិច្ច \n\n"<b>"កម្រិត 3"</b>" \n- រារាំងការរំខានលើអេក្រង់ពេញ \n- លោតឡើងជានិច្ច \n\n"<b>"កម្រិត 2"</b>" \n- រារាំងការរំខានលើអេក្រង់ពេញ \n- លោតឡើងជានិច្ច \n- មិនបន្លឺសំឡេង ឬញ័រ \n\n"<b>"កម្រិត 1"</b>" \n- រារាំងការរំខានលើអេក្រង់ពេញ \n- លោតឡើងជានិច្ច \n- មិនបន្លឺសំឡេង ឬញ័រ \n- លាក់ពីអេក្រង់ចាក់សោ និងរបារស្ថានភាព \n- បង្ហាញនៅផ្នែកខាងក្រោមបញ្ជីជូនដំណឹង \n\n"<b>"កម្រិត 0"</b>" \n- រារាំងការជូនដំណឹងទាំងអស់ពីកម្មវិធី"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"ការ​ជូនដំណឹង"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"អ្នក​នឹង​មិន​ទទួល​បានការ​ជូនដំណឹង​ទាំងនេះ​ទៀត​ទេ"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"ប្រភេទនៃការជូនដំណឹងចំនួន <xliff:g id="NUMBER">%d</xliff:g>"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"កម្មវិធីនេះ​មិនមាន​ប្រភេទនៃ​ការជូនដំណឹង​ទេ"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"ការជូនដំណឹងពី​កម្មវិធីនេះមិនអាចបិទបានទេ"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="other">ប្រភេទនៃការ​ជូនដំណឹង 1 ក្នុង​ចំណោម <xliff:g id="NUMBER_1">%s</xliff:g> ដែលបានពី​កម្មវិធី​នេះ</item>
-      <item quantity="one">ប្រភេទនៃការ​ជូនដំណឹង 1 ក្នុង​ចំណោម <xliff:g id="NUMBER_0">%s</xliff:g> ដែលបានពី​កម្មវិធី​នេះ</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g>, និង <xliff:g id="NUMBER_5">%3$d</xliff:g> ផ្សេងទៀត</item>
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_0">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_1">%2$s</xliff:g>, និង <xliff:g id="NUMBER_2">%3$d</xliff:g> ផ្សេងទៀត</item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"អ្នក​នឹង​មិនឃើញ​ការជូនដំណឹង​ទាំងនេះ​ទៀតទេ"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"បន្ត​បង្ហាញ​ការជូនដំណឹង​ទាំងនេះ?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"បញ្ឈប់​ការជូនដំណឹង"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"បន្ត​បង្ហាញ"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"បន្ត​បង្ហាញ​ការជូនដំណឹង​សម្រាប់​កម្មវិធីនេះ?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"​មិនអាច​បិទការជូនដំណឹង​ទាំងនេះបានទេ"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"ការគ្រប់គ្រងការជូនដំណឹងសម្រាប់ <xliff:g id="APP_NAME">%1$s</xliff:g> បានបើក"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"ការគ្រប់គ្រងការជូនដំណឹងសម្រាប់ <xliff:g id="APP_NAME">%1$s</xliff:g> បានបិទ"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"អនុញ្ញាតឲ្យមានការជូនដំណឹងពីប៉ុស្តិ៍នេះ"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"ប្រភេទ​ទាំងអស់"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"ការកំណត់ច្រើនទៀត"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"ប្ដូរ​តាម​បំណង៖ <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"ប្ដូរតាមបំណង"</string>
     <string name="notification_done" msgid="5279426047273930175">"រួចរាល់"</string>
+    <string name="inline_undo" msgid="558916737624706010">"ត្រឡប់វិញ"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"ការគ្រប់គ្រង​ការជូន​ដំណឹង"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"ជម្រើស​ផ្អាកការ​ជូនដំណឹង"</string>
@@ -731,8 +728,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"ពង្រីក"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"បង្រួម"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"បិទ"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"ការកំណត់"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"អូស​ចុះក្រោម​ដើម្បី​បដិសេធ"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"ម៉ឺនុយ"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> ស្ថិតក្នុងមុខងាររូបក្នុងរូប"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 7fa87ed..285c569 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -33,7 +33,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"진행 중"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"알림"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"배터리 부족"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"배터리가 부족합니다. 배터리 세이버를 사용 설정하세요"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> 남았습니다."</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> 남음, 내 사용량을 기준으로 약 <xliff:g id="TIME">%s</xliff:g> 남음"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> 남음, 약 <xliff:g id="TIME">%s</xliff:g> 남음"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> 남았습니다. 배터리 세이버를 사용 중입니다."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"USB 충전이 지원되지 않습니다.\n제공된 충전기만 사용하세요."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"USB 충전은 지원되지 않습니다."</string>
@@ -67,14 +70,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"현재 이 기기에 로그인한 사용자는 USB 디버깅을 사용 설정할 수 없습니다. 이 기능을 사용하려면 기본 사용자로 전환하세요."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"전체화면 모드로 확대"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"전체화면 모드로 확대"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"스크린샷"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"캡쳐화면 저장 중..."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"캡쳐화면 저장 중..."</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"캡쳐화면을 저장하는 중입니다."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"캡쳐화면 저장됨"</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"스크린샷을 확인하려면 탭하세요."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"캡쳐화면을 캡쳐하지 못했습니다."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"스크린샷을 저장하는 중 문제가 발생했습니다."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"저장용량이 부족하여 스크린샷을 저장할 수 없습니다."</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"스크린샷을 저장하는 중입니다"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"스크린샷 저장됨"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"스크린샷을 확인하려면 탭하세요"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"스크린샷을 캡쳐하지 못함"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"스크린샷을 저장하는 중 문제가 발생했습니다"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"저장용량이 부족하여 스크린샷을 저장할 수 없습니다"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"앱이나 조직에서 스크린샷 촬영을 허용하지 않습니다."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB 파일 전송 옵션"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"미디어 플레이어로 마운트(MTP)"</string>
@@ -559,26 +563,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"사용 안함"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"전원 알림 컨트롤을 사용하면 앱 알림 관련 중요도를 0부터 5까지로 설정할 수 있습니다. \n\n"<b>"레벨 5"</b>" \n- 알림 목록 상단에 표시 \n- 전체 화면일 경우 알림 표시 허용 \n- 항상 엿보기 표시 \n\n"<b>"레벨 4"</b>" \n- 전체 화면에 알림 표시 금지 \n- 항상 엿보기 표시 \n\n"<b>"레벨 3"</b>" \n- 전체 화면에 알림 표시 금지 \n- 엿보기 표시 안함 \n\n"<b>"레벨 2"</b>" \n- 전체 화면에 알림 표시 금지 \n- 엿보기 표시 안함 \n- 소리나 진동으로 알리지 않음 \n\n"<b>"레벨 1"</b>" \n- 전체 화면에 알림 표시 금지 \n- 엿보기 표시 안함 \n- 소리나 진동으로 알리지 않음 \n- 잠금 화면 및 상태 표시줄에서 숨김 \n- 알림 목록 하단에 표시 \n\n"<b>"레벨 0"</b>" \n- 앱의 모든 알림 차단"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"알림"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"더 이상 다음의 알림을 받지 않습니다."</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"알림 카테고리 <xliff:g id="NUMBER">%d</xliff:g>개"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"이 앱에는 알림 카테고리가 없습니다."</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"이 앱의 알림을 사용 중지할 수 없습니다."</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="other">이 앱에서 <xliff:g id="NUMBER_1">%s</xliff:g>개의 알림 카테고리 중 1개가 정의됨</item>
-      <item quantity="one">이 앱에서 <xliff:g id="NUMBER_0">%s</xliff:g>개의 알림 카테고리 중 1개가 정의됨</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> 외 <xliff:g id="NUMBER_5">%3$d</xliff:g>개</item>
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_0">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_1">%2$s</xliff:g> 외 <xliff:g id="NUMBER_2">%3$d</xliff:g>개</item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"더 이상 다음의 알림을 받지 않습니다"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"이 알림을 계속 표시하시겠습니까?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"알림 중지"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"계속 표시하기"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"이 앱의 알림을 계속 표시하시겠습니까?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"이 알림은 끌 수 없습니다"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"<xliff:g id="APP_NAME">%1$s</xliff:g> 알림 컨트롤을 열었습니다."</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"<xliff:g id="APP_NAME">%1$s</xliff:g> 알림 컨트롤을 닫았습니다."</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"이 채널의 알림을 허용합니다."</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"전체 카테고리"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"설정 더보기"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"맞춤설정: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"맞춤설정"</string>
     <string name="notification_done" msgid="5279426047273930175">"완료"</string>
+    <string name="inline_undo" msgid="558916737624706010">"실행취소"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"알림 관리"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"알림 일시 중지 옵션"</string>
@@ -733,8 +730,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"펼치기"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"최소화"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"닫기"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"설정"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"아래로 드래그하여 닫기"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"메뉴"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g>에서 PIP 사용 중"</string>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index e3f1fa3..0687c2d 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -33,7 +33,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Учурдагы"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Эскертмелер"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"Батареянын кубаты аз"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"Батарея аз калды. Батареяны үнөмдөгүчтү күйгүзүңүз"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> калды"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> калды, колдонушуңузга караганда болжол менен дагы <xliff:g id="TIME">%s</xliff:g> бар"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> калды, болжол менен дагы <xliff:g id="TIME">%s</xliff:g> бар"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> калды. Батареяны үнөмдөгүч режими күйүк."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"USB менен кубаттоо колдоого алынбайт.\nБерилген заряддагычты гана колдонуңуз."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"USB аркылуу кубаттоого болбойт."</string>
@@ -67,14 +70,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Учурда бул түзмөккө каттоо эсеби менен кирген колдонуучу USB мүчүлүштүктөрүн оңдоо функциясын күйгүзө албай жатат. Бул функцияны колдонуу үчүн негизги колдонуучунун каттоо эсебине которулуңуз."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Экрнд тлтр ү. чен өлч өзг"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Экранды толтуруу ү-н чоюу"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Скриншот"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Скриншот сакталууда…"</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Скриншот сакталууда..."</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"Скриншот сакталууда."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Скриншот тартылды."</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"Скриншотуңузду көрүү үчүн таптап коюңуз."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"Скриншот кылынбай жатат."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Скриншотту сактоо учурунда көйгөй пайда болду."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Сактагычта бош орун аз болгондуктан скриншот сакталбай жатат."</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"Скриншот сакталууда"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"Скриншот сакталды"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"Скриншотуңузду көрүү үчүн таптап коюңуз"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"Скриншот тартылбай жатат"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"Скриншотту сактоо учурунда көйгөй пайда болду"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Сактагычта бош орун аз болгондуктан скриншот сакталбай жатат"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Скриншот тартууга колдонмо же ишканаңыз тыюу салган."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB менен файл өткөрүү мүмкүнчүлүктөрү"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Медиа ойноткуч катары кошуу (MTP)"</string>
@@ -557,26 +561,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"Өчүк"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Бул функциянын жардамы менен ар бир колдонмо үчүн эскертменин маанилүүлүк деңгээлин 0дон 5ке чейин койсоңуз болот. \n\n"<b>"5-деңгээл"</b>" \n- Эскертмелер тизмесинин башында көрсөтүлсүн \n- Эскертмелер толук экранда көрсөтүлсүн \n- Калкып чыгуучу эскертмелерге уруксат берилсин \n\n"<b>"4-деңгээл"</b>" \n- Эскертмелер толук экранда көрсөтүлбөсүн \n- Калкып чыгуучу эскертмелерге уруксат берилсин \n\n"<b>"3-деңгээл"</b>" \n- Эскертмелер толук экранда көрсөтүлбөсүн \n- Калкып чыгуучу эскертмелерге тыюу салынсын \n\n"<b>"2-деңгээл"</b>" \n- Эскертмелер толук экранда көрсөтүлбөсүн \n- Калкып чыгуучу эскертмелерге тыюу салынсын \n- Эч качан добуш чыгып же дирилдебесин \n\n"<b>"1-деңгээл"</b>" \n- Эскертмелер толук экранда көрсөтүлбөсүн \n- Калкып чыгуучу эскертмелерге тыюу салынсын \n- Эч качан добуш чыгып же дирилдебесин \n- Кулпуланган экрандан жана абал тилкесинен жашырылсын \n- Эскертмелер тизмесинин аягында көрсөтүлсүн \n\n"<b>"0-деңгээл"</b>" \n- Колдонмодон алынган бардык эскертмелер бөгөттөлсүн"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Эскертмелер"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"Мындан ары бул эскертмелер сизге жөнөтүлбөйт"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"Эскертмелердин <xliff:g id="NUMBER">%d</xliff:g> категориясы"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"Бул колдонмонун эскертме категориялары жок"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"Бул колдонмонун эскертмелерин өчүрүүгө болбойт"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="other">Бул колдонмодогу <xliff:g id="NUMBER_1">%s</xliff:g> эскертме категориянын ичинен 1 категория</item>
-      <item quantity="one">Бул колдонмодогу <xliff:g id="NUMBER_0">%s</xliff:g> эскертме категориянын ичинен 1 категория</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> жана дагы <xliff:g id="NUMBER_5">%3$d</xliff:g></item>
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_0">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_1">%2$s</xliff:g> жана дагы <xliff:g id="NUMBER_2">%3$d</xliff:g></item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"Мындан ары бул эскертмелер сизге көрсөтүлбөйт"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"Бул эскертмелер көрсөтүлө берсинби?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"Эскертмелерди токтотуу"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"Көрсөтүлө берсин"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"Бул колдонмонун эскертмелери көрсөтүлө берсинби?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"Бул эскертмелерди өчүрүүгө болбойт"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосу үчүн эскертмени көзөмөлдөө функциялары ачылды"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосу үчүн эскертмени көзөмөлдөө функциялары жабылды"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Бул каналдан келген эскертмелерге уруксат берүү"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"Бардык категориялар"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Дагы жөндөөлөр"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"Ыңгайлаштыруу: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"Ыңгайлаштыруу"</string>
     <string name="notification_done" msgid="5279426047273930175">"Бүттү"</string>
+    <string name="inline_undo" msgid="558916737624706010">"Кайтаруу"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"эскертмелерди башкаруу каражаттары"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"эскертмени тындыруу опциялары"</string>
@@ -731,8 +728,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"Жайып көрсөтүү"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Кичирейтүү"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Жабуу"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"Жөндөөлөр"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Четке кагуу үчүн төмөн сүйрөңүз"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"Меню"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> – сүрөт ичиндеги сүрөт"</string>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index fe262ee..587686f 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -33,7 +33,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"ດຳເນີນຢູ່"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"ການແຈ້ງເຕືອນ"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"ແບັດເຕີຣີ​ເຫຼືອ​ໜ້ອຍ"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"ແບັດເຕີຣີເຫຼືອໜ້ອຍ. ກະລຸນາເປີດໃຊ້ຕົວປະຢັດແບັດເຕີຣີ"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"ຍັງ​ເຫຼືອ <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"ຍັງເຫຼືອ <xliff:g id="PERCENTAGE">%s</xliff:g>, ປະມານ <xliff:g id="TIME">%s</xliff:g> ໂດຍອ້າງອີງຈາກການນຳໃຊ້ຂອງທ່ານ"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"ຍັງເຫຼືອ <xliff:g id="PERCENTAGE">%s</xliff:g>, ປະມານ <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"ຍັງເຫຼືອ <xliff:g id="PERCENTAGE">%s</xliff:g>. ເປີດໃຊ້ຕົວປະຢັດແບັດເຕີຣີແລ້ວ."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"ບໍ່ຮອງຮັບການສາກໄຟດ້ວຍ USB.\nຕ້ອງໃຊ້ສະເພາະເຄື່ອງສາກທີ່ແຖມມານຳເທົ່ານັ້ນ."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"ບໍ່​ຮອງຮັບ​ການ​ສາກ​ຜ່ານ USB."</string>
@@ -67,14 +70,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"ຜູ້ໃຊ້ທີ່ກຳລັງເຂົ້າສູ່ລະບົບອຸປະກອນຢູ່ໃນຕອນນີ້ບໍ່ສາມາດເປີດໃຊ້ການດີບັກ USB ໄດ້. ເພື່ອໃຊ້ຄຸນສົມບັດນີ້, ໃຫ້ສະຫຼັບໄປໃຊ້ຜູ້ໃຊ້ຫຼັກ."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"ຊູມໃຫ້ເຕັມໜ້າຈໍ"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"ປັບໃຫ້ເຕັມໜ້າຈໍ"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"ພາບໜ້າຈໍ"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"ກຳລັງບັນທຶກຮູບໜ້າຈໍ"</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"ກຳລັງບັນທຶກພາບໜ້າຈໍ..."</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"ກຳລັງບັນທຶກພາບໜ້າຈໍ."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"ຖ່າຍຮູບໜ້າຈໍແລ້ວ"</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"ແຕະເພື່ອເບິ່ງພາບຖ່າຍໜ້າຈໍຂອງທ່ານ."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"ບໍ່ສາມາດຖ່າຍຮູບໜ້າຈໍໄດ້"</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"ເກີດບັນຫາໃນການບັນທຶກພາບໜ້າຈໍຂອງທ່ານ."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"ບໍ່ສາມາດຖ່າຍຮູບໜ້າຈໍໄດ້ເນື່ອງຈາກພື້ນທີ່ຈັດເກັບຂໍ້ມູນມີຈຳກັດ."</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"ກຳລັງບັນທຶກພາບໜ້າຈໍ"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"ບັນທຶກຮູບໜ້າຈໍໄວ້ແລ້ວ"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"ແຕະເພື່ອເບິ່ງພາບຖ່າຍໜ້າຈໍຂອງທ່ານ"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"ບໍ່ສາມາດຖ່າຍຮູບໜ້າຈໍໄດ້"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"ເກີດບັນຫາໃນການບັນທຶກພາບໜ້າຈໍຂອງທ່ານ"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"ບໍ່ສາມາດຖ່າຍຮູບໜ້າຈໍໄດ້ເນື່ອງຈາກພື້ນທີ່ຈັດເກັບຂໍ້ມູນມີຈຳກັດ"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"ແອັບ ຫຼື ອົງກອນຂອງທ່ານບໍ່ອະນຸຍາດໃຫ້ຖ່າຍຮູບໜ້າຈໍ"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB ໂຕເລືອກການຍ້າຍໄຟລ໌"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"ເຊື່ອມຕໍ່ເປັນ media player (MTP)"</string>
@@ -557,26 +561,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"ປິດ"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"ດ້ວຍການຄວບຄຸມການແຈ້ງເຕືອນ, ທ່ານສາມາດຕັ້ງລະດັບຄວາມສຳຄັນຈາກ 0 ຮອດ 5 ໃຫ້ກັບການແຈ້ງເຕືອນແອັບໃດໜຶ່ງໄດ້. \n\n"<b>"ລະດັບ 5"</b>" \n- ສະແດງຢູ່ເທິງສຸດຂອງລາຍການແຈ້ງເຕືອນ \n- ອະນຸຍາດໃຫ້ຂັດຈັງຫວະຕອນເປີດເຕັມຈໍ \n- ແນມເບິ່ງທຸກເທື່ອ \n\n"<b>"ລະດັບ 4"</b>" \n- ກັນບໍ່ໃຫ້ຂັດຈັງຫວະຕອນເປີດເຕັມຈໍ \n- ແນມເບິ່ງທຸກເທື່ອ \n\n"<b>"ລະດັບ 3"</b>" \n- ກັນບໍ່ໃຫ້ຂັດຈັງຫວະຕອນເປີດເຕັມຈໍ \n- ບໍ່ແນມເບິ່ງ \n\n"<b>"ລະດັບ 2"</b>" \n- ກັນບໍ່ໃຫ້ຂັດຈັງຫວະຕອນເປີດເຕັມຈໍ \n- ບໍ່ແນມເບິ່ງ \n- ບໍ່ມີສຽງ ແລະ ບໍ່ມີການສັ່ນເຕືອນ \n\n"<b>"ລະດັບ 1"</b>" \n- ກັນບໍ່ໃຫ້ຂັດຈັງຫວະຕອນເປີດເຕັມຈໍ \n- ບໍ່ແນມເບິ່ງ \n- ບໍ່ມີສຽງ ແລະ ບໍ່ມີການສັ່ນເຕືອນ \n- ເຊື່ອງຈາກໜ້າຈໍລັອກ ແລະ ແຖບສະຖານະ \n- ສະແດງຢູ່ລຸ່ມສຸດຂອງລາຍການແຈ້ງເຕືອນ \n\n"<b>"ລະດັບ 0"</b>" \n- ປິດກັ້ນການແຈ້ງເຕືອນທັງໝົດຈາກແອັບ"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"ການແຈ້ງເຕືອນ"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"ທ່ານຈະບໍ່ໄດ້ຮັບການແຈ້ງເຕືອນເຫຼົ່ານີ້ອີກຕໍ່ໄປ"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> ໝວດໝູ່ການແຈ້ງເຕືອນ"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"ແອັບນີ້ບໍ່ມີໝວດໝູ່ການແຈ້ງເຕືອນ"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"ການແຈ້ງເຕືອນຈາກແອັບນີ້ບໍ່ສາມາດປິດໄວ້ໄດ້"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="other">1 ຈາກທັງໝົດ <xliff:g id="NUMBER_1">%s</xliff:g> ໝວດໝູ່ການແຈ້ງເຕືອນຈາກແອັບນີ້</item>
-      <item quantity="one">1 ຈາກທັງໝົດ <xliff:g id="NUMBER_0">%s</xliff:g> ໝວດໝູ່ການແຈ້ງເຕືອນຈາກແອັບນີ້</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> ແລະ ອີກ <xliff:g id="NUMBER_5">%3$d</xliff:g> ຊ່ອງອື່ນໆ</item>
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_0">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_1">%2$s</xliff:g> ແລະ ອີກ <xliff:g id="NUMBER_2">%3$d</xliff:g> ຊ່ອງອື່ນໆ</item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"ທ່ານຈະບໍ່ໄດ້ຮັບການແຈ້ງເຕືອນເຫຼົ່ານີ້ອີກຕໍ່ໄປ"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"ສະແດງການແຈ້ງເຕືອນເຫຼົ່ານີ້ຕໍ່ໄປບໍ?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"ຢຸດການແຈ້ງເຕືອນ"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"ສະແດງຕໍ່ໄປ"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"ສະແດງການແຈ້ງເຕືອນຈາກແອັບນີ້ຕໍ່ໄປບໍ?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"ບໍ່ສາມາດປິດການແຈ້ງເຕືອນເຫຼົ່ານີ້ໄດ້"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"ເປີດຕົວຄວບຄຸມການແຈ້ງເຕືອນສຳລັບ <xliff:g id="APP_NAME">%1$s</xliff:g> ແລ້ວ"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"ປິດຕົວຄວບຄຸມການແຈ້ງເຕືອນສຳລັບ <xliff:g id="APP_NAME">%1$s</xliff:g> ແລ້ວ"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"ອະນຸຍາດການແຈ້ງເຕືອນຈາກຊ່ອງນີ້"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"ທຸກໝວດໝູ່"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"​ການ​ຕັ້ງ​ຄ່າ​ເພີ່ມ​ເຕີມ"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"ປັບແຕ່ງ: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"ປັບແຕ່ງ"</string>
     <string name="notification_done" msgid="5279426047273930175">"ສຳເລັດແລ້ວ"</string>
+    <string name="inline_undo" msgid="558916737624706010">"ຍົກເລີກ"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"ການຄວບຄຸມການແຈ້ງເຕືອນ"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"ຕົວເລືອກການເລື່ອນການແຈ້ງເຕືອນ"</string>
@@ -731,8 +728,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"ຂະຫຍາຍ"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"ຫຍໍ້"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"ປິດ"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"ການຕັ້ງຄ່າ"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"ລາກລົງເພື່ອປິດໄວ້"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"ເມນູ"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> ແມ່ນເປັນການສະແດງຜົນຫຼາຍຢ່າງພ້ອມກັນ"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 574d898..a02a20b 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -34,7 +34,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Notiekošs"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Paziņojumi"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"Zems akumulatora enerģijas līmenis"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"Akumulatora uzlādes līmenis ir zems. Ieslēdziet akumulatora jaudas taupīšanas režīmu."</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"Atlikuši <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Atlikušais laiks: <xliff:g id="PERCENTAGE">%s</xliff:g> — aptuveni <xliff:g id="TIME">%s</xliff:g> (ņemot vērā lietojumu)"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Atlikušais laiks: <xliff:g id="PERCENTAGE">%s</xliff:g> — aptuveni <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Atlikuši <xliff:g id="PERCENTAGE">%s</xliff:g>. Ir ieslēgts akumulatora jaudas taupīšanas režīms."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"USB lādēšana netiek atbalstīta.\nIzmantojiet tikai komplektā iekļauto lādētāju."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"USB uzlāde netiek atbalstīta."</string>
@@ -68,14 +71,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Lietotājs, kurš pašlaik ir pierakstījies šajā ierīcē, nevar iespējot USB atkļūdošanu. Lai izmantotu šo funkciju, pārslēdzieties uz galveno lietotāju."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Tālumm., lai aizp. ekr."</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Stiepiet, lai aizp. ekr."</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Ekrānuzņēmums"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Saglabā ekrānuzņēmumu…"</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Notiek ekrānuzņēmuma saglabāšana..."</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"Notiek ekrānuzņēmuma saglabāšana."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Ekrānuzņēmums ir uzņemts."</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"Pieskarieties, lai skatītu ekrānuzņēmumu."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"Nevarēja uzņemt ekrānuzņēmumu."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Saglabājot ekrānuzņēmumu, radās problēma."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Nevar saglabāt ekrānuzņēmumu, jo krātuvē nepietiek vietas."</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"Notiek ekrānuzņēmuma saglabāšana."</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"Ekrānuzņēmums saglabāts"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"Pieskarieties, lai skatītu ekrānuzņēmumu."</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"Nevarēja uzņemt ekrānuzņēmumu"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"Saglabājot ekrānuzņēmumu, radās problēma."</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Nevar saglabāt ekrānuzņēmumu, jo krātuvē nepietiek vietas."</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Lietotne vai jūsu organizācija neatļauj veikt ekrānuzņēmumus."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB failu pārsūtīšanas opcijas"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Pievienot kā multivides atskaņotāju (MTP)"</string>
@@ -559,28 +563,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"Izslēgts"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Izmantojot barošanas paziņojumu vadīklas, varat lietotnes paziņojumiem iestatīt svarīguma līmeni (no 0 līdz 5). \n\n"<b>"5. līmenis"</b>" \n- Tiek rādīts paziņojumu saraksta augšdaļā \n- Tiek atļauta pilnekrāna režīma pārtraukšana \n- Ieskats vienmēr atļauts \n\n"<b>"4. līmenis"</b>" \n- Tiek novērsta pilnekrāna režīma pārtraukšana \n- Ieskats vienmēr atļauts \n\n"<b>"3. līmenis"</b>" \n- Tiek novērsta pilnekrāna režīma pārtraukšana \n- Ieskats nav atļauts \n\n"<b>"2. līmenis"</b>" \n- Tiek novērsta pilnekrāna režīma pārtraukšana \n- Ieskats nav atļauts \n- Nav atļautas skaņas un vibrosignāls \n\n"<b>"1. līmenis"</b>" \n- Tiek novērsta pilnekrāna režīma pārtraukšana \n- Ieskats nav atļauts \n- Nav atļautas skaņas un vibrosignāls \n- Paziņojumi tiek paslēpti bloķēšanas ekrānā un statusa joslā \n- Paziņojumi tiek rādīti paziņojumu saraksta apakšdaļā \n\n"<b>"0. līmenis"</b>" \n- Visi lietotnes paziņojumi tiek bloķēti"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Paziņojumi"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"Jūs vairs nesaņemsiet šos paziņojumus"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> paziņojumu kategorijas"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"Paziņojumu kategorijas šajā lietotnē nav pieejamas."</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"Paziņojumus no šīs lietotnes nevar izslēgt"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="zero">1 no <xliff:g id="NUMBER_1">%s</xliff:g> šīs lietotnes paziņojumu kategorijām.</item>
-      <item quantity="one">1 no <xliff:g id="NUMBER_1">%s</xliff:g> šīs lietotnes paziņojumu kategorijas.</item>
-      <item quantity="other">1 no <xliff:g id="NUMBER_1">%s</xliff:g> šīs lietotnes paziņojumu kategorijām.</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="zero"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> un vēl <xliff:g id="NUMBER_5">%3$d</xliff:g></item>
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> un vēl <xliff:g id="NUMBER_5">%3$d</xliff:g></item>
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> un vēl <xliff:g id="NUMBER_5">%3$d</xliff:g></item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"Jūs vairs neredzēsiet šos paziņojumus."</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"Vai turpināt rādīt šos paziņojumus?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"Apturēt paziņojumu rādīšanu"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"Turpināt rādīt"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"Vai turpināt rādīt paziņojumus no šīs lietotnes?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"Šos paziņojumus nevar izslēgt."</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"Lietotnes <xliff:g id="APP_NAME">%1$s</xliff:g> paziņojumu vadīklas ir atvērtas"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"Lietotnes <xliff:g id="APP_NAME">%1$s</xliff:g> paziņojumu vadīklas ir aizvērtas"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Atļaut paziņojumus no šī kanāla"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"Visas kategorijas"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Citi iestatījumi"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"Pielāgot: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"Pielāgot"</string>
     <string name="notification_done" msgid="5279426047273930175">"Gatavs"</string>
+    <string name="inline_undo" msgid="558916737624706010">"Atsaukt"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"paziņojumu vadīklas"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"paziņojumu atlikšanas opcijas"</string>
@@ -737,8 +732,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"Izvērst"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimizēt"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Aizvērt"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"Iestatījumi"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Velciet lejup, lai noraidītu"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"Izvēlne"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> ir attēlā attēlā"</string>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index b64217d..886e083 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -33,7 +33,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Во тек"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Известувања"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"Батеријата е слаба"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"Батеријата е слаба. Вклучете го штедачот на батерија"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"Преостануваат <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Преостануваат <xliff:g id="PERCENTAGE">%s</xliff:g>, уште околу <xliff:g id="TIME">%s</xliff:g> според користењето"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Преостануваат <xliff:g id="PERCENTAGE">%s</xliff:g>, уште околу <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Преостануваат <xliff:g id="PERCENTAGE">%s</xliff:g>. Штедачот на батерија е вклучен."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"Полначот на USB меморијата не е поддржан.\nКористете го само полначот доставен со уредот."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"Полнењето преку USB не е поддржано."</string>
@@ -67,14 +70,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Корисникот што моментално е најавен на уредов не може да вклучи отстранување грешки на USB. За да ја користите функцијава, префрлете се на примарниот корисник."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Зумирај да се исполни екранот"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Растегни да се исполни екранот"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Слика од екранот"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Сликата на екранот се зачувува..."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Сликата на екранот се зачувува..."</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"Сликата на екранот се зачувува."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Сликата на екранот е снимена."</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"Допрете за да ја видите сликата на екранот."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"Сликата на екранот не можеше да се сними."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Се појави проблем при зачувување на сликата од екранот."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Сликата од екранот не може да се зачува поради ограничена меморија."</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"Сликата од екранот се зачувува"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"Сликата од екранот е зачувана"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"Допрете за да ја видите сликата од екранот"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"Сликата од екранот не можеше да се сними"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"Проблем при зачувувањето слика од екранот"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Сликата од екранот не може да се зачува поради ограничена меморија"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Апликацијата или вашата организација не дозволува снимање слики од екранот"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Пренос на датотека со USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Монтирај како мултимедијален плеер (MTP)"</string>
@@ -557,26 +561,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"Исклучено"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Со контролите за известувањата за напојување, може да поставите ниво на важност од 0 до 5 за известувањата на која било апликација. \n\n"<b>"Ниво 5"</b>" \n- Прикажувај на врвот на списокот со известувања \n- Дозволи прекин во цел екран \n- Секогаш користи појавување \n\n"<b>"Ниво 4"</b>" \n- Спречи прекин во цел екран \n- Секогаш користи појавување \n\n"<b>"Ниво 3"</b>" \n- Спречи прекин во цел екран \n- Без појавување \n\n"<b>"Ниво 2"</b>" \n- Спречи прекин во цел екран \n- Без појавување \n- Без звук и вибрации \n\n"<b>"Ниво 1"</b>" \n- Спречи прекин во цел екран \n- Без појавување \n- Без звук и вибрации \n- Сокриј од заклучен екран и статусна лента \n- Прикажувај на дното на списокот со известувања \n\n"<b>"Ниво 0"</b>" \n- Блокирај ги сите известувања од апликацијата"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Известувања"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"Веќе нема да ги добивате овие известувања"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> категории известувања"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"Апликацијава нема катерии известувања"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"Известувањата од апликацијава не може да се исклучат"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="one">1 од <xliff:g id="NUMBER_1">%s</xliff:g> категорија известувања од апликацијава</item>
-      <item quantity="other">1 од <xliff:g id="NUMBER_1">%s</xliff:g> категории известувања од апликацијава</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> и уште <xliff:g id="NUMBER_5">%3$d</xliff:g></item>
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> и уште <xliff:g id="NUMBER_5">%3$d</xliff:g></item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"Веќе нема да ги гледате овие известувања"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"Дали да продолжат да се прикажуваат известувањава?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"Запри ги известувањата"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"Продолжи да ги прикажуваш"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"Дали да продолжат да се прикажуваат известувања од апликацијава?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"Известувањава не може да се исклучат"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"Контролите за известувањата за <xliff:g id="APP_NAME">%1$s</xliff:g> се отворија"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"Контролите за известувањата за <xliff:g id="APP_NAME">%1$s</xliff:g> се затворија"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Дозволете известувања од овој канал"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"Сите категории"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Повеќе поставки"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"Приспособи: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"Приспособете"</string>
     <string name="notification_done" msgid="5279426047273930175">"Готово"</string>
+    <string name="inline_undo" msgid="558916737624706010">"Врати"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"контроли за известувањето"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"опции за одложување на известувањето"</string>
@@ -731,8 +728,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"Проширете"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Минимизирај"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Затвори"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"Поставки"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Повлечете надолу за да отфрлите"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"Мени"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> е во слика во слика"</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index 42bd38b..c8aba01 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -31,7 +31,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Гарсан"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Мэдэгдэл"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"Батерей дуусаж байна"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"Батерей бага байна. Тэжээл хэмнэгчийг асаана уу"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> үлдсэн"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> үлдсэн байна. Таны хэрэглээнд тулгуурлан ойролцоогоор <xliff:g id="TIME">%s</xliff:g>-н хугацаа үлдсэн"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> үлдсэн байна. Ойролцоогоор <xliff:g id="TIME">%s</xliff:g>-н хугацаа үлдсэн"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> үлдсэн. Тэжээл хэмнэгч асаалттай байна."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"USB цэнэглэлт дэмжигдэхгүй байна.\nЗөвхөн нийлүүлэгдсэн цэнэглэгчийг ашиглана уу."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"USB-р цэнэглэх дэмжигддэггүй."</string>
@@ -65,14 +68,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Энэ төхөөрөмжид нэвтэрсэн хэрэглэгч USB дебаг хийх онцлогийг асаах боломжгүй байна. Энэ онцлогийг ашиглахын тулд үндсэн хэрэглэгч рүү сэлгэнэ үү."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Дэлгэц дүүргэх бол өсгөнө үү"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Дэлгэц дүүргэх бол татна уу"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Дэлгэцийн зураг дарах"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Дэлгэцийн агшинг хадгалж байна…"</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Дэлгэцийн агшинг хадгалж байна…"</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"Дэлгэцийн агшин хадгалагдав."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Дэлгэцийн агшинг авсан."</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"Дэлгэцийн агшингаа харахын тулд дарна уу."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"Дэлгэцийн агшинг авч чадсангүй."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Дэлгэцийн агшинг хадгалахад алдаа гарлаа."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Хадгалах сангийн багтаамж бага байгаа тул дэлгэцийн авсан зургийг хадгалах боломжгүй байна."</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"Дэлгэцээс дарсан зургийг хадгалж байна"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"Дэлгэцээс дарсан зургийг хадгалсан"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"Дэлгэцээс дарсан зургийг харах бол товшино уу"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"Дэлгэцийн зургийг дарж чадсангүй"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"Дэлгэцээс дарсан зургийг хадгалахад алдаа гарлаа"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Сангийн багтаамж бага байгаа тул дэлгэцээс дарсан зургийг хадгалах боломжгүй байна"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Таны апп, байгууллагад дэлгэцийн зураг авахыг зөвшөөрдөггүй"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB файл шилжүүлэх сонголт"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Медиа тоглуулагч(MTP) болгон залгах"</string>
@@ -557,26 +561,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"Идэвхгүй"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Тэжээлийн мэдэгдлийн удирдлагын тусламжтайгаар та апп-н мэдэгдэлд 0-5 хүртэлх ач холбогдлын түвшин тогтоох боломжтой. \n\n"<b>"5-р түвшин"</b>" \n- Мэдэгдлийн жагсаалтын хамгийн дээр харуулна \n- Бүтэн дэлгэцэд саад болно \n- Дэлгэцэд тогтмол гарч ирнэ \n\n"<b>"4-р түвшин"</b>" \n- Бүтэн дэлгэцэд саад болохоос сэргийлнэ \n- Дэлгэцэд тогтмол гарч ирнэ \n\n"<b>"3-р түвшин"</b>" \n- Бүтэн дэлгэцэд саад болохоос сэргийлнэ \n- Дэлгэцэд хэзээ ч гарч ирэхгүй \n\n"<b>"2-р түвшин"</b>" \n- Бүтэн дэлгэцэд саад болохоос сэргийлнэ \n- Дэлгэцэд хэзээ ч гарч ирэхгүй \n- Дуу болон чичиргээ хэзээ ч гаргахгүй \n\n"<b>"1-р түвшин"</b>" \n- Бүтэн дэлгэцэд саад болохоос сэргийлнэ \n- Дэлгэцэд хэзээ ч гарч ирэхгүй \n- Дуу болон чичиргээ хэзээ ч гаргахгүй \n- Түгжигдсэн дэлгэц болон статусын самбараас нууна \n- Мэдэгдлийн жагсаалтын доор харуулна \n\n"<b>"0-р түвшин"</b>" \n- Энэ апп-н бүх мэдэгдлийг блоклоно"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Мэдэгдэл"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"Ta цаашид эдгээр мэдэгдлийг авахгүй"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> мэдэгдлийн ангилал"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"Энэ апп-д мэдэгдлийн категори алга"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"Энэ аппын мэдэгдлийг унтраах боломжгүй"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="other">Энэ аппын <xliff:g id="NUMBER_1">%s</xliff:g> мэдэгдлийн категорийн 1</item>
-      <item quantity="one">Энэ аппын <xliff:g id="NUMBER_0">%s</xliff:g> мэдэгдлийн категорийн 1</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g>, бусад <xliff:g id="NUMBER_5">%3$d</xliff:g></item>
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_0">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_1">%2$s</xliff:g>, бусад <xliff:g id="NUMBER_2">%3$d</xliff:g></item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"Та эдгээр мэдэгдлийг цаашид харахгүй"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"Эдгээр мэдэгдлийг харуулсан хэвээр байх уу?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"Мэдэгдлийг зогсоох"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"Харуулсан хэвээр байх"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"Энэ аппаас мэдэгдэл харуулсан хэвээр байх уу?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"Эдгээр мэдэгдлийг унтраах боломжгүй"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"<xliff:g id="APP_NAME">%1$s</xliff:g>-н мэдэгдлийн хяналтыг нээсэн"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"<xliff:g id="APP_NAME">%1$s</xliff:g>-н мэдэгдлийн хяналтыг хаасан"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Энэ сувгийн мэдэгдлийг зөвшөөрөх"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"Бүх ангилал"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Бусад тохиргоо"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"Өөрчлөх: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"Тохируулах"</string>
     <string name="notification_done" msgid="5279426047273930175">"Дууссан"</string>
+    <string name="inline_undo" msgid="558916737624706010">"Болих"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"мэдэгдлийн удирдлага"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"мэдэгдэл түр хойшлуулагчийн сонголт"</string>
@@ -731,8 +728,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"Дэлгэх"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Багасгах"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Хаах"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"Тохиргоо"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Хаахын тулд доош чирэх"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"Цэс"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> дэлгэцэн доторх дэлгэцэд байна"</string>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 118d2c7..399be8b 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -33,7 +33,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Sedang berlangsung"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Pemberitahuan"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"Bateri lemah"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"Bateri lemah. Hidupkan Penjimat Bateri"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> yang tinggal"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Tinggal <xliff:g id="PERCENTAGE">%s</xliff:g>, kira-kira <xliff:g id="TIME">%s</xliff:g> lagi berdasarkan penggunaan anda"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Tinggal <xliff:g id="PERCENTAGE">%s</xliff:g>, kira-kira <xliff:g id="TIME">%s</xliff:g> lagi"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Tinggal <xliff:g id="PERCENTAGE">%s</xliff:g>. Penjimat Bateri dihidupkan."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"Pengecasan USB tidak disokong.\nGunakan hanya pengecas yang dibekalkan."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"Pengecasan USB tidak disokong."</string>
@@ -67,14 +70,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Pengguna yang log masuk ke peranti ini pada masa ini tidak boleh menghidupkan penyahpepijatan USB. Untuk menggunakan ciri ini, tukar kepada pengguna utama."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zum untuk memenuhi skrin"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Regang utk memenuhi skrin"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Tangkapan skrin"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Menyimpan tangkapan skrin..."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Menyimpan tangkapan skrin..."</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"Tangkapan skrin sedang disimpan."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Tangkapan skrin ditangkap."</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"Ketik untuk melihat tangkapan skrin anda."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"Tidak dapat menangkap tangkapan skrin."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Berlaku masalah semasa menyimpan tangkapan skrin."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Tidak dapat menyimpan tangkapan skrin kerana ruang storan terhad."</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"Tangkapan skrin sedang disimpan"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"Tangkapan skrin disimpan"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"Ketik untuk melihat tangkapan skrin anda"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"Tidak dapat menangkap tangkapan skrin"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"Masalah berlaku semasa menyimpan tangkapan skrin"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Tidak dapat menyimpan tangkapan skrin kerana ruang storan terhad"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Pengambilan tangkapan skrin tidak dibenarkan oleh apl atau organisasi anda"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Pilihan pemindahan fail USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Lekapkan sebagai pemain media (MTP)"</string>
@@ -557,26 +561,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"Mati"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Dengan kawalan pemberitahuan berkuasa, anda boleh menetapkan tahap kepentingan dari 0 hingga 5 untuk pemberitahuan apl. \n\n"<b>"Tahap 5"</b>" \n- Tunjukkan pada bahagian atas senarai pemberitahuan \n- Benarkan gangguan skrin penuh \n- Sentiasa intai \n\n"<b>"Tahap 4"</b>" \n- Halang gangguan skrin penuh \n- Sentiasa intai \n\n"<b>"Tahap 3"</b>" \n- Halang gangguan skrin penuh \n- Jangan intai \n\n"<b>"Tahap 2"</b>" \n- Halang gangguan skrin penuh \n- Jangan intai \n- Jangan berbunyi dan bergetar \n\n"<b>"Tahap 1"</b>" \n- Halang gangguan skrin penuh \n- Jangan intai \n- Jangan berbunyi atau bergetar \n- Sembunyikan daripada skrin kunci dan bar status \n- Tunjukkan di bahagian bawah senarai pemberitahuan \n\n"<b>"Tahap 0"</b>" \n- Sekat semua pemberitahuan daripada apl"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Pemberitahuan"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"Anda tidak akan menerima pemberitahuan ini lagi"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> kategori pemberitahuan"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"Apl ini tiada kategori pemberitahuan"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"Pemberitahuan daripada apl ini tidak boleh dimatikan"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="other">1 daripada <xliff:g id="NUMBER_1">%s</xliff:g> kategori pemberitahuan daripada apl ini</item>
-      <item quantity="one">1 daripada <xliff:g id="NUMBER_0">%s</xliff:g> kategori pemberitahuan daripada apl ini</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> dan <xliff:g id="NUMBER_5">%3$d</xliff:g> yang lain</item>
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_0">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_1">%2$s</xliff:g> dan <xliff:g id="NUMBER_2">%3$d</xliff:g> yang lain</item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"Anda tidak akan melihat pemberitahuan ini lagi"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"Terus tunjukkan pemberitahuan ini?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"Hentikan pemberitahuan"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"Terus tunjukkan"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"Terus tunjukkan pemberitahuan daripada apl ini?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"Pemberitahuan ini tidak boleh dimatikan"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"Kawalan pemberitahuan untuk <xliff:g id="APP_NAME">%1$s</xliff:g> dibuka"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"Kawalan pemberitahuan untuk <xliff:g id="APP_NAME">%1$s</xliff:g> ditutup"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Benarkan pemberitahuan daripada saluran ini"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"Semua Kategori"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Lagi tetapan"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"Sesuaikan: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"Sesuaikan"</string>
     <string name="notification_done" msgid="5279426047273930175">"Selesai"</string>
+    <string name="inline_undo" msgid="558916737624706010">"Buat asal"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"kawalan pemberitahuan"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"pilihan tunda pemberitahuan"</string>
@@ -731,8 +728,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"Kembangkan"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimumkan"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Tutup"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"Tetapan"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Seret ke bawah untuk mengetepikan"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"Menu"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> terdapat dalam gambar dalam gambar"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 1afd635..0e7447a 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -33,13 +33,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Aktiviteter"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Varsler"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"Batterikapasiteten er lav"</string>
-    <!-- no translation found for battery_low_title_hybrid (6268991275887381595) -->
-    <skip />
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"Du har lite batteri. Slå på batterisparing"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> gjenstår"</string>
-    <!-- no translation found for battery_low_percent_format_hybrid (6838677459286775617) -->
-    <skip />
-    <!-- no translation found for battery_low_percent_format_hybrid_short (9025795469949145586) -->
-    <skip />
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> gjenstår, omtrent <xliff:g id="TIME">%s</xliff:g> igjen basert på bruken din"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> gjenstår, omtrent <xliff:g id="TIME">%s</xliff:g> igjen"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> gjenstår. Batterisparing er på."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"USB-lading støttes ikke.\nBruk kun den medfølgende laderen."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"Lading via USB støttes ikke."</string>
@@ -73,22 +70,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Brukeren som for øyeblikket er logget på denne enheten, kan ikke slå på USB-feilsøking. For å bruke denne funksjonen, bytt til hovedbrukeren."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoom for å fylle skjermen"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Strekk for å fylle skjerm"</string>
-    <!-- no translation found for global_action_screenshot (8329831278085426283) -->
-    <skip />
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Skjermdump"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Lagrer skjermdumpen …"</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Lagrer skjermdumpen …"</string>
-    <!-- no translation found for screenshot_saving_text (2545047868936087248) -->
-    <skip />
-    <!-- no translation found for screenshot_saved_title (5637073968117370753) -->
-    <skip />
-    <!-- no translation found for screenshot_saved_text (7574667448002050363) -->
-    <skip />
-    <!-- no translation found for screenshot_failed_title (9096484883063264803) -->
-    <skip />
-    <!-- no translation found for screenshot_failed_to_save_unknown_text (8844781948876286488) -->
-    <skip />
-    <!-- no translation found for screenshot_failed_to_save_text (3041612585107107310) -->
-    <skip />
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"Skjermdumpen lagres"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"Skjermdumpen er lagret"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"Trykk for å se skjermdumpen"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"Kan ikke lagre skjermdumpen"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"Det oppsto et problem under lagring av skjermdumpen"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Kan ikke lagre skjermdumpen på grunn av begrenset lagringsplass"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Appen eller organisasjonen din tillater ikke at du tar skjermdumper"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Altern. for USB-filoverføring"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Sett inn som mediespiller (MTP)"</string>
@@ -571,27 +561,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"Av"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Med effektive varselinnstillinger kan du angi viktighetsnivåer fra 0 til 5 for appvarsler. \n\n"<b>"Nivå 5"</b>" \n– Vis øverst på varsellisten \n– Tillat forstyrrelser ved fullskjermmodus \n– Vis alltid raskt \n\n"<b>"Nivå 4"</b>" \n– Forhindre forstyrrelser ved fullskjermmodus \n– Vis alltid raskt \n\n"<b>"Nivå 3"</b>" \n– Forhindre forstyrrelser ved fullskjermmodus \n– Vis aldri raskt \n\n"<b>"Nivå 2"</b>" \n– Forhindre forstyrrelser ved fullskjermmodus \n– Vis aldri fort \n– Tillat aldri lyder eller vibrering \n\n"<b>"Nivå 1"</b>" \n– Forhindre forstyrrelser ved fullskjermmodus \n– Vis aldri raskt \n– Tillat aldri lyder eller vibrering \n– Skjul fra låseskjermen og statusfeltet \n– Vis nederst på varsellisten \n\n"<b>"Nivå 0"</b>" \n– Blokkér alle varsler fra appen"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Varsler"</string>
-    <!-- no translation found for notification_channel_disabled (344536703863700565) -->
-    <skip />
-    <!-- no translation found for inline_keep_showing (8945102997083836858) -->
-    <skip />
-    <!-- no translation found for inline_stop_button (4172980096860941033) -->
-    <skip />
-    <!-- no translation found for inline_keep_button (6665940297019018232) -->
-    <skip />
-    <!-- no translation found for inline_keep_showing_app (1723113469580031041) -->
-    <skip />
-    <!-- no translation found for notification_unblockable_desc (1037434112919403708) -->
-    <skip />
+    <string name="notification_channel_disabled" msgid="344536703863700565">"Du ser ikke disse varslene lenger"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"Vil du fortsette å vise disse varslene?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"Stopp varsler"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"Fortsett å vise"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"Vil du fortsette å vise varsler fra denne appen?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"Du kan ikke slå av disse varslene"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"Varselinnstillingene for <xliff:g id="APP_NAME">%1$s</xliff:g> er åpnet"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"Varselinnstillingene for <xliff:g id="APP_NAME">%1$s</xliff:g> er lukket"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Tillat varsler fra denne kanalen"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Flere innstillinger"</string>
-    <!-- no translation found for notification_app_settings (420348114670768449) -->
-    <skip />
+    <string name="notification_app_settings" msgid="420348114670768449">"Tilpass"</string>
     <string name="notification_done" msgid="5279426047273930175">"Ferdig"</string>
-    <!-- no translation found for inline_undo (558916737624706010) -->
-    <skip />
+    <string name="inline_undo" msgid="558916737624706010">"Angre"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"varselinnstillinger"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"slumrealternativer for varsler"</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index a5c13f1..5814542 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -33,13 +33,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"चलिरहेको"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"सूचनाहरू"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"ब्याट्री कम छ"</string>
-    <!-- no translation found for battery_low_title_hybrid (6268991275887381595) -->
-    <skip />
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"ब्याट्रीको स्तर न्यून छ। ब्याट्री सेभर सक्रिय गर्नुहोस्"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> बाँकी"</string>
-    <!-- no translation found for battery_low_percent_format_hybrid (6838677459286775617) -->
-    <skip />
-    <!-- no translation found for battery_low_percent_format_hybrid_short (9025795469949145586) -->
-    <skip />
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> बाँकी, तपाईंको प्रयोगका आधारमा करिब <xliff:g id="TIME">%s</xliff:g> बाँकी छ"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> बाँकी, करिब <xliff:g id="TIME">%s</xliff:g> बाँकी छ"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> बाँकी। ब्याट्री सेभर सक्रिय छ।"</string>
     <string name="invalid_charger" msgid="4549105996740522523">"USB चार्ज गर्न समर्थित छैन।\n आपूर्ति गरिएको चार्जर मात्र प्रयोग गर्नुहोस्।"</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"USB चार्ज समर्थित छैन।"</string>
@@ -73,22 +70,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"हाल यस यन्त्रमा साइन इन हुनुभएको प्रयोगकर्ताले USB डिबग सक्रिय गर्न सक्नुहुन्न। यो सुविधाको प्रयोग गर्न प्राथमिक प्रयोगकर्तामा बदल्नुहोस्‌।"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"स्क्रिन भर्न जुम गर्नुहोस्"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"स्क्रिन भर्न तन्काउनुहोस्"</string>
-    <!-- no translation found for global_action_screenshot (8329831278085426283) -->
-    <skip />
+    <string name="global_action_screenshot" msgid="8329831278085426283">"स्क्रिनसट"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"स्क्रिनसट बचत गर्दै…"</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"स्क्रिनसट बचत गर्दै…"</string>
-    <!-- no translation found for screenshot_saving_text (2545047868936087248) -->
-    <skip />
-    <!-- no translation found for screenshot_saved_title (5637073968117370753) -->
-    <skip />
-    <!-- no translation found for screenshot_saved_text (7574667448002050363) -->
-    <skip />
-    <!-- no translation found for screenshot_failed_title (9096484883063264803) -->
-    <skip />
-    <!-- no translation found for screenshot_failed_to_save_unknown_text (8844781948876286488) -->
-    <skip />
-    <!-- no translation found for screenshot_failed_to_save_text (3041612585107107310) -->
-    <skip />
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"स्क्रिनसट सुरक्षित गरिँदै छ"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"स्क्रिनसट सुरक्षित गरियो"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"आफ्नो स्क्रिनसट हेर्न ट्याप गर्नुहोस्"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"स्क्रिनसट खिच्न सकिएन"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"स्क्रिनसट सुरक्षित गर्ने क्रममा समस्या आइपर्‍यो"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"भण्डारण ठाउँ सीमित भएका कारण स्क्रिनसट सुरक्षित गर्न सकिएन"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"उक्त अनुप्रयोग वा तपाईंको संगठनले स्क्रिनसटहरू लिन दिँदैन"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB फाइल सार्ने विकल्पहरू"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"मिडिया प्लेयर(MTP)को रूपमा माउन्ट गर्नुहोस्"</string>
@@ -571,27 +561,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"निष्क्रिय"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"सशक्त सूचना नियन्त्रणहरू मार्फत तपाईं अनुप्रयाेगका सूचनाहरूका लागि ० देखि ५ सम्मको महत्व सम्बन्धी स्तर सेट गर्न सक्नुहुन्छ। \n\n"<b>"स्तर ५"</b>" \n- सूचनाको सूचीको माथिल्लो भागमा देखाउने \n- पूर्ण स्क्रिनमा अवरोधका लागि अनुमति दिने \n- सधैँ चियाउने \n\n"<b>"स्तर ४"</b>" \n- पूर्ण स्क्रिनमा अवरोधलाई रोक्ने \n- सधैँ चियाउने \n\n"<b>"स्तर ३"</b>" \n- पूर्ण स्क्रिनमा अवरोधलाई रोक्ने \n- कहिल्यै नचियाउने \n\n"<b>"स्तर २"</b>" \n- पूर्ण स्क्रिनमा अवरोधलाई रोक्ने \n- कहिल्यै नचियाउने \n- कहिल्यै पनि आवाज ननिकाल्ने र कम्पन नगर्ने \n\n"<b>"स्तर १"</b>" \n- पूर्ण स्क्रिनमा अवरोध रोक्ने \n- कहिल्यै नचियाउने \n- कहिल्यै पनि आवाज ननिकाल्ने वा कम्पन नगर्ने \n- लक स्क्रिन र वस्तुस्थिति पट्टीबाट लुकाउने \n- सूचनाको सूचीको तल्लो भागमा देखाउने \n\n"<b>"स्तर ०"</b>" \n- अनुप्रयोगका सबै सूचनाहरूलाई रोक्ने"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"सूचनाहरू"</string>
-    <!-- no translation found for notification_channel_disabled (344536703863700565) -->
-    <skip />
-    <!-- no translation found for inline_keep_showing (8945102997083836858) -->
-    <skip />
-    <!-- no translation found for inline_stop_button (4172980096860941033) -->
-    <skip />
-    <!-- no translation found for inline_keep_button (6665940297019018232) -->
-    <skip />
-    <!-- no translation found for inline_keep_showing_app (1723113469580031041) -->
-    <skip />
-    <!-- no translation found for notification_unblockable_desc (1037434112919403708) -->
-    <skip />
+    <string name="notification_channel_disabled" msgid="344536703863700565">"तपाईं अब उप्रान्त यी सूचनाहरू देख्नु हुने छैन"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"यी सूचनाहरू देखाउने क्रम जारी राख्ने हो?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"सूचनाहरू देखाउन छाड्नुहोस्"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"देखाउने क्रम जारी राख्नुहोस्"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"यो अनुप्रयोगका सूचनाहरू देखाउने क्रम जारी राख्ने हो?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"यी सूचनाहरूलाई निष्क्रिय पार्न सकिँदैन"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"<xliff:g id="APP_NAME">%1$s</xliff:g> का सूचना सम्बन्धी नियन्त्रणहरूलाई खोलियो"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"<xliff:g id="APP_NAME">%1$s</xliff:g> का सूचना सम्बन्धी नियन्त्रणहरूलाई बन्द गरियो"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"यो च्यानलका सूचनाहरूलाई अनुमति दिनुहोस्"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"थप सेटिङहरू"</string>
-    <!-- no translation found for notification_app_settings (420348114670768449) -->
-    <skip />
+    <string name="notification_app_settings" msgid="420348114670768449">"आफू अनुकूल पार्नुहोस्"</string>
     <string name="notification_done" msgid="5279426047273930175">"सम्पन्‍न भयो"</string>
-    <!-- no translation found for inline_undo (558916737624706010) -->
-    <skip />
+    <string name="inline_undo" msgid="558916737624706010">"अन्डू गर्नुहोस्"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"सूचना सम्बन्धी नियन्त्रणहरू"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"सूचना स्नुज गर्ने विकल्पहरू"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 7139a63..55a6cb88 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -33,7 +33,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Actief"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Meldingen"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"Batterij is bijna leeg"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"De batterij is bijna leeg. Schakel Batterijbesparing in."</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> resterend"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> resterend, nog ongeveer <xliff:g id="TIME">%s</xliff:g> over op basis van je gebruik"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> resterend, nog ongeveer <xliff:g id="TIME">%s</xliff:g> over"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> resterend. Batterijbesparing is ingeschakeld."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"Opladen via USB niet ondersteund.\nGebruik alleen de bijgeleverde oplader."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"Opladen via USB wordt niet ondersteund."</string>
@@ -67,14 +70,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"De gebruiker die momenteel is ingelogd op dit apparaat, kan USB-foutopsporing niet inschakelen. Als je deze functie wilt gebruiken, schakel je naar de primaire gebruiker."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoom om scherm te vullen"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Rek uit v. schermvulling"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Screenshot"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Screenshot opslaan..."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Screenshot opslaan..."</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"Screenshot wordt opgeslagen."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Screenshot gemaakt."</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"Tik om je screenshot te bekijken."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"Screenshot is niet gemaakt."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Er is een probleem opgetreden bij het opslaan van het screenshot."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Kan screenshot niet opslaan vanwege beperkte opslagruimte."</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"Screenshot wordt opgeslagen"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"Screenshot opgeslagen"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"Tik om je screenshot te bekijken"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"Kan geen screenshot maken"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"Er is een probleem opgetreden bij het opslaan van het screenshot"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Kan screenshot niet opslaan vanwege beperkte opslagruimte"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Het maken van screenshots wordt niet toegestaan door de app of je organisatie"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opties voor USB-bestandsoverdracht"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Koppelen als mediaspeler (MTP)"</string>
@@ -557,26 +561,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"Uit"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Met beheeropties voor meldingen met betrekking tot stroomverbruik kun je een belangrijkheidsniveau van 0 tot 5 instellen voor de meldingen van een app. \n\n"<b>"Niveau 5"</b>" \n- Boven aan de lijst met meldingen weergeven \n- Onderbreking op volledig scherm toestaan \n- Altijd korte weergave \n\n"<b>"Niveau 4"</b>" \n- Geen onderbreking op volledig scherm \n- Altijd korte weergave \n\n"<b>"Niveau 3"</b>" \n- Geen onderbreking op volledig scherm \n- Nooit korte weergave \n\n"<b>"Niveau 2"</b>" \n- Geen onderbreking op volledig scherm \n- Nooit korte weergave \n- Nooit geluid laten horen of trillen \n\n"<b>"Niveau 1"</b>" \n- Geen onderbreking op volledig scherm \n- Nooit korte weergave \n- Nooit geluid laten horen of trillen \n- Verbergen op vergrendelingsscherm en statusbalk \n- Onder aan de lijst met meldingen weergeven \n\n"<b>"Niveau 0"</b>" \n- Alle meldingen van de app blokkeren"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Meldingen"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"Je ontvangt deze meldingen niet meer"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> meldingscategorieën"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"Deze app heeft geen meldingscategorieën"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"Meldingen van deze app kunnen niet worden uitgeschakeld"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="other">1 van <xliff:g id="NUMBER_1">%s</xliff:g> meldingscategorieën van deze app</item>
-      <item quantity="one">1 van <xliff:g id="NUMBER_0">%s</xliff:g> meldingscategorie van deze app</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> en <xliff:g id="NUMBER_5">%3$d</xliff:g> andere</item>
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_0">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_1">%2$s</xliff:g> en <xliff:g id="NUMBER_2">%3$d</xliff:g> andere</item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"Deze meldingen worden niet meer weergegeven"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"Deze meldingen blijven weergeven?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"Meldingen stoppen"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"Blijven weergeven"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"Meldingen van deze app blijven weergeven?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"Deze meldingen kunnen niet worden uitgeschakeld"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"Beheeropties voor meldingen voor <xliff:g id="APP_NAME">%1$s</xliff:g> geopend"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"Beheeropties voor meldingen voor <xliff:g id="APP_NAME">%1$s</xliff:g> gesloten"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Meldingen van dit kanaal toestaan"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"Alle categorieën"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Meer instellingen"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"Aanpassen: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"Aanpassen"</string>
     <string name="notification_done" msgid="5279426047273930175">"Gereed"</string>
+    <string name="inline_undo" msgid="558916737624706010">"Ongedaan maken"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"beheeropties voor meldingen"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"snooze-opties voor meldingen"</string>
@@ -731,8 +728,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"Uitvouwen"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimaliseren"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Sluiten"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"Instellingen"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Sleep omlaag om te sluiten"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"Menu"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> is in scherm-in-scherm"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 4c385b7..0c4b71e 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -35,7 +35,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Bieżące"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Powiadomienia"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"Niski poziom baterii"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"Niski poziom naładowania baterii. Włącz Oszczędzanie baterii"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"Pozostało <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Pozostało <xliff:g id="PERCENTAGE">%s</xliff:g>, jeszcze około <xliff:g id="TIME">%s</xliff:g> (na podstawie Twojego sposobu korzystania)"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Pozostało <xliff:g id="PERCENTAGE">%s</xliff:g>, jeszcze około <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Pozostało <xliff:g id="PERCENTAGE">%s</xliff:g>. Oszczędzanie baterii jest włączone."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"Ładowanie przy użyciu złącza USB nie jest obsługiwane.\nNależy używać tylko dołączonej ładowarki."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"Ładowanie przez USB nie jest obsługiwane."</string>
@@ -69,14 +72,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Użytkownik obecnie zalogowany na tym urządzeniu nie może włączyć debugowania USB. Aby użyć tej funkcji, przełącz się na użytkownika głównego."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Powiększ, aby wypełnić ekran"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Rozciągnij, aby wypełnić ekran"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Zrzut ekranu"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Zapisywanie zrzutu ekranu..."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Zapisywanie zrzutu ekranu..."</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"Zapisywanie zrzutu ekranu."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Wykonano zrzut ekranu."</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"Kliknij, by zobaczyć zrzut ekranu."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"Nie udało się wykonać zrzutu ekranu."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Podczas zapisywania zrzutu ekranu wystąpił błąd."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Nie można zapisać zrzutu ekranu, bo brakuje miejsca w pamięci."</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"Zapisywanie zrzutu ekranu"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"Zrzut ekranu został zapisany"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"Kliknij, by zobaczyć zrzut ekranu"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"Nie udało się wykonać zrzutu ekranu"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"Podczas zapisywania zrzutu ekranu wystąpił błąd"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Nie można zapisać zrzutu ekranu, bo brakuje miejsca w pamięci"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Nie możesz wykonać zrzutu ekranu, bo nie zezwala na to aplikacja lub Twoja organizacja."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB – opcje przesyłania plików"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Podłącz jako odtwarzacz multimedialny (MTP)"</string>
@@ -561,30 +565,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"Wył."</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Dzięki zaawansowanym ustawieniom możesz określić poziom ważności powiadomień z aplikacji w skali od 0 do 5. \n\n"<b>"Poziom 5"</b>" \n– Pokazuj u góry listy powiadomień \n– Zezwalaj na powiadomienia na pełnym ekranie \n– Zawsze pokazuj podgląd \n\n"<b>"Poziom 4"</b>" \n– Wyłącz powiadomienia na pełnym ekranie \n– Zawsze pokazuj podgląd \n\n"<b>"Poziom 3"</b>" \n– Wyłącz powiadomienia na pełnym ekranie \n– Nigdy nie pokazuj podglądu \n\n"<b>"Poziom 2"</b>" \n– Wyłącz powiadomienia na pełnym ekranie \n– Nigdy nie pokazuj podglądu \n– NIgdy nie powiadamiaj dźwiękiem ani wibracjami \n\n"<b>"Poziom 1"</b>" \n– Wyłącz powiadomienia na pełnym ekranie \n– Nigdy nie pokazuj podglądu \n– NIgdy nie powiadamiaj dźwiękiem ani wibracjami \n– Ukrywaj na ekranie blokady i pasku stanu \n– Pokazuj u dołu listy powiadomień \n\n"<b>"Poziom 0"</b>" \n– Blokuj wszystkie powiadomienia aplikacji"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Powiadomienia"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"Nie będziesz już otrzymywać tych powiadomień"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"Kategorie powiadomień: <xliff:g id="NUMBER">%d</xliff:g>"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"Ta aplikacja nie ma kategorii powiadomień"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"Powiadomień z tej aplikacji nie można wyłączyć"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="few">1 z <xliff:g id="NUMBER_1">%s</xliff:g> kategorii powiadomień z tej aplikacji</item>
-      <item quantity="many">1 z <xliff:g id="NUMBER_1">%s</xliff:g> kategorii powiadomień z tej aplikacji</item>
-      <item quantity="other">1 z <xliff:g id="NUMBER_1">%s</xliff:g> kategorii powiadomień z tej aplikacji</item>
-      <item quantity="one">1 z <xliff:g id="NUMBER_0">%s</xliff:g> kategorii powiadomień z tej aplikacji</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="few"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> i <xliff:g id="NUMBER_5">%3$d</xliff:g> inne</item>
-      <item quantity="many"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> i <xliff:g id="NUMBER_5">%3$d</xliff:g> innych</item>
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> i <xliff:g id="NUMBER_5">%3$d</xliff:g> innego</item>
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_0">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_1">%2$s</xliff:g> i <xliff:g id="NUMBER_2">%3$d</xliff:g> inny</item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"Te powiadomienia nie będą już wyświetlane"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"Nadal pokazywać te powiadomienia?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"Zatrzymaj powiadomienia"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"Pokazuj nadal"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"Nadal pokazywać powiadomienia z tej aplikacji?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"Tych powiadomień nie można wyłączyć"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"Sterowanie powiadomieniami aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g> otwarte"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"Sterowanie powiadomieniami aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g> zamknięte"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Zezwól na powiadomienia z tego kanału"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"Wszystkie kategorie"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Więcej ustawień"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"Dostosuj: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"Dostosuj"</string>
     <string name="notification_done" msgid="5279426047273930175">"Gotowe"</string>
+    <string name="inline_undo" msgid="558916737624706010">"Cofnij"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"sterowanie powiadomieniami"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"opcje odkładania powiadomień"</string>
@@ -743,8 +736,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"Rozwiń"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimalizuj"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Zamknij"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"Ustawienia"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Przeciągnij w dół, by zamknąć"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"Menu"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"Aplikacja <xliff:g id="NAME">%s</xliff:g> działa w trybie obraz w obrazie"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 49415a5..618c950 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -35,7 +35,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Prebiehajúce"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Upozornenia"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"Batéria je takmer vybitá"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"Batéria je takmer vybitá. Zapnite Šetrič batérie."</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"Zostáva <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Zostáva <xliff:g id="PERCENTAGE">%s</xliff:g>, približne <xliff:g id="TIME">%s</xliff:g> v závislosti od intenzity využitia"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Zostáva <xliff:g id="PERCENTAGE">%s</xliff:g>, približne <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Zostáva: <xliff:g id="PERCENTAGE">%s</xliff:g>. Šetrič batérie je zapnutý."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"Nabíjanie pomocou rozhrania USB nie je podporované.\nPoužívajte iba nabíjačku, ktorá bola dodaná spolu so zariadením."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"Nabíjanie prostredníctvom USB nie je podporované."</string>
@@ -69,14 +72,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Používateľ, ktorý je práve prihlásený v tomto zariadení, nemôže zapnúť ladenie USB. Ak chcete použiť túto funkciu, prepnite na hlavného používateľa."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Priblížiť na celú obrazovku"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Na celú obrazovku"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Snímka obrazovky"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Prebieha ukladanie snímky obrazovky..."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Prebieha ukladanie snímky obrazovky..."</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"Snímka obrazovky sa ukladá."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Snímka obrazovky bola zaznamenaná."</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"Klepnutím zobrazíte snímku obrazovky."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"Snímku obrazovky sa nepodarilo zachytiť."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Pri ukladaní snímky obrazovky sa vyskytol problém."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Snímku obrazovky nie je možné vytvoriť z dôvodu nedostatku miesta v úložisku."</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"Ukladá sa snímka obrazovky"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"Snímka obrazovky bola uložená"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"Klepnutím zobrazíte snímku obrazovky"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"Snímku obrazovky sa nepodarilo zachytiť"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"Pri ukladaní snímky obrazovky sa vyskytol problém"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Snímka obrazovky sa nedá uložiť z dôvodu nedostatku miesta v úložisku"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Vytváranie snímok obrazovky je zakázané aplikáciou alebo vašou organizáciou"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Možnosti prenosu súborov USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Pripojiť ako prehrávač médií (MTP)"</string>
@@ -563,30 +567,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"Vypnuté"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Pomocou ovládacích prvkov zobrazovania upozornení môžete nastaviť pre upozornenia aplikácie úroveň dôležitosti od 0 do 5. \n\n"<b>"Úroveň 5"</b>" \n– Zobrazovať v hornej časti zoznamu upozornení. \n– Povoliť prerušenia na celú obrazovku. \n– Vždy zobrazovať čiastočne. \n\n"<b>"Úroveň 4"</b>" \n– Zabrániť prerušeniam na celú obrazovku. \n– Vždy zobrazovať čiastočne. \n\n"<b>"Úroveň 3"</b>" \n– Zabrániť prerušeniam na celú obrazovku. \n– Nikdy nezobrazovať čiastočne. \n\n"<b>"Úroveň 2"</b>" \n– Zabrániť prerušeniam na celú obrazovku. \n– Nikdy nezobrazovať čiastočne. \n– Nikdy nespúšťať zvuk ani vibrácie. \n\n"<b>"Úroveň 1"</b>" \n– Zabrániť prerušeniam na celú obrazovku. \n– Nikdy nezobrazovať čiastočne. \n– Nikdy nespúšťať zvuk ani vibrácie. \n– Skryť na uzamknutej obrazovke a v stavovom riadku. \n– Zobraziť v dolnej časti zoznamu upozornení. \n\n"<b>"Úroveň 0"</b>" \n– Blokovať všetky upozornenia z aplikácie."</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Upozornenia"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"Tieto upozornenia už nebudete dostávať"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"Počet kategórií upozornení: <xliff:g id="NUMBER">%d</xliff:g>"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"Táto aplikácia nemá kategórie upozornení"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"Upozornenia z tejto aplikácie sa nedajú vypnúť"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="few">1 z <xliff:g id="NUMBER_1">%s</xliff:g> kategórií upozornení z tejto aplikácie</item>
-      <item quantity="many">1 z <xliff:g id="NUMBER_1">%s</xliff:g> kategórie upozornení z tejto aplikácie</item>
-      <item quantity="other">1 z <xliff:g id="NUMBER_1">%s</xliff:g> kategórií upozornení z tejto aplikácie</item>
-      <item quantity="one">1 z <xliff:g id="NUMBER_0">%s</xliff:g> kategórie upozornení z tejto aplikácie</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="few"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> a <xliff:g id="NUMBER_5">%3$d</xliff:g> ďalšie</item>
-      <item quantity="many"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> a <xliff:g id="NUMBER_5">%3$d</xliff:g> ďalšieho</item>
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> a <xliff:g id="NUMBER_5">%3$d</xliff:g> ďalších</item>
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_0">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_1">%2$s</xliff:g> a <xliff:g id="NUMBER_2">%3$d</xliff:g> ďalší</item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"Tieto upozornenia sa už nebudú zobrazovať"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"Majú sa tieto upozornenia naďalej zobrazovať?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"Prestať zobrazovať upozornenia"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"Naďalej zobrazovať"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"Majú sa upozornenia z tejto aplikácie naďalej zobrazovať?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"Tieto upozornenia sa nedajú vypnúť"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"Ovládanie upozornení pre aplikáciu <xliff:g id="APP_NAME">%1$s</xliff:g> je otvorené"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"Ovládanie upozornení pre aplikáciu <xliff:g id="APP_NAME">%1$s</xliff:g> je zatvorené"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Povoliť upozornenia z tohto kanála"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"Všetky kategórie"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Ďalšie nastavenia"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"Prispôsobiť: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"Prispôsobiť"</string>
     <string name="notification_done" msgid="5279426047273930175">"Hotovo"</string>
+    <string name="inline_undo" msgid="558916737624706010">"Späť"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"ovládacie prvky pre upozornenia"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"možnosti stlmenia upozornení"</string>
@@ -745,8 +738,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"Rozbaliť"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimalizovať"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Zavrieť"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"Nastavenia"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Zrušíte presunutím nadol"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"Ponuka"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> je v režime obraz v obraze"</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index 2d1591f..61f1c86 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -33,7 +33,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Në vazhdim"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Njoftimet"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"Niveli i baterisë është i ulët"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"Niveli i baterisë është i ulët. Aktivizo \"Kursyesin e baterisë\""</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"Ka mbetur edhe <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> të mbetura, rreth <xliff:g id="TIME">%s</xliff:g> të mbetura bazuar në përdorimin tënd"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> të mbetura, rreth <xliff:g id="TIME">%s</xliff:g> të mbetura"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Ka mbetur edhe <xliff:g id="PERCENTAGE">%s</xliff:g>. \"Kursyesi i baterisë\" është i aktivizuar."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"Ngarkuesi USB nuk mbështetet.\nPërdor vetëm ngarkuesin e dhënë."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"Ngarkimi i USB-së nuk mbështetet."</string>
@@ -67,14 +70,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Përdoruesi i identifikuar aktualisht në këtë pajisje nuk mund ta aktivizojë korrigjimin e USB-së. Për ta përdorur këtë funksion, kalo te përdoruesi parësor."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zmadho për të mbushur ekranin"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Shtrije për të mbushur ekranin"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Pamja e ekranit"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Po ruan pamjen e ekranit..."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Po ruan pamjen e ekranit…"</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"Pamja e ekranit po ruhet."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Pamja e ekranit u kap."</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"Trokit për të parë pamjen e ekranit."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"Nuk mundi të kapte pamjen e ekranit."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"U has problem gjatë ruajtjes së pamjes së ekranit."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Pamja e ekranit nuk mund të ruhet për shkak të hapësirës ruajtëse të kufizuar."</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"Pamja e ekranit po ruhet"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"Pamja e ekranit u ruajt"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"Trokit për të parë pamjen e ekranit"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"Pamja e ekranit nuk mund të regjistrohej"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"U ndesh një problem gjatë ruajtjes së pamjes së ekranit"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Pamja e ekranit nuk mund të ruhet për shkak të hapësirës ruajtëse të kufizuar"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Nxjerrja e pamjeve të ekranit nuk lejohet nga aplikacioni ose organizata jote."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opsionet e transferimit të dosjeve të USB-së"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Lidh si një lexues \"media\" (MTP)"</string>
@@ -557,26 +561,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"Joaktiv"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Me kontrollet e njoftimit të energjisë, mund të caktosh një nivel rëndësie nga 0 në 5 për njoftimet e një aplikacioni. \n\n"<b>"Niveli 5"</b>" \n- Shfaq në krye të listës së njoftimeve \n- Lejo ndërprerjen e ekranit të plotë \n- Gjithmonë shfaq shpejt \n\n"<b>"Niveli 4"</b>" \n- Parandalo ndërprerjen e ekranit të plotë \n- Gijthmonë shfaq shpejt \n\n"<b>"Niveli 3"</b>" \n- Parandalo ndërprerjen e ekranit të plotë \n- Asnjëherë mos shfaq shpejt \n\n"<b>"Niveli 2"</b>" \n- Parandalo ndërprerjen e ekranit të plotë \n- Asnjëherë mos shfaq shpejt \n- Asnjëherë mos lësho tingull dhe dridhje \n\n"<b>"Niveli 1"</b>" \n- Parandalo ndërprerjen e ekranit të plotë \n- Asnjëherë mos shfaq shpejt \n- Asnjëherë mos lësho tingull ose dridhje \n- Fshih nga ekrani i kyçjes dhe shiriti i statusit \n- Shfaq në fund të listës së njoftimeve \n\n"<b>"Niveli 0"</b>" \n- Blloko të gjitha njoftimet nga aplikacioni"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Njoftime"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"Këto njoftime nuk do t\'i marrësh më"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> kategori njoftimesh"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"Ky aplikacion nuk ka kategori njoftimesh"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"Njoftimet nga ky aplikacion nuk mund të çaktivizohen"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="other">1 nga <xliff:g id="NUMBER_1">%s</xliff:g> kategori njoftimi nga ky aplikacion</item>
-      <item quantity="one">1 nga <xliff:g id="NUMBER_0">%s</xliff:g> kategori njoftimi nga ky aplikacion</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> dhe <xliff:g id="NUMBER_5">%3$d</xliff:g> të tjerë</item>
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_0">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_1">%2$s</xliff:g> dhe <xliff:g id="NUMBER_2">%3$d</xliff:g> të tjerë</item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"Nuk do t\'i shikosh më këto njoftime"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"Do të vazhdosh t\'i shfaqësh këto njoftime?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"Ndalo njoftimet"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"Vazhdo të shfaqësh"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"Do të vazhdosh t\'i shfaqësh njoftimet nga ky aplikacion?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"Këto njoftime nuk mund të çaktivizohen"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"Kontrollet e njoftimeve për <xliff:g id="APP_NAME">%1$s</xliff:g> janë hapur"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"Kontrollet e njoftimeve për <xliff:g id="APP_NAME">%1$s</xliff:g> janë mbyllur"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Lejo njoftimet nga ky kanal"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"Të gjitha kategoritë"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Cilësime të tjera"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"Peresonalizoje: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"Personalizo"</string>
     <string name="notification_done" msgid="5279426047273930175">"U krye"</string>
+    <string name="inline_undo" msgid="558916737624706010">"Zhbëj"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"kontrollet e njoftimit"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"opsionet e shtyrjes së njoftimit"</string>
@@ -731,8 +728,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"Zgjero"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimizo"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Mbyll"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"Cilësimet"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Zvarrit poshtë për të larguar"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"Menyja"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> është në figurë brenda figurës"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 99d8008..7eb86c2 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -34,7 +34,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Текуће"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Обавештења"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"Ниво напуњености батерије је низак"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"Батерија је скоро празна. Укључите Уштеду батерије"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"Још <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Још <xliff:g id="PERCENTAGE">%s</xliff:g>, на основу коришћења остало је око <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Још <xliff:g id="PERCENTAGE">%s</xliff:g>, остало је око <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Још <xliff:g id="PERCENTAGE">%s</xliff:g>. Уштеда батерије је укључена."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"Пуњење преко USB-а није подржано.\nКористите само приложени пуњач."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"Пуњење преко USB-а није подржано."</string>
@@ -68,14 +71,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Корисник који је тренутно пријављен на овај уређај не може да укључи отклањање грешака на USB-у. Да бисте користили ову функцију, пребаците на примарног корисника."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Зумирај на целом екрану"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Развуци на цео екран"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Снимак екрана"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Чување снимка екрана..."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Чување снимка екрана..."</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"Снимак екрана се чува."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Снимак екрана је направљен."</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"Додирните да бисте видели снимак екрана."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"Није могуће направити снимак екрана."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Дошло је до проблема при чувању снимка екрана."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Чување снимка екрана није успело због ограниченог меморијског простора."</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"Снимак екрана се чува"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"Снимак екрана је сачуван"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"Додирните да бисте видели снимак екрана"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"Не можете да направите снимак екрана"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"Дошло је до проблема при чувању снимка екрана"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Чување снимка екрана није успело због ограниченог меморијског простора"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Апликација или организација не дозвољавају прављење снимака екрана"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Опције USB преноса датотека"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Прикључи као медија плејер (MTP)"</string>
@@ -559,28 +563,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"Искључено"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Помоћу напредних контрола за обавештења можете да подесите ниво важности од 0. до 5. за обавештења апликације. \n\n"<b>"5. ниво"</b>" \n– Приказују се у врху листе обавештења \n- Дозволи прекид режима целог екрана \n– Увек завируј \n\n"<b>"4. ниво"</b>" \n– Спречи прекид режима целог екрана \n– Увек завируј \n\n"<b>"3. ниво"</b>" \n– Спречи прекид режима целог екрана \n– Никада не завируј \n\n"<b>"2. ниво"</b>" \n– Спречи прекид режима целог екрана \n– Никада не завируј \n– Никада не производи звук или вибрацију \n\n"<b>"1. ниво"</b>" \n– Спречи прекид режима целог екрана \n– Никада не завируј \n– Никада не производи звук или вибрацију \n– Сакриј на закључаном екрану и статусној траци \n– Приказују се у дну листе обавештења \n\n"<b>"0. ниво"</b>" \n– Блокирај сва обавештења из апликације"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Обавештења"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"Више нећете добијати ова обавештења"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"Категорија обавештења: <xliff:g id="NUMBER">%d</xliff:g>"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"Ова апликација нема категорије обавештења"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"Обавештења из ове апликације не могу да се искључе"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="one">1 од <xliff:g id="NUMBER_1">%s</xliff:g> категорије обавештења за ову апликацију</item>
-      <item quantity="few">1 од <xliff:g id="NUMBER_1">%s</xliff:g> категорије обавештења за ову апликацију</item>
-      <item quantity="other">1 од <xliff:g id="NUMBER_1">%s</xliff:g> категорија обавештења за ову апликацију</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> и још <xliff:g id="NUMBER_5">%3$d</xliff:g></item>
-      <item quantity="few"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> и још <xliff:g id="NUMBER_5">%3$d</xliff:g></item>
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> и још <xliff:g id="NUMBER_5">%3$d</xliff:g></item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"Више нећете видети ова обавештења"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"Желите ли да се ова обавештења и даље приказују?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"Престани да приказујеш обавештења"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"Настави да приказујеш"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"Желите ли да се обавештења из ове апликације и даље приказују?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"Не можете да искључите ова обавештења"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"Контроле обавештења за отварање апликације <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"Контроле обавештења за затварање апликације <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Дозволи обавештења са овог канала"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"Све категорије"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Још подешавања"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"Прилагодите: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"Прилагоди"</string>
     <string name="notification_done" msgid="5279426047273930175">"Готово"</string>
+    <string name="inline_undo" msgid="558916737624706010">"Опозови"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"контроле обавештења"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"опције за одлагање обавештења"</string>
@@ -737,8 +732,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"Прошири"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Умањи"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Затвори"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"Подешавања"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Превуците надоле да бисте одбили"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"Мени"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> је слика у слици"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 2d267df..d2da3b7 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -33,7 +33,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Pågående"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Meddelanden"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"Lågt batteri"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"Batterinivån är låg. Aktivera batterisparläge"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> kvar"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> återstår, cirka <xliff:g id="TIME">%s</xliff:g> kvar utifrån din användning"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> återstår, cirka <xliff:g id="TIME">%s</xliff:g> kvar"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> kvar. Batterisparläget är aktiverat."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"Det går inte att ladda via USB.\nAnvänd endast den laddare som levererades med telefonen."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"Det finns inget stöd för laddning via USB."</string>
@@ -67,14 +70,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Användaren som är inloggad på enheten för närvarande kan inte aktivera USB-felsökning. Byt till den primära användaren om du vill använda den här funktionen."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zooma för att fylla skärm"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Dra för att fylla skärmen"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Skärmdump"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Skärmdumpen sparas ..."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Skärmdumpen sparas ..."</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"Skärmdumpen sparas."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Skärmdumpen har tagits."</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"Visa skärmdumpen genom att trycka här."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"Det gick inte att ta någon skärmdump."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Det gick inte att spara skärmdumpen."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Det går inte att spara skärmdumpen eftersom lagringsutrymmet inte räcker."</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"Skärmdumpen sparas"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"Skärmdumpen har sparats"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"Visa skärmdumpen genom att trycka här"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"Det gick inte att ta en skärmdump"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"Det gick inte att spara skärmdumpen"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Det går inte att spara skärmdumpen eftersom lagringsutrymmet inte räcker"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Appen eller organisationen tillåter inte att du tar skärmdumpar"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Överföringsalternativ"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Montera som mediaspelare (MTP)"</string>
@@ -557,26 +561,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"På"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Med aviseringsinställningarna kan du ange prioritetsnivå från 0 till 5 för aviseringar från en app. \n\n"<b>"Nivå 5"</b>" \n– Visa högst upp i aviseringslistan\n– Tillåt avbrott i helskärmsläge \n– Snabbvisa alltid \n\n"<b>"Nivå 4"</b>" \n– Tillåt inte avbrott i helskärmsläge \n– Snabbvisa alltid \n\n"<b>"Nivå 3"</b>" \n- Tillåt inte avbrott i helskärmsläge \n– Snabbvisa aldrig \n\n"<b>"Nivå 2"</b>" \n– Tillåt inte avbrott i helskärmsläge \n– Snabbvisa aldrig \n– Aldrig med ljud eller vibration \n\n"<b>"Nivå 1"</b>" \n– Tillåt inte avbrott i helskärmsläge \n– Snabbvisa aldrig \n– Aldrig med ljud eller vibration \n– Visa inte på låsskärmen och i statusfältet \n– Visa längst ned i aviseringslistan \n\n"<b>"Nivå 0"</b>" \n– Blockera alla aviseringar från appen"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Aviseringar"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"Inga fler aviseringar av det här slaget visas"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> aviseringskategorier"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"Det finns inga aviseringskategorier i appen"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"Det går inte att inaktivera aviseringar från den här appen"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="other">1 av <xliff:g id="NUMBER_1">%s</xliff:g> aviseringskategorier från denna app</item>
-      <item quantity="one">1 av <xliff:g id="NUMBER_0">%s</xliff:g> aviseringskategorier från denna app</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> och <xliff:g id="NUMBER_5">%3$d</xliff:g> till</item>
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_0">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_1">%2$s</xliff:g> och <xliff:g id="NUMBER_2">%3$d</xliff:g> till</item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"De här aviseringarna visas inte längre"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"Vill du fortsätta visa de här aviseringarna?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"Stoppa aviseringar"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"Fortsätt visa"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"Vill du fortsätta visa aviseringar för den här appen?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"De här aviseringarna kan inte inaktiveras"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"Aviseringsinställningarna för <xliff:g id="APP_NAME">%1$s</xliff:g> är öppna"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"Aviseringsinställningarna för <xliff:g id="APP_NAME">%1$s</xliff:g> har stängts"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Tillåt aviseringar från den här kanalen"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"Alla kategorier"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Fler inställningar"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"Anpassa: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"Anpassa"</string>
     <string name="notification_done" msgid="5279426047273930175">"Klar"</string>
+    <string name="inline_undo" msgid="558916737624706010">"Ångra"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"inställningar för aviseringar"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"alternativ för att snooza aviseringar"</string>
@@ -731,8 +728,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"Utöka"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Minimera"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Stäng"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"Inställningar"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Tryck och dra nedåt för att avvisa"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"Meny"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> visas i bild-i-bild"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 58eac29..8cae1c4 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -35,8 +35,8 @@
     <string name="battery_low_title" msgid="6456385927409742437">"Betri inaisha"</string>
     <string name="battery_low_title_hybrid" msgid="6268991275887381595">"Chaji imepungua. Washa Kiokoa Betri"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"Imebakisha <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
-    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Imesalia <xliff:g id="PERCENTAGE">%s</xliff:g>, zimesalia takribani <xliff:g id="TIME">%s</xliff:g> kulingana na jinsi unavyotumia"</string>
-    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Imesalia <xliff:g id="PERCENTAGE">%s</xliff:g>, zimesalia takribani <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Imesalia <xliff:g id="PERCENTAGE">%s</xliff:g>, itadumu takribani <xliff:g id="TIME">%s</xliff:g> kulingana na jinsi unavyotumia"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Imesalia <xliff:g id="PERCENTAGE">%s</xliff:g>, itadumu takribani <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Imesalia <xliff:g id="PERCENTAGE">%s</xliff:g>. Umewasha Kiokoa Betri."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"Chaji ya USB haihamiliwi.\n Tumia chaka iliyopeanwa."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"Kuchaji kwa kutumia USB hakutumiki."</string>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index 544cd79..5a209b0 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -33,7 +33,13 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"செயலில் இருக்கும்"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"அறிவிப்புகள்"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"பேட்டரி குறைவு"</string>
+    <!-- no translation found for battery_low_title_hybrid (6268991275887381595) -->
+    <skip />
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> உள்ளது"</string>
+    <!-- no translation found for battery_low_percent_format_hybrid (6838677459286775617) -->
+    <skip />
+    <!-- no translation found for battery_low_percent_format_hybrid_short (9025795469949145586) -->
+    <skip />
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> மீதமுள்ளது. பேட்டரி சேமிப்பான் ஆன் செய்யப்பட்டுள்ளது."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"USB மூலம் சார்ஜ் செய்வது ஆதரிக்கப்படவில்லை.\nவழங்கப்பட்ட சார்ஜரை மட்டும் பயன்படுத்தவும்."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"USB சார்ஜிங் ஆதரிக்கப்படவில்லை."</string>
@@ -67,14 +73,22 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"தற்போது இந்தச் சாதனத்தில் உள்நுழைந்துள்ள பயனரால் USB பிழைத்திருத்தத்தை இயக்க முடியாது. இந்த அம்சத்தை இயக்க, முதன்மைப் பயனருக்கு மாறவும்."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"திரையை நிரப்ப அளவை மாற்று"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"திரையை நிரப்ப இழு"</string>
+    <!-- no translation found for global_action_screenshot (8329831278085426283) -->
+    <skip />
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"ஸ்க்ரீன் ஷாட்டைச் சேமிக்கிறது…"</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"ஸ்க்ரீன் ஷாட்டைச் சேமிக்கிறது…"</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"ஸ்க்ரீன் ஷாட் சேமிக்கப்படுகிறது."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"ஸ்கிரீன் ஷாட் எடுக்கப்பட்டது."</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"ஸ்கிரீன்ஷாட்டைப் பார்க்க, தட்டவும்."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"ஸ்க்ரீன் ஷாட்டை எடுக்க முடியவில்லை."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"ஸ்க்ரீன்ஷாட்டைச் சேமிக்கும் போது, பிழை ஏற்பட்டது."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"போதுமான சேமிப்பிடம் இல்லாததால் ஸ்கிரீன்ஷாட்டைச் சேமிக்க முடியவில்லை."</string>
+    <!-- no translation found for screenshot_saving_text (2545047868936087248) -->
+    <skip />
+    <!-- no translation found for screenshot_saved_title (5637073968117370753) -->
+    <skip />
+    <!-- no translation found for screenshot_saved_text (7574667448002050363) -->
+    <skip />
+    <!-- no translation found for screenshot_failed_title (9096484883063264803) -->
+    <skip />
+    <!-- no translation found for screenshot_failed_to_save_unknown_text (8844781948876286488) -->
+    <skip />
+    <!-- no translation found for screenshot_failed_to_save_text (3041612585107107310) -->
+    <skip />
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"ஸ்கிரீன் ஷாட்டுகளை எடுப்பதை, பயன்பாடு அல்லது உங்கள் நிறுவனம் அனுமதிக்கவில்லை"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB கோப்பு இடமாற்ற விருப்பங்கள்"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"(MTP) மீடியா பிளேயராக ஏற்று"</string>
@@ -557,26 +571,27 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"ஆஃப்"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"ஆற்றல்மிக்க அறிவிப்புக் கட்டுப்பாடுகள் மூலம், பயன்பாட்டின் அறிவிப்புகளுக்கு முக்கியத்துவ நிலையை (0-5) அமைக்கலாம். \n\n"<b>"நிலை 5"</b>" \n- அறிவிப்புப் பட்டியலின் மேலே காட்டும் \n- முழுத் திரைக் குறுக்கீட்டை அனுமதிக்கும் \n- எப்போதும் நடப்புத் திரையின் மேல் பகுதியில் அறிவிப்புகளைக் காட்டும் \n\n"<b>"நிலை 4"</b>" \n- முழுத் திரைக் குறுக்கீட்டைத் தடுக்கும் \n- எப்போதும் நடப்புத் திரையின் மேல் பகுதியில் அறிவிப்புகளைக் காட்டும் \n\n"<b>"நிலை 3"</b>" \n- முழுத் திரைக் குறுக்கீட்டைத் தடுக்கும் \n- ஒருபோதும் நடப்புத் திரையின் மேல் பகுதியில் அறிவிப்புகளைக் காட்டாது \n\n"<b>"நிலை 2"</b>" \n- முழுத் திரைக் குறுக்கீட்டைத் தடுக்கும் \n- ஒருபோதும் நடப்புத் திரையின் மேல் பகுதியில் அறிவிப்புகளைக் காட்டாது \n- ஒருபோதும் ஒலி எழுப்பாது, அதிர்வுறாது \n\n"<b>"நிலை 1"</b>" \n- முழுத் திரைக் குறுக்கீட்டைத் தடுக்கும் \n- ஒருபோதும் நடப்புத் திரையின் மேல் பகுதியில் அறிவிப்புகளைக் காட்டாது \n- ஒருபோதும் ஒலி எழுப்பாது அல்லது அதிர்வுறாது \n- பூட்டுத்திரை மற்றும் நிலைப்பட்டியிலிருந்து மறைக்கும் \n- அறிவிப்புகள் பட்டியலின் கீழே காட்டும் \n\n"<b>"நிலை 0"</b>" \n- பயன்பாட்டின் எல்லா அறிவிப்புகளையும் தடுக்கும்"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"அறிவிப்புகள்"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"இந்த அறிவிப்புகளை இனி பெறமாட்டீர்கள்"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> அறிவிப்பு வகைகள்"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"இந்தப் பயன்பாட்டில் அறிவிப்பு வகைகள் இல்லை"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"இந்தப் பயன்பாட்டிலிருந்து அறிவிப்புகளைப் பெறுவதை முடக்க முடியாது"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="other">இந்தப் பயன்பாடு வழங்கும் <xliff:g id="NUMBER_1">%s</xliff:g> அறிவிப்பு வகைகளில் ஒரு அறிவிப்பு வகை</item>
-      <item quantity="one">இந்தப் பயன்பாடு வழங்கும் <xliff:g id="NUMBER_0">%s</xliff:g> அறிவிப்பு வகையில் ஒரு அறிவிப்பு வகை</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g>, மேலும் <xliff:g id="NUMBER_5">%3$d</xliff:g> சேனல்கள்</item>
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_0">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_1">%2$s</xliff:g>, மேலும் <xliff:g id="NUMBER_2">%3$d</xliff:g> சேனல்</item>
-    </plurals>
+    <!-- no translation found for notification_channel_disabled (344536703863700565) -->
+    <skip />
+    <!-- no translation found for inline_keep_showing (8945102997083836858) -->
+    <skip />
+    <!-- no translation found for inline_stop_button (4172980096860941033) -->
+    <skip />
+    <!-- no translation found for inline_keep_button (6665940297019018232) -->
+    <skip />
+    <!-- no translation found for inline_keep_showing_app (1723113469580031041) -->
+    <skip />
+    <!-- no translation found for notification_unblockable_desc (1037434112919403708) -->
+    <skip />
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"<xliff:g id="APP_NAME">%1$s</xliff:g>க்கான அறிவிப்புக் கட்டுப்பாடுகள் திறக்கப்பட்டன"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"<xliff:g id="APP_NAME">%1$s</xliff:g>க்கான அறிவிப்புக் கட்டுப்பாடுகள் மூடப்பட்டன"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"இந்தச் சேனலிலிருந்து அறிவிப்புகளைப் பெறுவதை அனுமதிக்கும்"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"எல்லா வகைகளும்"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"மேலும் அமைப்புகள்"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"தனிப்பயனாக்கு: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <!-- no translation found for notification_app_settings (420348114670768449) -->
+    <skip />
     <string name="notification_done" msgid="5279426047273930175">"முடிந்தது"</string>
+    <!-- no translation found for inline_undo (558916737624706010) -->
+    <skip />
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"அறிவிப்புக் கட்டுப்பாடுகள்"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"அறிவிப்பை உறக்கநிலையாக்கும் விருப்பங்கள்"</string>
@@ -731,8 +746,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"விரி"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"சிறிதாக்கு"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"மூடு"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"அமைப்புகள்"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"நிராகரிக்க, கீழே இழுக்கவும்"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"மெனு"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> தற்போது பிக்ச்சர்-இன்-பிக்ச்சரில் உள்ளது"</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 5b31061..01b75e3 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -33,7 +33,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"ดำเนินอยู่"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"การแจ้งเตือน"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"แบตเตอรี่เหลือน้อย"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"แบตเตอรี่เหลือน้อย โปรดเปิดโหมดประหยัดแบตเตอรี่"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"เหลืออีก <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"เหลือ <xliff:g id="PERCENTAGE">%s</xliff:g> หรืออีกราว <xliff:g id="TIME">%s</xliff:g> ขึ้นอยู่กับการใช้งานของคุณ"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"เหลือ <xliff:g id="PERCENTAGE">%s</xliff:g> หรืออีกราว <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"แบตเตอรี่เหลือ <xliff:g id="PERCENTAGE">%s</xliff:g> เปิดโหมดประหยัดแบตเตอรี่อยู่"</string>
     <string name="invalid_charger" msgid="4549105996740522523">"ไม่สนับสนุนการชาร์จแบบ USB\nใช้เฉพาะที่ชาร์จที่ให้มาเท่านั้น"</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"ไม่รองรับการชาร์จผ่าน USB"</string>
@@ -67,14 +70,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"ผู้ใช้ที่ลงชื่อเข้าใช้อุปกรณ์อยู่ในขณะนี้ไม่สามารถเปิดการแก้ไขข้อบกพร่องผ่าน USB ได้ หากต้องการใช้ฟีเจอร์นี้ ให้เปลี่ยนไปเป็นผู้ใช้หลัก"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"ขยายจนเต็มหน้าจอ"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"ยืดจนเต็มหน้าจอ"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"ภาพหน้าจอ"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"กำลังบันทึกภาพหน้าจอ..."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"กำลังบันทึกภาพหน้าจอ..."</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"กำลังบันทึกภาพหน้าจอ"</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"จับภาพหน้าจอแล้ว"</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"แตะเพื่อดูภาพหน้าจอของคุณ"</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"ไม่สามารถจับภาพหน้าจอ"</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"พบปัญหาขณะกำลังบันทึกภาพหน้าจอ"</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"ไม่สามารถบันทึกภาพหน้าจอเนื่องจากพื้นที่เก็บข้อมูลมีจำกัด"</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"กำลังบันทึกภาพหน้าจอ"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"บันทึกภาพหน้าจอแล้ว"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"แตะเพื่อดูภาพหน้าจอ"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"จับภาพหน้าจอไม่ได้"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"พบปัญหาขณะบันทึกภาพหน้าจอ"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"บันทึกภาพหน้าจอไม่ได้เนื่องจากพื้นที่เก็บข้อมูลมีจำกัด"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"แอปหรือองค์กรของคุณไม่อนุญาตให้จับภาพหน้าจอ"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"ตัวเลือกการถ่ายโอนไฟล์ USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"ต่อเชื่อมเป็นโปรแกรมเล่นสื่อ (MTP)"</string>
@@ -557,26 +561,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"ปิด"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"ส่วนควบคุมการแจ้งเตือนแบบเปิด/ปิดช่วยให้คุณตั้งค่าระดับความสำคัญสำหรับการแจ้งเตือนของแอปได้ตั้งแต่ระดับ 0-5 \n\n"<b>"ระดับ 5"</b>" \n- แสดงที่ด้านบนของรายการแจ้งเตือน \n- อนุญาตให้รบกวนแบบเต็มหน้าจอ \n- อนุญาตให้แสดงชั่วครู่ \n\n"<b>"ระดับ 4"</b>" \n- ป้องกันการรบกวนแบบเต็มหน้าจอ \n- แสดงชั่วครู่เสมอ \n\n"<b>"ระดับ 3"</b>" \n- ป้องกันการรบกวนแบบเต็มหน้าจอ \n- ไม่แสดงชั่วครู่เลย \n\n"<b>"ระดับ 2"</b>" \n- ป้องกันการรบกวนแบบเต็มหน้าจอ \n- ไม่แสดงชั่วครู่เลย \n- ไม่ส่งเสียงหรือสั่นเลย \n\n"<b>"ระดับ 1"</b>" \n- ป้องกันการรบกวนแบบเต็มหน้าจอ \n- ไม่แสดงชั่วครู่เลย \n- ไม่ส่งเสียงหรือสั่นเลย \n- ซ่อนจากหน้าจอล็อกและแถบสถานะ \n- แสดงที่ด้านล่างของรายการแจ้งเตือน \n\n"<b>"ระดับ 0"</b>" \n- บล็อกการแจ้งเตือนทั้งหมดจากแอป"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"การแจ้งเตือน"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"คุณจะไม่ได้รับการแจ้งเตือนเหล่านี้อีก"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"หมวดหมู่การแจ้งเตือน <xliff:g id="NUMBER">%d</xliff:g> หมวด"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"แอปนี้ไม่มีหมวดหมู่การแจ้งเตือน"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"ไม่สามารถปิดการแจ้งเตือนจากแอปนี้"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="other">การแจ้งเตือน 1 ใน <xliff:g id="NUMBER_1">%s</xliff:g> หมวดหมู่จากแอปนี้</item>
-      <item quantity="one">การแจ้งเตือน 1 ใน <xliff:g id="NUMBER_0">%s</xliff:g> หมวดหมู่จากแอปนี้</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> และอีก <xliff:g id="NUMBER_5">%3$d</xliff:g> ช่องทาง</item>
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_0">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_1">%2$s</xliff:g> และอีก <xliff:g id="NUMBER_2">%3$d</xliff:g> ช่องทาง</item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"คุณจะไม่เห็นการแจ้งเตือนเหล่านี้อีก"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"แสดงการแจ้งเตือนเหล่านี้ต่อไปไหม"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"ปิดการแจ้งเตือน"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"แสดงต่อไป"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"แสดงการแจ้งเตือนจากแอปนี้ต่อไปไหม"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"ปิดการแจ้งเตือนเหล่านี้ไม่ได้"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"ส่วนควบคุมการแจ้งเตือนของ <xliff:g id="APP_NAME">%1$s</xliff:g> เปิดอยู่"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"ส่วนควบคุมการแจ้งเตือนของ <xliff:g id="APP_NAME">%1$s</xliff:g> ปิดอยู่"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"อนุญาตการแจ้งเตือนจากช่องนี้"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"ทุกหมวดหมู่"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"การตั้งค่าเพิ่มเติม"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"ปรับแต่ง: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"ปรับแต่ง"</string>
     <string name="notification_done" msgid="5279426047273930175">"เสร็จสิ้น"</string>
+    <string name="inline_undo" msgid="558916737624706010">"เลิกทำ"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"ส่วนควบคุมการแจ้งเตือน"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"ตัวเลือกการปิดเสียงแจ้งเตือนชั่วคราว"</string>
@@ -731,8 +728,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"ขยาย"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"ย่อเล็กสุด"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"ปิด"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"การตั้งค่า"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"ลากลงเพื่อปิด"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"เมนู"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> ใช้การแสดงภาพซ้อนภาพ"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index dadd57e..5352cf0 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -33,7 +33,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Nagpapatuloy"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Mga Notification"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"Mahina na ang baterya"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"Paubos na ang baterya. I-on ang Pangtipid sa Baterya"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> na lang ang natitira"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> na lang ang natitira, humigit-kumulang <xliff:g id="TIME">%s</xliff:g> ang natitira batay sa iyong paggamit"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> na lang ang natitira, humigit-kumulang <xliff:g id="TIME">%s</xliff:g> ang natitira"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> na lang ang natitira. Naka-on ang Pangtipid sa Baterya."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"Hindi sinusuportahan ang pag-charge sa USB.\nGamitin lang ang ibinigay na charger."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"Hindi sinusuportahan ang pagtsa-charge gamit ang USB."</string>
@@ -67,14 +70,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Hindi mao-on ng user na kasalukuyang naka-sign in sa device na ito ang pag-debug ng USB. Upang magamit ang feature na ito, lumipat sa pangunahing user."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"I-zoom upang punan screen"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"I-stretch upang mapuno screen"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Screenshot"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Sine-save ang screenshot…"</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Sine-save ang screenshot…"</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"Sine-save ang screenshot."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Nakuha ang screenshot."</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"I-tap upang tingnan ang iyong screenshot."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"Hindi makuha ang screenshot."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Nagkaroon ng problema habang sine-save ang screenshot."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Hindi ma-save ang screenshot dahil sa limitadong espasyo ng storage."</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"Sine-save ang screenshot"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"Na-save ang screenshot"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"I-tap upang tingnan ang iyong screenshot"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"Hindi makunan ng screenshot"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"Nagkaproblema habang sine-save ang screenshot"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Hindi ma-save ang screenshot dahil sa limitadong espasyo ng storage"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Hindi pinahihintulutan ng app o ng iyong organisasyon ang pagkuha ng mga screenshot"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Opsyon paglipat ng USB file"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"I-mount bilang isang media player (MTP)"</string>
@@ -557,26 +561,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"Naka-off"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Sa pamamagitan ng mga kontrol sa notification ng power, magagawa mong itakda ang antas ng kahalagahan ng mga notification ng isang app mula 0 hanggang 5. \n\n"<b>"Antas 5"</b>" \n- Ipakita sa itaas ng listahan ng notification \n- Payagan ang pag-istorbo kapag full screen \n- Palaging sumilip \n\n"<b>"Antas 4"</b>" \n- Pigilan ang pag-istorbo kapag full screen \n- Palaging sumilip \n\n"<b>"Antas 3"</b>" \n- Pigilan ang pag-istorbo kapag full screen \n- Huwag kailanman sumilip \n\n"<b>"Antas 2"</b>" \n- Pigilan ang pag-istorbo kapag full screen \n- Huwag kailanman sumilip \n- Huwag kailanman tumunog o mag-vibrate \n\n"<b>"Antas 1"</b>" \n- Pigilan ang pag-istorbo kapag full screen \n- Huwag kailanman sumilip \n- Huwag kailanman tumunog o mag-vibrate \n- Itago sa lock screen at status bar \n- Ipakita sa ibaba ng listahan ng notification \n\n"<b>"Antas 0"</b>" \n- I-block ang lahat ng notification mula sa app"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Mga Notification"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"Hindi ka na makakatanggap ng ganitong mga notification"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> (na) kategorya ng notification"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"Walang kategorya ng notification ang app na ito"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"Hindi maaaring i-off ang mga notification mula sa app na ito"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="one">1 sa <xliff:g id="NUMBER_1">%s</xliff:g> kategorya ng notification mula sa app na ito</item>
-      <item quantity="other">1 sa <xliff:g id="NUMBER_1">%s</xliff:g> na kategorya ng notification mula sa app na ito</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g>, at <xliff:g id="NUMBER_5">%3$d</xliff:g> pang iba</item>
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g>, at <xliff:g id="NUMBER_5">%3$d</xliff:g> pang iba</item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"Hindi mo na makikita ang mga notification na ito"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"Patuloy na ipakita ang mga notification na ito?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"Ihinto ang mga notification"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"Patuloy na ipakita"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"Patuloy na ipakita ang mga notification mula sa app na ito?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"Hindi maaaring i-off ang mga notification na ito"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"Binuksan ang mga kontrol sa notification para sa <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"Isinara ang mga kontrol sa notification para sa <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Payagan ang mga notification mula sa channel na ito"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"Lahat ng Kategorya"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Higit pang mga setting"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"I-customize: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"I-customize"</string>
     <string name="notification_done" msgid="5279426047273930175">"Tapos Na"</string>
+    <string name="inline_undo" msgid="558916737624706010">"I-undo"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"mga kontrol ng notification"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"mga opsyon sa pag-snooze ng notification"</string>
@@ -731,8 +728,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"Palawakin"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"I-minimize"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Isara"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"Mga Setting"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"I-drag pababa upang i-dismiss"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"Menu"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"Nasa picture-in-picture ang <xliff:g id="NAME">%s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index d2d8ac6..092cfa5 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -33,7 +33,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Sürüyor"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Bildirimler"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"Pil gücü düşük"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"Pil az. Pil Tasarrufu\'nu açın"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> kaldı"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> kaldı (kullanımınıza göre yaklaşık <xliff:g id="TIME">%s</xliff:g>)"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> (yaklaşık <xliff:g id="TIME">%s</xliff:g>) kaldı"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> kaldı. Pil Tasarrufu açık."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"USB üzerinden şarj desteklenmiyor.\nYalnızca ürünle birlikte verilen şarj cihazını kullanın."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"USB şarjı desteklenmiyor."</string>
@@ -67,14 +70,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Bu cihazda geçerli olarak oturum açmış olan kullanıcı, USB hata ayıklama özelliğini açamaz. Bu özelliği kullanmak için birincil kullanıcıya geçin."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Yakınlaştır (ekranı kaplasın)"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Genişlet (ekran kapansın)"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Ekran görüntüsü"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Ekran görüntüsü kaydediliyor..."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Ekran görüntüsü kaydediliyor..."</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"Ekran görüntüsü kaydediliyor."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Ekran görüntüsü alındı."</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"Ekran görüntünüzü görüntülemek için dokunun."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"Ekran görüntüsü alınamadı."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Ekran görüntüsü kaydedilirken sorun oluştu."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Depolama alanı sınırlı olduğundan ekran görüntüsü kaydedilemiyor."</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"Ekran görüntüsü kaydediliyor"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"Ekran görüntüsü kaydedildi"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"Ekran görüntünüzü görmek için dokunun"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"Ekran görüntüsü alınamadı"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"Ekran görüntüsü kaydedilirken sorun oluştu"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Depolama alanı sınırlı olduğundan ekran görüntüsü kaydedilemiyor"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Uygulama veya kuruluşunuz, ekran görüntüsü alınmasına izin vermiyor."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB dosya aktarım seçenekleri"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Medya oynatıcı olarak ekle (MTP)"</string>
@@ -557,26 +561,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"Kapalı"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Güç bildirim kontrolleriyle, bir uygulamanın bildirimleri için 0 ile 5 arasında bir önem düzeyi ayarlayabilirsiniz. \n\n"<b>"5. Düzey"</b>" \n- Bildirim listesinin en üstünde gösterilsin \n- Tam ekran kesintisine izin verilsin \n- Ekranda her zaman kısaca belirsin \n\n"<b>"4. Düzey"</b>" \n- Tam ekran kesintisi engellensin \n- Ekranda her zaman kısaca belirsin \n\n"<b>"3. Düzey"</b>" \n- Tam ekran kesintisi engellensin \n- Ekranda hiçbir zaman kısaca belirmesin \n\n"<b>"2. Düzey"</b>" \n- Tam ekran kesintisi engellensin \n- Ekranda hiçbir zaman belirmesin \n- Hiçbir zaman ses çıkarmasın ve titreştirmesin \n\n"<b>"1. Düzey"</b>" \n- Tam ekran kesintisi engellensin \n- Ekranda hiçbir zaman kısaca belirmesin \n- Hiçbir zaman ses çıkarmasın veya titreştirmesin \n- Kilit ekranından ve durum çubuğundan gizlensin \n- Bildirim listesinin en altında gösterilsin \n\n"<b>"0. Düzey"</b>" \n- Uygulamadan gelen tüm bildirimler engellensin"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Bildirimler"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"Bu bildirimleri artık almayacaksınız"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> bildirim kategorisi"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"Bu uygulamanın bildirim kategorisi yok"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"Bu uygulamanın bildirimleri kapatılamaz"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="other">Bu uygulamadaki <xliff:g id="NUMBER_1">%s</xliff:g> bildirim kategorisinden 1 tanesi</item>
-      <item quantity="one">Bu uygulamadaki <xliff:g id="NUMBER_0">%s</xliff:g> bildirim kategorisinden 1 tanesi</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> ve diğer <xliff:g id="NUMBER_5">%3$d</xliff:g></item>
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_0">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_1">%2$s</xliff:g> ve <xliff:g id="NUMBER_2">%3$d</xliff:g> tane daha</item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"Bu bildirimleri artık görmeyeceksiniz"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"Bu bildirimler gösterilmeye devam edilsin mi?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"Bildirimleri durdur"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"Göstermeye devam et"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"Bu uygulamadan gelen bildirimler gösterilmeye devam edilsin mi?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"Bu bildirimler kapatılamaz"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"<xliff:g id="APP_NAME">%1$s</xliff:g> için bildirim kontrolleri açıldı"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"<xliff:g id="APP_NAME">%1$s</xliff:g> için bildirim kontrolleri kapatıldı"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Bu kanaldan bildirimlere izin verir"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"Tüm Kategoriler"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Diğer ayarlar"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"Özelleştir: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"Özelleştir"</string>
     <string name="notification_done" msgid="5279426047273930175">"Bitti"</string>
+    <string name="inline_undo" msgid="558916737624706010">"Geri al"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"Bildirim kontrolleri"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"bildirim erteleme seçenekleri"</string>
@@ -731,8 +728,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"Genişlet"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Simge durumuna getir"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Kapat"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"Ayarlar"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Kapatmak için aşağıya sürükleyin"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"Menü"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g>, pencere içinde pencere özelliğini kullanıyor"</string>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index e202363..ffcb60a 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -33,13 +33,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"جاری"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"اطلاعات"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"بیٹری کم ہے"</string>
-    <!-- no translation found for battery_low_title_hybrid (6268991275887381595) -->
-    <skip />
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"بیٹری کم ہے۔ بیٹری سیور آن کریں"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"<xliff:g id="PERCENTAGE">%s</xliff:g> باقی ہے"</string>
-    <!-- no translation found for battery_low_percent_format_hybrid (6838677459286775617) -->
-    <skip />
-    <!-- no translation found for battery_low_percent_format_hybrid_short (9025795469949145586) -->
-    <skip />
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"<xliff:g id="PERCENTAGE">%s</xliff:g> باقی، آپ کے استعمال کی بنیاد پر تقریباً <xliff:g id="TIME">%s</xliff:g> باقی ہے"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"<xliff:g id="PERCENTAGE">%s</xliff:g> باقی، تقریباً <xliff:g id="TIME">%s</xliff:g> باقی ہے"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"<xliff:g id="PERCENTAGE">%s</xliff:g> باقی ہے۔ بیٹری سیور آن ہے۔"</string>
     <string name="invalid_charger" msgid="4549105996740522523">"‏USB چارجنگ تعاون یافتہ نہیں ہے.\nصرف فراہم کردہ چارجر کا ہی استعمال کریں۔"</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"‏USB چارجنگ تعاون یافتہ نہیں ہے۔"</string>
@@ -73,22 +70,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"‏اس آلہ پر فی الحال سائن ان کردہ صارف USB ڈیبگنگ آن نہیں کر سکتا۔ اس خصوصیت کا استعمال کرنے کیلئے، ابتدائی صارف پر سوئچ کریں۔"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"پوری سکرین پر زوم کریں"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"پوری سکرین پر پھیلائیں"</string>
-    <!-- no translation found for global_action_screenshot (8329831278085426283) -->
-    <skip />
+    <string name="global_action_screenshot" msgid="8329831278085426283">"اسکرین شاٹ"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"اسکرین شاٹ محفوظ ہو رہا ہے…"</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"اسکرین شاٹ محفوظ ہو رہا ہے…"</string>
-    <!-- no translation found for screenshot_saving_text (2545047868936087248) -->
-    <skip />
-    <!-- no translation found for screenshot_saved_title (5637073968117370753) -->
-    <skip />
-    <!-- no translation found for screenshot_saved_text (7574667448002050363) -->
-    <skip />
-    <!-- no translation found for screenshot_failed_title (9096484883063264803) -->
-    <skip />
-    <!-- no translation found for screenshot_failed_to_save_unknown_text (8844781948876286488) -->
-    <skip />
-    <!-- no translation found for screenshot_failed_to_save_text (3041612585107107310) -->
-    <skip />
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"اسکرین شاٹ محفوظ کیا جا رہا ہے"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"اسکرین شاٹ محفوظ ہو گیا"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"اپنا اسکرین شاٹ دیکھنے کیلئے تھپتھپائیں"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"اسکرین شاٹ کیپچر نہیں ہو سکا"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"اسکرین شاٹ محفوظ کرتے وقت مسئلہ پیش آ گیا"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"اسٹوریج کی محدود جگہ کی وجہ سے اسکرین شاٹ کو محفوظ نہیں کیا جا سکتا"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"ایپ یا آپ کی تنظیم کی جانب سے اسکرین شاٹس لینے کی اجازت نہیں ہے"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"‏USB فائل منتقل کرنیکے اختیارات"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"‏ایک میڈیا پلیئر (MTP) کے بطور ماؤنٹ کریں"</string>
@@ -571,27 +561,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"آف"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"پاور اطلاع کنٹرولز کے ساتھ آپ کسی ایپ کی اطلاعات کیلئے 0 سے 5 تک اہمیت کی سطح سیٹ کر سکتے ہیں۔ \n\n"<b>"سطح 5"</b>\n"- اطلاعات کی فہرست کے اوپر دکھائیں \n- پوری اسکرین کی مداخلت کی اجازت دیں \n- ہمیشہ جھانکنا\n\n"<b>"سطح 4"</b>\n"- پوری اسکرین کی مداخلت کو روکیں \n- ہمیشہ جھانکنا\n\n"<b>"سطح 3"</b>\n"- پوری اسکرین کی مداخلت کو روکیں \n- کبھی نہ جھانکنا \n\n"<b>"سطح 2"</b>\n"- پوری اسکرین کی مداخلت کو روکیں \n- کبھی نہ جھانکنا \n- کبھی آواز اور ارتعاش پیدا نہ کرنا \n\n"<b>" سطح 1"</b>\n"- پوری اسکرین کی مداخلت کو روکنا \n- کبھی نہ جھانکنا \n- کبھی بھی آواز یا ارتعاش پیدا نہ کرنا\n- مقفل اسکرین اور اسٹیٹس بار سے چھپانا \n - اطلاع کی فہرست کی نیچے دکھانا \n\n"<b>"سطح 0"</b>\n"- ایپ سے تمام اطلاعات مسدود کریں"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"اطلاعات"</string>
-    <!-- no translation found for notification_channel_disabled (344536703863700565) -->
-    <skip />
-    <!-- no translation found for inline_keep_showing (8945102997083836858) -->
-    <skip />
-    <!-- no translation found for inline_stop_button (4172980096860941033) -->
-    <skip />
-    <!-- no translation found for inline_keep_button (6665940297019018232) -->
-    <skip />
-    <!-- no translation found for inline_keep_showing_app (1723113469580031041) -->
-    <skip />
-    <!-- no translation found for notification_unblockable_desc (1037434112919403708) -->
-    <skip />
+    <string name="notification_channel_disabled" msgid="344536703863700565">"آپ کو یہ اطلاعات مزید دکھائی نہیں دیں گی"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"یہ اطلاعات دکھانا جاری رکھیں؟"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"اطلاعات روک دیں"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"دکھانا جاری رکھیں"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"اس ایپ کی طرف سے اطلاعات دکھانا جاری رکھیں؟"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"ان اطلاعات کو آف نہیں کیا جا سکتا"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"<xliff:g id="APP_NAME">%1$s</xliff:g> کیلئے اطلاعی کنٹرولز کھلے ہیں"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"<xliff:g id="APP_NAME">%1$s</xliff:g> کیلئے اطلاعی کنٹرولز بند کر دئے گئے ہیں"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"اس چینل سے اطلاعات کی اجازت دیں"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"مزید ترتیبات"</string>
-    <!-- no translation found for notification_app_settings (420348114670768449) -->
-    <skip />
+    <string name="notification_app_settings" msgid="420348114670768449">"حسب ضرورت بنائیں"</string>
     <string name="notification_done" msgid="5279426047273930175">"ہوگیا"</string>
-    <!-- no translation found for inline_undo (558916737624706010) -->
-    <skip />
+    <string name="inline_undo" msgid="558916737624706010">"کالعدم کریں"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"اطلاع کے کنٹرولز"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"اطلاع اسنوز کرنے کے اختیارات"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 75b18ca..e5c25dc 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -33,7 +33,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Đang diễn ra"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Thông báo"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"Pin yếu"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"Pin yếu. Bật Trình tiết kiệm pin"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"Còn lại <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"Còn lại <xliff:g id="PERCENTAGE">%s</xliff:g>, còn khoảng <xliff:g id="TIME">%s</xliff:g> dựa trên mức sử dụng của bạn"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"Còn lại <xliff:g id="PERCENTAGE">%s</xliff:g>, còn khoảng <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"Còn lại <xliff:g id="PERCENTAGE">%s</xliff:g>. Trình tiết kiệm pin đang bật."</string>
     <string name="invalid_charger" msgid="4549105996740522523">"Không hỗ trợ sạc qua USB.\nChỉ sử dụng bộ sạc được cung cấp."</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"Sạc qua USB không được hỗ trợ."</string>
@@ -67,14 +70,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"Người dùng hiện đã đăng nhập vào thiết bị này không thể bật tính năng gỡ lỗi USB. Để sử dụng tính năng này, hãy chuyển sang người dùng chính."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"T.phóng để lấp đầy m.hình"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"Giãn ra để lấp đầy m.hình"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"Ảnh chụp màn hình"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Đang lưu ảnh chụp màn hình..."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"Đang lưu ảnh chụp màn hình..."</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"Ảnh chụp màn hình đang được lưu."</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"Đã chụp ảnh màn hình."</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"Nhấn để xem ảnh chụp màn hình của bạn."</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"Không thể chụp ảnh màn hình."</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Đã gặp phải sự cố khi đang lưu ảnh chụp màn hình."</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Không thể lưu ảnh chụp màn hình do giới hạn dung lượng bộ nhớ."</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"Đang lưu ảnh chụp màn hình"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"Đã lưu ảnh chụp màn hình"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"Nhấn để xem ảnh chụp màn hình của bạn"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"Không thể chụp ảnh màn hình"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"Đã xảy ra sự cố khi lưu ảnh chụp màn hình"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"Không thể lưu ảnh chụp màn hình do giới hạn dung lượng bộ nhớ"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Ứng dụng hoặc tổ chức của bạn không cho phép chụp ảnh màn hình"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"Tùy chọn truyền tệp USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Gắn như một trình phát đa phương tiện (MTP)"</string>
@@ -559,26 +563,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"Tắt"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"Với các kiểm soát thông báo nguồn, bạn có thể đặt cấp độ quan trọng từ 0 đến 5 cho các thông báo của ứng dụng. \n\n"<b>"Cấp 5"</b>" \n- Hiển thị ở đầu danh sách thông báo \n- Cho phép gián đoạn ở chế độ toàn màn hình \n- Luôn xem nhanh \n\n"<b>"Cấp 4"</b>" \n- Ngăn gián đoạn ở chế độ toàn màn hình \n- Luôn xem nhanh \n\n"<b>"Cấp 3"</b>" \n- Ngăn gián đoạn ở chế độ toàn màn hình \n- Không bao giờ xem nhanh \n\n"<b>"Cấp 2"</b>" \n- Ngăn gián đoạn ở chế độ toàn màn hình \n- Không bao giờ xem nhanh \n- Không bao giờ có âm báo và rung \n\n"<b>"Cấp 1"</b>" \n- Ngăn gián đoạn ở chế độ toàn màn hình \n- Không bao giờ xem nhanh \n- Không bao giờ có âm báo và rung \n- Ẩn khỏi màn hình khóa và thanh trạng thái \n- Hiển thị ở cuối danh sách thông báo \n\n"<b>"Cấp 0"</b>" \n- Chặn tất cả các thông báo từ ứng dụng"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"Thông báo"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"Bạn sẽ không nhận được những thông báo này nữa"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> danh mục thông báo"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"Ứng dụng này không có loại thông báo"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"Không thể tắt thông báo từ ứng dụng này"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="other">1 trên tổng số <xliff:g id="NUMBER_1">%s</xliff:g> loại thông báo từ ứng dụng này</item>
-      <item quantity="one">1 trên tổng số <xliff:g id="NUMBER_0">%s</xliff:g> loại thông báo từ ứng dụng này</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> và <xliff:g id="NUMBER_5">%3$d</xliff:g> kênh khác</item>
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_0">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_1">%2$s</xliff:g> và <xliff:g id="NUMBER_2">%3$d</xliff:g> kênh khác</item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"Bạn sẽ không thấy các thông báo này nữa"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"Tiếp tục hiển thị các thông báo này?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"Dừng thông báo"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"Tiếp tục hiển thị"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"Tiếp tục hiển thị các thông báo từ ứng dụng này?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"Không thể tắt các thông báo này"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"Đã mở điều khiển thông báo đối với <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"Đã đóng điều khiển thông báo đối với <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"Cho phép thông báo từ kênh này"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"Tất cả danh mục"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"Cài đặt khác"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"Tùy chỉnh: <xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"Tùy chỉnh"</string>
     <string name="notification_done" msgid="5279426047273930175">"Xong"</string>
+    <string name="inline_undo" msgid="558916737624706010">"Hoàn tác"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"điều khiển thông báo"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"Tùy chọn báo lại thông báo"</string>
@@ -733,8 +730,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"Mở rộng"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"Thu nhỏ"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"Đóng"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"Cài đặt"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Kéo xuống để loại bỏ"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"Menu"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> đang ở chế độ ảnh trong ảnh"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 16161ee..94a9961 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -33,7 +33,13 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"正在进行的"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"通知"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"电池电量偏低"</string>
+    <!-- no translation found for battery_low_title_hybrid (6268991275887381595) -->
+    <skip />
     <string name="battery_low_percent_format" msgid="2900940511201380775">"剩余<xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
+    <!-- no translation found for battery_low_percent_format_hybrid (6838677459286775617) -->
+    <skip />
+    <!-- no translation found for battery_low_percent_format_hybrid_short (9025795469949145586) -->
+    <skip />
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"剩余 <xliff:g id="PERCENTAGE">%s</xliff:g>。省电模式已开启。"</string>
     <string name="invalid_charger" msgid="4549105996740522523">"不支持USB充电功能。\n只能使用随附的充电器充电。"</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"不支持USB充电。"</string>
@@ -67,14 +73,22 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"目前已登录此设备的用户无法开启 USB 调试功能。要使用此功能,请切换为主要用户的帐号。"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"缩放以填满屏幕"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"拉伸以填满屏幕"</string>
+    <!-- no translation found for global_action_screenshot (8329831278085426283) -->
+    <skip />
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"正在保存屏幕截图..."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"正在保存屏幕截图..."</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"正在保存屏幕截图。"</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"已抓取屏幕截图。"</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"点按即可查看您的屏幕截图。"</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"无法抓取屏幕截图。"</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"保存屏幕截图时出现问题。"</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"由于存储空间有限,无法保存屏幕截图。"</string>
+    <!-- no translation found for screenshot_saving_text (2545047868936087248) -->
+    <skip />
+    <!-- no translation found for screenshot_saved_title (5637073968117370753) -->
+    <skip />
+    <!-- no translation found for screenshot_saved_text (7574667448002050363) -->
+    <skip />
+    <!-- no translation found for screenshot_failed_title (9096484883063264803) -->
+    <skip />
+    <!-- no translation found for screenshot_failed_to_save_unknown_text (8844781948876286488) -->
+    <skip />
+    <!-- no translation found for screenshot_failed_to_save_text (3041612585107107310) -->
+    <skip />
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"此应用或您所在的单位不允许进行屏幕截图"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB文件传输选项"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"作为媒体播放器(MTP)装载"</string>
@@ -557,26 +571,27 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"关闭"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"利用高级通知设置,您可以为应用通知设置从 0 级到 5 级的重要程度等级。\n\n"<b>"5 级"</b>" \n- 在通知列表顶部显示 \n- 允许全屏打扰 \n- 一律短暂显示通知 \n\n"<b>"4 级"</b>" \n- 禁止全屏打扰 \n- 一律短暂显示通知 \n\n"<b>"3 级"</b>" \n- 禁止全屏打扰 \n- 一律不短暂显示通知 \n\n"<b>"2 级"</b>" \n- 禁止全屏打扰 \n- 一律不短暂显示通知 \n- 一律不发出声音或振动 \n\n"<b>"1 级"</b>" \n- 禁止全屏打扰 \n- 一律不短暂显示通知 \n- 一律不发出声音或振动 \n- 不在锁定屏幕和状态栏中显示 \n- 在通知列表底部显示 \n\n"<b>"0 级"</b>" \n- 屏蔽应用的所有通知"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"通知"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"您将不会再收到这类通知"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> 个通知类别"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"此应用没有通知类别"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"无法关闭来自此应用的通知"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="other">此应用指定的 1 个通知类别(共 <xliff:g id="NUMBER_1">%s</xliff:g> 个)</item>
-      <item quantity="one">此应用指定的 1 个通知类别(共 <xliff:g id="NUMBER_0">%s</xliff:g> 个)</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>、<xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>、<xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g>以及另外 <xliff:g id="NUMBER_5">%3$d</xliff:g> 项</item>
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_0">%1$s</xliff:g>、<xliff:g id="CHANNEL_NAME_2_1">%2$s</xliff:g>以及另外 <xliff:g id="NUMBER_2">%3$d</xliff:g> 项</item>
-    </plurals>
+    <!-- no translation found for notification_channel_disabled (344536703863700565) -->
+    <skip />
+    <!-- no translation found for inline_keep_showing (8945102997083836858) -->
+    <skip />
+    <!-- no translation found for inline_stop_button (4172980096860941033) -->
+    <skip />
+    <!-- no translation found for inline_keep_button (6665940297019018232) -->
+    <skip />
+    <!-- no translation found for inline_keep_showing_app (1723113469580031041) -->
+    <skip />
+    <!-- no translation found for notification_unblockable_desc (1037434112919403708) -->
+    <skip />
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"<xliff:g id="APP_NAME">%1$s</xliff:g>的通知控件已打开"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"<xliff:g id="APP_NAME">%1$s</xliff:g>的通知控件已关闭"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"允许接收来自此频道的通知"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"所有类别"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"更多设置"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"自定义:<xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <!-- no translation found for notification_app_settings (420348114670768449) -->
+    <skip />
     <string name="notification_done" msgid="5279426047273930175">"完成"</string>
+    <!-- no translation found for inline_undo (558916737624706010) -->
+    <skip />
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g><xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"通知设置"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"通知延后选项"</string>
@@ -731,8 +746,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"展开"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"最小化"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"关闭"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"设置"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"向下拖动即可关闭"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"菜单"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g>目前位于“画中画”中"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index e0ab7e4..3e624f2 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -33,7 +33,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"持續進行"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"通知"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"電量低"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"電量不足。請開啟省電模式"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"剩餘 <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"電量剩餘 <xliff:g id="PERCENTAGE">%s</xliff:g>,根據您的使用情況,剩餘時間大約 <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"電量剩餘 <xliff:g id="PERCENTAGE">%s</xliff:g>,剩餘時間大約 <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"剩餘 <xliff:g id="PERCENTAGE">%s</xliff:g>。省電模式已開啟。"</string>
     <string name="invalid_charger" msgid="4549105996740522523">"不支援 USB 充電。\n僅能使用隨附的充電器。"</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"不支援 USB 充電功能。"</string>
@@ -67,14 +70,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"目前登入此裝置的使用者無法啟用 USB 偵錯功能。如要使用此功能,請切換至主要使用者。"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"放大為全螢幕"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"放大為全螢幕"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"擷取螢幕畫面"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"正在儲存螢幕擷取畫面..."</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"正在儲存螢幕擷取畫面..."</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"正在儲存螢幕擷取畫面。"</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"已擷取螢幕畫面。"</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"輕按即可查看螢幕擷圖。"</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"無法擷取螢幕畫面。"</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"儲存螢幕擷圖時發生問題。"</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"由於儲存空間有限,因此無法儲存螢幕擷取畫面。"</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"正在儲存螢幕擷取畫面"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"螢幕擷取畫面已儲存"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"輕按即可查看螢幕擷取畫面"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"無法擷取螢幕畫面"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"儲存螢幕擷取畫面時發生問題"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"由於儲存空間有限,因此無法儲存螢幕擷取畫面"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"應用程式或您的機構不允許擷取螢幕畫面"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB 檔案傳輸選項"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"掛接為媒體播放器 (MTP)"</string>
@@ -559,26 +563,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"關閉"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"通知控制項讓您設定應用程式通知的重要性 (0 至 5 級)。\n\n"<b>"第 5 級"</b>" \n- 在通知清單頂部顯示 \n- 允許全螢幕騷擾 \n- 一律顯示通知 \n\n"<b>"第 4 級"</b>" \n- 阻止全螢幕騷擾 \n- 一律顯示通知 \n\n"<b>"第 3 級"</b>" \n- 阻止全螢幕騷擾 \n- 永不顯示通知 \n\n"<b>"第 2 級"</b>" \n- 阻止全螢幕騷擾 \n- 永不顯示通知 \n- 永不發出聲響和震動 \n\n"<b>"第 1 級"</b>" \n- 阻止全螢幕騷擾 \n- 永不顯示通知 \n- 永不發出聲響和震動 \n- 從上鎖畫面和狀態列中隱藏 \n- 在通知清單底部顯示 \n\n"<b>"第 0 級"</b>" \n- 封鎖所有應用程式通知"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"通知"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"您不會再收到這些通知"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> 個通知類別"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"此應用程式沒有通知類別"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"無法關閉此應用程式的通知"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="other">此應用程式的 1 個通知類別 (共 <xliff:g id="NUMBER_1">%s</xliff:g> 個)</item>
-      <item quantity="one">此應用程式的 1 個通知類別 (共 <xliff:g id="NUMBER_0">%s</xliff:g> 個)</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>、<xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>、<xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g>和另外 <xliff:g id="NUMBER_5">%3$d</xliff:g> 個頻道</item>
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_0">%1$s</xliff:g>、<xliff:g id="CHANNEL_NAME_2_1">%2$s</xliff:g>和另外 <xliff:g id="NUMBER_2">%3$d</xliff:g> 個頻道</item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"您不會再看到這些通知"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"要繼續顯示這些通知嗎?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"停止通知"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"繼續顯示"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"要繼續顯示此應用程式的通知嗎?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"無法關閉這些通知"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"開咗「<xliff:g id="APP_NAME">%1$s</xliff:g>」嘅通知控制項"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"閂咗「<xliff:g id="APP_NAME">%1$s</xliff:g>」嘅通知控制項"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"允許收到呢個頻道嘅通知"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"所有類別"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"更多設定"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"自訂:<xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"自訂"</string>
     <string name="notification_done" msgid="5279426047273930175">"完成"</string>
+    <string name="inline_undo" msgid="558916737624706010">"復原"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"通知控制項"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"通知延後選項"</string>
@@ -733,8 +730,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"展開"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"最小化"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"關閉"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"設定"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"向下拖曳即可關閉"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"選單"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"「<xliff:g id="NAME">%s</xliff:g>」目前在畫中畫模式"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 2d43da8..e6ff9d7 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -33,7 +33,10 @@
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"進行中"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"通知"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"電池電力不足"</string>
+    <string name="battery_low_title_hybrid" msgid="6268991275887381595">"電池電力不足,請開啟節約耗電量模式"</string>
     <string name="battery_low_percent_format" msgid="2900940511201380775">"僅剩 <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid" msgid="6838677459286775617">"電力剩餘 <xliff:g id="PERCENTAGE">%s</xliff:g>,根據你的使用情形,剩餘時間大約還有 <xliff:g id="TIME">%s</xliff:g>"</string>
+    <string name="battery_low_percent_format_hybrid_short" msgid="9025795469949145586">"電力剩餘 <xliff:g id="PERCENTAGE">%s</xliff:g>,剩餘時間大約還有 <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="battery_low_percent_format_saver_started" msgid="7879389868952879166">"僅剩 <xliff:g id="PERCENTAGE">%s</xliff:g>。節約耗電量模式已開啟。"</string>
     <string name="invalid_charger" msgid="4549105996740522523">"不支援 USB 充電。\n僅能使用隨附的充電器。"</string>
     <string name="invalid_charger_title" msgid="3515740382572798460">"不支援 USB 充電功能。"</string>
@@ -67,14 +70,15 @@
     <string name="usb_debugging_secondary_user_message" msgid="6067122453571699801">"目前登入這個裝置的使用者無法啟用 USB 偵錯功能。如要使用這項功能,請切換到主要使用者。"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"放大為全螢幕"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"放大為全螢幕"</string>
+    <string name="global_action_screenshot" msgid="8329831278085426283">"擷取螢幕畫面"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"正在儲存螢幕擷取畫面…"</string>
     <string name="screenshot_saving_title" msgid="8242282144535555697">"正在儲存螢幕擷取畫面…"</string>
-    <string name="screenshot_saving_text" msgid="2419718443411738818">"正在儲存螢幕擷取畫面。"</string>
-    <string name="screenshot_saved_title" msgid="6461865960961414961">"已拍攝螢幕擷取畫面。"</string>
-    <string name="screenshot_saved_text" msgid="2685605830386712477">"輕觸即可查看螢幕擷圖。"</string>
-    <string name="screenshot_failed_title" msgid="705781116746922771">"無法拍攝螢幕擷取畫面。"</string>
-    <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"儲存螢幕擷取畫面時發生問題。"</string>
-    <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"由於儲存空間有限,因此無法儲存螢幕擷取畫面。"</string>
+    <string name="screenshot_saving_text" msgid="2545047868936087248">"正在儲存螢幕擷取畫面"</string>
+    <string name="screenshot_saved_title" msgid="5637073968117370753">"螢幕擷取畫面已儲存"</string>
+    <string name="screenshot_saved_text" msgid="7574667448002050363">"輕觸即可查看螢幕擷取畫面"</string>
+    <string name="screenshot_failed_title" msgid="9096484883063264803">"無法擷取螢幕畫面"</string>
+    <string name="screenshot_failed_to_save_unknown_text" msgid="8844781948876286488">"儲存螢幕擷取畫面時發生問題"</string>
+    <string name="screenshot_failed_to_save_text" msgid="3041612585107107310">"由於儲存空間有限,因此無法儲存螢幕擷取畫面"</string>
     <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"這個應用程式或貴機構不允許擷取螢幕畫面"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB 檔案傳輸選項"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"掛接為媒體播放器 (MTP)"</string>
@@ -557,26 +561,19 @@
     <string name="tuner_full_importance_settings_off" msgid="8208165412614935229">"關閉"</string>
     <string name="power_notification_controls_description" msgid="4372459941671353358">"只要使用電源通知控制項,你就能為應用程式通知設定從 0 到 5 的重要性等級。\n\n"<b>"等級 5"</b>" \n- 顯示在通知清單頂端 \n- 允許全螢幕通知 \n- 一律允許短暫顯示通知 \n\n"<b>"等級 4"</b>" \n- 禁止全螢幕通知 \n- 一律允許短暫顯示通知 \n\n"<b>"等級 3"</b>" \n- 禁止全螢幕通知 \n- 一律不允許短暫顯示通知 \n\n"<b>"等級 2"</b>" \n- 禁止全螢幕通知 \n- 一律不允許短暫顯示通知 \n- 一律不發出音效或震動 \n\n"<b>"等級 1"</b>" \n- 禁止全螢幕通知 \n- 一律不允許短暫顯示通知 \n- 一律不發出音效或震動 \n- 在鎖定畫面和狀態列中隱藏 \n- 顯示在通知清單底端 \n\n"<b>"等級 0"</b>" \n- 封鎖應用程式的所有通知"</string>
     <string name="notification_header_default_channel" msgid="7506845022070889909">"通知"</string>
-    <string name="notification_channel_disabled" msgid="2139193533791840539">"你不會再收到這類通知"</string>
-    <string name="notification_num_channels" msgid="2048144408999179471">"<xliff:g id="NUMBER">%d</xliff:g> 個通知類別"</string>
-    <string name="notification_default_channel_desc" msgid="2506053815870808359">"這個應用程式沒有通知類別"</string>
-    <string name="notification_unblockable_desc" msgid="3561016061737896906">"無法關閉這個應用程式發出的通知"</string>
-    <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="other">在 <xliff:g id="NUMBER_1">%s</xliff:g> 個通知類別中,有 1 個類別是來自這個應用程式</item>
-      <item quantity="one">在 <xliff:g id="NUMBER_0">%s</xliff:g> 個通知類別中,有 1 個類別是來自這個應用程式</item>
-    </plurals>
-    <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>、<xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
-    <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>、<xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g>和另外 <xliff:g id="NUMBER_5">%3$d</xliff:g> 個管道</item>
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_0">%1$s</xliff:g>、<xliff:g id="CHANNEL_NAME_2_1">%2$s</xliff:g>和另外 <xliff:g id="NUMBER_2">%3$d</xliff:g> 個管道</item>
-    </plurals>
+    <string name="notification_channel_disabled" msgid="344536703863700565">"你不會再看到這些通知"</string>
+    <string name="inline_keep_showing" msgid="8945102997083836858">"要繼續顯示這些通知嗎?"</string>
+    <string name="inline_stop_button" msgid="4172980096860941033">"停止通知"</string>
+    <string name="inline_keep_button" msgid="6665940297019018232">"繼續顯示"</string>
+    <string name="inline_keep_showing_app" msgid="1723113469580031041">"要繼續顯示這個應用程式的通知嗎?"</string>
+    <string name="notification_unblockable_desc" msgid="1037434112919403708">"無法關閉這些通知"</string>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」的通知控制項已開啟"</string>
     <string name="notification_channel_controls_closed_accessibility" msgid="7521619812603693144">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」的通知控制項已關閉"</string>
     <string name="notification_channel_switch_accessibility" msgid="3420796005601900717">"允許來自這個頻道的通知"</string>
-    <string name="notification_all_categories" msgid="5407190218055113282">"所有類別"</string>
     <string name="notification_more_settings" msgid="816306283396553571">"更多設定"</string>
-    <string name="notification_app_settings" msgid="3743278649182392015">"自訂:<xliff:g id="SUB_CATEGORY">%1$s</xliff:g>"</string>
+    <string name="notification_app_settings" msgid="420348114670768449">"自訂"</string>
     <string name="notification_done" msgid="5279426047273930175">"完成"</string>
+    <string name="inline_undo" msgid="558916737624706010">"復原"</string>
     <string name="notification_menu_accessibility" msgid="2046162834248888553">"<xliff:g id="APP_NAME">%1$s</xliff:g> <xliff:g id="MENU_DESCRIPTION">%2$s</xliff:g>"</string>
     <string name="notification_menu_gear_description" msgid="2204480013726775108">"通知控制項"</string>
     <string name="notification_menu_snooze_description" msgid="3653669438131034525">"通知延後選項"</string>
@@ -731,8 +728,7 @@
     <string name="pip_phone_expand" msgid="5889780005575693909">"展開"</string>
     <string name="pip_phone_minimize" msgid="1079119422589131792">"最小化"</string>
     <string name="pip_phone_close" msgid="8416647892889710330">"關閉"</string>
-    <!-- no translation found for pip_phone_settings (8080777499521528521) -->
-    <skip />
+    <string name="pip_phone_settings" msgid="8080777499521528521">"設定"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"向下拖曳即可關閉"</string>
     <string name="pip_menu_title" msgid="4707292089961887657">"選單"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"「<xliff:g id="NAME">%s</xliff:g>」目前在子母畫面中"</string>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index dde4dcf..6437903 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -775,6 +775,15 @@
     <string name="quick_settings_work_mode_label">Work mode</string>
     <!-- QuickSettings: Label for the toggle to activate Night display (renamed "Night Light" with title caps). [CHAR LIMIT=20] -->
     <string name="quick_settings_night_display_label">Night Light</string>
+    <!-- QuickSettings: Secondary text for when the Night Light will be enabled at sunset. [CHAR LIMIT=20] -->
+    <string name="quick_settings_night_secondary_label_on_at_sunset">On at sunset</string>
+    <!-- QuickSettings: Secondary text for when the Night Light will be on until sunrise. [CHAR LIMIT=20] -->
+    <string name="quick_settings_night_secondary_label_until_sunrise">Until sunrise</string>
+    <!-- QuickSettings: Secondary text for when the Night Light will be enabled at some user-selected time. [CHAR LIMIT=20] -->
+    <string name="quick_settings_night_secondary_label_on_at">On at <xliff:g id="time" example="10 pm">%s</xliff:g></string>
+    <!-- QuickSettings: Secondary text for when the Night Light will be on until some user-selected time. [CHAR LIMIT=20] -->
+    <string name="quick_settings_night_secondary_label_until">Until <xliff:g id="time" example="7 am">%s</xliff:g></string>
+
     <!-- QuickSettings: NFC tile [CHAR LIMIT=NONE] -->
     <string name="quick_settings_nfc_label">NFC</string>
     <!-- QuickSettings: NFC (off) [CHAR LIMIT=NONE] -->
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 90c5977..4837fef 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -476,7 +476,6 @@
     <style name="TextAppearance.NotificationInfo.Button">
         <item name="android:fontFamily">sans-serif-medium</item>
         <item name="android:textSize">14sp</item>
-        <item name="android:textAllCaps">true</item>
         <item name="android:textColor">?android:attr/colorAccent</item>
         <item name="android:background">@drawable/btn_borderless_rect</item>
         <item name="android:gravity">center</item>
diff --git a/packages/SystemUI/src/com/android/systemui/RecentsComponent.java b/packages/SystemUI/src/com/android/systemui/RecentsComponent.java
index 880ae70..f9dbf4a 100644
--- a/packages/SystemUI/src/com/android/systemui/RecentsComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/RecentsComponent.java
@@ -21,7 +21,7 @@
 import android.view.View;
 
 public interface RecentsComponent {
-    void showRecentApps(boolean triggeredFromAltTab, boolean fromHome);
+    void showRecentApps(boolean triggeredFromAltTab);
     void showNextAffiliatedTask();
     void showPrevAffiliatedTask();
 
diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
index 592dda0..a64ce29 100644
--- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
@@ -21,6 +21,7 @@
 import android.animation.ObjectAnimator;
 import android.animation.ValueAnimator;
 import android.animation.ValueAnimator.AnimatorUpdateListener;
+import android.annotation.NonNull;
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.RectF;
@@ -316,10 +317,12 @@
                     float deltaPerpendicular = perpendicularPos - mPerpendicularInitialTouchPos;
                     if (Math.abs(delta) > mPagingTouchSlop
                             && Math.abs(delta) > Math.abs(deltaPerpendicular)) {
-                        mCallback.onBeginDrag(mCurrView);
-                        mDragging = true;
-                        mInitialTouchPos = getPos(ev);
-                        mTranslation = getTranslation(mCurrView);
+                        if (mCallback.canChildBeDragged(mCurrView)) {
+                            mCallback.onBeginDrag(mCurrView);
+                            mDragging = true;
+                            mInitialTouchPos = getPos(ev);
+                            mTranslation = getTranslation(mCurrView);
+                        }
                         cancelLongPress();
                     }
                 }
@@ -722,5 +725,10 @@
          * @return The factor the falsing threshold should be multiplied with
          */
         float getFalsingThresholdFactor();
+
+        /**
+         * @return If true, the given view is draggable.
+         */
+        default boolean canChildBeDragged(@NonNull View animView) { return true; }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/analytics/DataCollector.java b/packages/SystemUI/src/com/android/systemui/analytics/DataCollector.java
index 931a994..69e347c9 100644
--- a/packages/SystemUI/src/com/android/systemui/analytics/DataCollector.java
+++ b/packages/SystemUI/src/com/android/systemui/analytics/DataCollector.java
@@ -463,4 +463,8 @@
     public boolean isReportingEnabled() {
         return mAllowReportRejectedTouch;
     }
+
+    public void onFalsingSessionStarted() {
+        sessionEntrypoint();
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
index e4b405f..ed659e2 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java
@@ -167,6 +167,9 @@
         if (mDataCollector.isEnabledFull()) {
             registerSensors(COLLECTOR_SENSORS);
         }
+        if (mDataCollector.isEnabled()) {
+            mDataCollector.onFalsingSessionStarted();
+        }
     }
 
     private void registerSensors(int [] sensors) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 653e500..8501519 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -707,6 +707,10 @@
                     && !mLockPatternUtils.isLockScreenDisabled(
                             KeyguardUpdateMonitor.getCurrentUser()),
                     mSecondaryDisplayShowing, true /* forceCallbacks */);
+        } else {
+            // The system's keyguard is disabled or missing.
+            setShowingLocked(mLockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser()),
+                    mSecondaryDisplayShowing, true);
         }
 
         mStatusBarKeyguardViewManager =
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileView.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileView.java
index a226f3c..9eb9906 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileView.java
@@ -29,7 +29,6 @@
 
 import com.android.systemui.FontSizeUtils;
 import com.android.systemui.R;
-import com.android.systemui.R.id;
 import com.android.systemui.plugins.qs.QSIconView;
 import com.android.systemui.plugins.qs.QSTile;
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
index 763ffc6..99a9be3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.qs.tiles;
 
+import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.content.Intent;
 import android.provider.Settings;
@@ -29,9 +30,17 @@
 import com.android.systemui.plugins.qs.QSTile.BooleanState;
 import com.android.systemui.qs.tileimpl.QSTileImpl;
 
+import java.time.format.DateTimeFormatter;
+
 public class NightDisplayTile extends QSTileImpl<BooleanState>
         implements ColorDisplayController.Callback {
 
+    /**
+     * Pattern for {@link java.time.format.DateTimeFormatter} used to approximate the time to the
+     * nearest hour and add on the AM/PM indicator.
+     */
+    private static final String APPROXIMATE_HOUR_DATE_TIME_PATTERN = "H a";
+
     private ColorDisplayController mController;
     private boolean mIsListening;
 
@@ -74,13 +83,49 @@
 
     @Override
     protected void handleUpdateState(BooleanState state, Object arg) {
-        final boolean isActivated = mController.isActivated();
-        state.value = isActivated;
+        state.value = mController.isActivated();
         state.label = state.contentDescription =
                 mContext.getString(R.string.quick_settings_night_display_label);
         state.icon = ResourceIcon.get(R.drawable.ic_qs_night_display_on);
         state.expandedAccessibilityClassName = Switch.class.getName();
         state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
+        state.secondaryLabel = getSecondaryLabel(state.value);
+    }
+
+    /**
+     * Returns a {@link String} for the secondary label that reflects when the light will be turned
+     * on or off based on the current auto mode and night light activated status.
+     */
+    @Nullable
+    private String getSecondaryLabel(boolean isNightLightActivated) {
+        switch(mController.getAutoMode()) {
+            case ColorDisplayController.AUTO_MODE_TWILIGHT:
+                // Auto mode related to sunrise & sunset. If the light is on, it's guaranteed to be
+                // turned off at sunrise. If it's off, it's guaranteed to be turned on at sunset.
+                return isNightLightActivated
+                        ? mContext.getString(
+                                R.string.quick_settings_night_secondary_label_until_sunrise)
+                        : mContext.getString(
+                                R.string.quick_settings_night_secondary_label_on_at_sunset);
+
+            case ColorDisplayController.AUTO_MODE_CUSTOM:
+                // User-specified time, approximated to the nearest hour.
+                return isNightLightActivated
+                        ? mContext.getString(
+                                R.string.quick_settings_night_secondary_label_until,
+                                mController.getCustomEndTime().format(
+                                        DateTimeFormatter.ofPattern(
+                                                APPROXIMATE_HOUR_DATE_TIME_PATTERN)))
+                        : mContext.getString(
+                                R.string.quick_settings_night_secondary_label_on_at,
+                                mController.getCustomStartTime().format(
+                                        DateTimeFormatter.ofPattern(
+                                                APPROXIMATE_HOUR_DATE_TIME_PATTERN)));
+
+            default:
+                // No secondary label when auto mode is disabled.
+                return null;
+        }
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
index 1e00894..60422ee 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
@@ -36,20 +36,8 @@
 
 /** Quick settings tile: Rotation **/
 public class RotationLockTile extends QSTileImpl<BooleanState> {
-    private final AnimationIcon mPortraitToAuto
-            = new AnimationIcon(R.drawable.ic_portrait_to_auto_rotate_animation,
-            R.drawable.ic_portrait_from_auto_rotate);
-    private final AnimationIcon mAutoToPortrait
-            = new AnimationIcon(R.drawable.ic_portrait_from_auto_rotate_animation,
-            R.drawable.ic_portrait_to_auto_rotate);
 
-    private final AnimationIcon mLandscapeToAuto
-            = new AnimationIcon(R.drawable.ic_landscape_to_auto_rotate_animation,
-            R.drawable.ic_landscape_from_auto_rotate);
-    private final AnimationIcon mAutoToLandscape
-            = new AnimationIcon(R.drawable.ic_landscape_from_auto_rotate_animation,
-            R.drawable.ic_landscape_to_auto_rotate);
-
+    private final Icon mIcon = ResourceIcon.get(R.drawable.ic_qs_auto_rotate);
     private final RotationLockController mController;
 
     public RotationLockTile(QSHost host) {
@@ -93,19 +81,10 @@
     protected void handleUpdateState(BooleanState state, Object arg) {
         if (mController == null) return;
         final boolean rotationLocked = mController.isRotationLocked();
-        // TODO: Handle accessibility rotation lock and whatnot.
 
         state.value = !rotationLocked;
-        final boolean portrait = isCurrentOrientationLockPortrait(mController, mContext);
-        if (rotationLocked) {
-            final int label = portrait ? R.string.quick_settings_rotation_locked_portrait_label
-                    : R.string.quick_settings_rotation_locked_landscape_label;
-            state.label = mContext.getString(label);
-            state.icon = portrait ? mAutoToPortrait : mAutoToLandscape;
-        } else {
-            state.label = mContext.getString(R.string.quick_settings_rotation_unlocked_label);
-            state.icon = portrait ? mPortraitToAuto : mLandscapeToAuto;
-        }
+        state.label = mContext.getString(R.string.quick_settings_rotation_unlocked_label);
+        state.icon = mIcon;
         state.contentDescription = getAccessibilityString(rotationLocked);
         state.expandedAccessibilityClassName = Switch.class.getName();
         state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
@@ -134,18 +113,7 @@
      * @param locked Whether or not rotation is locked.
      */
     private String getAccessibilityString(boolean locked) {
-        if (locked) {
-            return mContext.getString(R.string.accessibility_quick_settings_rotation_value,
-                    isCurrentOrientationLockPortrait(mController, mContext)
-                            ? mContext.getString(
-                                    R.string.quick_settings_rotation_locked_portrait_label)
-                            : mContext.getString(
-                                    R.string.quick_settings_rotation_locked_landscape_label))
-                    + "," + mContext.getString(R.string.accessibility_quick_settings_rotation);
-
-        } else {
-            return mContext.getString(R.string.accessibility_quick_settings_rotation);
-        }
+        return mContext.getString(R.string.accessibility_quick_settings_rotation);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/IRecentsNonSystemUserCallbacks.aidl b/packages/SystemUI/src/com/android/systemui/recents/IRecentsNonSystemUserCallbacks.aidl
index 5ae7f22c..fc1831d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/IRecentsNonSystemUserCallbacks.aidl
+++ b/packages/SystemUI/src/com/android/systemui/recents/IRecentsNonSystemUserCallbacks.aidl
@@ -27,7 +27,7 @@
     void preloadRecents();
     void cancelPreloadingRecents();
     void showRecents(boolean triggeredFromAltTab, boolean draggingInRecents, boolean animate,
-            boolean reloadTasks, boolean fromHome, int recentsGrowTarget);
+            int recentsGrowTarget);
     void hideRecents(boolean triggeredFromAltTab, boolean triggeredFromHomeKey);
     void toggleRecents(int recentsGrowTarget);
     void onConfigurationChanged();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
index 5b62c7d..1da4deb 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
@@ -240,7 +240,7 @@
      * Shows the Recents.
      */
     @Override
-    public void showRecentApps(boolean triggeredFromAltTab, boolean fromHome) {
+    public void showRecentApps(boolean triggeredFromAltTab) {
         // Ensure the device has been provisioned before allowing the user to interact with
         // recents
         if (!isUserSetup()) {
@@ -252,7 +252,7 @@
         int currentUser = sSystemServicesProxy.getCurrentUser();
         if (sSystemServicesProxy.isSystemUser(currentUser)) {
             mImpl.showRecents(triggeredFromAltTab, false /* draggingInRecents */,
-                    true /* animate */, false /* reloadTasks */, fromHome, recentsGrowTarget);
+                    true /* animate */, recentsGrowTarget);
         } else {
             if (mSystemToUserCallbacks != null) {
                 IRecentsNonSystemUserCallbacks callbacks =
@@ -260,8 +260,7 @@
                 if (callbacks != null) {
                     try {
                         callbacks.showRecents(triggeredFromAltTab, false /* draggingInRecents */,
-                                true /* animate */, false /* reloadTasks */, fromHome,
-                                recentsGrowTarget);
+                                true /* animate */, recentsGrowTarget);
                     } catch (RemoteException e) {
                         Log.e(TAG, "Callback failed", e);
                     }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index 06dfd18..b0a2fad 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -356,15 +356,15 @@
         registerReceiver(mSystemBroadcastReceiver, filter);
 
         getWindow().addPrivateFlags(LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION);
-
-        // Reload the stack view
-        reloadStackView();
     }
 
     @Override
     protected void onStart() {
         super.onStart();
 
+        // Reload the stack view whenever we are made visible again
+        reloadStackView();
+
         // Notify that recents is now visible
         EventBus.getDefault().send(new RecentsVisibilityChangedEvent(this, true));
         MetricsLogger.visible(this, MetricsEvent.OVERVIEW_ACTIVITY);
@@ -411,14 +411,6 @@
         }
     }
 
-    @Override
-    protected void onNewIntent(Intent intent) {
-        super.onNewIntent(intent);
-
-        // Reload the stack view
-        reloadStackView();
-    }
-
     /**
      * Reloads the stack views upon launching Recents.
      */
@@ -530,7 +522,11 @@
         // Set the window background
         mRecentsView.updateBackgroundScrim(getWindow(), isInMultiWindowMode);
 
-        reloadTaskStack(isInMultiWindowMode, true /* sendConfigChangedEvent */);
+        // Reload the task stack view if we are still visible to pick up the change in tasks that
+        // result from entering/exiting multi-window
+        if (mIsVisible) {
+            reloadTaskStack(isInMultiWindowMode, true /* sendConfigChangedEvent */);
+        }
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index 8359690..ee1b091 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -255,7 +255,6 @@
             // When this fires, then the user has not released alt-tab for at least
             // FAST_ALT_TAB_DELAY_MS milliseconds
             showRecents(mTriggeredFromAltTab, false /* draggingInRecents */, true /* animate */,
-                    false /* reloadTasks */, false /* fromHome */,
                     DividerView.INVALID_RECENTS_GROW_TARGET);
         }
     });
@@ -322,8 +321,15 @@
     }
 
     public void showRecents(boolean triggeredFromAltTab, boolean draggingInRecents,
-            boolean animate, boolean launchedWhileDockingTask, boolean fromHome,
-            int growTarget) {
+            boolean animate, int growTarget) {
+        final SystemServicesProxy ssp = Recents.getSystemServices();
+        final MutableBoolean isHomeStackVisible = new MutableBoolean(true);
+        final boolean isRecentsVisible = Recents.getSystemServices().isRecentsActivityVisible(
+                isHomeStackVisible);
+        final boolean fromHome = isHomeStackVisible.value;
+        final boolean launchedWhileDockingTask =
+                Recents.getSystemServices().getSplitScreenPrimaryStack() != null;
+
         mTriggeredFromAltTab = triggeredFromAltTab;
         mDraggingInRecents = draggingInRecents;
         mLaunchedWhileDocking = launchedWhileDockingTask;
@@ -349,10 +355,8 @@
 
         try {
             // Check if the top task is in the home stack, and start the recents activity
-            SystemServicesProxy ssp = Recents.getSystemServices();
-            boolean forceVisible = launchedWhileDockingTask || draggingInRecents;
-            MutableBoolean isHomeStackVisible = new MutableBoolean(forceVisible);
-            if (forceVisible || !ssp.isRecentsActivityVisible(isHomeStackVisible)) {
+            final boolean forceVisible = launchedWhileDockingTask || draggingInRecents;
+            if (forceVisible || !isRecentsVisible) {
                 ActivityManager.RunningTaskInfo runningTask =
                         ActivityManagerWrapper.getInstance().getRunningTask();
                 startRecentsActivityAndDismissKeyguardIfNeeded(runningTask,
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImplProxy.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImplProxy.java
index 9493c78..beec4b3 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImplProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImplProxy.java
@@ -58,15 +58,12 @@
 
     @Override
     public void showRecents(boolean triggeredFromAltTab, boolean draggingInRecents, boolean animate,
-            boolean reloadTasks, boolean fromHome, int growTarget)
-            throws RemoteException {
+            int growTarget) throws RemoteException {
         SomeArgs args = SomeArgs.obtain();
         args.argi1 = triggeredFromAltTab ? 1 : 0;
         args.argi2 = draggingInRecents ? 1 : 0;
         args.argi3 = animate ? 1 : 0;
-        args.argi4 = reloadTasks ? 1 : 0;
-        args.argi5 = fromHome ? 1 : 0;
-        args.argi6 = growTarget;
+        args.argi4 = growTarget;
         mHandler.sendMessage(mHandler.obtainMessage(MSG_SHOW_RECENTS, args));
     }
 
@@ -130,7 +127,7 @@
                 case MSG_SHOW_RECENTS:
                     args = (SomeArgs) msg.obj;
                     mImpl.showRecents(args.argi1 != 0, args.argi2 != 0, args.argi3 != 0,
-                            args.argi4 != 0, args.argi5 != 0, args.argi6);
+                            args.argi4);
                     break;
                 case MSG_HIDE_RECENTS:
                     mImpl.hideRecents(msg.arg1 != 0, msg.arg2 != 0);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index 130a5e3..613d9fb 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -274,20 +274,21 @@
         return false;
     }
 
+    public ActivityManager.StackInfo getSplitScreenPrimaryStack() {
+        try {
+            return mIam.getStackInfo(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_UNDEFINED);
+        } catch (RemoteException e) {
+            return null;
+        }
+    }
+
     /**
      * @return whether there are any docked tasks for the current user.
      */
     public boolean hasDockedTask() {
         if (mIam == null) return false;
 
-        ActivityManager.StackInfo stackInfo = null;
-        try {
-            stackInfo =
-                    mIam.getStackInfo(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_UNDEFINED);
-        } catch (RemoteException e) {
-            e.printStackTrace();
-        }
-
+        ActivityManager.StackInfo stackInfo = getSplitScreenPrimaryStack();
         if (stackInfo != null) {
             int userId = getCurrentUser();
             boolean hasUserTask = false;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index 36c9095..5be2900 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -210,7 +210,7 @@
     private boolean mStackActionButtonVisible;
 
     // Percentage of last ScrollP from the min to max scrollP that lives after configuration changes
-    private float mLastScrollPPercent;
+    private float mLastScrollPPercent = -1;
 
     // We keep track of the task view focused by user interaction and draw a frame around it in the
     // grid layout.
@@ -647,14 +647,12 @@
      * an animation provided in {@param animationOverrides}, that will be used instead.
      */
     private void relayoutTaskViews(AnimationProps animation,
-            ArrayMap<Task, AnimationProps> animationOverrides,
-            boolean ignoreTaskOverrides) {
+            ArrayMap<Task, AnimationProps> animationOverrides, boolean ignoreTaskOverrides) {
         // If we had a deferred animation, cancel that
         cancelDeferredTaskViewLayoutAnimation();
 
         // Synchronize the current set of TaskViews
-        bindVisibleTaskViews(mStackScroller.getStackScroll(),
-                ignoreTaskOverrides /* ignoreTaskOverrides */);
+        bindVisibleTaskViews(mStackScroller.getStackScroll(), ignoreTaskOverrides);
 
         // Animate them to their final transforms with the given animation
         List<TaskView> taskViews = getTaskViews();
@@ -2067,8 +2065,11 @@
         // Update the Clear All button in case we're switching in or out of grid layout.
         updateStackActionButtonVisibility();
 
-        // Trigger a new layout and update to the initial state if necessary
-        if (event.fromMultiWindow) {
+        // Trigger a new layout and update to the initial state if necessary. When entering split
+        // screen, the multi-window configuration change event can happen after the stack is already
+        // reloaded (but pending measure/layout), in this case, do not override the intiial state
+        // and just wait for the upcoming measure/layout pass.
+        if (event.fromMultiWindow && mInitialState == INITIAL_STATE_UPDATE_NONE) {
             mInitialState = INITIAL_STATE_UPDATE_LAYOUT_ONLY;
             requestLayout();
         } else if (event.fromDeviceOrientationChange) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 8e1b104..657b953 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -116,7 +116,7 @@
         default void topAppWindowChanged(boolean visible) { }
         default void setImeWindowStatus(IBinder token, int vis, int backDisposition,
                 boolean showImeSwitcher) { }
-        default void showRecentApps(boolean triggeredFromAltTab, boolean fromHome) { }
+        default void showRecentApps(boolean triggeredFromAltTab) { }
         default void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) { }
         default void toggleRecentApps() { }
         default void toggleSplitScreen() { }
@@ -268,11 +268,11 @@
         }
     }
 
-    public void showRecentApps(boolean triggeredFromAltTab, boolean fromHome) {
+    public void showRecentApps(boolean triggeredFromAltTab) {
         synchronized (mLock) {
             mHandler.removeMessages(MSG_SHOW_RECENT_APPS);
-            mHandler.obtainMessage(MSG_SHOW_RECENT_APPS,
-                    triggeredFromAltTab ? 1 : 0, fromHome ? 1 : 0, null).sendToTarget();
+            mHandler.obtainMessage(MSG_SHOW_RECENT_APPS, triggeredFromAltTab ? 1 : 0, 0,
+                    null).sendToTarget();
         }
     }
 
@@ -541,7 +541,7 @@
                     break;
                 case MSG_SHOW_RECENT_APPS:
                     for (int i = 0; i < mCallbacks.size(); i++) {
-                        mCallbacks.get(i).showRecentApps(msg.arg1 != 0, msg.arg2 != 0);
+                        mCallbacks.get(i).showRecentApps(msg.arg1 != 0);
                     }
                     break;
                 case MSG_HIDE_RECENT_APPS:
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
index b113675..e09d31c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
@@ -26,6 +26,7 @@
 import android.view.IWindowManager;
 import android.view.MotionEvent;
 import android.view.View;
+import android.view.View.OnLayoutChangeListener;
 
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.systemui.Dependency;
@@ -41,6 +42,7 @@
 
     private boolean mLightsOut;
     private boolean mAutoDim;
+    private View mNavButtons;
 
     public NavigationBarTransitions(NavigationBarView view) {
         super(view, R.drawable.nav_background);
@@ -66,6 +68,18 @@
                 }, Display.DEFAULT_DISPLAY);
         } catch (RemoteException e) {
         }
+        mView.addOnLayoutChangeListener(
+                (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
+                    View currentView = mView.getCurrentView();
+                    if (currentView != null) {
+                        mNavButtons = currentView.findViewById(R.id.nav_buttons);
+                        applyLightsOut(false, true);
+                    }
+                });
+        View currentView = mView.getCurrentView();
+        if (currentView != null) {
+            mNavButtons = currentView.findViewById(R.id.nav_buttons);
+        }
     }
 
     public void init() {
@@ -105,21 +119,20 @@
         if (!force && lightsOut == mLightsOut) return;
 
         mLightsOut = lightsOut;
-
-        final View navButtons = mView.getCurrentView().findViewById(R.id.nav_buttons);
+        if (mNavButtons == null) return;
 
         // ok, everyone, stop it right there
-        navButtons.animate().cancel();
+        mNavButtons.animate().cancel();
 
         // Bump percentage by 10% if dark.
         float darkBump = mLightTransitionsController.getCurrentDarkIntensity() / 10;
         final float navButtonsAlpha = lightsOut ? 0.6f + darkBump : 1f;
 
         if (!animate) {
-            navButtons.setAlpha(navButtonsAlpha);
+            mNavButtons.setAlpha(navButtonsAlpha);
         } else {
             final int duration = lightsOut ? LIGHTS_OUT_DURATION : LIGHTS_IN_DURATION;
-            navButtons.animate()
+            mNavButtons.animate()
                 .alpha(navButtonsAlpha)
                 .setDuration(duration)
                 .start();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index f41cb29..6857337 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -39,7 +39,6 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
-import android.content.pm.UserInfo;
 import android.graphics.drawable.Icon;
 import android.media.AudioManager;
 import android.net.Uri;
@@ -66,7 +65,6 @@
 import com.android.systemui.qs.tiles.DndTile;
 import com.android.systemui.qs.tiles.RotationLockTile;
 import com.android.systemui.recents.misc.SysUiTaskStackChangeListener;
-import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.CommandQueue.Callbacks;
@@ -146,7 +144,6 @@
     private boolean mDockedStackExists;
 
     private boolean mManagedProfileIconVisible = false;
-    private boolean mManagedProfileInQuietMode = false;
 
     private BluetoothController mBluetooth;
 
@@ -474,17 +471,6 @@
         }
     }
 
-    private void updateQuietState() {
-        mManagedProfileInQuietMode = false;
-        int currentUserId = ActivityManager.getCurrentUser();
-        for (UserInfo ui : mUserManager.getEnabledProfiles(currentUserId)) {
-            if (ui.isManagedProfile() && ui.isQuietModeEnabled()) {
-                mManagedProfileInQuietMode = true;
-                return;
-            }
-        }
-    }
-
     private void updateManagedProfile() {
         // getLastResumedActivityUserId needds to acquire the AM lock, which may be contended in
         // some cases. Since it doesn't really matter here whether it's updated in this frame
@@ -502,11 +488,6 @@
                         mIconController.setIcon(mSlotManagedProfile,
                                 R.drawable.stat_sys_managed_profile_status,
                                 mContext.getString(R.string.accessibility_managed_profile));
-                    } else if (mManagedProfileInQuietMode) {
-                        showIcon = true;
-                        mIconController.setIcon(mSlotManagedProfile,
-                                R.drawable.stat_sys_managed_profile_status_off,
-                                mContext.getString(R.string.accessibility_managed_profile));
                     } else {
                         showIcon = false;
                     }
@@ -676,7 +657,6 @@
                 public void onUserSwitchComplete(int newUserId) throws RemoteException {
                     mHandler.post(() -> {
                         updateAlarm();
-                        updateQuietState();
                         updateManagedProfile();
                         updateForegroundInstantApps();
                     });
@@ -724,7 +704,6 @@
         if (mCurrentUserSetup == userSetup) return;
         mCurrentUserSetup = userSetup;
         updateAlarm();
-        updateQuietState();
     }
 
     @Override
@@ -793,7 +772,6 @@
             } else if (action.equals(Intent.ACTION_MANAGED_PROFILE_AVAILABLE) ||
                     action.equals(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE) ||
                     action.equals(Intent.ACTION_MANAGED_PROFILE_REMOVED)) {
-                updateQuietState();
                 updateManagedProfile();
             } else if (action.equals(AudioManager.ACTION_HEADSET_PLUG)) {
                 updateHeadsetPlug(intent);
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 5e08ec3..c9dc253 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -1704,7 +1704,7 @@
         if (mReportRejectedTouch == null) {
             return;
         }
-        mReportRejectedTouch.setVisibility(mState == StatusBarState.KEYGUARD
+        mReportRejectedTouch.setVisibility(mState == StatusBarState.KEYGUARD && !mDozing
                 && mFalsingManager.isReportingEnabled() ? View.VISIBLE : View.INVISIBLE);
     }
 
@@ -4506,6 +4506,7 @@
             ((DozeReceiver) mAmbientIndicationContainer).setDozing(mDozing);
         }
         updateDozingState();
+        updateReportRejectedTouchVisibility();
         Trace.endSection();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverControllerImpl.java
index 2951943..2ede327 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DataSaverControllerImpl.java
@@ -74,17 +74,9 @@
         }
     }
 
-    private final INetworkPolicyListener mPolicyListener = new INetworkPolicyListener.Stub() {
+    private final INetworkPolicyListener mPolicyListener = new NetworkPolicyManager.Listener() {
         @Override
-        public void onUidRulesChanged(int uid, int uidRules) throws RemoteException {
-        }
-
-        @Override
-        public void onMeteredIfacesChanged(String[] strings) throws RemoteException {
-        }
-
-        @Override
-        public void onRestrictBackgroundChanged(final boolean isDataSaving) throws RemoteException {
+        public void onRestrictBackgroundChanged(final boolean isDataSaving) {
             mHandler.post(new Runnable() {
                 @Override
                 public void run() {
@@ -92,10 +84,6 @@
                 }
             });
         }
-
-        @Override
-        public void onUidPoliciesChanged(int uid, int uidPolicies) throws RemoteException {
-        }
     };
 
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
index 4d8da44..ebf4cda 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.statusbar.stack;
 
+import android.annotation.Nullable;
 import android.content.Context;
 import android.view.View;
 
@@ -236,6 +237,7 @@
         mShelf = shelf;
     }
 
+    @Nullable
     public NotificationShelf getShelf() {
         return mShelf;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
index 7374f11..2ce6df2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -122,7 +122,9 @@
     }
     private void updateShelfState(StackScrollState resultState, AmbientState ambientState) {
         NotificationShelf shelf = ambientState.getShelf();
-        shelf.updateState(resultState, ambientState);
+        if (shelf != null) {
+            shelf.updateState(resultState, ambientState);
+        }
     }
 
     private void updateClipping(StackScrollState resultState,
@@ -495,6 +497,10 @@
      */
     private void clampPositionToShelf(ExpandableViewState childViewState,
             AmbientState ambientState) {
+        if (ambientState.getShelf() == null) {
+            return;
+        }
+
         int shelfStart = ambientState.getInnerHeight()
                 - ambientState.getShelf().getIntrinsicHeight();
         childViewState.yTranslation = Math.min(childViewState.yTranslation, shelfStart);
@@ -556,7 +562,8 @@
         } else if (i == 0 && ambientState.isAboveShelf(child)) {
             // In case this is a new view that has never been measured before, we don't want to
             // elevate if we are currently expanded more then the notification
-            int shelfHeight = ambientState.getShelf().getIntrinsicHeight();
+            int shelfHeight = ambientState.getShelf() == null ? 0 :
+                    ambientState.getShelf().getIntrinsicHeight();
             float shelfStart = ambientState.getInnerHeight()
                     - shelfHeight + ambientState.getTopPadding()
                     + ambientState.getStackTranslation();
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index 9041d5a..9f7c5a7 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -103,7 +103,6 @@
     private ViewGroup mDialogView;
     private ViewGroup mDialogRowsView;
     private ImageButton mRingerIcon;
-    private ImageButton mOutputChooser;
     private TextView mRingerStatus;
     private final List<VolumeRow> mRows = new ArrayList<>();
     private ConfigurableTexts mConfigurableTexts;
@@ -225,9 +224,6 @@
             addExistingRows();
         }
 
-        mOutputChooser = mDialogView.findViewById(R.id.output_chooser);
-        mOutputChooser.setOnClickListener(mClickOutputChooser);
-
         updateRowsH(getActiveRow());
         initRingerH();
     }
@@ -335,6 +331,9 @@
         row.slider.setOnSeekBarChangeListener(new VolumeSeekBarChangeListener(row));
         row.anim = null;
 
+        ImageButton outputChooser = row.view.findViewById(R.id.output_chooser);
+        outputChooser.setOnClickListener(mClickOutputChooser);
+
         // forward events above the slider into the slider
         row.view.setOnTouchListener(new OnTouchListener() {
             private final Rect mSliderHitRect = new Rect();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
index 9603207..a02ef98 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
@@ -119,9 +119,9 @@
 
     @Test
     public void testShowRecentApps() {
-        mCommandQueue.showRecentApps(true, false);
+        mCommandQueue.showRecentApps(true);
         waitForIdleSync();
-        verify(mCallbacks).showRecentApps(eq(true), eq(false));
+        verify(mCallbacks).showRecentApps(eq(true));
     }
 
     @Test
diff --git a/packages/VpnDialogs/res/values-hi/strings.xml b/packages/VpnDialogs/res/values-hi/strings.xml
index fc4fdcd..526541d 100644
--- a/packages/VpnDialogs/res/values-hi/strings.xml
+++ b/packages/VpnDialogs/res/values-hi/strings.xml
@@ -17,7 +17,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="prompt" msgid="3183836924226407828">"कनेक्शन अनुरोध"</string>
-    <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> VPN कनेक्‍शन सेट करना चाहता है जिससे वह नेटवर्क ट्रैफ़िक पर नज़र रख पाएगा. इसकी मंज़ूरी तभी दें जब आपको आप इसपर भरोसा हो. VPN चालू होने पर आपकी स्क्रीन के सबसे ऊपर &lt;br /&gt; &lt;br /&gt; &lt;img src=vpn_icon /&gt; दिखाई देता है."</string>
+    <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> VPN कनेक्‍शन सेट अप करना चाहता है, जिससे वह नेटवर्क ट्रैफ़िक पर नज़र रख पाएगा. इसकी मंज़ूरी तभी दें जब आपको आप इस पर भरोसा हो. VPN चालू होने पर आपकी स्क्रीन के सबसे ऊपर &lt;br /&gt; &lt;br /&gt; &lt;img src=vpn_icon /&gt; दिखाई देता है."</string>
     <string name="legacy_title" msgid="192936250066580964">"VPN कनेक्‍ट है"</string>
     <string name="session" msgid="6470628549473641030">"सत्र:"</string>
     <string name="duration" msgid="3584782459928719435">"अवधि:"</string>
diff --git a/packages/overlays/DisplayCutoutEmulationOverlay/res/values/config.xml b/packages/overlays/DisplayCutoutEmulationOverlay/res/values/config.xml
index 88c19c7..30e8b68 100644
--- a/packages/overlays/DisplayCutoutEmulationOverlay/res/values/config.xml
+++ b/packages/overlays/DisplayCutoutEmulationOverlay/res/values/config.xml
@@ -18,17 +18,26 @@
 
     <!-- The bounding path of the cutout region of the main built-in display.
          Must either be empty if there is no cutout region, or a string that is parsable by
-         {@link android.util.PathParser}. -->
+         {@link android.util.PathParser}.
+
+         The path is assumed to be specified in display coordinates with pixel units and in
+         the display's native orientation, with the origin of the coordinate system at the
+         center top of the display.
+
+         To facilitate writing device-independent emulation overlays, the marker `@dp` can be
+         appended after the path string to interpret coordinates in dp instead of px units.
+         Note that a physical cutout should be configured in pixels for the best results.
+         -->
     <string translatable="false" name="config_mainBuiltInDisplayCutout">
-        M 687.0,0
-        l -66,50
-        l 0,50
-        l 66,50
-        l 66,0
-        l 66,-50
-        l 0,-50
-        l -66,-50
-        z
+        M 0,0
+        L -24, 0
+        L -21.9940446283, 20.0595537175
+        C -21.1582133885, 28.4178661152 -17.2, 32.0 -8.8, 32.0
+        L 8.8, 32.0
+        C 17.2, 32.0 21.1582133885, 28.4178661152 21.9940446283, 20.0595537175
+        L 24, 0
+        Z
+        @dp
     </string>
 
     <!-- Whether the display cutout region of the main built-in display should be forced to
@@ -37,7 +46,7 @@
     <bool name="config_fillMainBuiltInDisplayCutout">true</bool>
 
     <!-- Height of the status bar -->
-    <dimen name="status_bar_height">150px</dimen>
+    <dimen name="status_bar_height">48dp</dimen>
 
 </resources>
 
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index 04cee67..9b67f8f 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -5134,15 +5134,20 @@
     // OS: P
     ACTION_SCREENSHOT_POWER_MENU = 1282;
 
-    // OPEN: Settings > Apps & Notifications -> Special app access -> Storage Access
+    // OPEN: Settings > Apps & Notifications -> Special app access -> Directory Access
     // CATEGORY: SETTINGS
     // OS: P
-    STORAGE_ACCESS = 1283;
+    DIRECTORY_ACCESS = 1283;
 
-    // OPEN: Settings > Apps & Notifications -> Special app access -> Storage Access -> Package
+    // OPEN: Settings > Apps & Notifications -> Special app access -> Directory Access -> Package
     // CATEGORY: SETTINGS
     // OS: P
-    APPLICATIONS_STORAGE_DETAIL = 1284;
+    APPLICATIONS_DIRECTORY_ACCESS_DETAIL = 1284;
+
+    // OPEN: Settings > Battery > Smart Battery > Restricted apps
+    // CATEGORY: SETTINGS
+    // OS: P
+    FUELGAUGE_RESTRICTED_APP_DETAILS = 1285;
 
     // ---- End P Constants, all P constants go above this line ----
     // Add new aosp constants above this line.
diff --git a/proto/src/system_messages.proto b/proto/src/system_messages.proto
index d817da5..7c6019e 100644
--- a/proto/src/system_messages.proto
+++ b/proto/src/system_messages.proto
@@ -193,6 +193,9 @@
     // Inform the user that Wifi Wake has automatically re-enabled Wifi
     NOTE_WIFI_WAKE_TURNED_BACK_ON = 44;
 
+    // Inform the user that unexpectedly rapid network usage is happening
+    NOTE_NET_RAPID = 45;
+
     // ADD_NEW_IDS_ABOVE_THIS_LINE
     // Legacy IDs with arbitrary values appear below
     // Legacy IDs existed as stable non-conflicting constants prior to the O release
diff --git a/services/accessibility/java/com/android/server/accessibility/GlobalActionPerformer.java b/services/accessibility/java/com/android/server/accessibility/GlobalActionPerformer.java
index 3b8d4bc..672518c 100644
--- a/services/accessibility/java/com/android/server/accessibility/GlobalActionPerformer.java
+++ b/services/accessibility/java/com/android/server/accessibility/GlobalActionPerformer.java
@@ -21,6 +21,8 @@
 import android.content.Context;
 import android.hardware.input.InputManager;
 import android.os.Binder;
+import android.os.Handler;
+import android.os.Looper;
 import android.os.PowerManager;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -30,20 +32,34 @@
 import android.view.KeyCharacterMap;
 import android.view.KeyEvent;
 
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.ScreenshotHelper;
 import com.android.server.LocalServices;
 import com.android.server.statusbar.StatusBarManagerInternal;
 import com.android.server.wm.WindowManagerInternal;
 
+import java.util.function.Supplier;
+
 /**
  * Handle the back-end of AccessibilityService#performGlobalAction
  */
 public class GlobalActionPerformer {
     private final WindowManagerInternal mWindowManagerService;
     private final Context mContext;
+    private Supplier<ScreenshotHelper> mScreenshotHelperSupplier;
 
     public GlobalActionPerformer(Context context, WindowManagerInternal windowManagerInternal) {
         mContext = context;
         mWindowManagerService = windowManagerInternal;
+        mScreenshotHelperSupplier = null;
+    }
+
+    // Used to mock ScreenshotHelper
+    @VisibleForTesting
+    public GlobalActionPerformer(Context context, WindowManagerInternal windowManagerInternal,
+            Supplier<ScreenshotHelper> screenshotHelperSupplier) {
+        this(context, windowManagerInternal);
+        mScreenshotHelperSupplier = screenshotHelperSupplier;
     }
 
     public boolean performGlobalAction(int action) {
@@ -79,6 +95,9 @@
                 case AccessibilityService.GLOBAL_ACTION_LOCK_SCREEN: {
                     return lockScreen();
                 }
+                case AccessibilityService.GLOBAL_ACTION_TAKE_SCREENSHOT: {
+                    return takeScreenshot();
+                }
             }
             return false;
         } finally {
@@ -167,4 +186,12 @@
         mWindowManagerService.lockNow();
         return true;
     }
+
+    private boolean takeScreenshot() {
+        ScreenshotHelper screenshotHelper = (mScreenshotHelperSupplier != null)
+                ? mScreenshotHelperSupplier.get() : new ScreenshotHelper(mContext);
+        screenshotHelper.takeScreenshot(android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN,
+                true, true, new Handler(Looper.getMainLooper()));
+        return true;
+    }
 }
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index cac7fed..978ed25 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -44,6 +44,7 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
+import android.os.RemoteCallback;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.ShellCallback;
@@ -78,6 +79,7 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Objects;
 
@@ -443,6 +445,18 @@
         }
     }
 
+    // Called by Shell command.
+    public void getScore(@Nullable String algorithmName, @NonNull String value1,
+            @NonNull String value2, @NonNull RemoteCallback callback) {
+        mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG);
+
+        final FieldClassificationStrategy strategy =
+                new FieldClassificationStrategy(mContext, UserHandle.USER_CURRENT);
+
+        strategy.getScores(callback, algorithmName, null,
+                Arrays.asList(AutofillValue.forText(value1)), new String[] { value2 });
+    }
+
     private void setDebugLocked(boolean debug) {
         com.android.server.autofill.Helper.sDebug = debug;
         android.view.autofill.Helper.sDebug = debug;
@@ -518,6 +532,8 @@
                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                 if (service != null) {
                     service.removeClientLocked(client);
+                } else if (sVerbose) {
+                    Slog.v(TAG, "removeClient(): no service for " + userId);
                 }
             }
         }
@@ -574,6 +590,8 @@
                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                 if (service != null) {
                     return service.getFillEventHistory(getCallingUid());
+                } else if (sVerbose) {
+                    Slog.v(TAG, "getFillEventHistory(): no service for " + userId);
                 }
             }
 
@@ -588,6 +606,8 @@
                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                 if (service != null) {
                     return service.getUserData(getCallingUid());
+                } else if (sVerbose) {
+                    Slog.v(TAG, "getUserData(): no service for " + userId);
                 }
             }
 
@@ -602,6 +622,8 @@
                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                 if (service != null) {
                     service.setUserData(getCallingUid(), userData);
+                } else if (sVerbose) {
+                    Slog.v(TAG, "setUserData(): no service for " + userId);
                 }
             }
         }
@@ -614,6 +636,8 @@
                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                 if (service != null) {
                     return service.isFieldClassificationEnabled(getCallingUid());
+                } else if (sVerbose) {
+                    Slog.v(TAG, "isFieldClassificationEnabled(): no service for " + userId);
                 }
             }
 
@@ -628,24 +652,30 @@
                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                 if (service != null) {
                     return service.getDefaultFieldClassificationAlgorithm(getCallingUid());
-                }
+                } else {
+                    if (sVerbose) {
+                        Slog.v(TAG, "getDefaultFcAlgorithm(): no service for " + userId);
+                    }
+                    return null;
+               }
             }
-
-            return null;
         }
 
         @Override
-        public List<String> getAvailableFieldClassificationAlgorithms() throws RemoteException {
+        public String[] getAvailableFieldClassificationAlgorithms() throws RemoteException {
             final int userId = UserHandle.getCallingUserId();
 
             synchronized (mLock) {
                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                 if (service != null) {
                     return service.getAvailableFieldClassificationAlgorithms(getCallingUid());
+                } else {
+                    if (sVerbose) {
+                        Slog.v(TAG, "getAvailableFcAlgorithms(): no service for " + userId);
+                    }
+                    return null;
                 }
             }
-
-            return null;
         }
 
         @Override
@@ -656,6 +686,8 @@
                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                 if (service != null) {
                     return service.getServiceComponentName();
+                } else if (sVerbose) {
+                    Slog.v(TAG, "getAutofillServiceComponentName(): no service for " + userId);
                 }
             }
 
@@ -665,15 +697,17 @@
         @Override
         public boolean restoreSession(int sessionId, IBinder activityToken, IBinder appCallback)
                 throws RemoteException {
+            final int userId = UserHandle.getCallingUserId();
             activityToken = Preconditions.checkNotNull(activityToken, "activityToken");
             appCallback = Preconditions.checkNotNull(appCallback, "appCallback");
 
             synchronized (mLock) {
-                final AutofillManagerServiceImpl service = mServicesCache.get(
-                        UserHandle.getCallingUserId());
+                final AutofillManagerServiceImpl service = mServicesCache.get(userId);
                 if (service != null) {
                     return service.restoreSession(sessionId, getCallingUid(), activityToken,
                             appCallback);
+                } else if (sVerbose) {
+                    Slog.v(TAG, "restoreSession(): no service for " + userId);
                 }
             }
 
@@ -688,6 +722,8 @@
                 if (service != null) {
                     service.updateSessionLocked(sessionId, getCallingUid(), autoFillId, bounds,
                             value, action, flags);
+                } else if (sVerbose) {
+                    Slog.v(TAG, "updateSession(): no service for " + userId);
                 }
             }
         }
@@ -703,6 +739,8 @@
                 if (service != null) {
                     restart = service.updateSessionLocked(sessionId, getCallingUid(), autoFillId,
                             bounds, value, action, flags);
+                } else if (sVerbose) {
+                    Slog.v(TAG, "updateOrRestartSession(): no service for " + userId);
                 }
             }
             if (restart) {
@@ -720,6 +758,8 @@
                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                 if (service != null) {
                     service.finishSessionLocked(sessionId, getCallingUid());
+                } else if (sVerbose) {
+                    Slog.v(TAG, "finishSession(): no service for " + userId);
                 }
             }
         }
@@ -730,6 +770,8 @@
                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                 if (service != null) {
                     service.cancelSessionLocked(sessionId, getCallingUid());
+                } else if (sVerbose) {
+                    Slog.v(TAG, "cancelSession(): no service for " + userId);
                 }
             }
         }
@@ -740,6 +782,8 @@
                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                 if (service != null) {
                     service.disableOwnedAutofillServicesLocked(Binder.getCallingUid());
+                } else if (sVerbose) {
+                    Slog.v(TAG, "cancelSession(): no service for " + userId);
                 }
             }
         }
@@ -755,8 +799,12 @@
         public boolean isServiceEnabled(int userId, String packageName) {
             synchronized (mLock) {
                 final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
-                if (service == null) return false;
-                return Objects.equals(packageName, service.getServicePackageName());
+                if (service != null) {
+                    return Objects.equals(packageName, service.getServicePackageName());
+                } else if (sVerbose) {
+                    Slog.v(TAG, "isServiceEnabled(): no service for " + userId);
+                }
+                return false;
             }
         }
 
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index da74dba..6bcfc4b 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -43,20 +43,15 @@
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.Looper;
-import android.os.Parcel;
-import android.os.Parcelable;
+import android.os.RemoteCallback;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.UserManager;
-import android.os.Parcelable.Creator;
-import android.os.RemoteCallback;
 import android.provider.Settings;
 import android.service.autofill.AutofillService;
 import android.service.autofill.AutofillServiceInfo;
-import android.service.autofill.Dataset;
-import android.service.autofill.EditDistanceScorer;
 import android.service.autofill.FieldClassification;
 import android.service.autofill.FieldClassification.Match;
 import android.service.autofill.FillEventHistory;
@@ -69,8 +64,6 @@
 import android.util.ArraySet;
 import android.util.DebugUtils;
 import android.util.LocalLog;
-import android.util.Log;
-import android.util.Pair;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.TimeUtils;
@@ -89,7 +82,6 @@
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
 import java.util.Random;
 
@@ -124,137 +116,7 @@
 
     private final LocalLog mRequestsHistory;
     private final LocalLog mUiLatencyHistory;
-
-    // TODO(b/70939974): temporary, will be moved to ExtServices
-    static final class FieldClassificationAlgorithmService {
-
-        static final String EXTRA_SCORES = "scores";
-
-        /**
-         * Gets the name of all available algorithms.
-         */
-        @NonNull
-        public List<String> getAvailableAlgorithms() {
-            return Arrays.asList(EditDistanceScorer.NAME);
-        }
-
-        /**
-         * Gets the default algorithm that's used when an algorithm is not specified or is invalid.
-         */
-        @NonNull
-        public String getDefaultAlgorithm() {
-            return EditDistanceScorer.NAME;
-        }
-
-        /**
-         * Gets the field classification scores.
-         *
-         * @param algorithmName algorithm to be used. If invalid, the default algorithm will be used
-         * instead.
-         * @param algorithmArgs optional arguments to be passed to the algorithm.
-         * @param currentValues values entered by the user.
-         * @param userValues values from the user data.
-         * @param callback returns a nullable bundle with the parcelable results on
-         * {@link #EXTRA_SCORES}.
-         */
-        @Nullable
-        void getScores(@NonNull String algorithmName, @Nullable Bundle algorithmArgs,
-                List<AutofillValue> currentValues, @NonNull String[] userValues,
-                @NonNull RemoteCallback callback) {
-            if (currentValues == null || userValues == null) {
-                // TODO(b/70939974): use preconditions / add unit test
-                throw new IllegalArgumentException("values cannot be null");
-            }
-            if (currentValues.isEmpty() || userValues.length == 0) {
-                Slog.w(TAG, "getScores(): empty currentvalues (" + currentValues
-                        + ") or userValues (" + Arrays.toString(userValues) + ")");
-                // TODO(b/70939974): add unit test
-                callback.sendResult(null);
-            }
-            String actualAlgorithName = algorithmName;
-            if (!EditDistanceScorer.NAME.equals(algorithmName)) {
-                Slog.w(TAG, "Ignoring invalid algorithm (" + algorithmName + ") and using "
-                        + EditDistanceScorer.NAME + " instead");
-                actualAlgorithName = EditDistanceScorer.NAME;
-            }
-            final int currentValuesSize = currentValues.size();
-            if (sDebug) {
-                Log.d(TAG, "getScores() will return a " + currentValuesSize + "x"
-                        + userValues.length + " matrix for " + actualAlgorithName);
-            }
-            final FieldClassificationScores scores = new FieldClassificationScores(
-                    actualAlgorithName, currentValuesSize, userValues.length);
-            final EditDistanceScorer algorithm = EditDistanceScorer.getInstance();
-            for (int i = 0; i < currentValuesSize; i++) {
-                for (int j = 0; j < userValues.length; j++) {
-                    final float score = algorithm.getScore(currentValues.get(i), userValues[j]);
-                    scores.scores[i][j] = score;
-                }
-            }
-            final Bundle result = new Bundle();
-            result.putParcelable(EXTRA_SCORES, scores);
-            callback.sendResult(result);
-        }
-    }
-
-    // TODO(b/70939974): temporary, will be moved to ExtServices
-    public static final class FieldClassificationScores implements Parcelable {
-        public final String algorithmName;
-        public final float[][] scores;
-
-        public FieldClassificationScores(String algorithmName, int size1, int size2) {
-            this.algorithmName = algorithmName;
-            scores = new float[size1][size2];
-        }
-
-        public FieldClassificationScores(Parcel parcel) {
-            algorithmName = parcel.readString();
-            final int size1 = parcel.readInt();
-            final int size2 = parcel.readInt();
-            scores = new float[size1][size2];
-            for (int i = 0; i < size1; i++) {
-                for (int j = 0; j < size2; j++) {
-                    scores[i][j] = parcel.readFloat();
-                }
-            }
-        }
-
-        @Override
-        public int describeContents() {
-            return 0;
-        }
-
-        @Override
-        public void writeToParcel(Parcel parcel, int flags) {
-            parcel.writeString(algorithmName);
-            int size1 = scores.length;
-            int size2 = scores[0].length;
-            parcel.writeInt(size1);
-            parcel.writeInt(size2);
-            for (int i = 0; i < size1; i++) {
-                for (int j = 0; j < size2; j++) {
-                    parcel.writeFloat(scores[i][j]);
-                }
-            }
-        }
-
-        public static final Creator<FieldClassificationScores> CREATOR = new Creator<FieldClassificationScores>() {
-
-            @Override
-            public FieldClassificationScores createFromParcel(Parcel parcel) {
-                return new FieldClassificationScores(parcel);
-            }
-
-            @Override
-            public FieldClassificationScores[] newArray(int size) {
-                return new FieldClassificationScores[size];
-            }
-
-        };
-    }
-
-    private final FieldClassificationAlgorithmService mFcService =
-            new FieldClassificationAlgorithmService();
+    private final FieldClassificationStrategy mFieldClassificationStrategy;
 
     /**
      * Apps disabled by the service; key is package name, value is when they will be enabled again.
@@ -324,6 +186,7 @@
         mUiLatencyHistory = uiLatencyHistory;
         mUserId = userId;
         mUi = ui;
+        mFieldClassificationStrategy = new FieldClassificationStrategy(context, userId);
         updateLocked(disabled);
     }
 
@@ -1089,10 +952,8 @@
             mUserData.dump(prefix2, pw);
         }
 
-        pw.print(prefix); pw.print("Available Field Classification algorithms: ");
-        pw.println(mFcService.getAvailableAlgorithms());
-        pw.print(prefix); pw.print("Default Field Classification algorithm: ");
-        pw.println(mFcService.getDefaultAlgorithm());
+        pw.print(prefix); pw.println("Field Classification strategy: ");
+        mFieldClassificationStrategy.dump(prefix2, pw);
     }
 
     void destroySessionsLocked() {
@@ -1288,17 +1149,17 @@
                 mUserId) == 1;
     }
 
-    FieldClassificationAlgorithmService getFieldClassificationService() {
-        return mFcService;
+    FieldClassificationStrategy getFieldClassificationStrategy() {
+        return mFieldClassificationStrategy;
     }
 
-    List<String> getAvailableFieldClassificationAlgorithms(int callingUid) {
+    String[] getAvailableFieldClassificationAlgorithms(int callingUid) {
         synchronized (mLock) {
             if (!isCalledByServiceLocked("getFCAlgorithms()", callingUid)) {
                 return null;
             }
         }
-        return mFcService.getAvailableAlgorithms();
+        return mFieldClassificationStrategy.getAvailableAlgorithms();
     }
 
     String getDefaultFieldClassificationAlgorithm(int callingUid) {
@@ -1307,7 +1168,7 @@
                 return null;
             }
         }
-        return mFcService.getDefaultAlgorithm();
+        return mFieldClassificationStrategy.getDefaultAlgorithm();
     }
 
     @Override
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java
index f3de557..4d69ef9 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java
@@ -16,11 +16,15 @@
 
 package com.android.server.autofill;
 
+import static android.service.autofill.AutofillFieldClassificationService.EXTRA_SCORES;
+
 import static com.android.server.autofill.AutofillManagerService.RECEIVER_BUNDLE_EXTRA_SESSIONS;
 
 import android.os.Bundle;
+import android.os.RemoteCallback;
 import android.os.ShellCommand;
 import android.os.UserHandle;
+import android.service.autofill.AutofillFieldClassificationService.Scores;
 import android.view.autofill.AutofillManager;
 
 import com.android.internal.os.IResultReceiver;
@@ -80,13 +84,16 @@
             pw.println("    Sets the maximum number of partitions per session.");
             pw.println("");
             pw.println("  list sessions [--user USER_ID]");
-            pw.println("    List all pending sessions.");
+            pw.println("    Lists all pending sessions.");
             pw.println("");
             pw.println("  destroy sessions [--user USER_ID]");
-            pw.println("    Destroy all pending sessions.");
+            pw.println("    Destroys all pending sessions.");
             pw.println("");
             pw.println("  reset");
-            pw.println("    Reset all pending sessions and cached service connections.");
+            pw.println("    Resets all pending sessions and cached service connections.");
+            pw.println("");
+            pw.println("  get fc_score [--algorithm ALGORITHM] value1 value2");
+            pw.println("    Gets the field classification score for 2 fields.");
             pw.println("");
         }
     }
@@ -98,6 +105,8 @@
                 return getLogLevel(pw);
             case "max_partitions":
                 return getMaxPartitions(pw);
+            case "fc_score":
+                return getFieldClassificationScore(pw);
             default:
                 pw.println("Invalid set: " + what);
                 return -1;
@@ -164,6 +173,32 @@
         return 0;
     }
 
+    private int getFieldClassificationScore(PrintWriter pw) {
+        final String nextArg = getNextArgRequired();
+        final String algorithm, value1;
+        if ("--algorithm".equals(nextArg)) {
+            algorithm = getNextArgRequired();
+            value1 = getNextArgRequired();
+        } else {
+            algorithm = null;
+            value1 = nextArg;
+        }
+        final String value2 = getNextArgRequired();
+
+        final CountDownLatch latch = new CountDownLatch(1);
+        mService.getScore(algorithm, value1, value2, new RemoteCallback((result) -> {
+            final Scores scores = result.getParcelable(EXTRA_SCORES);
+            if (scores == null) {
+                pw.println("no score");
+            } else {
+                pw.println(scores.scores[0][0]);
+            }
+            latch.countDown();
+        }));
+
+        return waitForLatch(pw, latch);
+    }
+
     private int requestDestroy(PrintWriter pw) {
         if (!isNextArgSessions(pw)) {
             return -1;
@@ -210,19 +245,13 @@
         return true;
     }
 
-    private boolean isNextArgLogLevel(PrintWriter pw, String cmd) {
-        final String type = getNextArgRequired();
-        if (!type.equals("log_level")) {
-            pw.println("Error: invalid " + cmd + " type: " + type);
-            return false;
-        }
-        return true;
-    }
-
     private int requestSessionCommon(PrintWriter pw, CountDownLatch latch,
             Runnable command) {
         command.run();
+        return waitForLatch(pw, latch);
+    }
 
+    private int waitForLatch(PrintWriter pw, CountDownLatch latch) {
         try {
             final boolean received = latch.await(5, TimeUnit.SECONDS);
             if (!received) {
diff --git a/services/autofill/java/com/android/server/autofill/FieldClassificationStrategy.java b/services/autofill/java/com/android/server/autofill/FieldClassificationStrategy.java
new file mode 100644
index 0000000..da52201
--- /dev/null
+++ b/services/autofill/java/com/android/server/autofill/FieldClassificationStrategy.java
@@ -0,0 +1,289 @@
+/*
+ * 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.autofill;
+
+import static android.view.autofill.AutofillManager.FC_SERVICE_TIMEOUT;
+
+import static com.android.server.autofill.Helper.sDebug;
+import static com.android.server.autofill.Helper.sVerbose;
+import static android.service.autofill.AutofillFieldClassificationService.SERVICE_META_DATA_KEY_AVAILABLE_ALGORITHMS;
+import static android.service.autofill.AutofillFieldClassificationService.SERVICE_META_DATA_KEY_DEFAULT_ALGORITHM;
+
+import android.Manifest;
+import android.annotation.MainThread;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.content.res.Resources;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.RemoteCallback;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.service.autofill.AutofillFieldClassificationService;
+import android.service.autofill.IAutofillFieldClassificationService;
+import android.util.Log;
+import android.util.Slog;
+import android.view.autofill.AutofillValue;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Strategy used to bridge the field classification algorithms provided by a service in an external
+ * package.
+ */
+//TODO(b/70291841): add unit tests ?
+final class FieldClassificationStrategy {
+
+    private static final String TAG = "FieldClassificationStrategy";
+
+    private final Context mContext;
+    private final Object mLock = new Object();
+    private final int mUserId;
+
+    @GuardedBy("mLock")
+    private ServiceConnection mServiceConnection;
+
+    @GuardedBy("mLock")
+    private IAutofillFieldClassificationService mRemoteService;
+
+    @GuardedBy("mLock")
+    private ArrayList<Command> mQueuedCommands;
+
+    public FieldClassificationStrategy(Context context, int userId) {
+        mContext = context;
+        mUserId = userId;
+    }
+
+    @Nullable
+    private ServiceInfo getServiceInfo() {
+        final String packageName =
+                mContext.getPackageManager().getServicesSystemSharedLibraryPackageName();
+        if (packageName == null) {
+            Slog.w(TAG, "no external services package!");
+            return null;
+        }
+
+        final Intent intent = new Intent(AutofillFieldClassificationService.SERVICE_INTERFACE);
+        intent.setPackage(packageName);
+        final ResolveInfo resolveInfo = mContext.getPackageManager().resolveService(intent,
+                PackageManager.GET_SERVICES | PackageManager.GET_META_DATA);
+        if (resolveInfo == null || resolveInfo.serviceInfo == null) {
+            Slog.w(TAG, "No valid components found.");
+            return null;
+        }
+        return resolveInfo.serviceInfo;
+    }
+
+    @Nullable
+    private ComponentName getServiceComponentName() {
+        final ServiceInfo serviceInfo = getServiceInfo();
+        if (serviceInfo == null) return null;
+
+        final ComponentName name = new ComponentName(serviceInfo.packageName, serviceInfo.name);
+        if (!Manifest.permission.BIND_AUTOFILL_FIELD_CLASSIFICATION_SERVICE
+                .equals(serviceInfo.permission)) {
+            Slog.w(TAG, name.flattenToShortString() + " does not require permission "
+                    + Manifest.permission.BIND_AUTOFILL_FIELD_CLASSIFICATION_SERVICE);
+            return null;
+        }
+
+        if (sVerbose) Slog.v(TAG, "getServiceComponentName(): " + name);
+        return name;
+    }
+
+    /**
+     * Run a command, starting the service connection if necessary.
+     */
+    private void connectAndRun(@NonNull Command command) {
+        synchronized (mLock) {
+            if (mRemoteService != null) {
+                try {
+                    if (sVerbose) Slog.v(TAG, "running command right away");
+                    command.run(mRemoteService);
+                } catch (RemoteException e) {
+                    Slog.w(TAG, "exception calling service: " + e);
+                }
+                return;
+            } else {
+                if (sDebug) Slog.d(TAG, "service is null; queuing command");
+                if (mQueuedCommands == null) {
+                    mQueuedCommands = new ArrayList<>(1);
+                }
+                mQueuedCommands.add(command);
+                // If we're already connected, don't create a new connection, just leave - the
+                // command will be run when the service connects
+                if (mServiceConnection != null) return;
+            }
+
+            if (sVerbose) Slog.v(TAG, "creating connection");
+
+            // Create the connection
+            mServiceConnection = new ServiceConnection() {
+                @Override
+                public void onServiceConnected(ComponentName name, IBinder service) {
+                    if (sVerbose) Slog.v(TAG, "onServiceConnected(): " + name);
+                    synchronized (mLock) {
+                        mRemoteService = IAutofillFieldClassificationService.Stub
+                                .asInterface(service);
+                        if (mQueuedCommands != null) {
+                            final int size = mQueuedCommands.size();
+                            if (sDebug) Slog.d(TAG, "running " + size + " queued commands");
+                            for (int i = 0; i < size; i++) {
+                                final Command queuedCommand = mQueuedCommands.get(i);
+                                try {
+                                    if (sVerbose) Slog.v(TAG, "running queued command #" + i);
+                                    queuedCommand.run(mRemoteService);
+                                } catch (RemoteException e) {
+                                    Slog.w(TAG, "exception calling " + name + ": " + e);
+                                }
+                            }
+                            mQueuedCommands = null;
+                        } else if (sDebug) Slog.d(TAG, "no queued commands");
+                    }
+                }
+
+                @Override
+                @MainThread
+                public void onServiceDisconnected(ComponentName name) {
+                    if (sVerbose) Slog.v(TAG, "onServiceDisconnected(): " + name);
+                    synchronized (mLock) {
+                        mRemoteService = null;
+                    }
+                }
+
+                @Override
+                public void onBindingDied(ComponentName name) {
+                    if (sVerbose) Slog.v(TAG, "onBindingDied(): " + name);
+                    synchronized (mLock) {
+                        mRemoteService = null;
+                    }
+                }
+
+                @Override
+                public void onNullBinding(ComponentName name) {
+                    if (sVerbose) Slog.v(TAG, "onNullBinding(): " + name);
+                    synchronized (mLock) {
+                        mRemoteService = null;
+                    }
+                }
+            };
+
+            final ComponentName component = getServiceComponentName();
+            if (sVerbose) Slog.v(TAG, "binding to: " + component);
+            if (component != null) {
+                final Intent intent = new Intent();
+                intent.setComponent(component);
+                final long token = Binder.clearCallingIdentity();
+                try {
+                    mContext.bindServiceAsUser(intent, mServiceConnection, Context.BIND_AUTO_CREATE,
+                            UserHandle.of(mUserId));
+                    if (sVerbose) Slog.v(TAG, "bound");
+                } finally {
+                    Binder.restoreCallingIdentity(token);
+                }
+            }
+        }
+    }
+
+    /**
+     * Gets the name of all available algorithms.
+     */
+    @Nullable
+    String[] getAvailableAlgorithms() {
+        return getMetadataValue(SERVICE_META_DATA_KEY_AVAILABLE_ALGORITHMS,
+                (res, id) -> res.getStringArray(id));
+    }
+
+    /**
+     * Gets the default algorithm that's used when an algorithm is not specified or is invalid.
+     */
+    @Nullable
+    String getDefaultAlgorithm() {
+        return getMetadataValue(SERVICE_META_DATA_KEY_DEFAULT_ALGORITHM, (res, id) -> res.getString(id));
+    }
+
+    @Nullable
+    private <T> T getMetadataValue(String field, MetadataParser<T> parser) {
+        final ServiceInfo serviceInfo = getServiceInfo();
+        if (serviceInfo == null) return null;
+
+        final PackageManager pm = mContext.getPackageManager();
+
+        final Resources res;
+        try {
+            res = pm.getResourcesForApplication(serviceInfo.applicationInfo);
+        } catch (PackageManager.NameNotFoundException e) {
+            Log.e(TAG, "Error getting application resources for " + serviceInfo, e);
+            return null;
+        }
+
+        final int resourceId = serviceInfo.metaData.getInt(field);
+        return parser.get(res, resourceId);
+    }
+
+    //TODO(b/70291841): rename this method (and all others in the chain) to something like
+    // calculateScores() ?
+    void getScores(RemoteCallback callback, @Nullable String algorithmName,
+            @Nullable Bundle algorithmArgs, @NonNull List<AutofillValue> actualValues,
+            @NonNull String[] userDataValues) {
+        connectAndRun((service) -> service.getScores(callback, algorithmName,
+                algorithmArgs, actualValues, userDataValues));
+    }
+
+    void dump(String prefix, PrintWriter pw) {
+        final ComponentName impl = getServiceComponentName();
+        pw.print(prefix); pw.print("User ID: "); pw.println(mUserId);
+        pw.print(prefix); pw.print("Queued commands: ");
+        if (mQueuedCommands == null) {
+            pw.println("N/A");
+        } else {
+            pw.println(mQueuedCommands.size());
+        }
+        pw.print(prefix); pw.print("Implementation: ");
+        if (impl == null) {
+            pw.println("N/A");
+            return;
+        }
+        pw.println(impl.flattenToShortString());
+
+        pw.print(prefix); pw.print("Available algorithms: ");
+        pw.println(Arrays.toString(getAvailableAlgorithms()));
+        pw.print(prefix); pw.print("Default algorithm: "); pw.println(getDefaultAlgorithm());
+    }
+
+    private static interface Command {
+        void run(IAutofillFieldClassificationService service) throws RemoteException;
+    }
+
+    private static interface MetadataParser<T> {
+        T get(Resources res, int resId);
+    }
+}
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index f5d1336..63f8384 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -18,6 +18,7 @@
 
 import static android.app.ActivityManagerInternal.ASSIST_KEY_RECEIVER_EXTRAS;
 import static android.app.ActivityManagerInternal.ASSIST_KEY_STRUCTURE;
+import static android.service.autofill.AutofillFieldClassificationService.EXTRA_SCORES;
 import static android.service.autofill.FillRequest.FLAG_MANUAL_REQUEST;
 import static android.service.autofill.FillRequest.INVALID_REQUEST_ID;
 import static android.view.autofill.AutofillManager.ACTION_START_SESSION;
@@ -25,7 +26,6 @@
 import static android.view.autofill.AutofillManager.ACTION_VIEW_ENTERED;
 import static android.view.autofill.AutofillManager.ACTION_VIEW_EXITED;
 
-import static com.android.server.autofill.AutofillManagerServiceImpl.FieldClassificationAlgorithmService.EXTRA_SCORES;
 import static com.android.server.autofill.Helper.sDebug;
 import static com.android.server.autofill.Helper.sPartitionMaxCount;
 import static com.android.server.autofill.Helper.sVerbose;
@@ -54,11 +54,11 @@
 import android.os.RemoteCallback;
 import android.os.RemoteException;
 import android.os.SystemClock;
+import android.service.autofill.AutofillFieldClassificationService.Scores;
 import android.service.autofill.AutofillService;
 import android.service.autofill.Dataset;
 import android.service.autofill.FieldClassification;
 import android.service.autofill.FieldClassification.Match;
-import android.service.carrier.CarrierMessagingService.ResultCallback;
 import android.service.autofill.FillContext;
 import android.service.autofill.FillRequest;
 import android.service.autofill.FillResponse;
@@ -86,8 +86,6 @@
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.os.HandlerCaller;
 import com.android.internal.util.ArrayUtils;
-import com.android.server.autofill.AutofillManagerServiceImpl.FieldClassificationAlgorithmService;
-import com.android.server.autofill.AutofillManagerServiceImpl.FieldClassificationScores;
 import com.android.server.autofill.ui.AutoFillUI;
 import com.android.server.autofill.ui.PendingUi;
 
@@ -99,7 +97,6 @@
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicReference;
 
 /**
  * A session for a given activity.
@@ -1101,10 +1098,9 @@
         }
 
         // Sets field classification scores
-        final FieldClassificationAlgorithmService fcService =
-                mService.getFieldClassificationService();
-        if (userData != null && fcService != null) {
-            logFieldClassificationScoreLocked(fcService, ignoredDatasets, changedFieldIds,
+        final FieldClassificationStrategy fcStrategy = mService.getFieldClassificationStrategy();
+        if (userData != null && fcStrategy != null) {
+            logFieldClassificationScoreLocked(fcStrategy, ignoredDatasets, changedFieldIds,
                     changedDatasetIds, manuallyFilledFieldIds, manuallyFilledDatasetIds,
                     manuallyFilledIds, userData,
                     mViewStates.values());
@@ -1121,7 +1117,7 @@
      * {@code fieldId} based on its {@code currentValue} and {@code userData}.
      */
     private void logFieldClassificationScoreLocked(
-            @NonNull AutofillManagerServiceImpl.FieldClassificationAlgorithmService fcService,
+            @NonNull FieldClassificationStrategy fcStrategy,
             @NonNull ArraySet<String> ignoredDatasets,
             @NonNull ArrayList<AutofillId> changedFieldIds,
             @NonNull ArrayList<String> changedDatasetIds,
@@ -1161,6 +1157,7 @@
             fieldIds[k++] = viewState.id;
         }
 
+        // Then use the results, asynchronously
         final RemoteCallback callback = new RemoteCallback((result) -> {
             if (result == null) {
                 if (sDebug) Slog.d(TAG, "setFieldClassificationScore(): no results");
@@ -1170,35 +1167,43 @@
                         mComponentName.getPackageName());
                 return;
             }
-            final FieldClassificationScores matrix = result.getParcelable(EXTRA_SCORES);
+            final Scores scores = result.getParcelable(EXTRA_SCORES);
+            if (scores == null) {
+                Slog.w(TAG, "No field classification score on " + result);
+                return;
+            }
+            int i = 0, j = 0;
+            try {
+                for (i = 0; i < viewsSize; i++) {
+                    final AutofillId fieldId = fieldIds[i];
 
-            // Then use the results.
-            for (int i = 0; i < viewsSize; i++) {
-                final AutofillId fieldId = fieldIds[i];
-
-                ArrayList<Match> matches = null;
-                for (int j = 0; j < userValues.length; j++) {
-                    String remoteId = remoteIds[j];
-                    final String actualAlgorithm = matrix.algorithmName;
-                    final float score = matrix.scores[i][j];
-                    if (score > 0) {
-                        if (sVerbose) {
-                            Slog.v(TAG, "adding score " + score + " at index " + j + " and id "
-                                    + fieldId);
+                    ArrayList<Match> matches = null;
+                    for (j = 0; j < userValues.length; j++) {
+                        String remoteId = remoteIds[j];
+                        final float score = scores.scores[i][j];
+                        if (score > 0) {
+                            if (sVerbose) {
+                                Slog.v(TAG, "adding score " + score + " at index " + j + " and id "
+                                        + fieldId);
+                            }
+                            if (matches == null) {
+                                matches = new ArrayList<>(userValues.length);
+                            }
+                            matches.add(new Match(remoteId, score));
                         }
-                        if (matches == null) {
-                            matches = new ArrayList<>(userValues.length);
+                        else if (sVerbose) {
+                            Slog.v(TAG, "skipping score 0 at index " + j + " and id " + fieldId);
                         }
-                        matches.add(new Match(remoteId, score, actualAlgorithm));
                     }
-                    else if (sVerbose) {
-                        Slog.v(TAG, "skipping score 0 at index " + j + " and id " + fieldId);
+                    if (matches != null) {
+                        detectedFieldIds.add(fieldId);
+                        detectedFieldClassifications.add(new FieldClassification(matches));
                     }
                 }
-                if (matches != null) {
-                    detectedFieldIds.add(fieldId);
-                    detectedFieldClassifications.add(new FieldClassification(matches));
-                }
+            } catch (ArrayIndexOutOfBoundsException e) {
+                Slog.wtf(TAG, "Error accessing FC score at " + i + " x " + j + ": "
+                        + Arrays.toString(scores.scores), e);
+                return;
             }
 
             mService.logContextCommittedLocked(id, mClientState, mSelectedDatasetIds,
@@ -1207,7 +1212,7 @@
                     mComponentName.getPackageName());
         });
 
-        fcService.getScores(algorithm, algorithmArgs, currentValues, userValues, callback);
+        fcStrategy.getScores(callback, algorithm, algorithmArgs, currentValues, userValues);
     }
 
     /**
diff --git a/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java b/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java
index 5188910..465bb09 100644
--- a/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java
@@ -3464,16 +3464,21 @@
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.BACKUP, "isAppEligibleForBackup");
 
-        String callerLogString = "BMS.isAppEligibleForBackup";
-        TransportClient transportClient =
-                mTransportManager.getCurrentTransportClient(callerLogString);
-        boolean eligible =
-                AppBackupUtils.appIsRunningAndEligibleForBackupWithTransport(
-                        transportClient, packageName, mPackageManager);
-        if (transportClient != null) {
-            mTransportManager.disposeOfTransportClient(transportClient, callerLogString);
+        long oldToken = Binder.clearCallingIdentity();
+        try {
+            String callerLogString = "BMS.isAppEligibleForBackup";
+            TransportClient transportClient =
+                    mTransportManager.getCurrentTransportClient(callerLogString);
+            boolean eligible =
+                    AppBackupUtils.appIsRunningAndEligibleForBackupWithTransport(
+                            transportClient, packageName, mPackageManager);
+            if (transportClient != null) {
+                mTransportManager.disposeOfTransportClient(transportClient, callerLogString);
+            }
+            return eligible;
+        } finally {
+            Binder.restoreCallingIdentity(oldToken);
         }
-        return eligible;
     }
 
     @Override
@@ -3481,21 +3486,26 @@
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.BACKUP, "filterAppsEligibleForBackup");
 
-        String callerLogString = "BMS.filterAppsEligibleForBackup";
-        TransportClient transportClient =
-                mTransportManager.getCurrentTransportClient(callerLogString);
-        List<String> eligibleApps = new LinkedList<>();
-        for (String packageName : packages) {
-            if (AppBackupUtils
-                    .appIsRunningAndEligibleForBackupWithTransport(
-                            transportClient, packageName, mPackageManager)) {
-                eligibleApps.add(packageName);
+        long oldToken = Binder.clearCallingIdentity();
+        try {
+            String callerLogString = "BMS.filterAppsEligibleForBackup";
+            TransportClient transportClient =
+                    mTransportManager.getCurrentTransportClient(callerLogString);
+            List<String> eligibleApps = new LinkedList<>();
+            for (String packageName : packages) {
+                if (AppBackupUtils
+                        .appIsRunningAndEligibleForBackupWithTransport(
+                                transportClient, packageName, mPackageManager)) {
+                    eligibleApps.add(packageName);
+                }
             }
+            if (transportClient != null) {
+                mTransportManager.disposeOfTransportClient(transportClient, callerLogString);
+            }
+            return eligibleApps.toArray(new String[eligibleApps.size()]);
+        } finally {
+            Binder.restoreCallingIdentity(oldToken);
         }
-        if (transportClient != null) {
-            mTransportManager.disposeOfTransportClient(transportClient, callerLogString);
-        }
-        return eligibleApps.toArray(new String[eligibleApps.size()]);
     }
 
     @Override
@@ -3514,6 +3524,9 @@
                     } else if ("agents".startsWith(arg)) {
                         dumpAgents(pw);
                         return;
+                    } else if ("transportclients".equals(arg.toLowerCase())) {
+                        mTransportManager.dump(pw);
+                        return;
                     }
                 }
             }
@@ -3576,6 +3589,8 @@
                 }
             }
 
+            mTransportManager.dump(pw);
+
             pw.println("Pending init: " + mPendingInits.size());
             for (String s : mPendingInits) {
                 pw.println("    " + s);
diff --git a/services/backup/java/com/android/server/backup/TransportManager.java b/services/backup/java/com/android/server/backup/TransportManager.java
index 30fd25a..7e179e5 100644
--- a/services/backup/java/com/android/server/backup/TransportManager.java
+++ b/services/backup/java/com/android/server/backup/TransportManager.java
@@ -29,6 +29,7 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.util.ArrayMap;
+import android.util.ArraySet;
 import android.util.Slog;
 
 import com.android.internal.annotations.GuardedBy;
@@ -42,13 +43,12 @@
 import com.android.server.backup.transport.TransportNotAvailableException;
 import com.android.server.backup.transport.TransportNotRegisteredException;
 
+import java.io.PrintWriter;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.function.Consumer;
 import java.util.function.Predicate;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
 
 /** Handles in-memory bookkeeping of all BackupTransport objects. */
 public class TransportManager {
@@ -62,9 +62,17 @@
     private final PackageManager mPackageManager;
     private final Set<ComponentName> mTransportWhitelist;
     private final TransportClientManager mTransportClientManager;
-    private final Object mTransportLock = new Object();
     private OnTransportRegisteredListener mOnTransportRegisteredListener = (c, n) -> {};
 
+    /**
+     * Lock for registered transports and currently selected transport.
+     *
+     * <p><b>Warning:</b> No calls to {@link IBackupTransport} or calls that result in transport
+     * code being executed such as {@link TransportClient#connect(String)}} and its variants should
+     * be made with this lock held, risk of deadlock.
+     */
+    private final Object mTransportLock = new Object();
+
     /** @see #getRegisteredTransportNames() */
     @GuardedBy("mTransportLock")
     private final Map<ComponentName, TransportDescription> mRegisteredTransportsDescriptionMap =
@@ -109,15 +117,16 @@
 
     @WorkerThread
     void onPackageChanged(String packageName, String... components) {
-        synchronized (mTransportLock) {
-            Set<ComponentName> transportComponents =
-                    Stream.of(components)
-                            .map(component -> new ComponentName(packageName, component))
-                            .collect(Collectors.toSet());
-
-            mRegisteredTransportsDescriptionMap.keySet().removeIf(transportComponents::contains);
-            registerTransportsFromPackage(packageName, transportComponents::contains);
+        // Unfortunately this can't be atomic because we risk a deadlock if
+        // registerTransportsFromPackage() is put inside the synchronized block
+        Set<ComponentName> transportComponents = new ArraySet<>(components.length);
+        for (String componentName : components) {
+            transportComponents.add(new ComponentName(packageName, componentName));
         }
+        synchronized (mTransportLock) {
+            mRegisteredTransportsDescriptionMap.keySet().removeIf(transportComponents::contains);
+        }
+        registerTransportsFromPackage(packageName, transportComponents::contains);
     }
 
     /**
@@ -142,11 +151,13 @@
      */
     String[] getRegisteredTransportNames() {
         synchronized (mTransportLock) {
-            return mRegisteredTransportsDescriptionMap
-                    .values()
-                    .stream()
-                    .map(transportDescription -> transportDescription.name)
-                    .toArray(String[]::new);
+            String[] transportNames = new String[mRegisteredTransportsDescriptionMap.size()];
+            int i = 0;
+            for (TransportDescription description : mRegisteredTransportsDescriptionMap.values()) {
+                transportNames[i] = description.name;
+                i++;
+            }
+            return transportNames;
         }
     }
 
@@ -263,6 +274,9 @@
      * This is called with an internal lock held, ensuring that the transport will remain registered
      * while {@code transportConsumer} is being executed. Don't do heavy operations in {@code
      * transportConsumer}.
+     *
+     * <p><b>Warning:</b> Do NOT make any calls to {@link IBackupTransport} or call any variants of
+     * {@link TransportClient#connect(String)} here, otherwise you risk deadlock.
      */
     public void forEachRegisteredTransport(Consumer<String> transportConsumer) {
         synchronized (mTransportLock) {
@@ -465,20 +479,27 @@
      */
     @WorkerThread
     public int registerAndSelectTransport(ComponentName transportComponent) {
+        // If it's already registered we select and return
         synchronized (mTransportLock) {
-            if (!mRegisteredTransportsDescriptionMap.containsKey(transportComponent)) {
-                int result = registerTransport(transportComponent);
-                if (result != BackupManager.SUCCESS) {
-                    return result;
-                }
-            }
-
             try {
                 selectTransport(getTransportName(transportComponent));
                 return BackupManager.SUCCESS;
             } catch (TransportNotRegisteredException e) {
-                // Shouldn't happen because we are holding the lock
-                Slog.wtf(TAG, "Transport unexpectedly not registered");
+                // Fall through and release lock
+            }
+        }
+
+        // We can't call registerTransport() with the transport lock held
+        int result = registerTransport(transportComponent);
+        if (result != BackupManager.SUCCESS) {
+            return result;
+        }
+        synchronized (mTransportLock) {
+            try {
+                selectTransport(getTransportName(transportComponent));
+                return BackupManager.SUCCESS;
+            } catch (TransportNotRegisteredException e) {
+                Slog.wtf(TAG, "Transport got unregistered");
                 return BackupManager.ERROR_TRANSPORT_UNAVAILABLE;
             }
         }
@@ -512,13 +533,11 @@
         if (hosts == null) {
             return;
         }
-        synchronized (mTransportLock) {
-            for (ResolveInfo host : hosts) {
-                ComponentName transportComponent = host.serviceInfo.getComponentName();
-                if (transportComponentFilter.test(transportComponent)
-                        && isTransportTrusted(transportComponent)) {
-                    registerTransport(transportComponent);
-                }
+        for (ResolveInfo host : hosts) {
+            ComponentName transportComponent = host.serviceInfo.getComponentName();
+            if (transportComponentFilter.test(transportComponent)
+                    && isTransportTrusted(transportComponent)) {
+                registerTransport(transportComponent);
             }
         }
     }
@@ -547,22 +566,24 @@
     /**
      * Tries to register transport represented by {@code transportComponent}.
      *
+     * <p><b>Warning:</b> Don't call this with the transport lock held.
+     *
      * @param transportComponent Host of the transport that we want to register.
      * @return One of {@link BackupManager#SUCCESS}, {@link BackupManager#ERROR_TRANSPORT_INVALID}
      *     or {@link BackupManager#ERROR_TRANSPORT_UNAVAILABLE}.
      */
     @WorkerThread
     private int registerTransport(ComponentName transportComponent) {
+        checkCanUseTransport();
+
         if (!isTransportTrusted(transportComponent)) {
             return BackupManager.ERROR_TRANSPORT_INVALID;
         }
 
         String transportString = transportComponent.flattenToShortString();
-
         String callerLogString = "TransportManager.registerTransport()";
         TransportClient transportClient =
                 mTransportClientManager.getTransportClient(transportComponent, callerLogString);
-
         final IBackupTransport transport;
         try {
             transport = transportClient.connectOrThrow(callerLogString);
@@ -593,20 +614,30 @@
     /** If {@link RemoteException} is thrown the transport is guaranteed to not be registered. */
     private void registerTransport(ComponentName transportComponent, IBackupTransport transport)
             throws RemoteException {
+        checkCanUseTransport();
+
+        TransportDescription description =
+                new TransportDescription(
+                        transport.name(),
+                        transport.transportDirName(),
+                        transport.configurationIntent(),
+                        transport.currentDestinationString(),
+                        transport.dataManagementIntent(),
+                        transport.dataManagementLabel());
         synchronized (mTransportLock) {
-            String name = transport.name();
-            TransportDescription description =
-                    new TransportDescription(
-                            name,
-                            transport.transportDirName(),
-                            transport.configurationIntent(),
-                            transport.currentDestinationString(),
-                            transport.dataManagementIntent(),
-                            transport.dataManagementLabel());
             mRegisteredTransportsDescriptionMap.put(transportComponent, description);
         }
     }
 
+    private void checkCanUseTransport() {
+        Preconditions.checkState(
+                !Thread.holdsLock(mTransportLock), "Can't call transport with transport lock held");
+    }
+
+    public void dump(PrintWriter pw) {
+        mTransportClientManager.dump(pw);
+    }
+
     private static Predicate<ComponentName> fromPackageFilter(String packageName) {
         return transportComponent -> packageName.equals(transportComponent.getPackageName());
     }
diff --git a/services/backup/java/com/android/server/backup/transport/TransportClient.java b/services/backup/java/com/android/server/backup/transport/TransportClient.java
index 399f338..7b2e3df 100644
--- a/services/backup/java/com/android/server/backup/transport/TransportClient.java
+++ b/services/backup/java/com/android/server/backup/transport/TransportClient.java
@@ -16,6 +16,8 @@
 
 package com.android.server.backup.transport;
 
+import static com.android.server.backup.transport.TransportUtils.formatMessage;
+
 import android.annotation.IntDef;
 import android.annotation.Nullable;
 import android.annotation.WorkerThread;
@@ -28,6 +30,7 @@
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.UserHandle;
+import android.text.format.DateFormat;
 import android.util.ArrayMap;
 import android.util.EventLog;
 import android.util.Log;
@@ -41,6 +44,9 @@
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
 import java.util.Map;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ExecutionException;
@@ -65,6 +71,7 @@
  */
 public class TransportClient {
     private static final String TAG = "TransportClient";
+    private static final int LOG_BUFFER_SIZE = 5;
 
     private final Context mContext;
     private final Intent mBindIntent;
@@ -73,6 +80,10 @@
     private final Handler mListenerHandler;
     private final String mPrefixForLog;
     private final Object mStateLock = new Object();
+    private final Object mLogBufferLock = new Object();
+
+    @GuardedBy("mLogBufferLock")
+    private final List<String> mLogBuffer = new LinkedList<>();
 
     @GuardedBy("mStateLock")
     private final Map<TransportConnectionListener, String> mListeners = new ArrayMap<>();
@@ -112,7 +123,7 @@
 
         // For logging
         String classNameForLog = mTransportComponent.getShortClassName().replaceFirst(".*\\.", "");
-        mPrefixForLog = classNameForLog + "#" + mIdentifier + ": ";
+        mPrefixForLog = classNameForLog + "#" + mIdentifier + ":";
     }
 
     public ComponentName getTransportComponent() {
@@ -229,7 +240,7 @@
 
             switch (mState) {
                 case State.UNUSABLE:
-                    log(Log.DEBUG, caller, "Async connect: UNUSABLE client");
+                    log(Log.WARN, caller, "Async connect: UNUSABLE client");
                     notifyListener(listener, null, caller);
                     break;
                 case State.IDLE:
@@ -324,14 +335,14 @@
 
         IBackupTransport transport = mTransport;
         if (transport != null) {
-            log(Log.DEBUG, caller, "Sync connect: reusing transport");
+            log(Log.INFO, caller, "Sync connect: reusing transport");
             return transport;
         }
 
         // If it's already UNUSABLE we return straight away, no need to go to main-thread
         synchronized (mStateLock) {
             if (mState == State.UNUSABLE) {
-                log(Log.DEBUG, caller, "Sync connect: UNUSABLE client");
+                log(Log.WARN, caller, "Sync connect: UNUSABLE client");
                 return null;
             }
         }
@@ -403,13 +414,16 @@
     }
 
     private void notifyListener(
-            TransportConnectionListener listener, IBackupTransport transport, String caller) {
-        log(Log.VERBOSE, caller, "Notifying listener of transport = " + transport);
+            TransportConnectionListener listener,
+            @Nullable IBackupTransport transport,
+            String caller) {
+        String transportString = (transport != null) ? "IBackupTransport" : "null";
+        log(Log.INFO, "Notifying [" + caller + "] transport = " + transportString);
         mListenerHandler.post(() -> listener.onTransportConnectionResult(transport, this));
     }
 
     @GuardedBy("mStateLock")
-    private void notifyListenersAndClearLocked(IBackupTransport transport) {
+    private void notifyListenersAndClearLocked(@Nullable IBackupTransport transport) {
         for (Map.Entry<TransportConnectionListener, String> entry : mListeners.entrySet()) {
             TransportConnectionListener listener = entry.getKey();
             String caller = entry.getValue();
@@ -509,13 +523,30 @@
     }
 
     private void log(int priority, String message) {
-        TransportUtils.log(priority, TAG, message);
+        TransportUtils.log(priority, TAG, formatMessage(mPrefixForLog, null, message));
+        saveLogEntry(formatMessage(null, null, message));
     }
 
-    private void log(int priority, String caller, String msg) {
-        TransportUtils.log(priority, TAG, mPrefixForLog, caller, msg);
-        // TODO(brufino): Log in internal list for dump
-        // CharSequence time = DateFormat.format("yyyy-MM-dd HH:mm:ss", System.currentTimeMillis());
+    private void log(int priority, String caller, String message) {
+        TransportUtils.log(priority, TAG, formatMessage(mPrefixForLog, caller, message));
+        saveLogEntry(formatMessage(null, caller, message));
+    }
+
+    private void saveLogEntry(String message) {
+        CharSequence time = DateFormat.format("yyyy-MM-dd HH:mm:ss", System.currentTimeMillis());
+        message = time + " " + message;
+        synchronized (mLogBufferLock) {
+            if (mLogBuffer.size() == LOG_BUFFER_SIZE) {
+                mLogBuffer.remove(mLogBuffer.size() - 1);
+            }
+            mLogBuffer.add(0, message);
+        }
+    }
+
+    List<String> getLogBuffer() {
+        synchronized (mLogBufferLock) {
+            return Collections.unmodifiableList(mLogBuffer);
+        }
     }
 
     @IntDef({Transition.DOWN, Transition.NO_TRANSITION, Transition.UP})
diff --git a/services/backup/java/com/android/server/backup/transport/TransportClientManager.java b/services/backup/java/com/android/server/backup/transport/TransportClientManager.java
index 1cbe7471..1132bce 100644
--- a/services/backup/java/com/android/server/backup/transport/TransportClientManager.java
+++ b/services/backup/java/com/android/server/backup/transport/TransportClientManager.java
@@ -17,19 +17,20 @@
 package com.android.server.backup.transport;
 
 import static com.android.server.backup.TransportManager.SERVICE_ACTION_TRANSPORT_HOST;
+import static com.android.server.backup.transport.TransportUtils.formatMessage;
 
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.util.Log;
-
 import com.android.server.backup.TransportManager;
+import java.io.PrintWriter;
+import java.util.Map;
+import java.util.WeakHashMap;
 
 /**
  * Manages the creation and disposal of {@link TransportClient}s. The only class that should use
  * this is {@link TransportManager}, all the other usages should go to {@link TransportManager}.
- *
- * <p>TODO(brufino): Implement pool of TransportClients
  */
 public class TransportClientManager {
     private static final String TAG = "TransportClientManager";
@@ -37,6 +38,7 @@
     private final Context mContext;
     private final Object mTransportClientsLock = new Object();
     private int mTransportClientsCreated = 0;
+    private Map<TransportClient, String> mTransportClientsCallerMap = new WeakHashMap<>();
 
     public TransportClientManager(Context context) {
         mContext = context;
@@ -62,8 +64,10 @@
                             bindIntent,
                             transportComponent,
                             Integer.toString(mTransportClientsCreated));
+            mTransportClientsCallerMap.put(transportClient, caller);
             mTransportClientsCreated++;
-            TransportUtils.log(Log.DEBUG, TAG, caller, "Retrieving " + transportClient);
+            TransportUtils.log(
+                    Log.DEBUG, TAG, formatMessage(null, caller, "Retrieving " + transportClient));
             return transportClient;
         }
     }
@@ -77,7 +81,25 @@
      *     details.
      */
     public void disposeOfTransportClient(TransportClient transportClient, String caller) {
-        TransportUtils.log(Log.DEBUG, TAG, caller, "Disposing of " + transportClient);
         transportClient.unbind(caller);
+        synchronized (mTransportClientsLock) {
+            TransportUtils.log(
+                    Log.DEBUG, TAG, formatMessage(null, caller, "Disposing of " + transportClient));
+            mTransportClientsCallerMap.remove(transportClient);
+        }
+    }
+
+    public void dump(PrintWriter pw) {
+        pw.println("Transport clients created: " + mTransportClientsCreated);
+        synchronized (mTransportClientsLock) {
+            pw.println("Current transport clients: " + mTransportClientsCallerMap.size());
+            for (TransportClient transportClient : mTransportClientsCallerMap.keySet()) {
+                String caller = mTransportClientsCallerMap.get(transportClient);
+                pw.println("    " + transportClient + " [" + caller + "]");
+                for (String logEntry : transportClient.getLogBuffer()) {
+                    pw.println("        " + logEntry);
+                }
+            }
+        }
     }
 }
diff --git a/services/backup/java/com/android/server/backup/transport/TransportUtils.java b/services/backup/java/com/android/server/backup/transport/TransportUtils.java
index 92bba9b..56b2d44 100644
--- a/services/backup/java/com/android/server/backup/transport/TransportUtils.java
+++ b/services/backup/java/com/android/server/backup/transport/TransportUtils.java
@@ -41,22 +41,21 @@
     }
 
     static void log(int priority, String tag, String message) {
-        log(priority, tag, null, message);
-    }
-
-    static void log(int priority, String tag, @Nullable String caller, String message) {
-        log(priority, tag, "", caller, message);
-    }
-
-    static void log(
-            int priority, String tag, String prefix, @Nullable String caller, String message) {
         if (Log.isLoggable(tag, priority)) {
-            if (caller != null) {
-                prefix += "[" + caller + "] ";
-            }
-            Slog.println(priority, tag, prefix + message);
+            Slog.println(priority, tag, message);
         }
     }
 
+    static String formatMessage(@Nullable String prefix, @Nullable String caller, String message) {
+        StringBuilder string = new StringBuilder();
+        if (prefix != null) {
+            string.append(prefix).append(" ");
+        }
+        if (caller != null) {
+            string.append("[").append(caller).append("] ");
+        }
+        return string.append(message).toString();
+    }
+
     private TransportUtils() {}
 }
diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
index 04d292f..dc5f5a2 100644
--- a/services/core/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -383,16 +383,16 @@
         }
     }
 
-    private void update(HealthInfo info) {
+    private void update(android.hardware.health.V2_0.HealthInfo info) {
         traceBegin("HealthInfoUpdate");
         synchronized (mLock) {
             if (!mUpdatesStopped) {
-                mHealthInfo = info;
+                mHealthInfo = info.legacy;
                 // Process the new values.
                 processValuesLocked(false);
                 mLock.notifyAll(); // for any waiters on new info
             } else {
-                copy(mLastHealthInfo, info);
+                copy(mLastHealthInfo, info.legacy);
             }
         }
         traceEnd();
@@ -1010,7 +1010,7 @@
 
     private final class HealthHalCallback extends IHealthInfoCallback.Stub
             implements HealthServiceWrapper.Callback {
-        @Override public void healthInfoChanged(HealthInfo props) {
+        @Override public void healthInfoChanged(android.hardware.health.V2_0.HealthInfo props) {
             BatteryService.this.update(props);
         }
         // on new service registered
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 337406d..2077790 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -439,10 +439,17 @@
                 Settings.Global.AIRPLANE_MODE_ON, 0) == 1;
     }
 
+    private boolean supportBluetoothPersistedState() {
+        return mContext.getResources().getBoolean(R.bool.config_supportBluetoothPersistedState);
+    }
+
     /**
      *  Returns true if the Bluetooth saved state is "on"
      */
     private boolean isBluetoothPersistedStateOn() {
+        if (!supportBluetoothPersistedState()) {
+            return false;
+        }
         int state = Settings.Global.getInt(mContentResolver, Settings.Global.BLUETOOTH_ON, -1);
         if (DBG) {
             Slog.d(TAG, "Bluetooth persisted state: " + state);
@@ -454,6 +461,9 @@
      *  Returns true if the Bluetooth saved state is BLUETOOTH_ON_BLUETOOTH
      */
     private boolean isBluetoothPersistedStateOnBluetooth() {
+        if (!supportBluetoothPersistedState()) {
+            return false;
+        }
         return Settings.Global.getInt(mContentResolver, Settings.Global.BLUETOOTH_ON,
                 BLUETOOTH_ON_BLUETOOTH) == BLUETOOTH_ON_BLUETOOTH;
     }
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 9574545..c1f4b78 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -63,6 +63,7 @@
 import android.net.NetworkInfo;
 import android.net.NetworkInfo.DetailedState;
 import android.net.NetworkMisc;
+import android.net.NetworkPolicyManager;
 import android.net.NetworkQuotaInfo;
 import android.net.NetworkRequest;
 import android.net.NetworkSpecifier;
@@ -1501,15 +1502,12 @@
         return true;
     }
 
-    private final INetworkPolicyListener mPolicyListener = new INetworkPolicyListener.Stub() {
+    private final INetworkPolicyListener mPolicyListener = new NetworkPolicyManager.Listener() {
         @Override
         public void onUidRulesChanged(int uid, int uidRules) {
             // TODO: notify UID when it has requested targeted updates
         }
         @Override
-        public void onMeteredIfacesChanged(String[] meteredIfaces) {
-        }
-        @Override
         public void onRestrictBackgroundChanged(boolean restrictBackground) {
             // TODO: relocate this specific callback in Tethering.
             if (restrictBackground) {
@@ -1517,9 +1515,6 @@
                 mTethering.untetherAll();
             }
         }
-        @Override
-        public void onUidPoliciesChanged(int uid, int uidPolicies) {
-        }
     };
 
     /**
@@ -4990,10 +4985,12 @@
         } catch (Exception e) {
             loge("Exception setting default network :" + e);
         }
+
         notifyLockdownVpn(newNetwork);
         handleApplyDefaultProxy(newNetwork.linkProperties.getHttpProxy());
         updateTcpBufferSizes(newNetwork);
         mDnsManager.setDefaultDnsSystemProperties(newNetwork.linkProperties.getDnsServers());
+        notifyIfacesChangedForNetworkStats();
     }
 
     private void processListenRequests(NetworkAgentInfo nai, boolean capabilitiesChanged) {
@@ -5567,12 +5564,30 @@
     }
 
     /**
+     * Returns the list of all interfaces that could be used by network traffic that does not
+     * explicitly specify a network. This includes the default network, but also all VPNs that are
+     * currently connected.
+     *
+     * Must be called on the handler thread.
+     */
+    private Network[] getDefaultNetworks() {
+        ArrayList<Network> defaultNetworks = new ArrayList<>();
+        NetworkAgentInfo defaultNetwork = getDefaultNetwork();
+        for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
+            if (nai.everConnected && (nai == defaultNetwork || nai.isVPN())) {
+                defaultNetworks.add(nai.network);
+            }
+        }
+        return defaultNetworks.toArray(new Network[0]);
+    }
+
+    /**
      * Notify NetworkStatsService that the set of active ifaces has changed, or that one of the
      * properties tracked by NetworkStatsService on an active iface has changed.
      */
     private void notifyIfacesChangedForNetworkStats() {
         try {
-            mStatsService.forceUpdateIfaces();
+            mStatsService.forceUpdateIfaces(getDefaultNetworks());
         } catch (Exception ignored) {
         }
     }
@@ -5604,7 +5619,7 @@
             success = mVpns.get(user).setUnderlyingNetworks(networks);
         }
         if (success) {
-            notifyIfacesChangedForNetworkStats();
+            mHandler.post(() -> notifyIfacesChangedForNetworkStats());
         }
         return success;
     }
diff --git a/services/core/java/com/android/server/ForceAppStandbyTracker.java b/services/core/java/com/android/server/ForceAppStandbyTracker.java
index 4551611..a538bde 100644
--- a/services/core/java/com/android/server/ForceAppStandbyTracker.java
+++ b/services/core/java/com/android/server/ForceAppStandbyTracker.java
@@ -26,8 +26,6 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.database.ContentObserver;
-import android.net.Uri;
-import android.os.BatteryManager;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
@@ -91,9 +89,6 @@
 
     private final MyHandler mHandler;
 
-    @VisibleForTesting
-    FeatureFlagsObserver mFlagsObserver;
-
     /**
      * Pair of (uid (not user-id), packageName) with OP_RUN_ANY_IN_BACKGROUND *not* allowed.
      */
@@ -119,32 +114,13 @@
     boolean mStarted;
 
     @GuardedBy("mLock")
-    boolean mIsCharging;
+    boolean mForceAllAppsStandby;   // True if device is in extreme battery saver mode
 
     @GuardedBy("mLock")
-    boolean mBatterySaverEnabled;
+    boolean mForcedAppStandbyEnabled;   // True if the forced app standby feature is enabled
 
-    /**
-     * True if the forced app standby is currently enabled
-     */
-    @GuardedBy("mLock")
-    boolean mForceAllAppsStandby;
-
-    /**
-     * True if the forced app standby for small battery devices feature is enabled in settings
-     */
-    @GuardedBy("mLock")
-    boolean mForceAllAppStandbyForSmallBattery;
-
-    /**
-     * True if the forced app standby feature is enabled in settings
-     */
-    @GuardedBy("mLock")
-    boolean mForcedAppStandbyEnabled;
-
-    @VisibleForTesting
-    class FeatureFlagsObserver extends ContentObserver {
-        FeatureFlagsObserver() {
+    private class FeatureFlagObserver extends ContentObserver {
+        FeatureFlagObserver() {
             super(null);
         }
 
@@ -152,9 +128,6 @@
             mContext.getContentResolver().registerContentObserver(
                     Settings.Global.getUriFor(Settings.Global.FORCED_APP_STANDBY_ENABLED),
                     false, this);
-
-            mContext.getContentResolver().registerContentObserver(Settings.Global.getUriFor(
-                    Settings.Global.FORCED_APP_STANDBY_FOR_SMALL_BATTERY_ENABLED), false, this);
         }
 
         boolean isForcedAppStandbyEnabled() {
@@ -162,43 +135,20 @@
                     Settings.Global.FORCED_APP_STANDBY_ENABLED, 1) == 1;
         }
 
-        boolean isForcedAppStandbyForSmallBatteryEnabled() {
-            return Settings.Global.getInt(mContext.getContentResolver(),
-                    Settings.Global.FORCED_APP_STANDBY_FOR_SMALL_BATTERY_ENABLED, 0) == 1;
-        }
-
         @Override
-        public void onChange(boolean selfChange, Uri uri) {
-            if (Settings.Global.getUriFor(Settings.Global.FORCED_APP_STANDBY_ENABLED).equals(uri)) {
-                final boolean enabled = isForcedAppStandbyEnabled();
-                synchronized (mLock) {
-                    if (mForcedAppStandbyEnabled == enabled) {
-                        return;
-                    }
-                    mForcedAppStandbyEnabled = enabled;
-                    if (DEBUG) {
-                        Slog.d(TAG,
-                                "Forced app standby feature flag changed: " + mForcedAppStandbyEnabled);
-                    }
+        public void onChange(boolean selfChange) {
+            final boolean enabled = isForcedAppStandbyEnabled();
+            synchronized (mLock) {
+                if (mForcedAppStandbyEnabled == enabled) {
+                    return;
                 }
-                mHandler.notifyForcedAppStandbyFeatureFlagChanged();
-            } else if (Settings.Global.getUriFor(
-                    Settings.Global.FORCED_APP_STANDBY_FOR_SMALL_BATTERY_ENABLED).equals(uri)) {
-                final boolean enabled = isForcedAppStandbyForSmallBatteryEnabled();
-                synchronized (mLock) {
-                    if (mForceAllAppStandbyForSmallBattery == enabled) {
-                        return;
-                    }
-                    mForceAllAppStandbyForSmallBattery = enabled;
-                    if (DEBUG) {
-                        Slog.d(TAG, "Forced app standby for small battery feature flag changed: "
-                                + mForceAllAppStandbyForSmallBattery);
-                    }
-                    updateForceAllAppStandbyState();
+                mForcedAppStandbyEnabled = enabled;
+                if (DEBUG) {
+                    Slog.d(TAG,
+                            "Forced app standby feature flag changed: " + mForcedAppStandbyEnabled);
                 }
-            } else {
-                Slog.w(TAG, "Unexpected feature flag uri encountered: " + uri);
             }
+            mHandler.notifyFeatureFlagChanged();
         }
     }
 
@@ -339,11 +289,9 @@
             mAppOpsManager = Preconditions.checkNotNull(injectAppOpsManager());
             mAppOpsService = Preconditions.checkNotNull(injectIAppOpsService());
             mPowerManagerInternal = Preconditions.checkNotNull(injectPowerManagerInternal());
-            mFlagsObserver = new FeatureFlagsObserver();
-            mFlagsObserver.register();
-            mForcedAppStandbyEnabled = mFlagsObserver.isForcedAppStandbyEnabled();
-            mForceAllAppStandbyForSmallBattery =
-                    mFlagsObserver.isForcedAppStandbyForSmallBatteryEnabled();
+            final FeatureFlagObserver flagObserver = new FeatureFlagObserver();
+            flagObserver.register();
+            mForcedAppStandbyEnabled = flagObserver.isForcedAppStandbyEnabled();
 
             try {
                 mIActivityManager.registerUidObserver(new UidObserver(),
@@ -358,24 +306,16 @@
 
             IntentFilter filter = new IntentFilter();
             filter.addAction(Intent.ACTION_USER_REMOVED);
-            filter.addAction(Intent.ACTION_BATTERY_CHANGED);
             mContext.registerReceiver(new MyReceiver(), filter);
 
             refreshForcedAppStandbyUidPackagesLocked();
 
             mPowerManagerInternal.registerLowPowerModeObserver(
                     ServiceType.FORCE_ALL_APPS_STANDBY,
-                    (state) -> {
-                        synchronized (mLock) {
-                            mBatterySaverEnabled = state.batterySaverEnabled;
-                            updateForceAllAppStandbyState();
-                        }
-                    });
+                    (state) -> updateForceAllAppsStandby(state.batterySaverEnabled));
 
-            mBatterySaverEnabled = mPowerManagerInternal.getLowPowerState(
-                    ServiceType.FORCE_ALL_APPS_STANDBY).batterySaverEnabled;
-
-            updateForceAllAppStandbyState();
+            updateForceAllAppsStandby(mPowerManagerInternal.getLowPowerState(
+                    ServiceType.FORCE_ALL_APPS_STANDBY).batterySaverEnabled);
         }
     }
 
@@ -400,11 +340,6 @@
         return LocalServices.getService(PowerManagerInternal.class);
     }
 
-    @VisibleForTesting
-    boolean isSmallBatteryDevice() {
-        return ActivityManager.isSmallBatteryDevice();
-    }
-
     /**
      * Update {@link #mRunAnyRestrictedPackages} with the current app ops state.
      */
@@ -434,29 +369,18 @@
         }
     }
 
-    private void updateForceAllAppStandbyState() {
-        synchronized (mLock) {
-            if (mIsCharging) {
-                toggleForceAllAppsStandbyLocked(false);
-            } else if (mForceAllAppStandbyForSmallBattery
-                    && isSmallBatteryDevice()) {
-                toggleForceAllAppsStandbyLocked(true);
-            } else {
-                toggleForceAllAppsStandbyLocked(mBatterySaverEnabled);
-            }
-        }
-    }
-
     /**
      * Update {@link #mForceAllAppsStandby} and notifies the listeners.
      */
-    private void toggleForceAllAppsStandbyLocked(boolean enable) {
-        if (enable == mForceAllAppsStandby) {
-            return;
-        }
-        mForceAllAppsStandby = enable;
+    void updateForceAllAppsStandby(boolean enable) {
+        synchronized (mLock) {
+            if (enable == mForceAllAppsStandby) {
+                return;
+            }
+            mForceAllAppsStandby = enable;
 
-        mHandler.notifyForceAllAppsStandbyChanged();
+            mHandler.notifyForceAllAppsStandbyChanged();
+        }
     }
 
     private int findForcedAppStandbyUidPackageIndexLocked(int uid, @NonNull String packageName) {
@@ -591,13 +515,6 @@
                 if (userId > 0) {
                     mHandler.doUserRemoved(userId);
                 }
-            } else if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) {
-                int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
-                synchronized (mLock) {
-                    mIsCharging = (status == BatteryManager.BATTERY_STATUS_CHARGING
-                            || status == BatteryManager.BATTERY_STATUS_FULL);
-                }
-                updateForceAllAppStandbyState();
             }
         }
     }
@@ -616,7 +533,7 @@
         private static final int MSG_TEMP_WHITELIST_CHANGED = 5;
         private static final int MSG_FORCE_ALL_CHANGED = 6;
         private static final int MSG_USER_REMOVED = 7;
-        private static final int MSG_FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED = 8;
+        private static final int MSG_FEATURE_FLAG_CHANGED = 8;
 
         public MyHandler(Looper looper) {
             super(looper);
@@ -646,8 +563,8 @@
             obtainMessage(MSG_FORCE_ALL_CHANGED).sendToTarget();
         }
 
-        public void notifyForcedAppStandbyFeatureFlagChanged() {
-            obtainMessage(MSG_FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED).sendToTarget();
+        public void notifyFeatureFlagChanged() {
+            obtainMessage(MSG_FEATURE_FLAG_CHANGED).sendToTarget();
         }
 
         public void doUserRemoved(int userId) {
@@ -701,7 +618,7 @@
                         l.onForceAllAppsStandbyChanged(sender);
                     }
                     return;
-                case MSG_FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED:
+                case MSG_FEATURE_FLAG_CHANGED:
                     // Feature flag for forced app standby changed.
                     final boolean unblockAlarms;
                     synchronized (mLock) {
@@ -820,21 +737,23 @@
      * @return whether alarms should be restricted for a UID package-name.
      */
     public boolean areAlarmsRestricted(int uid, @NonNull String packageName) {
-        return isRestricted(uid, packageName, /*useTempWhitelistToo=*/ false);
+        return isRestricted(uid, packageName, /*useTempWhitelistToo=*/ false,
+                /* exemptOnBatterySaver =*/ false);
     }
 
     /**
      * @return whether jobs should be restricted for a UID package-name.
      */
     public boolean areJobsRestricted(int uid, @NonNull String packageName) {
-        return isRestricted(uid, packageName, /*useTempWhitelistToo=*/ true);
+        return isRestricted(uid, packageName, /*useTempWhitelistToo=*/ true,
+                /* exemptOnBatterySaver =*/ false);
     }
 
     /**
      * @return whether force-app-standby is effective for a UID package-name.
      */
     private boolean isRestricted(int uid, @NonNull String packageName,
-            boolean useTempWhitelistToo) {
+            boolean useTempWhitelistToo, boolean exemptOnBatterySaver) {
         if (isInForeground(uid)) {
             return false;
         }
@@ -848,12 +767,13 @@
                     ArrayUtils.contains(mTempWhitelistedAppIds, appId)) {
                 return false;
             }
-
-            if (mForceAllAppsStandby) {
+            if (mForcedAppStandbyEnabled && isRunAnyRestrictedLocked(uid, packageName)) {
                 return true;
             }
-
-            return mForcedAppStandbyEnabled && isRunAnyRestrictedLocked(uid, packageName);
+            if (exemptOnBatterySaver) {
+                return false;
+            }
+            return mForceAllAppsStandby;
         }
     }
 
@@ -925,18 +845,6 @@
             pw.println(isForceAllAppsStandbyEnabled());
 
             pw.print(indent);
-            pw.print("Small Battery Device: ");
-            pw.println(isSmallBatteryDevice());
-
-            pw.print(indent);
-            pw.print("Force all apps standby for small battery device: ");
-            pw.println(mForceAllAppStandbyForSmallBattery);
-
-            pw.print(indent);
-            pw.print("Charging: ");
-            pw.println(mIsCharging);
-
-            pw.print(indent);
             pw.print("Foreground uids: [");
 
             String sep = "";
@@ -975,11 +883,6 @@
             final long token = proto.start(fieldId);
 
             proto.write(ForceAppStandbyTrackerProto.FORCE_ALL_APPS_STANDBY, mForceAllAppsStandby);
-            proto.write(ForceAppStandbyTrackerProto.IS_SMALL_BATTERY_DEVICE,
-                    isSmallBatteryDevice());
-            proto.write(ForceAppStandbyTrackerProto.FORCE_ALL_APPS_STANDBY_FOR_SMALL_BATTERY,
-                    mForceAllAppStandbyForSmallBattery);
-            proto.write(ForceAppStandbyTrackerProto.IS_CHARGING, mIsCharging);
 
             for (int i = 0; i < mForegroundUids.size(); i++) {
                 if (mForegroundUids.valueAt(i)) {
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 55046959..21137ad 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -51,6 +51,7 @@
 import org.xmlpull.v1.XmlSerializer;
 
 import android.Manifest;
+import android.annotation.AnyThread;
 import android.annotation.BinderThread;
 import android.annotation.ColorInt;
 import android.annotation.IntDef;
@@ -110,6 +111,7 @@
 import android.os.ShellCallback;
 import android.os.ShellCommand;
 import android.os.SystemClock;
+import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
@@ -256,6 +258,44 @@
     private static final String ACTION_SHOW_INPUT_METHOD_PICKER =
             "com.android.server.InputMethodManagerService.SHOW_INPUT_METHOD_PICKER";
 
+    /**
+     * Debug flag for overriding runtime {@link SystemProperties}.
+     */
+    @AnyThread
+    private static final class DebugFlag {
+        private static final Object LOCK = new Object();
+        private final String mKey;
+        @GuardedBy("LOCK")
+        private boolean mValue;
+
+        public DebugFlag(String key) {
+            mKey = key;
+            refresh();
+        }
+
+        void refresh() {
+            synchronized (LOCK) {
+                mValue = SystemProperties.getBoolean(mKey, true);
+            }
+        }
+
+        boolean value() {
+            synchronized (LOCK) {
+                return mValue;
+            }
+        }
+    }
+
+    /**
+     * Debug flags that can be overridden using "adb shell setprop <key>"
+     * Note: These flags are cached. To refresh, run "adb shell ime refresh_debug_properties".
+     */
+    private static final class DebugFlags {
+        static final DebugFlag FLAG_OPTIMIZE_START_INPUT =
+                new DebugFlag("debug.optimize_startinput");
+    }
+
+
     final Context mContext;
     final Resources mRes;
     final Handler mHandler;
@@ -2930,8 +2970,12 @@
                 }
 
                 if (!didStart && attribute != null) {
-                    res = startInputUncheckedLocked(cs, inputContext, missingMethods, attribute,
-                            controlFlags, startInputReason);
+                    if (!DebugFlags.FLAG_OPTIMIZE_START_INPUT.value()
+                            || (controlFlags
+                                    & InputMethodManager.CONTROL_WINDOW_IS_TEXT_EDITOR) != 0) {
+                        res = startInputUncheckedLocked(cs, inputContext, missingMethods, attribute,
+                                controlFlags, startInputReason);
+                    }
                 }
             }
         } finally {
@@ -4703,6 +4747,8 @@
                         return mService.handleShellCommandSetInputMethod(this);
                     case "reset":
                         return mService.handleShellCommandResetInputMethod(this);
+                    case "refresh_debug_properties":
+                        return refreshDebugProperties();
                     default:
                         getOutPrintWriter().println("Unknown command: " + imeCommand);
                         return ShellCommandResult.FAILURE;
@@ -4713,6 +4759,13 @@
         }
 
         @BinderThread
+        @ShellCommandResult
+        private int refreshDebugProperties() {
+            DebugFlags.FLAG_OPTIMIZE_START_INPUT.refresh();
+            return ShellCommandResult.SUCCESS;
+        }
+
+        @BinderThread
         @Override
         public void onHelp() {
             try (PrintWriter pw = getOutPrintWriter()) {
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index ea748db..6c63f43 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -232,10 +232,9 @@
 
     private final ArraySet<String> mBackgroundThrottlePackageWhitelist = new ArraySet<>();
 
-    private final ArrayMap<IGnssMeasurementsListener, Identity> mGnssMeasurementsListeners =
-            new ArrayMap<>();
+    private final ArrayMap<IBinder, Identity> mGnssMeasurementsListeners = new ArrayMap<>();
 
-    private final ArrayMap<IGnssNavigationMessageListener, Identity>
+    private final ArrayMap<IBinder, Identity>
             mGnssNavigationMessageListeners = new ArrayMap<>();
 
     // current active user on the device - other users are denied location data
@@ -438,23 +437,23 @@
                 applyRequirementsLocked(provider);
             }
 
-            for (Entry<IGnssMeasurementsListener, Identity> entry
-                    : mGnssMeasurementsListeners.entrySet()) {
+            for (Entry<IBinder, Identity> entry : mGnssMeasurementsListeners.entrySet()) {
                 if (entry.getValue().mUid == uid) {
                     if (D) {
                         Log.d(TAG, "gnss measurements listener from uid " + uid
                                 + " is now " + (foreground ? "foreground" : "background)"));
                     }
                     if (foreground || isThrottlingExemptLocked(entry.getValue())) {
-                        mGnssMeasurementsProvider.addListener(entry.getKey());
+                        mGnssMeasurementsProvider.addListener(
+                                IGnssMeasurementsListener.Stub.asInterface(entry.getKey()));
                     } else {
-                        mGnssMeasurementsProvider.removeListener(entry.getKey());
+                        mGnssMeasurementsProvider.removeListener(
+                                IGnssMeasurementsListener.Stub.asInterface(entry.getKey()));
                     }
                 }
             }
 
-            for (Entry<IGnssNavigationMessageListener, Identity> entry
-                    : mGnssNavigationMessageListeners.entrySet()) {
+            for (Entry<IBinder, Identity> entry : mGnssNavigationMessageListeners.entrySet()) {
                 if (entry.getValue().mUid == uid) {
                     if (D) {
                         Log.d(TAG, "gnss navigation message listener from uid "
@@ -462,9 +461,11 @@
                                 + (foreground ? "foreground" : "background)"));
                     }
                     if (foreground || isThrottlingExemptLocked(entry.getValue())) {
-                        mGnssNavigationMessageProvider.addListener(entry.getKey());
+                        mGnssNavigationMessageProvider.addListener(
+                                IGnssNavigationMessageListener.Stub.asInterface(entry.getKey()));
                     } else {
-                        mGnssNavigationMessageProvider.removeListener(entry.getKey());
+                        mGnssNavigationMessageProvider.removeListener(
+                                IGnssNavigationMessageListener.Stub.asInterface(entry.getKey()));
                     }
                 }
             }
@@ -2401,7 +2402,7 @@
         synchronized (mLock) {
             Identity callerIdentity
                     = new Identity(Binder.getCallingUid(), Binder.getCallingPid(), packageName);
-            mGnssMeasurementsListeners.put(listener, callerIdentity);
+            mGnssMeasurementsListeners.put(listener.asBinder(), callerIdentity);
             long identity = Binder.clearCallingIdentity();
             try {
                 if (isThrottlingExemptLocked(callerIdentity)
@@ -2421,7 +2422,7 @@
     public void removeGnssMeasurementsListener(IGnssMeasurementsListener listener) {
         if (mGnssMeasurementsProvider != null) {
             synchronized (mLock) {
-                mGnssMeasurementsListeners.remove(listener);
+                mGnssMeasurementsListeners.remove(listener.asBinder());
                 mGnssMeasurementsProvider.removeListener(listener);
             }
         }
@@ -2438,7 +2439,7 @@
         synchronized (mLock) {
             Identity callerIdentity
                     = new Identity(Binder.getCallingUid(), Binder.getCallingPid(), packageName);
-            mGnssNavigationMessageListeners.put(listener, callerIdentity);
+            mGnssNavigationMessageListeners.put(listener.asBinder(), callerIdentity);
             long identity = Binder.clearCallingIdentity();
             try {
                 if (isThrottlingExemptLocked(callerIdentity)
@@ -2458,7 +2459,7 @@
     public void removeGnssNavigationMessageListener(IGnssNavigationMessageListener listener) {
         if (mGnssNavigationMessageProvider != null) {
             synchronized (mLock) {
-                mGnssNavigationMessageListeners.remove(listener);
+                mGnssNavigationMessageListeners.remove(listener.asBinder());
                 mGnssNavigationMessageProvider.removeListener(listener);
             }
         }
@@ -3180,6 +3181,16 @@
                     pw.println("      " + record);
                 }
             }
+            pw.println("  Active GnssMeasurement Listeners:");
+            for (Identity identity : mGnssMeasurementsListeners.values()) {
+                pw.println("    " + identity.mPid + " " + identity.mUid + " "
+                        + identity.mPackageName + ": " + isThrottlingExemptLocked(identity));
+            }
+            pw.println("  Active GnssNavigationMessage Listeners:");
+            for (Identity identity : mGnssNavigationMessageListeners.values()) {
+                pw.println("    " + identity.mPid + " " + identity.mUid + " "
+                        + identity.mPackageName + ": " + isThrottlingExemptLocked(identity));
+            }
             pw.println("  Overlay Provider Packages:");
             for (LocationProviderInterface provider : mProviders) {
                 if (provider instanceof LocationProviderProxy) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 6e33afa..c0c684c 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -294,6 +294,7 @@
 import android.graphics.Bitmap;
 import android.graphics.Point;
 import android.graphics.Rect;
+import android.hardware.display.DisplayManagerInternal;
 import android.location.LocationManager;
 import android.media.audiofx.AudioEffect;
 import android.metrics.LogMaker;
@@ -474,6 +475,7 @@
 import java.util.Objects;
 import java.util.Set;
 import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executor;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicLong;
 
@@ -8599,6 +8601,16 @@
             }
             return false;
         }
+
+        @Override
+        public int getPackageUid(String packageName, int flags) {
+            try {
+                return mActivityManagerService.mContext.getPackageManager()
+                        .getPackageUid(packageName, flags);
+            } catch (NameNotFoundException nnfe) {
+                return -1;
+            }
+        }
     }
 
     class IntentFirewallInterface implements IntentFirewall.AMSInterface {
@@ -25357,9 +25369,18 @@
                 }
             }
         }
-        if (updateFrameworkRes && mWindowManager != null) {
-            ActivityThread.currentActivityThread().getExecutor().execute(
-                    mWindowManager::onOverlayChanged);
+        if (updateFrameworkRes) {
+            // Update system server components that need to know about changed overlays. Because the
+            // overlay is applied in ActivityThread, we need to serialize through its thread too.
+            final Executor executor = ActivityThread.currentActivityThread().getExecutor();
+            final DisplayManagerInternal display =
+                    LocalServices.getService(DisplayManagerInternal.class);
+            if (display != null) {
+                executor.execute(display::onOverlayChanged);
+            }
+            if (mWindowManager != null) {
+                executor.execute(mWindowManager::onOverlayChanged);
+            }
         }
     }
 
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index f496a67..9d06b0d 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -606,7 +606,7 @@
                         true /* onTop */);
                 recentStack.moveToFront("setWindowingMode");
                 // If task moved to docked stack - show recents if needed.
-                mService.mWindowManager.showRecentApps(false /* fromHome */);
+                mService.mWindowManager.showRecentApps();
             }
             wm.continueSurfaceLayout();
         }
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 81e8eb0..207aaa7 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -40,6 +40,7 @@
 import android.os.WorkSource;
 import android.os.WorkSource.WorkChain;
 import android.os.connectivity.CellularBatteryStats;
+import android.os.connectivity.GpsBatteryStats;
 import android.os.health.HealthStatsParceler;
 import android.os.health.HealthStatsWriter;
 import android.os.health.UidHealthStats;
@@ -594,6 +595,12 @@
         }
     }
 
+    public void noteGpsSignalQuality(int signalLevel) {
+        synchronized (mStats) {
+            mStats.noteGpsSignalQualityLocked(signalLevel);
+        }
+    }
+
     public void noteScreenState(int state) {
         enforceCallingPermission();
         if (DBG) Slog.d(TAG, "begin noteScreenState");
@@ -1448,6 +1455,16 @@
     }
 
     /**
+     * Gets a snapshot of Gps stats
+     * @hide
+     */
+    public GpsBatteryStats getGpsBatteryStats() {
+        synchronized (mStats) {
+            return mStats.getGpsBatteryStats();
+        }
+    }
+
+    /**
      * Gets a snapshot of the system health for a particular uid.
      */
     @Override
diff --git a/services/core/java/com/android/server/am/GlobalSettingsToPropertiesMapper.java b/services/core/java/com/android/server/am/GlobalSettingsToPropertiesMapper.java
index c9afc17..d6c6f96 100644
--- a/services/core/java/com/android/server/am/GlobalSettingsToPropertiesMapper.java
+++ b/services/core/java/com/android/server/am/GlobalSettingsToPropertiesMapper.java
@@ -23,6 +23,7 @@
 import android.provider.Settings;
 import android.text.TextUtils;
 import android.util.Slog;
+import android.view.ThreadedRenderer;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.Preconditions;
@@ -39,6 +40,7 @@
     //  List mapping entries in the following format:
     //  {Settings.Global.SETTING_NAME, "system_property_name"},
         {Settings.Global.SYS_VDSO, "sys.vdso"},
+        {Settings.Global.FPS_DEVISOR, ThreadedRenderer.DEBUG_FPS_DIVISOR},
     };
 
 
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index b131e86..809f19f6 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -749,12 +749,7 @@
         supervisor.handleNonResizableTaskIfNeeded(this, preferredStack.getWindowingMode(),
                 DEFAULT_DISPLAY, toStack);
 
-        boolean successful = (preferredStack == toStack);
-        if (successful && toStack.getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
-            // If task moved to docked stack - show recents if needed.
-            mService.mWindowManager.showRecentApps(false /* fromHome */);
-        }
-        return successful;
+        return (preferredStack == toStack);
     }
 
     /**
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index c7210a8..1a47aa5 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -795,11 +795,13 @@
      */
     private void stopGuestOrEphemeralUserIfBackground(int oldUserId) {
         if (DEBUG_MU) Slog.i(TAG, "Stop guest or ephemeral user if background: " + oldUserId);
-        UserState oldUss = mStartedUsers.get(oldUserId);
-        if (oldUserId == UserHandle.USER_SYSTEM || oldUserId == mCurrentUserId
-                || oldUss.state == UserState.STATE_STOPPING
-                || oldUss.state == UserState.STATE_SHUTDOWN) {
-            return;
+        synchronized(mLock) {
+            UserState oldUss = mStartedUsers.get(oldUserId);
+            if (oldUserId == UserHandle.USER_SYSTEM || oldUserId == mCurrentUserId || oldUss == null
+                    || oldUss.state == UserState.STATE_STOPPING
+                    || oldUss.state == UserState.STATE_SHUTDOWN) {
+                return;
+            }
         }
 
         UserInfo userInfo = getUserInfo(oldUserId);
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 799f2a9..f721049 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -1047,9 +1047,11 @@
 
     private void checkMuteAffectedStreams() {
         // any stream with a min level > 0 is not muteable by definition
+        // STREAM_VOICE_CALL can be muted by applications that has the the MODIFY_PHONE_STATE permission.
         for (int i = 0; i < mStreamStates.length; i++) {
             final VolumeStreamState vss = mStreamStates[i];
-            if (vss.mIndexMin > 0) {
+            if (vss.mIndexMin > 0 &&
+                vss.mStreamType != AudioSystem.STREAM_VOICE_CALL) {
                 mMuteAffectedStreams &= ~(1 << vss.mStreamType);
             }
         }
@@ -1412,6 +1414,18 @@
             return;
         }
 
+        // If adjust is mute and the stream is STREAM_VOICE_CALL, make sure
+        // that the calling app have the MODIFY_PHONE_STATE permission.
+        if (isMuteAdjust &&
+            streamType == AudioSystem.STREAM_VOICE_CALL &&
+            mContext.checkCallingOrSelfPermission(
+                android.Manifest.permission.MODIFY_PHONE_STATE)
+                    != PackageManager.PERMISSION_GRANTED) {
+            Log.w(TAG, "MODIFY_PHONE_STATE Permission Denial: adjustStreamVolume from pid="
+                    + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
+            return;
+        }
+
         // use stream type alias here so that streams with same alias have the same behavior,
         // including with regard to silent mode control (e.g the use of STREAM_RING below and in
         // checkForRingerModeChange() in place of STREAM_RING or STREAM_NOTIFICATION)
@@ -1712,6 +1726,15 @@
                     + " CHANGE_ACCESSIBILITY_VOLUME  callingPackage=" + callingPackage);
             return;
         }
+        if ((streamType == AudioManager.STREAM_VOICE_CALL) &&
+                (index == 0) &&
+                (mContext.checkCallingOrSelfPermission(
+                android.Manifest.permission.MODIFY_PHONE_STATE)
+                    != PackageManager.PERMISSION_GRANTED)) {
+            Log.w(TAG, "Trying to call setStreamVolume() for STREAM_VOICE_CALL and index 0 without"
+                    + " MODIFY_PHONE_STATE  callingPackage=" + callingPackage);
+            return;
+        }
         mVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_SET_STREAM_VOL, streamType,
                 index/*val1*/, flags/*val2*/, callingPackage));
         setStreamVolume(streamType, index, flags, callingPackage, callingPackage,
@@ -4503,27 +4526,30 @@
             if (mStreamType == srcStream.mStreamType) {
                 return;
             }
-            synchronized (VolumeStreamState.class) {
-                int srcStreamType = srcStream.getStreamType();
-                // apply default device volume from source stream to all devices first in case
-                // some devices are present in this stream state but not in source stream state
-                int index = srcStream.getIndex(AudioSystem.DEVICE_OUT_DEFAULT);
-                index = rescaleIndex(index, srcStreamType, mStreamType);
-                for (int i = 0; i < mIndexMap.size(); i++) {
-                    mIndexMap.put(mIndexMap.keyAt(i), index);
-                }
-                // Now apply actual volume for devices in source stream state
-                SparseIntArray srcMap = srcStream.mIndexMap;
-                for (int i = 0; i < srcMap.size(); i++) {
-                    int device = srcMap.keyAt(i);
-                    index = srcMap.valueAt(i);
+            synchronized (mSettingsLock) {
+                synchronized (VolumeStreamState.class) {
+                    int srcStreamType = srcStream.getStreamType();
+                    // apply default device volume from source stream to all devices first in case
+                    // some devices are present in this stream state but not in source stream state
+                    int index = srcStream.getIndex(AudioSystem.DEVICE_OUT_DEFAULT);
                     index = rescaleIndex(index, srcStreamType, mStreamType);
+                    for (int i = 0; i < mIndexMap.size(); i++) {
+                        mIndexMap.put(mIndexMap.keyAt(i), index);
+                    }
+                    // Now apply actual volume for devices in source stream state
+                    SparseIntArray srcMap = srcStream.mIndexMap;
+                    for (int i = 0; i < srcMap.size(); i++) {
+                        int device = srcMap.keyAt(i);
+                        index = srcMap.valueAt(i);
+                        index = rescaleIndex(index, srcStreamType, mStreamType);
 
-                    setIndex(index, device, caller);
+                        setIndex(index, device, caller);
+                    }
                 }
             }
         }
 
+        @GuardedBy("mSettingsLock")
         public void setAllIndexesToMax() {
             synchronized (VolumeStreamState.class) {
                 for (int i = 0; i < mIndexMap.size(); i++) {
diff --git a/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java b/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java
index e093c9d..1ae7d20 100644
--- a/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java
+++ b/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java
@@ -222,7 +222,7 @@
             MutableInt halResult = new MutableInt(Result.UNKNOWN_ERROR);
             MutableBoolean flagState = new MutableBoolean(false);
             try {
-                mHwSession.getConfigFlag(flag, (int result, boolean value) -> {
+                mHwSession.isConfigFlagSet(flag, (int result, boolean value) -> {
                     halResult.value = result;
                     flagState.value = value;
                 });
diff --git a/services/core/java/com/android/server/display/DisplayDevice.java b/services/core/java/com/android/server/display/DisplayDevice.java
index 839ab4d..3a8e291 100644
--- a/services/core/java/com/android/server/display/DisplayDevice.java
+++ b/services/core/java/com/android/server/display/DisplayDevice.java
@@ -143,6 +143,9 @@
     public void requestDisplayModesInTransactionLocked(int colorMode, int modeId) {
     }
 
+    public void onOverlayChangedLocked() {
+    }
+
     /**
      * Sets the display layer stack while in a transaction.
      */
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 9f18045..b97de65 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -2019,8 +2019,8 @@
         @Override
         public void onOverlayChanged() {
             synchronized (mSyncRoot) {
-                if (updateLogicalDisplaysLocked()) {
-                    scheduleTraversalLocked(false);
+                for (int i = 0; i < mDisplayDevices.size(); i++) {
+                    mDisplayDevices.get(i).onOverlayChangedLocked();
                 }
             }
         }
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 23e4c9b..b7385d8 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -404,7 +404,7 @@
                             && SystemProperties.getBoolean(PROPERTY_EMULATOR_CIRCULAR, false))) {
                         mInfo.flags |= DisplayDeviceInfo.FLAG_ROUND;
                     }
-                    mInfo.displayCutout = parseDefaultDisplayCutout(res);
+                    mInfo.displayCutout = DisplayCutout.fromResources(res, mInfo.width);
                     mInfo.type = Display.TYPE_BUILT_IN;
                     mInfo.densityDpi = (int)(phys.density * 160 + 0.5f);
                     mInfo.xDpi = phys.xDpi;
@@ -440,15 +440,6 @@
             return mInfo;
         }
 
-        private DisplayCutout parseDefaultDisplayCutout(Resources res) {
-            String cutoutString = res.getString(
-                    com.android.internal.R.string.config_mainBuiltInDisplayCutout);
-            if (TextUtils.isEmpty(cutoutString)) {
-                return null;
-            }
-            return DisplayCutout.fromBounds(PathParser.createPathFromPathData(cutoutString));
-        }
-
         @Override
         public Runnable requestDisplayStateLocked(final int state, final int brightness) {
             // Assume that the brightness is off if the display is being turned off.
@@ -600,6 +591,11 @@
             }
         }
 
+        @Override
+        public void onOverlayChangedLocked() {
+            updateDeviceInfoLocked();
+        }
+
         public boolean requestModeInTransactionLocked(int modeId) {
             if (modeId == 0) {
                 modeId = mDefaultModeId;
diff --git a/services/core/java/com/android/server/hdmi/DeviceDiscoveryAction.java b/services/core/java/com/android/server/hdmi/DeviceDiscoveryAction.java
old mode 100644
new mode 100755
index 97a6e85..db8dedb
--- a/services/core/java/com/android/server/hdmi/DeviceDiscoveryAction.java
+++ b/services/core/java/com/android/server/hdmi/DeviceDiscoveryAction.java
@@ -228,12 +228,20 @@
                 if (cmd.getOpcode() == Constants.MESSAGE_SET_OSD_NAME) {
                     handleSetOsdName(cmd);
                     return true;
+                } else if ((cmd.getOpcode() == Constants.MESSAGE_FEATURE_ABORT) &&
+                        ((cmd.getParams()[0] & 0xFF) == Constants.MESSAGE_GIVE_OSD_NAME)) {
+                    handleSetOsdName(cmd);
+                    return true;
                 }
                 return false;
             case STATE_WAITING_FOR_VENDOR_ID:
                 if (cmd.getOpcode() == Constants.MESSAGE_DEVICE_VENDOR_ID) {
                     handleVendorId(cmd);
                     return true;
+                } else if ((cmd.getOpcode() == Constants.MESSAGE_FEATURE_ABORT) &&
+                        ((cmd.getParams()[0] & 0xFF) == Constants.MESSAGE_GIVE_DEVICE_VENDOR_ID)) {
+                    handleVendorId(cmd);
+                    return true;
                 }
                 return false;
             case STATE_WAITING_FOR_DEVICE_POLLING:
@@ -281,7 +289,11 @@
 
         String displayName = null;
         try {
-            displayName = new String(cmd.getParams(), "US-ASCII");
+            if (cmd.getOpcode() == Constants.MESSAGE_FEATURE_ABORT) {
+                displayName = HdmiUtils.getDefaultDeviceName(current.mLogicalAddress);
+            } else {
+                displayName = new String(cmd.getParams(), "US-ASCII");
+            }
         } catch (UnsupportedEncodingException e) {
             Slog.w(TAG, "Failed to decode display name: " + cmd.toString());
             // If failed to get display name, use the default name of device.
@@ -302,9 +314,12 @@
             return;
         }
 
-        byte[] params = cmd.getParams();
-        int vendorId = HdmiUtils.threeBytesToInt(params);
-        current.mVendorId = vendorId;
+        if (cmd.getOpcode() != Constants.MESSAGE_FEATURE_ABORT) {
+            byte[] params = cmd.getParams();
+            int vendorId = HdmiUtils.threeBytesToInt(params);
+            current.mVendorId = vendorId;
+        }
+
         increaseProcessedDeviceCount();
         checkAndProceedStage();
     }
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index 81bccdc..1e09383 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -698,10 +698,9 @@
     protected boolean handleReportAudioStatus(HdmiCecMessage message) {
         assertRunOnServiceThread();
 
-        byte params[] = message.getParams();
-        int mute = params[0] & 0x80;
-        int volume = params[0] & 0x7F;
-        setAudioStatus(mute == 0x80, volume);
+        boolean mute = HdmiUtils.isAudioStatusMute(message);
+        int volume = HdmiUtils.getAudioStatusVolume(message);
+        setAudioStatus(mute, volume);
         return true;
     }
 
@@ -1004,6 +1003,9 @@
     }
 
     void setAudioStatus(boolean mute, int volume) {
+        if (!isSystemAudioActivated()) {
+            return;
+        }
         synchronized (mLock) {
             mSystemAudioMute = mute;
             mSystemAudioVolume = volume;
@@ -1019,6 +1021,10 @@
     @ServiceThreadOnly
     void changeVolume(int curVolume, int delta, int maxVolume) {
         assertRunOnServiceThread();
+        if (getAvrDeviceInfo() == null) {
+            // On initialization process, getAvrDeviceInfo() may return null and cause exception
+            return;
+        }
         if (delta == 0 || !isSystemAudioActivated()) {
             return;
         }
@@ -1048,6 +1054,10 @@
     @ServiceThreadOnly
     void changeMute(boolean mute) {
         assertRunOnServiceThread();
+        if (getAvrDeviceInfo() == null) {
+            // On initialization process, getAvrDeviceInfo() may return null and cause exception
+            return;
+        }
         HdmiLogger.debug("[A]:Change mute:%b", mute);
         synchronized (mLock) {
             if (mSystemAudioMute == mute) {
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 807b1b1..3d079cc 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -989,8 +989,12 @@
             }
             // FLAG_HDMI_SYSTEM_AUDIO_VOLUME prevents audio manager from announcing
             // volume change notification back to hdmi control service.
-            audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, volume,
-                    AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_HDMI_SYSTEM_AUDIO_VOLUME);
+            int flag = AudioManager.FLAG_HDMI_SYSTEM_AUDIO_VOLUME;
+            if (0 <= volume && volume <= 100) {
+                Slog.i(TAG, "volume: " + volume);
+                flag |= AudioManager.FLAG_SHOW_UI;
+                audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, volume, flag);
+            }
         }
     }
 
diff --git a/services/core/java/com/android/server/hdmi/HdmiUtils.java b/services/core/java/com/android/server/hdmi/HdmiUtils.java
index 8b16411..4ac3bba 100644
--- a/services/core/java/com/android/server/hdmi/HdmiUtils.java
+++ b/services/core/java/com/android/server/hdmi/HdmiUtils.java
@@ -152,6 +152,32 @@
     }
 
     /**
+     * Parse the <Report Audio Status> message and check if it is mute
+     *
+     * @param cmd the CEC message to parse
+     * @return true if the given parameter has [MUTE]
+     */
+    static boolean isAudioStatusMute(HdmiCecMessage cmd) {
+        byte params[] = cmd.getParams();
+        return (params[0] & 0x80) == 0x80;
+    }
+
+    /**
+     * Parse the <Report Audio Status> message and extract the volume
+     *
+     * @param cmd the CEC message to parse
+     * @return device's volume. Constants.UNKNOWN_VOLUME in case it is out of range
+     */
+    static int getAudioStatusVolume(HdmiCecMessage cmd) {
+        byte params[] = cmd.getParams();
+        int volume = params[0] & 0x7F;
+        if (volume < 0x00 || 0x64 < volume) {
+            volume = Constants.UNKNOWN_VOLUME;
+        }
+        return volume;
+    }
+
+    /**
      * Convert integer array to list of {@link Integer}.
      *
      * <p>The result is immutable.
diff --git a/services/core/java/com/android/server/hdmi/SystemAudioStatusAction.java b/services/core/java/com/android/server/hdmi/SystemAudioStatusAction.java
index cab8439..d41a36c 100644
--- a/services/core/java/com/android/server/hdmi/SystemAudioStatusAction.java
+++ b/services/core/java/com/android/server/hdmi/SystemAudioStatusAction.java
@@ -92,8 +92,8 @@
 
     private void handleReportAudioStatus(HdmiCecMessage cmd) {
         byte[] params = cmd.getParams();
-        boolean mute = (params[0] & 0x80) == 0x80;
-        int volume = params[0] & 0x7F;
+        boolean mute = HdmiUtils.isAudioStatusMute(cmd);
+        int volume = HdmiUtils.getAudioStatusVolume(cmd);
         tv().setAudioStatus(mute, volume);
 
         if (!(tv().isSystemAudioActivated() ^ mute)) {
diff --git a/services/core/java/com/android/server/hdmi/VolumeControlAction.java b/services/core/java/com/android/server/hdmi/VolumeControlAction.java
index cd38b1f..0011387 100644
--- a/services/core/java/com/android/server/hdmi/VolumeControlAction.java
+++ b/services/core/java/com/android/server/hdmi/VolumeControlAction.java
@@ -139,8 +139,8 @@
 
     private boolean handleReportAudioStatus(HdmiCecMessage cmd) {
         byte params[] = cmd.getParams();
-        boolean mute = (params[0] & 0x80) == 0x80;
-        int volume = params[0] & 0x7F;
+        boolean mute = HdmiUtils.isAudioStatusMute(cmd);
+        int volume = HdmiUtils.getAudioStatusVolume(cmd);
         mLastAvrVolume = volume;
         mLastAvrMute = mute;
         if (shouldUpdateAudioVolume(mute)) {
diff --git a/services/core/java/com/android/server/job/controllers/ConnectivityController.java b/services/core/java/com/android/server/job/controllers/ConnectivityController.java
index 03fd7b3..373d87d 100644
--- a/services/core/java/com/android/server/job/controllers/ConnectivityController.java
+++ b/services/core/java/com/android/server/job/controllers/ConnectivityController.java
@@ -16,6 +16,10 @@
 
 package com.android.server.job.controllers;
 
+import static android.net.NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
+
 import android.app.job.JobInfo;
 import android.content.Context;
 import android.net.ConnectivityManager;
@@ -35,6 +39,7 @@
 import android.util.proto.ProtoOutputStream;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.job.JobSchedulerService;
 import com.android.server.job.JobServiceContext;
 import com.android.server.job.StateChangedListener;
@@ -62,15 +67,15 @@
     private final ArraySet<JobStatus> mTrackedJobs = new ArraySet<>();
 
     /** Singleton. */
-    private static ConnectivityController mSingleton;
+    private static ConnectivityController sSingleton;
     private static Object sCreationLock = new Object();
 
     public static ConnectivityController get(JobSchedulerService jms) {
         synchronized (sCreationLock) {
-            if (mSingleton == null) {
-                mSingleton = new ConnectivityController(jms, jms.getContext(), jms.getLock());
+            if (sSingleton == null) {
+                sSingleton = new ConnectivityController(jms, jms.getContext(), jms.getLock());
             }
-            return mSingleton;
+            return sSingleton;
         }
     }
 
@@ -105,37 +110,29 @@
     }
 
     /**
-     * Test to see if running the given job on the given network is sane.
+     * Test to see if running the given job on the given network is insane.
      * <p>
      * For example, if a job is trying to send 10MB over a 128Kbps EDGE
      * connection, it would take 10.4 minutes, and has no chance of succeeding
      * before the job times out, so we'd be insane to try running it.
      */
-    private boolean isSane(JobStatus jobStatus, NetworkCapabilities capabilities) {
+    @SuppressWarnings("unused")
+    private static boolean isInsane(JobStatus jobStatus, Network network,
+            NetworkCapabilities capabilities) {
         final long estimatedBytes = jobStatus.getEstimatedNetworkBytes();
         if (estimatedBytes == JobInfo.NETWORK_BYTES_UNKNOWN) {
             // We don't know how large the job is; cross our fingers!
-            return true;
-        }
-        if (capabilities == null) {
-            // We don't know what the network is like; cross our fingers!
-            return true;
+            return false;
         }
 
         // We don't ask developers to differentiate between upstream/downstream
         // in their size estimates, so test against the slowest link direction.
-        final long downstream = capabilities.getLinkDownstreamBandwidthKbps();
-        final long upstream = capabilities.getLinkUpstreamBandwidthKbps();
-        final long slowest;
-        if (downstream > 0 && upstream > 0) {
-            slowest = Math.min(downstream, upstream);
-        } else if (downstream > 0) {
-            slowest = downstream;
-        } else if (upstream > 0) {
-            slowest = upstream;
-        } else {
+        final long slowest = NetworkCapabilities.minBandwidth(
+                capabilities.getLinkDownstreamBandwidthKbps(),
+                capabilities.getLinkUpstreamBandwidthKbps());
+        if (slowest == LINK_BANDWIDTH_UNSPECIFIED) {
             // We don't know what the network is like; cross our fingers!
-            return true;
+            return false;
         }
 
         final long estimatedMillis = ((estimatedBytes * DateUtils.SECOND_IN_MILLIS)
@@ -144,28 +141,87 @@
             // If we'd never finish before the timeout, we'd be insane!
             Slog.w(TAG, "Estimated " + estimatedBytes + " bytes over " + slowest
                     + " kbps network would take " + estimatedMillis + "ms; that's insane!");
-            return false;
-        } else {
             return true;
+        } else {
+            return false;
         }
     }
 
+    @SuppressWarnings("unused")
+    private static boolean isCongestionDelayed(JobStatus jobStatus, Network network,
+            NetworkCapabilities capabilities) {
+        // If network is congested, and job is less than 50% through the
+        // developer-requested window, then we're okay delaying the job.
+        if (!capabilities.hasCapability(NET_CAPABILITY_NOT_CONGESTED)) {
+            return jobStatus.getFractionRunTime() < 0.5;
+        } else {
+            return false;
+        }
+    }
+
+    @SuppressWarnings("unused")
+    private static boolean isStrictSatisfied(JobStatus jobStatus, Network network,
+            NetworkCapabilities capabilities) {
+        return jobStatus.getJob().getRequiredNetwork().networkCapabilities
+                .satisfiedByNetworkCapabilities(capabilities);
+    }
+
+    @SuppressWarnings("unused")
+    private static boolean isRelaxedSatisfied(JobStatus jobStatus, Network network,
+            NetworkCapabilities capabilities) {
+        // Only consider doing this for prefetching jobs
+        if ((jobStatus.getJob().getFlags() & JobInfo.FLAG_IS_PREFETCH) == 0) {
+            return false;
+        }
+
+        // See if we match after relaxing any unmetered request
+        final NetworkCapabilities relaxed = new NetworkCapabilities(
+                jobStatus.getJob().getRequiredNetwork().networkCapabilities)
+                        .removeCapability(NET_CAPABILITY_NOT_METERED);
+        if (relaxed.satisfiedByNetworkCapabilities(capabilities)) {
+            // TODO: treat this as "maybe" response; need to check quotas
+            return jobStatus.getFractionRunTime() > 0.5;
+        } else {
+            return false;
+        }
+    }
+
+    @VisibleForTesting
+    static boolean isSatisfied(JobStatus jobStatus, Network network,
+            NetworkCapabilities capabilities) {
+        // Zeroth, we gotta have a network to think about being satisfied
+        if (network == null || capabilities == null) return false;
+
+        // First, are we insane?
+        if (isInsane(jobStatus, network, capabilities)) return false;
+
+        // Second, is the network congested?
+        if (isCongestionDelayed(jobStatus, network, capabilities)) return false;
+
+        // Third, is the network a strict match?
+        if (isStrictSatisfied(jobStatus, network, capabilities)) return true;
+
+        // Third, is the network a relaxed match?
+        if (isRelaxedSatisfied(jobStatus, network, capabilities)) return true;
+
+        return false;
+    }
+
     private boolean updateConstraintsSatisfied(JobStatus jobStatus) {
         // TODO: consider matching against non-active networks
 
         final int jobUid = jobStatus.getSourceUid();
         final boolean ignoreBlocked = (jobStatus.getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) != 0;
+
         final Network network = mConnManager.getActiveNetworkForUid(jobUid, ignoreBlocked);
         final NetworkInfo info = mConnManager.getNetworkInfoForUid(network, jobUid, ignoreBlocked);
         final NetworkCapabilities capabilities = mConnManager.getNetworkCapabilities(network);
 
         final boolean connected = (info != null) && info.isConnected();
-        final boolean satisfied = jobStatus.getJob().getRequiredNetwork().networkCapabilities
-                .satisfiedByNetworkCapabilities(capabilities);
-        final boolean sane = isSane(jobStatus, capabilities);
+        final boolean satisfied = isSatisfied(jobStatus, network, capabilities);
 
         final boolean changed = jobStatus
-                .setConnectivityConstraintSatisfied(connected && satisfied && sane);
+                .setConnectivityConstraintSatisfied(connected && satisfied);
 
         // Pass along the evaluated network for job to use; prevents race
         // conditions as default routes change over time, and opens the door to
@@ -181,8 +237,7 @@
         if (DEBUG) {
             Slog.i(TAG, "Connectivity " + (changed ? "CHANGED" : "unchanged")
                     + " for " + jobStatus + ": connected=" + connected
-                    + " satisfied=" + satisfied
-                    + " sane=" + sane);
+                    + " satisfied=" + satisfied);
         }
         return changed;
     }
@@ -244,7 +299,7 @@
         }
     };
 
-    private final INetworkPolicyListener mNetPolicyListener = new INetworkPolicyListener.Stub() {
+    private final INetworkPolicyListener mNetPolicyListener = new NetworkPolicyManager.Listener() {
         @Override
         public void onUidRulesChanged(int uid, int uidRules) {
             if (DEBUG) {
@@ -254,11 +309,6 @@
         }
 
         @Override
-        public void onMeteredIfacesChanged(String[] meteredIfaces) {
-            // We track this via our NetworkCallback
-        }
-
-        @Override
         public void onRestrictBackgroundChanged(boolean restrictBackground) {
             if (DEBUG) {
                 Slog.v(TAG, "Background restriction change to " + restrictBackground);
diff --git a/services/core/java/com/android/server/job/controllers/JobStatus.java b/services/core/java/com/android/server/job/controllers/JobStatus.java
index 8f68713..0f5cb0a 100644
--- a/services/core/java/com/android/server/job/controllers/JobStatus.java
+++ b/services/core/java/com/android/server/job/controllers/JobStatus.java
@@ -24,6 +24,7 @@
 import android.app.job.JobWorkItem;
 import android.content.ClipData;
 import android.content.ComponentName;
+import android.content.pm.PackageManagerInternal;
 import android.net.Network;
 import android.net.Uri;
 import android.os.RemoteException;
@@ -96,6 +97,7 @@
     final JobInfo job;
     /** Uid of the package requesting this job. */
     final int callingUid;
+    final int targetSdkVersion;
     final String batteryName;
 
     final String sourcePackageName;
@@ -243,12 +245,13 @@
         return callingUid;
     }
 
-    private JobStatus(JobInfo job, int callingUid, String sourcePackageName,
+    private JobStatus(JobInfo job, int callingUid, int targetSdkVersion, String sourcePackageName,
             int sourceUserId, int standbyBucket, long heartbeat, String tag, int numFailures,
             long earliestRunTimeElapsedMillis, long latestRunTimeElapsedMillis,
             long lastSuccessfulRunTime, long lastFailedRunTime) {
         this.job = job;
         this.callingUid = callingUid;
+        this.targetSdkVersion = targetSdkVersion;
         this.standbyBucket = standbyBucket;
         this.baseHeartbeat = heartbeat;
 
@@ -307,7 +310,7 @@
     /** Copy constructor: used specifically when cloning JobStatus objects for persistence,
      *   so we preserve RTC window bounds if the source object has them. */
     public JobStatus(JobStatus jobStatus) {
-        this(jobStatus.getJob(), jobStatus.getUid(),
+        this(jobStatus.getJob(), jobStatus.getUid(), jobStatus.targetSdkVersion,
                 jobStatus.getSourcePackageName(), jobStatus.getSourceUserId(),
                 jobStatus.getStandbyBucket(), jobStatus.getBaseHeartbeat(),
                 jobStatus.getSourceTag(), jobStatus.getNumFailures(),
@@ -334,7 +337,7 @@
             long earliestRunTimeElapsedMillis, long latestRunTimeElapsedMillis,
             long lastSuccessfulRunTime, long lastFailedRunTime,
             Pair<Long, Long> persistedExecutionTimesUTC) {
-        this(job, callingUid, sourcePkgName, sourceUserId,
+        this(job, callingUid, resolveTargetSdkVersion(job), sourcePkgName, sourceUserId,
                 standbyBucket, baseHeartbeat,
                 sourceTag, 0,
                 earliestRunTimeElapsedMillis, latestRunTimeElapsedMillis,
@@ -357,7 +360,7 @@
             long newEarliestRuntimeElapsedMillis,
             long newLatestRuntimeElapsedMillis, int backoffAttempt,
             long lastSuccessfulRunTime, long lastFailedRunTime) {
-        this(rescheduling.job, rescheduling.getUid(),
+        this(rescheduling.job, rescheduling.getUid(), resolveTargetSdkVersion(rescheduling.job),
                 rescheduling.getSourcePackageName(), rescheduling.getSourceUserId(),
                 rescheduling.getStandbyBucket(), newBaseHeartbeat,
                 rescheduling.getSourceTag(), backoffAttempt, newEarliestRuntimeElapsedMillis,
@@ -392,7 +395,7 @@
                 sourceUserId, elapsedNow);
         JobSchedulerInternal js = LocalServices.getService(JobSchedulerInternal.class);
         long currentHeartbeat = js != null ? js.currentHeartbeat() : 0;
-        return new JobStatus(job, callingUid, sourcePkg, sourceUserId,
+        return new JobStatus(job, callingUid, resolveTargetSdkVersion(job), sourcePkg, sourceUserId,
                 standbyBucket, currentHeartbeat, tag, 0,
                 earliestRunTimeElapsedMillis, latestRunTimeElapsedMillis,
                 0 /* lastSuccessfulRunTime */, 0 /* lastFailedRunTime */);
@@ -539,6 +542,10 @@
         return job.getId();
     }
 
+    public int getTargetSdkVersion() {
+        return targetSdkVersion;
+    }
+
     public void printUniqueId(PrintWriter pw) {
         UserHandle.formatUid(pw, callingUid);
         pw.print("/");
@@ -713,6 +720,37 @@
         return latestRunTimeElapsedMillis;
     }
 
+    /**
+     * Return the fractional position of "now" within the "run time" window of
+     * this job.
+     * <p>
+     * For example, if the earliest run time was 10 minutes ago, and the latest
+     * run time is 30 minutes from now, this would return 0.25.
+     * <p>
+     * If the job has no window defined, returns 1. When only an earliest or
+     * latest time is defined, it's treated as an infinitely small window at
+     * that time.
+     */
+    public float getFractionRunTime() {
+        final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
+        if (earliestRunTimeElapsedMillis == 0 && latestRunTimeElapsedMillis == Long.MAX_VALUE) {
+            return 1;
+        } else if (earliestRunTimeElapsedMillis == 0) {
+            return now >= latestRunTimeElapsedMillis ? 1 : 0;
+        } else if (latestRunTimeElapsedMillis == Long.MAX_VALUE) {
+            return now >= earliestRunTimeElapsedMillis ? 1 : 0;
+        } else {
+            if (now <= earliestRunTimeElapsedMillis) {
+                return 0;
+            } else if (now >= latestRunTimeElapsedMillis) {
+                return 1;
+            } else {
+                return (float) (now - earliestRunTimeElapsedMillis)
+                        / (float) (latestRunTimeElapsedMillis - earliestRunTimeElapsedMillis);
+            }
+        }
+    }
+
     public Pair<Long, Long> getPersistedUtcTimes() {
         return mPersistedUtcTimes;
     }
@@ -1091,6 +1129,11 @@
         }
     }
 
+    private static int resolveTargetSdkVersion(JobInfo job) {
+        return LocalServices.getService(PackageManagerInternal.class)
+                .getPackageTargetSdkVersion(job.getService().getPackageName());
+    }
+
     // Dumpsys infrastructure
     public void dump(PrintWriter pw, String prefix, boolean full, long elapsedRealtimeMillis) {
         pw.print(prefix); UserHandle.formatUid(pw, callingUid);
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index e158819..48d275c 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -827,7 +827,7 @@
                 return isEnabled();
             }
         };
-        mGnssMetrics = new GnssMetrics();
+        mGnssMetrics = new GnssMetrics(mBatteryStats);
     }
 
     /**
@@ -2628,6 +2628,10 @@
         s.append("  mStarted=").append(mStarted).append('\n');
         s.append("  mFixInterval=").append(mFixInterval).append('\n');
         s.append("  mLowPowerMode=").append(mLowPowerMode).append('\n');
+        s.append("  mGnssMeasurementsProvider.isRegistered()=")
+                .append(mGnssMeasurementsProvider.isRegistered()).append('\n');
+        s.append("  mGnssNavigationMessageProvider.isRegistered()=")
+                .append(mGnssNavigationMessageProvider.isRegistered()).append('\n');
         s.append("  mDisableGps (battery saver mode)=").append(mDisableGps).append('\n');
         s.append("  mEngineCapabilities=0x").append(Integer.toHexString(mEngineCapabilities));
         s.append(" ( ");
diff --git a/services/core/java/com/android/server/location/RemoteListenerHelper.java b/services/core/java/com/android/server/location/RemoteListenerHelper.java
index 58a9516..fcdb9d1 100644
--- a/services/core/java/com/android/server/location/RemoteListenerHelper.java
+++ b/services/core/java/com/android/server/location/RemoteListenerHelper.java
@@ -46,7 +46,8 @@
 
     private final Map<IBinder, LinkedListener> mListenerMap = new HashMap<>();
 
-    private boolean mIsRegistered;  // must access only on handler thread
+    private volatile boolean mIsRegistered;  // must access only on handler thread, or read-only
+
     private boolean mHasIsSupported;
     private boolean mIsSupported;
 
@@ -58,6 +59,11 @@
         mTag = name;
     }
 
+    // read-only access for a dump() thread assured via volatile
+    public boolean isRegistered() {
+        return mIsRegistered;
+    }
+
     public boolean addListener(@NonNull TListener listener) {
         Preconditions.checkNotNull(listener, "Attempted to register a 'null' listener.");
         IBinder binder = listener.asBinder();
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java
index a29e1be..724073a 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java
@@ -228,6 +228,10 @@
                 counterId = generateAndStoreCounterId(recoveryAgentUid);
             }
         }
+
+        // TODO: make sure the same counter id is used during recovery and remove temporary fix.
+        counterId = 1L;
+
         byte[] vaultParams = KeySyncUtils.packVaultParams(
                 publicKey,
                 counterId,
@@ -263,12 +267,16 @@
         // If application keys are not updated, snapshot will not be created on next unlock.
         mRecoverableKeyStoreDb.setShouldCreateSnapshot(mUserId, recoveryAgentUid, false);
 
-        // TODO: use Builder.
-        mRecoverySnapshotStorage.put(recoveryAgentUid, new KeychainSnapshot(
-                snapshotVersion,
-                /*recoveryMetadata=*/ metadataList,
-                /*applicationKeyBlobs=*/ createApplicationKeyEntries(encryptedApplicationKeys),
-                /*encryptedRecoveryKeyblob=*/ encryptedRecoveryKey));
+        mRecoverySnapshotStorage.put(recoveryAgentUid, new KeychainSnapshot.Builder()
+                .setSnapshotVersion(snapshotVersion)
+                .setMaxAttempts(TRUSTED_HARDWARE_MAX_ATTEMPTS)
+                .setCounterId(counterId)
+                .setTrustedHardwarePublicKey(SecureBox.encodePublicKey(publicKey))
+                .setServerParams(vaultHandle)
+                .setKeychainProtectionParams(metadataList)
+                .setWrappedApplicationKeys(createApplicationKeyEntries(encryptedApplicationKeys))
+                .setEncryptedRecoveryKeyBlob(encryptedRecoveryKey)
+                .build());
 
         mSnapshotListenersStorage.recoverySnapshotAvailable(recoveryAgentUid);
     }
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncUtils.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncUtils.java
index 219f6e1..89e2deb 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncUtils.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncUtils.java
@@ -300,7 +300,7 @@
                 .put(SecureBox.encodePublicKey(thmPublicKey))
                 .putLong(counterId)
                 .putInt(maxAttempts)
-                .put(new byte[VAULT_HANDLE_LENGTH_BYTES]) // TODO: replace with real vaultHandle
+                .put(vaultHandle)
                 .array();
     }
 
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
index 59855be..76508d5 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
@@ -16,12 +16,12 @@
 
 package com.android.server.locksettings.recoverablekeystore;
 
-import static android.security.keystore.RecoveryManager.ERROR_BAD_CERTIFICATE_FORMAT;
-import static android.security.keystore.RecoveryManager.ERROR_DECRYPTION_FAILED;
-import static android.security.keystore.RecoveryManager.ERROR_INSECURE_USER;
-import static android.security.keystore.RecoveryManager.ERROR_NO_SNAPSHOT_PENDING;
-import static android.security.keystore.RecoveryManager.ERROR_SERVICE_INTERNAL_ERROR;
-import static android.security.keystore.RecoveryManager.ERROR_SESSION_EXPIRED;
+import static android.security.keystore.RecoveryController.ERROR_BAD_CERTIFICATE_FORMAT;
+import static android.security.keystore.RecoveryController.ERROR_DECRYPTION_FAILED;
+import static android.security.keystore.RecoveryController.ERROR_INSECURE_USER;
+import static android.security.keystore.RecoveryController.ERROR_NO_SNAPSHOT_PENDING;
+import static android.security.keystore.RecoveryController.ERROR_SERVICE_INTERNAL_ERROR;
+import static android.security.keystore.RecoveryController.ERROR_SESSION_EXPIRED;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -35,8 +35,8 @@
 
 import android.security.keystore.KeychainProtectionParams;
 import android.security.keystore.KeychainSnapshot;
+import android.security.keystore.RecoveryController;
 import android.security.keystore.WrappedApplicationKey;
-import android.security.keystore.RecoveryManager;
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -63,7 +63,7 @@
 import javax.crypto.AEADBadTagException;
 
 /**
- * Class with {@link RecoveryManager} API implementation and internal methods to interact
+ * Class with {@link RecoveryController} API implementation and internal methods to interact
  * with {@code LockSettingsService}.
  *
  * @hide
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/WrappedKey.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/WrappedKey.java
index 0042e10..c33c9de 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/WrappedKey.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/WrappedKey.java
@@ -16,8 +16,8 @@
 
 package com.android.server.locksettings.recoverablekeystore;
 
+import android.security.keystore.RecoveryController;
 import android.util.Log;
-import android.security.keystore.RecoveryManager;
 
 import java.security.InvalidAlgorithmParameterException;
 import java.security.InvalidKeyException;
@@ -97,7 +97,7 @@
                 /*nonce=*/ cipher.getIV(),
                 /*keyMaterial=*/ encryptedKeyMaterial,
                 /*platformKeyGenerationId=*/ wrappingKey.getGenerationId(),
-                RecoveryManager.RECOVERY_STATUS_SYNC_IN_PROGRESS);
+                RecoveryController.RECOVERY_STATUS_SYNC_IN_PROGRESS);
     }
 
     /**
@@ -107,14 +107,14 @@
      * @param keyMaterial The encrypted bytes of the key material.
      * @param platformKeyGenerationId The generation ID of the key used to wrap this key.
      *
-     * @see RecoveryManager.RECOVERY_STATUS_SYNC_IN_PROGRESS
+     * @see RecoveryController.RECOVERY_STATUS_SYNC_IN_PROGRESS
      * @hide
      */
     public WrappedKey(byte[] nonce, byte[] keyMaterial, int platformKeyGenerationId) {
         mNonce = nonce;
         mKeyMaterial = keyMaterial;
         mPlatformKeyGenerationId = platformKeyGenerationId;
-        mRecoveryStatus = RecoveryManager.RECOVERY_STATUS_SYNC_IN_PROGRESS;
+        mRecoveryStatus = RecoveryController.RECOVERY_STATUS_SYNC_IN_PROGRESS;
     }
 
     /**
diff --git a/services/core/java/com/android/server/net/NetworkIdentitySet.java b/services/core/java/com/android/server/net/NetworkIdentitySet.java
index ee00fdc..68cd5e7 100644
--- a/services/core/java/com/android/server/net/NetworkIdentitySet.java
+++ b/services/core/java/com/android/server/net/NetworkIdentitySet.java
@@ -39,6 +39,7 @@
     private static final int VERSION_ADD_ROAMING = 2;
     private static final int VERSION_ADD_NETWORK_ID = 3;
     private static final int VERSION_ADD_METERED = 4;
+    private static final int VERSION_ADD_DEFAULT_NETWORK = 5;
 
     public NetworkIdentitySet() {
     }
@@ -76,12 +77,20 @@
                 metered = (type == TYPE_MOBILE);
             }
 
-            add(new NetworkIdentity(type, subType, subscriberId, networkId, roaming, metered));
+            final boolean defaultNetwork;
+            if (version >= VERSION_ADD_DEFAULT_NETWORK) {
+                defaultNetwork = in.readBoolean();
+            } else {
+                defaultNetwork = true;
+            }
+
+            add(new NetworkIdentity(type, subType, subscriberId, networkId, roaming, metered,
+                    defaultNetwork));
         }
     }
 
     public void writeToStream(DataOutputStream out) throws IOException {
-        out.writeInt(VERSION_ADD_METERED);
+        out.writeInt(VERSION_ADD_DEFAULT_NETWORK);
         out.writeInt(size());
         for (NetworkIdentity ident : this) {
             out.writeInt(ident.getType());
@@ -90,6 +99,7 @@
             writeOptionalString(out, ident.getNetworkId());
             out.writeBoolean(ident.getRoaming());
             out.writeBoolean(ident.getMetered());
+            out.writeBoolean(ident.getDefaultNetwork());
         }
     }
 
@@ -119,6 +129,20 @@
         return false;
     }
 
+    /** @return whether any {@link NetworkIdentity} in this set is considered on the default
+            network. */
+    public boolean areAllMembersOnDefaultNetwork() {
+        if (isEmpty()) {
+            return true;
+        }
+        for (NetworkIdentity ident : this) {
+            if (!ident.getDefaultNetwork()) {
+                return false;
+            }
+        }
+        return true;
+    }
+
     private static void writeOptionalString(DataOutputStream out, String value) throws IOException {
         if (value != null) {
             out.writeByte(1);
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java b/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java
index 7934a96..e458f48 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java
@@ -16,6 +16,9 @@
 
 package com.android.server.net;
 
+import android.net.Network;
+import android.telephony.SubscriptionPlan;
+
 /**
  * Network Policy Manager local system service interface.
  *
@@ -47,4 +50,20 @@
      * @param added Denotes whether the {@param appId} has been added or removed from the whitelist.
      */
     public abstract void onTempPowerSaveWhitelistChange(int appId, boolean added);
+
+    /**
+     * Return the active {@link SubscriptionPlan} for the given network.
+     */
+    public abstract SubscriptionPlan getSubscriptionPlan(Network network);
+
+    public static final int QUOTA_TYPE_JOBS = 1;
+    public static final int QUOTA_TYPE_MULTIPATH = 2;
+
+    /**
+     * Return the daily quota (in bytes) that can be opportunistically used on
+     * the given network to improve the end user experience. It's called
+     * "opportunistic" because it's traffic that would typically not use the
+     * given network.
+     */
+    public abstract long getSubscriptionOpportunisticQuota(Network network, int quotaType);
 }
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index ff9b2fd..96b06c2 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -34,6 +34,7 @@
 import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_WHITELISTED;
 import static android.net.ConnectivityManager.TYPE_MOBILE;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
 import static android.net.NetworkPolicy.LIMIT_DISABLED;
 import static android.net.NetworkPolicy.SNOOZE_NEVER;
 import static android.net.NetworkPolicy.WARNING_DISABLED;
@@ -69,6 +70,7 @@
 import static android.telephony.CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED;
 import static android.telephony.CarrierConfigManager.DATA_CYCLE_THRESHOLD_DISABLED;
 import static android.telephony.CarrierConfigManager.DATA_CYCLE_USE_PLATFORM_DEFAULT;
+import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
 import static android.text.format.DateUtils.DAY_IN_MILLIS;
 
 import static com.android.internal.util.ArrayUtils.appendInt;
@@ -97,6 +99,7 @@
 
 import android.Manifest;
 import android.annotation.IntDef;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.app.ActivityManagerInternal;
@@ -134,8 +137,10 @@
 import android.net.NetworkPolicyManager;
 import android.net.NetworkQuotaInfo;
 import android.net.NetworkRequest;
+import android.net.NetworkSpecifier;
 import android.net.NetworkState;
 import android.net.NetworkTemplate;
+import android.net.StringNetworkSpecifier;
 import android.net.TrafficStats;
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiManager;
@@ -174,6 +179,7 @@
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.AtomicFile;
+import android.util.DataUnit;
 import android.util.Log;
 import android.util.NtpTrustedTime;
 import android.util.Pair;
@@ -182,6 +188,7 @@
 import android.util.SparseArray;
 import android.util.SparseBooleanArray;
 import android.util.SparseIntArray;
+import android.util.SparseLongArray;
 import android.util.TrustedTime;
 import android.util.Xml;
 
@@ -200,8 +207,10 @@
 import com.android.server.LocalServices;
 import com.android.server.ServiceThread;
 import com.android.server.SystemConfig;
+import com.android.server.SystemService;
 
 import libcore.io.IoUtils;
+import libcore.util.EmptyArray;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlSerializer;
@@ -219,7 +228,6 @@
 import java.time.ZoneId;
 import java.time.ZonedDateTime;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Calendar;
 import java.util.List;
 import java.util.Objects;
@@ -278,6 +286,8 @@
     public static final int TYPE_LIMIT = SystemMessage.NOTE_NET_LIMIT;
     @VisibleForTesting
     public static final int TYPE_LIMIT_SNOOZED = SystemMessage.NOTE_NET_LIMIT_SNOOZED;
+    @VisibleForTesting
+    public static final int TYPE_RAPID = SystemMessage.NOTE_NET_RAPID;
 
     private static final String TAG_POLICY_LIST = "policy-list";
     private static final String TAG_NETWORK_POLICY = "network-policy";
@@ -332,6 +342,7 @@
     private static final int MSG_REMOVE_INTERFACE_QUOTA = 11;
     private static final int MSG_POLICIES_CHANGED = 13;
     private static final int MSG_RESET_FIREWALL_RULES_BY_UID = 15;
+    private static final int MSG_SUBSCRIPTION_OVERRIDE = 16;
 
     private static final int UID_MSG_STATE_CHANGED = 100;
     private static final int UID_MSG_GONE = 101;
@@ -384,6 +395,10 @@
     @GuardedBy("mNetworkPoliciesSecondLock")
     final SparseArray<String> mSubscriptionPlansOwner = new SparseArray<>();
 
+    /** Map from subId to daily opportunistic quota. */
+    @GuardedBy("mNetworkPoliciesSecondLock")
+    final SparseLongArray mSubscriptionOpportunisticQuota = new SparseLongArray();
+
     /** Defined UID policies. */
     @GuardedBy("mUidRulesFirstLock") final SparseIntArray mUidPolicy = new SparseIntArray();
     /** Currently derived rules for each UID. */
@@ -453,6 +468,10 @@
     @GuardedBy("mNetworkPoliciesSecondLock")
     private final SparseBooleanArray mNetworkMetered = new SparseBooleanArray();
 
+    /** Map from netId to subId as of last update */
+    @GuardedBy("mNetworkPoliciesSecondLock")
+    private final SparseIntArray mNetIdToSubId = new SparseIntArray();
+
     private final RemoteCallbackList<INetworkPolicyListener>
             mListeners = new RemoteCallbackList<>();
 
@@ -984,6 +1003,13 @@
         }
     };
 
+    @VisibleForTesting
+    public void updateNotifications() {
+        synchronized (mNetworkPoliciesSecondLock) {
+            updateNotificationsNL();
+        }
+    }
+
     /**
      * Check {@link NetworkPolicy} against current {@link INetworkStatsService}
      * to show visible notifications as needed.
@@ -1028,6 +1054,44 @@
             }
         }
 
+        // Alert the user about heavy recent data usage that might result in
+        // going over their carrier limit.
+        for (int i = 0; i < mNetIdToSubId.size(); i++) {
+            final int subId = mNetIdToSubId.valueAt(i);
+            final SubscriptionPlan plan = getPrimarySubscriptionPlanLocked(subId);
+            if (plan == null) continue;
+
+            final long limitBytes = plan.getDataLimitBytes();
+            if (limitBytes == SubscriptionPlan.BYTES_UNKNOWN) {
+                // Ignore missing limits
+            } else if (limitBytes == SubscriptionPlan.BYTES_UNLIMITED) {
+                // Unlimited data; no rapid usage alerting
+            } else {
+                // Warn if average usage over last 4 days is on track to blow
+                // pretty far past the plan limits.
+                final long recentDuration = TimeUnit.DAYS.toMillis(4);
+                final long end = RecurrenceRule.sClock.millis();
+                final long start = end - recentDuration;
+
+                final NetworkTemplate template = NetworkTemplate.buildTemplateMobileAll(
+                        mContext.getSystemService(TelephonyManager.class).getSubscriberId(subId));
+                final long recentBytes = getTotalBytes(template, start, end);
+
+                final Pair<ZonedDateTime, ZonedDateTime> cycle = plan.cycleIterator().next();
+                final long cycleDuration = cycle.second.toInstant().toEpochMilli()
+                        - cycle.first.toInstant().toEpochMilli();
+
+                final long projectedBytes = (recentBytes * cycleDuration) / recentDuration;
+                final long alertBytes = (limitBytes * 3) / 2;
+                if (projectedBytes > alertBytes) {
+                    final NetworkPolicy policy = new NetworkPolicy(template, plan.getCycleRule(),
+                            NetworkPolicy.WARNING_DISABLED, NetworkPolicy.LIMIT_DISABLED,
+                            NetworkPolicy.SNOOZE_NEVER, NetworkPolicy.SNOOZE_NEVER, true, true);
+                    enqueueNotification(policy, TYPE_RAPID, 0);
+                }
+            }
+        }
+
         // cancel stale notifications that we didn't renew above
         for (int i = beforeNotifs.size()-1; i >= 0; i--) {
             final NotificationId notificationId = beforeNotifs.valueAt(i);
@@ -1049,11 +1113,12 @@
             final SubscriptionManager sub = SubscriptionManager.from(mContext);
 
             // Mobile template is relevant when any active subscriber matches
-            final int[] subIds = sub.getActiveSubscriptionIdList();
+            final int[] subIds = ArrayUtils.defeatNullable(sub.getActiveSubscriptionIdList());
             for (int subId : subIds) {
                 final String subscriberId = tele.getSubscriberId(subId);
                 final NetworkIdentity probeIdent = new NetworkIdentity(TYPE_MOBILE,
-                        TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, null, false, true);
+                        TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, null, false, true,
+                        true);
                 if (template.matches(probeIdent)) {
                     return true;
                 }
@@ -1186,6 +1251,21 @@
                         mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
                 break;
             }
+            case TYPE_RAPID: {
+                final CharSequence title = res.getText(R.string.data_usage_rapid_title);
+                body = res.getText(R.string.data_usage_rapid_body);
+
+                builder.setOngoing(true);
+                builder.setSmallIcon(R.drawable.stat_notify_error);
+                builder.setTicker(title);
+                builder.setContentTitle(title);
+                builder.setContentText(body);
+
+                final Intent intent = buildViewDataUsageIntent(res, policy.template);
+                builder.setContentIntent(PendingIntent.getActivity(
+                        mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
+                break;
+            }
         }
 
         // TODO: move to NotificationManager once we can mock it
@@ -1239,6 +1319,11 @@
         }
     };
 
+    @VisibleForTesting
+    public void updateNetworks() {
+        mConnReceiver.onReceive(null, null);
+    }
+
     /**
      * Update mobile policies with data cycle information from {@link CarrierConfigManager}
      * if necessary.
@@ -1254,7 +1339,7 @@
 
         // find and update the mobile NetworkPolicy for this subscriber id
         final NetworkIdentity probeIdent = new NetworkIdentity(TYPE_MOBILE,
-                TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, null, false, true);
+                TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, null, false, true, true);
         for (int i = mNetworkPolicy.size() - 1; i >= 0; i--) {
             final NetworkTemplate template = mNetworkPolicy.keyAt(i);
             if (template.matches(probeIdent)) {
@@ -1457,11 +1542,12 @@
             final SubscriptionManager sm = SubscriptionManager.from(mContext);
             final TelephonyManager tm = TelephonyManager.from(mContext);
 
-            final int[] subIds = sm.getActiveSubscriptionIdList();
+            final int[] subIds = ArrayUtils.defeatNullable(sm.getActiveSubscriptionIdList());
             for (int subId : subIds) {
                 final String subscriberId = tm.getSubscriberId(subId);
                 final NetworkIdentity probeIdent = new NetworkIdentity(TYPE_MOBILE,
-                        TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, null, false, true);
+                        TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, null, false, true,
+                        true);
                 // Template is matched when subscriber id matches.
                 if (template.matches(probeIdent)) {
                     tm.setPolicyDataEnabled(enabled, subId);
@@ -1496,7 +1582,7 @@
 
         final NetworkState[] states;
         try {
-            states = mConnManager.getAllNetworkState();
+            states = defeatNullable(mConnManager.getAllNetworkState());
         } catch (RemoteException e) {
             // ignored; service lives in system_server
             return;
@@ -1504,10 +1590,15 @@
 
         // First, generate identities of all connected networks so we can
         // quickly compare them against all defined policies below.
+        mNetIdToSubId.clear();
         final ArrayMap<NetworkState, NetworkIdentity> identified = new ArrayMap<>();
         for (NetworkState state : states) {
+            if (state.network != null) {
+                mNetIdToSubId.put(state.network.netId, parseSubId(state));
+            }
             if (state.networkInfo != null && state.networkInfo.isConnected()) {
-                final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state);
+                final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state,
+                        true);
                 identified.put(state, ident);
             }
         }
@@ -1607,6 +1698,42 @@
         }
         mMeteredIfaces = newMeteredIfaces;
 
+        // Finally, calculate our opportunistic quotas
+        // TODO: add experiments support to disable or tweak ratios
+        mSubscriptionOpportunisticQuota.clear();
+        for (NetworkState state : states) {
+            if (state.network == null) continue;
+            final int subId = getSubIdLocked(state.network);
+            final SubscriptionPlan plan = getPrimarySubscriptionPlanLocked(subId);
+            if (plan == null) continue;
+
+            // By default assume we have no quota
+            long quotaBytes = 0;
+
+            final long limitBytes = plan.getDataLimitBytes();
+            if (limitBytes == SubscriptionPlan.BYTES_UNKNOWN) {
+                // Ignore missing limits
+            } else if (limitBytes == SubscriptionPlan.BYTES_UNLIMITED) {
+                // Unlimited data; let's use 20MiB/day (600MiB/month)
+                quotaBytes = DataUnit.MEBIBYTES.toBytes(20);
+            } else {
+                // Limited data; let's only use 10% of remaining budget
+                final Pair<ZonedDateTime, ZonedDateTime> cycle = plan.cycleIterator().next();
+                final long start = cycle.first.toInstant().toEpochMilli();
+                final long end = cycle.second.toInstant().toEpochMilli();
+                final long totalBytes = getTotalBytes(
+                        NetworkTemplate.buildTemplateMobileAll(state.subscriberId), start, end);
+                final long remainingBytes = limitBytes - totalBytes;
+                final long remainingDays = Math.min(1, (end - RecurrenceRule.sClock.millis())
+                        / TimeUnit.DAYS.toMillis(1));
+                if (remainingBytes > 0) {
+                    quotaBytes = (remainingBytes / remainingDays) / 10;
+                }
+            }
+
+            mSubscriptionOpportunisticQuota.put(subId, quotaBytes);
+        }
+
         final String[] meteredIfaces = mMeteredIfaces.toArray(new String[mMeteredIfaces.size()]);
         mHandler.obtainMessage(MSG_METERED_IFACES_CHANGED, meteredIfaces).sendToTarget();
 
@@ -1624,7 +1751,7 @@
         final TelephonyManager tele = TelephonyManager.from(mContext);
         final SubscriptionManager sub = SubscriptionManager.from(mContext);
 
-        final int[] subIds = sub.getActiveSubscriptionIdList();
+        final int[] subIds = ArrayUtils.defeatNullable(sub.getActiveSubscriptionIdList());
         for (int subId : subIds) {
             final String subscriberId = tele.getSubscriberId(subId);
             ensureActiveMobilePolicyAL(subId, subscriberId);
@@ -1642,7 +1769,7 @@
     private boolean ensureActiveMobilePolicyAL(int subId, String subscriberId) {
         // Poke around to see if we already have a policy
         final NetworkIdentity probeIdent = new NetworkIdentity(TYPE_MOBILE,
-                TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, null, false, true);
+                TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, null, false, true, true);
         for (int i = mNetworkPolicy.size() - 1; i >= 0; i--) {
             final NetworkTemplate template = mNetworkPolicy.keyAt(i);
             if (template.matches(probeIdent)) {
@@ -2815,6 +2942,27 @@
     }
 
     @Override
+    public void setSubscriptionOverride(int subId, int overrideMask, int overrideValue,
+            long timeoutMillis, String callingPackage) {
+        enforceSubscriptionPlanAccess(subId, Binder.getCallingUid(), callingPackage);
+
+        // We can only override when carrier told us about plans
+        synchronized (mNetworkPoliciesSecondLock) {
+            if (ArrayUtils.isEmpty(mSubscriptionPlans.get(subId))) {
+                throw new IllegalStateException(
+                        "Must provide SubscriptionPlan information before overriding");
+            }
+        }
+
+        mHandler.sendMessage(mHandler.obtainMessage(MSG_SUBSCRIPTION_OVERRIDE,
+                overrideMask, overrideValue, subId));
+        if (timeoutMillis > 0) {
+            mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_SUBSCRIPTION_OVERRIDE,
+                    overrideMask, 0, subId), timeoutMillis);
+        }
+    }
+
+    @Override
     protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
         if (!DumpUtils.checkDumpPermission(mContext, TAG, writer)) return;
 
@@ -3819,6 +3967,16 @@
         }
     }
 
+    private void dispatchSubscriptionOverride(INetworkPolicyListener listener, int subId,
+            int overrideMask, int overrideValue) {
+        if (listener != null) {
+            try {
+                listener.onSubscriptionOverride(subId, overrideMask, overrideValue);
+            } catch (RemoteException ignored) {
+            }
+        }
+    }
+
     private final Handler.Callback mHandlerCallback = new Handler.Callback() {
         @Override
         public boolean handleMessage(Message msg) {
@@ -3922,6 +4080,18 @@
                     resetUidFirewallRules(msg.arg1);
                     return true;
                 }
+                case MSG_SUBSCRIPTION_OVERRIDE: {
+                    final int overrideMask = msg.arg1;
+                    final int overrideValue = msg.arg2;
+                    final int subId = (int) msg.obj;
+                    final int length = mListeners.beginBroadcast();
+                    for (int i = 0; i < length; i++) {
+                        final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
+                        dispatchSubscriptionOverride(listener, subId, overrideMask, overrideValue);
+                    }
+                    mListeners.finishBroadcast();
+                    return true;
+                }
                 default: {
                     return false;
                 }
@@ -4404,12 +4574,57 @@
                 updateRulesForTempWhitelistChangeUL(appId);
             }
         }
+
+        @Override
+        public SubscriptionPlan getSubscriptionPlan(Network network) {
+            synchronized (mNetworkPoliciesSecondLock) {
+                final int subId = getSubIdLocked(network);
+                return getPrimarySubscriptionPlanLocked(subId);
+            }
+        }
+
+        @Override
+        public long getSubscriptionOpportunisticQuota(Network network, int quotaType) {
+            synchronized (mNetworkPoliciesSecondLock) {
+                // TODO: handle splitting quota between use-cases
+                return mSubscriptionOpportunisticQuota.get(getSubIdLocked(network));
+            }
+        }
+    }
+
+    private int parseSubId(NetworkState state) {
+        // TODO: moved to using a legitimate NetworkSpecifier instead of string parsing
+        int subId = INVALID_SUBSCRIPTION_ID;
+        if (state != null && state.networkCapabilities != null
+                && state.networkCapabilities.hasTransport(TRANSPORT_CELLULAR)) {
+            NetworkSpecifier spec = state.networkCapabilities.getNetworkSpecifier();
+            if (spec instanceof StringNetworkSpecifier) {
+                try {
+                    subId = Integer.parseInt(((StringNetworkSpecifier) spec).specifier);
+                } catch (NumberFormatException e) {
+                }
+            }
+        }
+        return subId;
+    }
+
+    private int getSubIdLocked(Network network) {
+        return mNetIdToSubId.get(network.netId, INVALID_SUBSCRIPTION_ID);
+    }
+
+    private SubscriptionPlan getPrimarySubscriptionPlanLocked(int subId) {
+        final SubscriptionPlan[] plans = mSubscriptionPlans.get(subId);
+        return ArrayUtils.isEmpty(plans) ? null : plans[0];
     }
 
     private static boolean hasRule(int uidRules, int rule) {
         return (uidRules & rule) != 0;
     }
 
+    private static @NonNull NetworkState[] defeatNullable(@Nullable NetworkState[] val) {
+        return (val != null) ? val : new NetworkState[0];
+    }
+
     private class NotificationId {
         private final String mTag;
         private final int mId;
diff --git a/services/core/java/com/android/server/net/NetworkStatsCollection.java b/services/core/java/com/android/server/net/NetworkStatsCollection.java
index 4ceb592..961a451 100644
--- a/services/core/java/com/android/server/net/NetworkStatsCollection.java
+++ b/services/core/java/com/android/server/net/NetworkStatsCollection.java
@@ -17,6 +17,8 @@
 package com.android.server.net;
 
 import static android.net.NetworkStats.IFACE_ALL;
+import static android.net.NetworkStats.DEFAULT_NETWORK_NO;
+import static android.net.NetworkStats.DEFAULT_NETWORK_YES;
 import static android.net.NetworkStats.METERED_NO;
 import static android.net.NetworkStats.METERED_YES;
 import static android.net.NetworkStats.ROAMING_NO;
@@ -364,6 +366,8 @@
                 entry.uid = key.uid;
                 entry.set = key.set;
                 entry.tag = key.tag;
+                entry.defaultNetwork = key.ident.areAllMembersOnDefaultNetwork() ?
+                        DEFAULT_NETWORK_YES : DEFAULT_NETWORK_NO;
                 entry.metered = key.ident.isAnyMemberMetered() ? METERED_YES : METERED_NO;
                 entry.roaming = key.ident.isAnyMemberRoaming() ? ROAMING_YES : ROAMING_NO;
                 entry.rxBytes = historyEntry.rxBytes;
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index db61ef5..78fd4b4 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -25,6 +25,7 @@
 import static android.content.Intent.EXTRA_UID;
 import static android.net.ConnectivityManager.ACTION_TETHER_STATE_CHANGED;
 import static android.net.ConnectivityManager.isNetworkTypeMobile;
+import static android.net.NetworkStats.DEFAULT_NETWORK_ALL;
 import static android.net.NetworkStats.IFACE_ALL;
 import static android.net.NetworkStats.METERED_ALL;
 import static android.net.NetworkStats.ROAMING_ALL;
@@ -83,6 +84,7 @@
 import android.net.INetworkStatsService;
 import android.net.INetworkStatsSession;
 import android.net.LinkProperties;
+import android.net.Network;
 import android.net.NetworkCapabilities;
 import android.net.NetworkIdentity;
 import android.net.NetworkInfo;
@@ -231,14 +233,24 @@
     private final Object mStatsLock = new Object();
 
     /** Set of currently active ifaces. */
+    @GuardedBy("mStatsLock")
     private final ArrayMap<String, NetworkIdentitySet> mActiveIfaces = new ArrayMap<>();
+
     /** Set of currently active ifaces for UID stats. */
+    @GuardedBy("mStatsLock")
     private final ArrayMap<String, NetworkIdentitySet> mActiveUidIfaces = new ArrayMap<>();
+
     /** Current default active iface. */
     private String mActiveIface;
+
     /** Set of any ifaces associated with mobile networks since boot. */
+    @GuardedBy("mStatsLock")
     private String[] mMobileIfaces = new String[0];
 
+    /** Set of all ifaces currently used by traffic that does not explicitly specify a Network. */
+    @GuardedBy("mStatsLock")
+    private Network[] mDefaultNetworks = new Network[0];
+
     private final DropBoxNonMonotonicObserver mNonMonotonicObserver =
             new DropBoxNonMonotonicObserver();
 
@@ -666,9 +678,9 @@
         final NetworkStatsHistory.Entry entry = history.getValues(start, end, now, null);
 
         final NetworkStats stats = new NetworkStats(end - start, 1);
-        stats.addValues(new NetworkStats.Entry(IFACE_ALL, UID_ALL, SET_ALL, TAG_NONE, METERED_ALL,
-                ROAMING_ALL, entry.rxBytes, entry.rxPackets, entry.txBytes, entry.txPackets,
-                entry.operations));
+        stats.addValues(new NetworkStats.Entry(IFACE_ALL, UID_ALL, SET_ALL, TAG_NONE,
+                METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, entry.rxBytes, entry.rxPackets,
+                entry.txBytes, entry.txPackets, entry.operations));
         return stats;
     }
 
@@ -779,13 +791,13 @@
     }
 
     @Override
-    public void forceUpdateIfaces() {
+    public void forceUpdateIfaces(Network[] defaultNetworks) {
         mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
         assertBandwidthControlEnabled();
 
         final long token = Binder.clearCallingIdentity();
         try {
-            updateIfaces();
+            updateIfaces(defaultNetworks);
         } finally {
             Binder.restoreCallingIdentity(token);
         }
@@ -996,11 +1008,11 @@
         }
     };
 
-    private void updateIfaces() {
+    private void updateIfaces(Network[] defaultNetworks) {
         synchronized (mStatsLock) {
             mWakeLock.acquire();
             try {
-                updateIfacesLocked();
+                updateIfacesLocked(defaultNetworks);
             } finally {
                 mWakeLock.release();
             }
@@ -1013,7 +1025,7 @@
      * are active on a single {@code iface}, they are combined under a single
      * {@link NetworkIdentitySet}.
      */
-    private void updateIfacesLocked() {
+    private void updateIfacesLocked(Network[] defaultNetworks) {
         if (!mSystemReady) return;
         if (LOGV) Slog.v(TAG, "updateIfacesLocked()");
 
@@ -1040,12 +1052,18 @@
         // Rebuild active interfaces based on connected networks
         mActiveIfaces.clear();
         mActiveUidIfaces.clear();
+        if (defaultNetworks != null) {
+            // Caller is ConnectivityService. Update the list of default networks.
+            mDefaultNetworks = defaultNetworks;
+        }
 
         final ArraySet<String> mobileIfaces = new ArraySet<>();
         for (NetworkState state : states) {
             if (state.networkInfo.isConnected()) {
                 final boolean isMobile = isNetworkTypeMobile(state.networkInfo.getType());
-                final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state);
+                final boolean isDefault = ArrayUtils.contains(mDefaultNetworks, state.network);
+                final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state,
+                        isDefault);
 
                 // Traffic occurring on the base interface is always counted for
                 // both total usage and UID details.
@@ -1065,7 +1083,8 @@
                         // Copy the identify from IMS one but mark it as metered.
                         NetworkIdentity vtIdent = new NetworkIdentity(ident.getType(),
                                 ident.getSubType(), ident.getSubscriberId(), ident.getNetworkId(),
-                                ident.getRoaming(), true);
+                                ident.getRoaming(), true /* metered */,
+                                true /* onDefaultNetwork */);
                         findOrCreateNetworkIdentitySet(mActiveIfaces, VT_INTERFACE).add(vtIdent);
                         findOrCreateNetworkIdentitySet(mActiveUidIfaces, VT_INTERFACE).add(vtIdent);
                     }
@@ -1511,7 +1530,7 @@
                     return true;
                 }
                 case MSG_UPDATE_IFACES: {
-                    mService.updateIfaces();
+                    mService.updateIfaces(null);
                     return true;
                 }
                 case MSG_REGISTER_GLOBAL_ALERT: {
diff --git a/services/core/java/com/android/server/net/watchlist/NetworkWatchlistService.java b/services/core/java/com/android/server/net/watchlist/NetworkWatchlistService.java
index 3bcc36f..239ddbe 100644
--- a/services/core/java/com/android/server/net/watchlist/NetworkWatchlistService.java
+++ b/services/core/java/com/android/server/net/watchlist/NetworkWatchlistService.java
@@ -17,15 +17,11 @@
 package com.android.server.net.watchlist;
 
 import android.content.Context;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
 import android.net.IIpConnectivityMetrics;
 import android.net.INetdEventCallback;
-import android.net.NetworkWatchlistManager;
 import android.net.metrics.IpConnectivityLog;
 import android.os.Binder;
 import android.os.Process;
-import android.os.SharedMemory;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemProperties;
@@ -42,9 +38,7 @@
 import com.android.server.SystemService;
 
 import java.io.FileDescriptor;
-import java.io.IOException;
 import java.io.PrintWriter;
-import java.util.List;
 
 /**
  * Implementation of network watchlist service.
@@ -99,7 +93,7 @@
     private volatile boolean mIsLoggingEnabled = false;
     private final Object mLoggingSwitchLock = new Object();
 
-    private final WatchlistSettings mSettings;
+    private final WatchlistConfig mConfig;
     private final Context mContext;
 
     // Separate thread to handle expensive watchlist logging work.
@@ -112,7 +106,7 @@
 
     public NetworkWatchlistService(Context context) {
         mContext = context;
-        mSettings = WatchlistSettings.getInstance();
+        mConfig = WatchlistConfig.getInstance();
         mHandlerThread = new ServiceThread(TAG, Process.THREAD_PRIORITY_BACKGROUND,
                         /* allowIo */ false);
         mHandlerThread.start();
@@ -126,7 +120,7 @@
     NetworkWatchlistService(Context context, ServiceThread handlerThread,
             WatchlistLoggingHandler handler, IIpConnectivityMetrics ipConnectivityMetrics) {
         mContext = context;
-        mSettings = WatchlistSettings.getInstance();
+        mConfig = WatchlistConfig.getInstance();
         mHandlerThread = handlerThread;
         mNetworkWatchlistHandler = handler;
         mIpConnectivityMetrics = ipConnectivityMetrics;
@@ -228,7 +222,7 @@
     public void reloadWatchlist() throws RemoteException {
         enforceWatchlistLoggingPermission();
         Slog.i(TAG, "Reloading watchlist");
-        mSettings.reloadSettings();
+        mConfig.reloadConfig();
     }
 
     @Override
@@ -240,7 +234,7 @@
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
-        mSettings.dump(fd, pw, args);
+        mConfig.dump(fd, pw, args);
     }
 
 }
diff --git a/services/core/java/com/android/server/net/watchlist/PrivacyUtils.java b/services/core/java/com/android/server/net/watchlist/PrivacyUtils.java
new file mode 100644
index 0000000..c1231fa
--- /dev/null
+++ b/services/core/java/com/android/server/net/watchlist/PrivacyUtils.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.net.watchlist;
+
+import android.privacy.DifferentialPrivacyEncoder;
+import android.privacy.internal.longitudinalreporting.LongitudinalReportingConfig;
+import android.privacy.internal.longitudinalreporting.LongitudinalReportingEncoder;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Helper class to apply differential privacy to watchlist reports.
+ */
+class PrivacyUtils {
+
+    private static final String TAG = "PrivacyUtils";
+
+    /**
+     * Parameters used for encoding watchlist reports.
+     * These numbers are optimal parameters for protecting privacy with good utility.
+     *
+     * TODO: Add links to explain the math behind.
+     */
+    private static final String ENCODER_ID_PREFIX = "watchlist_encoder:";
+    private static final double PROB_F = 0.469;
+    private static final double PROB_P = 0.28;
+    private static final double PROB_Q = 1.0;
+
+    private PrivacyUtils() {
+    }
+
+    /**
+     * Get insecure DP encoder.
+     * Should not apply it directly on real data as seed is not randomized.
+     */
+    @VisibleForTesting
+    static DifferentialPrivacyEncoder createInsecureDPEncoderForTest(String appDigest) {
+        final LongitudinalReportingConfig config = createLongitudinalReportingConfig(appDigest);
+        return LongitudinalReportingEncoder.createInsecureEncoderForTest(config);
+    }
+
+    /**
+     * Get secure encoder to encode watchlist.
+     *
+     * Warning: If you use the same user secret and app digest, then you will get the same
+     * PRR result.
+     */
+    @VisibleForTesting
+    static DifferentialPrivacyEncoder createSecureDPEncoder(byte[] userSecret,
+            String appDigest) {
+        final LongitudinalReportingConfig config = createLongitudinalReportingConfig(appDigest);
+        return LongitudinalReportingEncoder.createEncoder(config, userSecret);
+    }
+
+    /**
+     * Get DP config for encoding watchlist reports.
+     */
+    private static LongitudinalReportingConfig createLongitudinalReportingConfig(String appDigest) {
+        return new LongitudinalReportingConfig(ENCODER_ID_PREFIX + appDigest, PROB_F, PROB_P,
+                PROB_Q);
+    }
+
+    /**
+     * Create a map that stores appDigest, encoded_visitedWatchlist pairs.
+     */
+    @VisibleForTesting
+    static Map<String, Boolean> createDpEncodedReportMap(boolean isSecure, byte[] userSecret,
+            List<String> appDigestList, WatchlistReportDbHelper.AggregatedResult aggregatedResult) {
+        final int appDigestListSize = appDigestList.size();
+        final HashMap<String, Boolean> resultMap = new HashMap<>(appDigestListSize);
+        for (int i = 0; i < appDigestListSize; i++) {
+            final String appDigest = appDigestList.get(i);
+            // Each app needs to have different PRR result, hence we use appDigest as encoder Id.
+            final DifferentialPrivacyEncoder encoder = isSecure
+                    ? createSecureDPEncoder(userSecret, appDigest)
+                    : createInsecureDPEncoderForTest(appDigest);
+            final boolean visitedWatchlist = aggregatedResult.appDigestList.contains(appDigest);
+            // Get the least significant bit of first byte, and set result to True if it is 1
+            boolean encodedVisitedWatchlist = ((int) encoder.encodeBoolean(visitedWatchlist)[0]
+                    & 0x1) == 0x1;
+            resultMap.put(appDigest, encodedVisitedWatchlist);
+        }
+        return resultMap;
+    }
+}
diff --git a/services/core/java/com/android/server/net/watchlist/ReportEncoder.java b/services/core/java/com/android/server/net/watchlist/ReportEncoder.java
new file mode 100644
index 0000000..5d7ff5a
--- /dev/null
+++ b/services/core/java/com/android/server/net/watchlist/ReportEncoder.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package com.android.server.net.watchlist;
+
+import android.annotation.Nullable;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.HexDump;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Helper class to encode and generate serialized DP encoded watchlist report.
+ *
+ * <p>Serialized report data structure:
+ * [4 bytes magic number][4_bytes_report_version_code][32_bytes_watchlist_hash]
+ * [app_1_digest_byte_array][app_1_encoded_visited_cnc_byte]
+ * [app_2_digest_byte_array][app_2_encoded_visited_cnc_byte]
+ * ...
+ *
+ * Total size: 4 + 4 + 32 + (32+1)*N, where N = number of digests
+ */
+class ReportEncoder {
+
+    private static final String TAG = "ReportEncoder";
+
+    // Report header magic number
+    private static final byte[] MAGIC_NUMBER = {(byte) 0x8D, (byte) 0x37, (byte) 0x0A, (byte) 0xAC};
+    // Report version number, as file format / parameters can be changed in later version, we need
+    // to have versioning on watchlist report format
+    private static final byte[] REPORT_VERSION = {(byte) 0x00, (byte) 0x01};
+
+    private static final int WATCHLIST_HASH_SIZE = 32;
+    private static final int APP_DIGEST_SIZE = 32;
+
+    /**
+     * Apply DP on watchlist results, and generate a serialized watchlist report ready to store
+     * in DropBox.
+     */
+    static byte[] encodeWatchlistReport(WatchlistConfig config, byte[] userSecret,
+            List<String> appDigestList, WatchlistReportDbHelper.AggregatedResult aggregatedResult) {
+        Map<String, Boolean> resultMap = PrivacyUtils.createDpEncodedReportMap(
+                config.isConfigSecure(), userSecret, appDigestList, aggregatedResult);
+        return serializeReport(config, resultMap);
+    }
+
+    /**
+     * Convert DP encoded watchlist report into byte[] format.
+     * TODO: Serialize it using protobuf
+     *
+     * @param encodedReportMap DP encoded watchlist report.
+     * @return Watchlist report in byte[] format, which will be shared in Dropbox. Null if
+     * watchlist report cannot be generated.
+     */
+    @Nullable
+    @VisibleForTesting
+    static byte[] serializeReport(WatchlistConfig config,
+            Map<String, Boolean> encodedReportMap) {
+        // TODO: Handle watchlist config changed case
+        final byte[] watchlistHash = config.getWatchlistConfigHash();
+        if (watchlistHash == null) {
+            Log.e(TAG, "No watchlist hash");
+            return null;
+        }
+        if (watchlistHash.length != WATCHLIST_HASH_SIZE) {
+            Log.e(TAG, "Unexpected hash length");
+            return null;
+        }
+        final int reportMapSize = encodedReportMap.size();
+        final byte[] outputReport =
+                new byte[MAGIC_NUMBER.length + REPORT_VERSION.length + WATCHLIST_HASH_SIZE
+                        + reportMapSize * (APP_DIGEST_SIZE + /* Result */ 1)];
+        final List<String> sortedKeys = new ArrayList(encodedReportMap.keySet());
+        Collections.sort(sortedKeys);
+
+        int offset = 0;
+
+        // Set magic number to report
+        System.arraycopy(MAGIC_NUMBER, 0, outputReport, offset, MAGIC_NUMBER.length);
+        offset += MAGIC_NUMBER.length;
+
+        // Set report version to report
+        System.arraycopy(REPORT_VERSION, 0, outputReport, offset, REPORT_VERSION.length);
+        offset += REPORT_VERSION.length;
+
+        // Set watchlist hash to report
+        System.arraycopy(watchlistHash, 0, outputReport, offset, watchlistHash.length);
+        offset += watchlistHash.length;
+
+        // Set app digest, encoded_isPha pair to report
+        for (int i = 0; i < reportMapSize; i++) {
+            String key = sortedKeys.get(i);
+            byte[] digest = HexDump.hexStringToByteArray(key);
+            boolean isPha = encodedReportMap.get(key);
+            System.arraycopy(digest, 0, outputReport, offset, APP_DIGEST_SIZE);
+            offset += digest.length;
+            outputReport[offset] = (byte) (isPha ? 1 : 0);
+            offset += 1;
+        }
+        if (outputReport.length != offset) {
+            Log.e(TAG, "Watchlist report size does not match! Offset: " + offset + ", report size: "
+                    + outputReport.length);
+
+        }
+        return outputReport;
+    }
+}
diff --git a/services/core/java/com/android/server/net/watchlist/WatchlistConfig.java b/services/core/java/com/android/server/net/watchlist/WatchlistConfig.java
new file mode 100644
index 0000000..fbf11fc
--- /dev/null
+++ b/services/core/java/com/android/server/net/watchlist/WatchlistConfig.java
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.net.watchlist;
+
+import android.util.AtomicFile;
+import android.util.Log;
+import android.util.Slog;
+import android.util.Xml;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.HexDump;
+import com.android.internal.util.XmlUtils;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.zip.CRC32;
+
+/**
+ * Class for watchlist config operations, like setting watchlist, query if a domain
+ * exists in watchlist.
+ */
+class WatchlistConfig {
+    private static final String TAG = "WatchlistConfig";
+
+    // Watchlist config that pushed by ConfigUpdater.
+    private static final String NETWORK_WATCHLIST_DB_PATH =
+            "/data/misc/network_watchlist/network_watchlist.xml";
+
+    // Hash for null / unknown config, a 32 byte array filled with content 0x00
+    private static final byte[] UNKNOWN_CONFIG_HASH = new byte[32];
+
+    private static class XmlTags {
+        private static final String WATCHLIST_CONFIG = "watchlist-config";
+        private static final String SHA256_DOMAIN = "sha256-domain";
+        private static final String CRC32_DOMAIN = "crc32-domain";
+        private static final String SHA256_IP = "sha256-ip";
+        private static final String CRC32_IP = "crc32-ip";
+        private static final String HASH = "hash";
+    }
+
+    private static class CrcShaDigests {
+        final HarmfulDigests crc32Digests;
+        final HarmfulDigests sha256Digests;
+
+        public CrcShaDigests(HarmfulDigests crc32Digests, HarmfulDigests sha256Digests) {
+            this.crc32Digests = crc32Digests;
+            this.sha256Digests = sha256Digests;
+        }
+    }
+
+    /*
+     * This is always true unless watchlist is being set by adb command, then it will be false
+     * until next reboot.
+     */
+    private boolean mIsSecureConfig = true;
+
+    private final static WatchlistConfig sInstance = new WatchlistConfig();
+    private final File mXmlFile;
+
+    private volatile CrcShaDigests mDomainDigests;
+    private volatile CrcShaDigests mIpDigests;
+
+    public static WatchlistConfig getInstance() {
+        return sInstance;
+    }
+
+    private WatchlistConfig() {
+        this(new File(NETWORK_WATCHLIST_DB_PATH));
+    }
+
+    @VisibleForTesting
+    protected WatchlistConfig(File xmlFile) {
+        mXmlFile = xmlFile;
+        reloadConfig();
+    }
+
+    /**
+     * Reload watchlist by reading config file.
+     */
+    public void reloadConfig() {
+        try (FileInputStream stream = new FileInputStream(mXmlFile)){
+            final List<byte[]> crc32DomainList = new ArrayList<>();
+            final List<byte[]> sha256DomainList = new ArrayList<>();
+            final List<byte[]> crc32IpList = new ArrayList<>();
+            final List<byte[]> sha256IpList = new ArrayList<>();
+
+            XmlPullParser parser = Xml.newPullParser();
+            parser.setInput(stream, StandardCharsets.UTF_8.name());
+            parser.nextTag();
+            parser.require(XmlPullParser.START_TAG, null, XmlTags.WATCHLIST_CONFIG);
+            while (parser.nextTag() == XmlPullParser.START_TAG) {
+                String tagName = parser.getName();
+                switch (tagName) {
+                    case XmlTags.CRC32_DOMAIN:
+                        parseHashes(parser, tagName, crc32DomainList);
+                        break;
+                    case XmlTags.CRC32_IP:
+                        parseHashes(parser, tagName, crc32IpList);
+                        break;
+                    case XmlTags.SHA256_DOMAIN:
+                        parseHashes(parser, tagName, sha256DomainList);
+                        break;
+                    case XmlTags.SHA256_IP:
+                        parseHashes(parser, tagName, sha256IpList);
+                        break;
+                    default:
+                        Log.w(TAG, "Unknown element: " + parser.getName());
+                        XmlUtils.skipCurrentTag(parser);
+                }
+            }
+            parser.require(XmlPullParser.END_TAG, null, XmlTags.WATCHLIST_CONFIG);
+            mDomainDigests = new CrcShaDigests(new HarmfulDigests(crc32DomainList),
+                    new HarmfulDigests(sha256DomainList));
+            mIpDigests = new CrcShaDigests(new HarmfulDigests(crc32IpList),
+                    new HarmfulDigests(sha256IpList));
+            Log.i(TAG, "Reload watchlist done");
+        } catch (IllegalStateException | NullPointerException | NumberFormatException |
+                XmlPullParserException | IOException | IndexOutOfBoundsException e) {
+            Slog.e(TAG, "Failed parsing xml", e);
+        }
+    }
+
+    private void parseHashes(XmlPullParser parser, String tagName, List<byte[]> hashList)
+            throws IOException, XmlPullParserException {
+        parser.require(XmlPullParser.START_TAG, null, tagName);
+        // Get all the hashes for this tag
+        while (parser.nextTag() == XmlPullParser.START_TAG) {
+            parser.require(XmlPullParser.START_TAG, null, XmlTags.HASH);
+            byte[] hash = HexDump.hexStringToByteArray(parser.nextText());
+            parser.require(XmlPullParser.END_TAG, null, XmlTags.HASH);
+            hashList.add(hash);
+        }
+        parser.require(XmlPullParser.END_TAG, null, tagName);
+    }
+
+    public boolean containsDomain(String domain) {
+        final CrcShaDigests domainDigests = mDomainDigests;
+        if (domainDigests == null) {
+            Slog.wtf(TAG, "domainDigests should not be null");
+            return false;
+        }
+        // First it does a quick CRC32 check.
+        final byte[] crc32 = getCrc32(domain);
+        if (!domainDigests.crc32Digests.contains(crc32)) {
+            return false;
+        }
+        // Now we do a slow SHA256 check.
+        final byte[] sha256 = getSha256(domain);
+        return domainDigests.sha256Digests.contains(sha256);
+    }
+
+    public boolean containsIp(String ip) {
+        final CrcShaDigests ipDigests = mIpDigests;
+        if (ipDigests == null) {
+            Slog.wtf(TAG, "ipDigests should not be null");
+            return false;
+        }
+        // First it does a quick CRC32 check.
+        final byte[] crc32 = getCrc32(ip);
+        if (!ipDigests.crc32Digests.contains(crc32)) {
+            return false;
+        }
+        // Now we do a slow SHA256 check.
+        final byte[] sha256 = getSha256(ip);
+        return ipDigests.sha256Digests.contains(sha256);
+    }
+
+
+    /** Get CRC32 of a string
+     *
+     * TODO: Review if we should use CRC32 or other algorithms
+     */
+    private byte[] getCrc32(String str) {
+        final CRC32 crc = new CRC32();
+        crc.update(str.getBytes());
+        final long tmp = crc.getValue();
+        return new byte[]{(byte) (tmp >> 24 & 255), (byte) (tmp >> 16 & 255),
+                (byte) (tmp >> 8 & 255), (byte) (tmp & 255)};
+    }
+
+    /** Get SHA256 of a string */
+    private byte[] getSha256(String str) {
+        MessageDigest messageDigest;
+        try {
+            messageDigest = MessageDigest.getInstance("SHA256");
+        } catch (NoSuchAlgorithmException e) {
+            /* can't happen */
+            return null;
+        }
+        messageDigest.update(str.getBytes());
+        return messageDigest.digest();
+    }
+
+    public boolean isConfigSecure() {
+        return mIsSecureConfig;
+    }
+
+    public byte[] getWatchlistConfigHash() {
+        if (!mXmlFile.exists()) {
+            return UNKNOWN_CONFIG_HASH;
+        }
+        try {
+            return DigestUtils.getSha256Hash(mXmlFile);
+        } catch (IOException | NoSuchAlgorithmException e) {
+            Log.e(TAG, "Unable to get watchlist config hash", e);
+        }
+        return UNKNOWN_CONFIG_HASH;
+    }
+
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        pw.println("Domain CRC32 digest list:");
+        mDomainDigests.crc32Digests.dump(fd, pw, args);
+        pw.println("Domain SHA256 digest list:");
+        mDomainDigests.sha256Digests.dump(fd, pw, args);
+        pw.println("Ip CRC32 digest list:");
+        mIpDigests.crc32Digests.dump(fd, pw, args);
+        pw.println("Ip SHA256 digest list:");
+        mIpDigests.sha256Digests.dump(fd, pw, args);
+    }
+}
diff --git a/services/core/java/com/android/server/net/watchlist/WatchlistLoggingHandler.java b/services/core/java/com/android/server/net/watchlist/WatchlistLoggingHandler.java
index 2247558..ee0049b 100644
--- a/services/core/java/com/android/server/net/watchlist/WatchlistLoggingHandler.java
+++ b/services/core/java/com/android/server/net/watchlist/WatchlistLoggingHandler.java
@@ -16,8 +16,10 @@
 
 package com.android.server.net.watchlist;
 
+import android.annotation.Nullable;
 import android.content.ContentResolver;
 import android.content.Context;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.os.Bundle;
@@ -30,14 +32,19 @@
 import android.text.TextUtils;
 import android.util.Slog;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.HexDump;
 
 import java.io.File;
 import java.io.IOException;
 import java.security.NoSuchAlgorithmException;
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.TimeUnit;
 
 /**
@@ -57,14 +64,17 @@
     private static final String DROPBOX_TAG = "network_watchlist_report";
 
     private final Context mContext;
+    private final @Nullable DropBoxManager mDropBoxManager;
     private final ContentResolver mResolver;
     private final PackageManager mPm;
     private final WatchlistReportDbHelper mDbHelper;
+    private final WatchlistConfig mConfig;
     private final WatchlistSettings mSettings;
     // A cache for uid and apk digest mapping.
     // As uid won't be reused until reboot, it's safe to assume uid is unique per signature and app.
     // TODO: Use more efficient data structure.
-    private final HashMap<Integer, byte[]> mCachedUidDigestMap = new HashMap<>();
+    private final ConcurrentHashMap<Integer, byte[]> mCachedUidDigestMap =
+            new ConcurrentHashMap<>();
 
     private interface WatchlistEventKeys {
         String HOST = "host";
@@ -79,7 +89,9 @@
         mPm = mContext.getPackageManager();
         mResolver = mContext.getContentResolver();
         mDbHelper = WatchlistReportDbHelper.getInstance(context);
+        mConfig = WatchlistConfig.getInstance();
         mSettings = WatchlistSettings.getInstance();
+        mDropBoxManager = mContext.getSystemService(DropBoxManager.class);
     }
 
     @Override
@@ -162,69 +174,88 @@
     }
 
     private void tryAggregateRecords() {
-        if (shouldReportNetworkWatchlist()) {
-            Slog.i(TAG, "Start aggregating watchlist records.");
-            final DropBoxManager dbox = mContext.getSystemService(DropBoxManager.class);
-            if (dbox != null && !dbox.isTagEnabled(DROPBOX_TAG)) {
-                final WatchlistReportDbHelper.AggregatedResult aggregatedResult =
-                        mDbHelper.getAggregatedRecords();
-                final byte[] encodedResult = encodeAggregatedResult(aggregatedResult);
-                if (encodedResult != null) {
-                    addEncodedReportToDropBox(encodedResult);
-                }
-            }
-            mDbHelper.cleanup();
-            Settings.Global.putLong(mResolver, Settings.Global.NETWORK_WATCHLIST_LAST_REPORT_TIME,
-                    System.currentTimeMillis());
-        } else {
+        // Check if it's necessary to generate watchlist report now.
+        if (!shouldReportNetworkWatchlist()) {
             Slog.i(TAG, "No need to aggregate record yet.");
+            return;
         }
+        Slog.i(TAG, "Start aggregating watchlist records.");
+        if (mDropBoxManager != null && mDropBoxManager.isTagEnabled(DROPBOX_TAG)) {
+            Settings.Global.putLong(mResolver,
+                    Settings.Global.NETWORK_WATCHLIST_LAST_REPORT_TIME,
+                    System.currentTimeMillis());
+            final WatchlistReportDbHelper.AggregatedResult aggregatedResult =
+                    mDbHelper.getAggregatedRecords();
+            // Get all digests for watchlist report, it should include all installed
+            // application digests and previously recorded app digests.
+            final List<String> digestsForReport = getAllDigestsForReport(aggregatedResult);
+            final byte[] secretKey = mSettings.getPrivacySecretKey();
+            final byte[] encodedResult = ReportEncoder.encodeWatchlistReport(mConfig,
+                    secretKey, digestsForReport, aggregatedResult);
+            if (encodedResult != null) {
+                addEncodedReportToDropBox(encodedResult);
+            }
+        }
+        mDbHelper.cleanup();
     }
 
-    private byte[] encodeAggregatedResult(
-            WatchlistReportDbHelper.AggregatedResult aggregatedResult) {
-        // TODO: Encode results using differential privacy.
-        return null;
+    /**
+     * Get all digests for watchlist report.
+     * It should include:
+     * (1) All installed app digests. We need this because we need to ensure after DP we don't know
+     * if an app is really visited C&C site.
+     * (2) App digests that previously recorded in database.
+     */
+    private List<String> getAllDigestsForReport(WatchlistReportDbHelper.AggregatedResult record) {
+        // Step 1: Get all installed application digests.
+        final List<ApplicationInfo> apps = mContext.getPackageManager().getInstalledApplications(
+                PackageManager.MATCH_ANY_USER | PackageManager.MATCH_ALL);
+        final HashSet<String> result = new HashSet<>(apps.size() + record.appDigestCNCList.size());
+        final int size = apps.size();
+        for (int i = 0; i < size; i++) {
+            byte[] digest = getDigestFromUid(apps.get(i).uid);
+            result.add(HexDump.toHexString(digest));
+        }
+        // Step 2: Add all digests from records
+        result.addAll(record.appDigestCNCList.keySet());
+        return new ArrayList<>(result);
     }
 
     private void addEncodedReportToDropBox(byte[] encodedReport) {
-        final DropBoxManager dbox = mContext.getSystemService(DropBoxManager.class);
-        dbox.addData(DROPBOX_TAG, encodedReport, 0);
+        mDropBoxManager.addData(DROPBOX_TAG, encodedReport, 0);
     }
 
     /**
      * Get app digest from app uid.
+     * Return null if system cannot get digest from uid.
      */
+    @Nullable
     private byte[] getDigestFromUid(int uid) {
-        final byte[] cachedDigest = mCachedUidDigestMap.get(uid);
-        if (cachedDigest != null) {
-            return cachedDigest;
-        }
-        final String[] packageNames = mPm.getPackagesForUid(uid);
-        final int userId = UserHandle.getUserId(uid);
-        if (!ArrayUtils.isEmpty(packageNames)) {
-            for (String packageName : packageNames) {
-                try {
-                    final String apkPath = mPm.getPackageInfoAsUser(packageName,
-                            PackageManager.MATCH_DIRECT_BOOT_AWARE
-                                    | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userId)
-                            .applicationInfo.publicSourceDir;
-                    if (TextUtils.isEmpty(apkPath)) {
-                        Slog.w(TAG, "Cannot find apkPath for " + packageName);
-                        continue;
+        return mCachedUidDigestMap.computeIfAbsent(uid, key -> {
+            final String[] packageNames = mPm.getPackagesForUid(key);
+            final int userId = UserHandle.getUserId(uid);
+            if (!ArrayUtils.isEmpty(packageNames)) {
+                for (String packageName : packageNames) {
+                    try {
+                        final String apkPath = mPm.getPackageInfoAsUser(packageName,
+                                PackageManager.MATCH_DIRECT_BOOT_AWARE
+                                        | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userId)
+                                .applicationInfo.publicSourceDir;
+                        if (TextUtils.isEmpty(apkPath)) {
+                            Slog.w(TAG, "Cannot find apkPath for " + packageName);
+                            continue;
+                        }
+                        return DigestUtils.getSha256Hash(new File(apkPath));
+                    } catch (NameNotFoundException | NoSuchAlgorithmException | IOException e) {
+                        Slog.e(TAG, "Should not happen", e);
+                        return null;
                     }
-                    final byte[] digest = DigestUtils.getSha256Hash(new File(apkPath));
-                    mCachedUidDigestMap.put(uid, digest);
-                    return digest;
-                } catch (NameNotFoundException | NoSuchAlgorithmException | IOException e) {
-                    Slog.e(TAG, "Should not happen", e);
-                    return null;
                 }
+            } else {
+                Slog.e(TAG, "Should not happen");
             }
-        } else {
-            Slog.e(TAG, "Should not happen");
-        }
-        return null;
+            return null;
+        });
     }
 
     /**
@@ -247,7 +278,7 @@
         if (ipAddr == null) {
             return false;
         }
-        return mSettings.containsIp(ipAddr);
+        return mConfig.containsIp(ipAddr);
     }
 
     /** Search if the host is in watchlist */
@@ -255,7 +286,7 @@
         if (host == null) {
             return false;
         }
-        return mSettings.containsDomain(host);
+        return mConfig.containsDomain(host);
     }
 
     /**
diff --git a/services/core/java/com/android/server/net/watchlist/WatchlistReportDbHelper.java b/services/core/java/com/android/server/net/watchlist/WatchlistReportDbHelper.java
index 838aa53..9559685 100644
--- a/services/core/java/com/android/server/net/watchlist/WatchlistReportDbHelper.java
+++ b/services/core/java/com/android/server/net/watchlist/WatchlistReportDbHelper.java
@@ -76,13 +76,20 @@
      */
     public static class AggregatedResult {
         // A list of digests that visited c&c domain or ip before.
-        Set<String> appDigestList;
+        final Set<String> appDigestList;
 
         // The c&c domain or ip visited before.
-        String cncDomainVisited;
+        final String cncDomainVisited;
 
         // A list of app digests and c&c domain visited.
-        HashMap<String, String> appDigestCNCList;
+        final HashMap<String, String> appDigestCNCList;
+
+        public AggregatedResult(Set<String> appDigestList, String cncDomainVisited,
+                HashMap<String, String> appDigestCNCList) {
+            this.appDigestList = appDigestList;
+            this.cncDomainVisited = cncDomainVisited;
+            this.appDigestCNCList = appDigestCNCList;
+        }
     }
 
     static File getSystemWatchlistDbFile() {
@@ -151,23 +158,21 @@
             if (c == null || c.getCount() == 0) {
                 return null;
             }
-            final AggregatedResult result = new AggregatedResult();
-            result.cncDomainVisited = null;
-            // After aggregation, each digest maximum will have only 1 record.
-            result.appDigestList = new HashSet<>();
-            result.appDigestCNCList = new HashMap<>();
+            final HashSet<String> appDigestList = new HashSet<>();
+            final HashMap<String, String> appDigestCNCList = new HashMap<>();
+            String cncDomainVisited = null;
             while (c.moveToNext()) {
                 // We use hex string here as byte[] cannot be a key in HashMap.
                 String digestHexStr = HexDump.toHexString(c.getBlob(INDEX_DIGEST));
                 String cncDomain = c.getString(INDEX_CNC_DOMAIN);
 
-                result.appDigestList.add(digestHexStr);
-                if (result.cncDomainVisited != null) {
-                    result.cncDomainVisited = cncDomain;
+                appDigestList.add(digestHexStr);
+                if (cncDomainVisited != null) {
+                    cncDomainVisited = cncDomain;
                 }
-                result.appDigestCNCList.put(digestHexStr, cncDomain);
+                appDigestCNCList.put(digestHexStr, cncDomain);
             }
-            return result;
+            return new AggregatedResult(appDigestList, cncDomainVisited, appDigestCNCList);
         } finally {
             if (c != null) {
                 c.close();
diff --git a/services/core/java/com/android/server/net/watchlist/WatchlistSettings.java b/services/core/java/com/android/server/net/watchlist/WatchlistSettings.java
index 70002ea..b78fe4d 100644
--- a/services/core/java/com/android/server/net/watchlist/WatchlistSettings.java
+++ b/services/core/java/com/android/server/net/watchlist/WatchlistSettings.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright 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.
@@ -22,7 +22,6 @@
 import android.util.Slog;
 import android.util.Xml;
 
-import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.HexDump;
@@ -35,199 +34,126 @@
 import java.io.File;
 import java.io.FileDescriptor;
 import java.io.FileInputStream;
-import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.nio.charset.StandardCharsets;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.zip.CRC32;
 
 /**
- * A util class to do watchlist settings operations, like setting watchlist, query if a domain
- * exists in watchlist.
+ * Class for handling watchlist settings operations, like getting differential privacy secret key.
+ * Unlike WatchlistConfig, which will read configs that pushed from ConfigUpdater only, this class
+ * can read and write all settings for watchlist operations.
  */
 class WatchlistSettings {
+
     private static final String TAG = "WatchlistSettings";
 
-    // Watchlist config that pushed by ConfigUpdater.
-    private static final String NETWORK_WATCHLIST_DB_PATH =
-            "/data/misc/network_watchlist/network_watchlist.xml";
-
-    private static class XmlTags {
-        private static final String WATCHLIST_SETTINGS = "watchlist-settings";
-        private static final String SHA256_DOMAIN = "sha256-domain";
-        private static final String CRC32_DOMAIN = "crc32-domain";
-        private static final String SHA256_IP = "sha256-ip";
-        private static final String CRC32_IP = "crc32-ip";
-        private static final String HASH = "hash";
-    }
-
-    private static class CrcShaDigests {
-        final HarmfulDigests crc32Digests;
-        final HarmfulDigests sha256Digests;
-
-        public CrcShaDigests(HarmfulDigests crc32Digests, HarmfulDigests sha256Digests) {
-            this.crc32Digests = crc32Digests;
-            this.sha256Digests = sha256Digests;
-        }
-    }
+    private static final String FILE_NAME = "watchlist_settings.xml";
+    // Rappor requires min entropy input size = 48 bytes
+    private static final int SECRET_KEY_LENGTH = 48;
 
     private final static WatchlistSettings sInstance = new WatchlistSettings();
     private final AtomicFile mXmlFile;
 
-    private volatile CrcShaDigests mDomainDigests;
-    private volatile CrcShaDigests mIpDigests;
+    private byte[] mPrivacySecretKey = null;
 
     public static WatchlistSettings getInstance() {
         return sInstance;
     }
 
     private WatchlistSettings() {
-        this(new File(NETWORK_WATCHLIST_DB_PATH));
+        this(getSystemWatchlistFile());
+    }
+
+    static File getSystemWatchlistFile() {
+        return new File(Environment.getDataSystemDirectory(), FILE_NAME);
     }
 
     @VisibleForTesting
     protected WatchlistSettings(File xmlFile) {
         mXmlFile = new AtomicFile(xmlFile);
         reloadSettings();
+        if (mPrivacySecretKey == null) {
+            // Generate a new secret key and save settings
+            mPrivacySecretKey = generatePrivacySecretKey();
+            saveSettings();
+        }
     }
 
     public void reloadSettings() {
         try (FileInputStream stream = mXmlFile.openRead()){
-
-            final List<byte[]> crc32DomainList = new ArrayList<>();
-            final List<byte[]> sha256DomainList = new ArrayList<>();
-            final List<byte[]> crc32IpList = new ArrayList<>();
-            final List<byte[]> sha256IpList = new ArrayList<>();
-
             XmlPullParser parser = Xml.newPullParser();
             parser.setInput(stream, StandardCharsets.UTF_8.name());
-            parser.nextTag();
-            parser.require(XmlPullParser.START_TAG, null, XmlTags.WATCHLIST_SETTINGS);
-            while (parser.nextTag() == XmlPullParser.START_TAG) {
-                String tagName = parser.getName();
-                switch (tagName) {
-                    case XmlTags.CRC32_DOMAIN:
-                        parseHash(parser, tagName, crc32DomainList);
-                        break;
-                    case XmlTags.CRC32_IP:
-                        parseHash(parser, tagName, crc32IpList);
-                        break;
-                    case XmlTags.SHA256_DOMAIN:
-                        parseHash(parser, tagName, sha256DomainList);
-                        break;
-                    case XmlTags.SHA256_IP:
-                        parseHash(parser, tagName, sha256IpList);
-                        break;
-                    default:
-                        Log.w(TAG, "Unknown element: " + parser.getName());
-                        XmlUtils.skipCurrentTag(parser);
+            XmlUtils.beginDocument(parser, "network-watchlist-settings");
+            final int outerDepth = parser.getDepth();
+            while (XmlUtils.nextElementWithin(parser, outerDepth)) {
+                if (parser.getName().equals("secret-key")) {
+                    mPrivacySecretKey = parseSecretKey(parser);
                 }
             }
-            parser.require(XmlPullParser.END_TAG, null, XmlTags.WATCHLIST_SETTINGS);
-            writeSettingsToMemory(crc32DomainList, sha256DomainList, crc32IpList, sha256IpList);
-            Log.i(TAG, "Reload watchlist done");
+            Log.i(TAG, "Reload watchlist settings done");
         } catch (IllegalStateException | NullPointerException | NumberFormatException |
                 XmlPullParserException | IOException | IndexOutOfBoundsException e) {
             Slog.e(TAG, "Failed parsing xml", e);
         }
     }
 
-    private void parseHash(XmlPullParser parser, String tagName, List<byte[]> hashSet)
+    private byte[] parseSecretKey(XmlPullParser parser)
             throws IOException, XmlPullParserException {
-        parser.require(XmlPullParser.START_TAG, null, tagName);
-        while (parser.nextTag() == XmlPullParser.START_TAG) {
-            parser.require(XmlPullParser.START_TAG, null, XmlTags.HASH);
-            byte[] hash = HexDump.hexStringToByteArray(parser.nextText());
-            parser.require(XmlPullParser.END_TAG, null, XmlTags.HASH);
-            hashSet.add(hash);
+        parser.require(XmlPullParser.START_TAG, null, "secret-key");
+        byte[] key = HexDump.hexStringToByteArray(parser.nextText());
+        parser.require(XmlPullParser.END_TAG, null, "secret-key");
+        if (key == null || key.length != SECRET_KEY_LENGTH) {
+            Log.e(TAG, "Unable to parse secret key");
+            return null;
         }
-        parser.require(XmlPullParser.END_TAG, null, tagName);
+        return key;
     }
 
     /**
-     * Write network watchlist settings to memory.
+     * Get DP secret key.
+     * Make sure it is not exported or logged in anywhere.
      */
-    public void writeSettingsToMemory(List<byte[]> newCrc32DomainList,
-            List<byte[]> newSha256DomainList,
-            List<byte[]> newCrc32IpList,
-            List<byte[]> newSha256IpList) {
-        mDomainDigests = new CrcShaDigests(new HarmfulDigests(newCrc32DomainList),
-                new HarmfulDigests(newSha256DomainList));
-        mIpDigests = new CrcShaDigests(new HarmfulDigests(newCrc32IpList),
-                new HarmfulDigests(newSha256IpList));
+    synchronized byte[] getPrivacySecretKey() {
+        final byte[] key = new byte[SECRET_KEY_LENGTH];
+        System.arraycopy(mPrivacySecretKey, 0, key, 0, SECRET_KEY_LENGTH);
+        return key;
     }
 
-    public boolean containsDomain(String domain) {
-        final CrcShaDigests domainDigests = mDomainDigests;
-        if (domainDigests == null) {
-            Slog.wtf(TAG, "domainDigests should not be null");
-            return false;
-        }
-        // First it does a quick CRC32 check.
-        final byte[] crc32 = getCrc32(domain);
-        if (!domainDigests.crc32Digests.contains(crc32)) {
-            return false;
-        }
-        // Now we do a slow SHA256 check.
-        final byte[] sha256 = getSha256(domain);
-        return domainDigests.sha256Digests.contains(sha256);
+    private byte[] generatePrivacySecretKey() {
+        final byte[] key = new byte[SECRET_KEY_LENGTH];
+        (new SecureRandom()).nextBytes(key);
+        return key;
     }
 
-    public boolean containsIp(String ip) {
-        final CrcShaDigests ipDigests = mIpDigests;
-        if (ipDigests == null) {
-            Slog.wtf(TAG, "ipDigests should not be null");
-            return false;
-        }
-        // First it does a quick CRC32 check.
-        final byte[] crc32 = getCrc32(ip);
-        if (!ipDigests.crc32Digests.contains(crc32)) {
-            return false;
-        }
-        // Now we do a slow SHA256 check.
-        final byte[] sha256 = getSha256(ip);
-        return ipDigests.sha256Digests.contains(sha256);
-    }
-
-
-    /** Get CRC32 of a string
-     *
-     * TODO: Review if we should use CRC32 or other algorithms
-     */
-    private byte[] getCrc32(String str) {
-        final CRC32 crc = new CRC32();
-        crc.update(str.getBytes());
-        final long tmp = crc.getValue();
-        return new byte[]{(byte) (tmp >> 24 & 255), (byte) (tmp >> 16 & 255),
-                (byte) (tmp >> 8 & 255), (byte) (tmp & 255)};
-    }
-
-    /** Get SHA256 of a string */
-    private byte[] getSha256(String str) {
-        MessageDigest messageDigest;
+    private void saveSettings() {
+        FileOutputStream stream;
         try {
-            messageDigest = MessageDigest.getInstance("SHA256");
-        } catch (NoSuchAlgorithmException e) {
-            /* can't happen */
-            return null;
+            stream = mXmlFile.startWrite();
+        } catch (IOException e) {
+            Log.w(TAG, "Failed to write display settings: " + e);
+            return;
         }
-        messageDigest.update(str.getBytes());
-        return messageDigest.digest();
-    }
-
-    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        pw.println("Domain CRC32 digest list:");
-        mDomainDigests.crc32Digests.dump(fd, pw, args);
-        pw.println("Domain SHA256 digest list:");
-        mDomainDigests.sha256Digests.dump(fd, pw, args);
-        pw.println("Ip CRC32 digest list:");
-        mIpDigests.crc32Digests.dump(fd, pw, args);
-        pw.println("Ip SHA256 digest list:");
-        mIpDigests.sha256Digests.dump(fd, pw, args);
+        try {
+            XmlSerializer out = new FastXmlSerializer();
+            out.setOutput(stream, StandardCharsets.UTF_8.name());
+            out.startDocument(null, true);
+            out.startTag(null, "network-watchlist-settings");
+            out.startTag(null, "secret-key");
+            out.text(HexDump.toHexString(mPrivacySecretKey));
+            out.endTag(null, "secret-key");
+            out.endTag(null, "network-watchlist-settings");
+            out.endDocument();
+            mXmlFile.finishWrite(stream);
+        } catch (IOException e) {
+            Log.w(TAG, "Failed to write display settings, restoring backup.", e);
+            mXmlFile.failWrite(stream);
+        }
     }
 }
diff --git a/services/core/java/com/android/server/notification/NotificationComparator.java b/services/core/java/com/android/server/notification/NotificationComparator.java
index 4c00921..2584187 100644
--- a/services/core/java/com/android/server/notification/NotificationComparator.java
+++ b/services/core/java/com/android/server/notification/NotificationComparator.java
@@ -160,7 +160,7 @@
     }
 
     private boolean isCall(NotificationRecord record) {
-        return record.getNotification().category == Notification.CATEGORY_CALL
+        return record.isCategory(Notification.CATEGORY_CALL)
                 && isDefaultPhoneApp(record.sbn.getPackageName());
     }
 
diff --git a/services/core/java/com/android/server/pm/crossprofile/CrossProfileAppsService.java b/services/core/java/com/android/server/pm/CrossProfileAppsService.java
similarity index 95%
rename from services/core/java/com/android/server/pm/crossprofile/CrossProfileAppsService.java
rename to services/core/java/com/android/server/pm/CrossProfileAppsService.java
index 0913269..027a302 100644
--- a/services/core/java/com/android/server/pm/crossprofile/CrossProfileAppsService.java
+++ b/services/core/java/com/android/server/pm/CrossProfileAppsService.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.server.pm.crossprofile;
+package com.android.server.pm;
 
 import android.content.Context;
 
diff --git a/services/core/java/com/android/server/pm/crossprofile/CrossProfileAppsServiceImpl.java b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
similarity index 98%
rename from services/core/java/com/android/server/pm/crossprofile/CrossProfileAppsServiceImpl.java
rename to services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
index a517d6d..2007a0e 100644
--- a/services/core/java/com/android/server/pm/crossprofile/CrossProfileAppsServiceImpl.java
+++ b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.server.pm.crossprofile;
+package com.android.server.pm;
 
 import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
 import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
@@ -25,14 +25,12 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
+import android.content.pm.ICrossProfileApps;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.ResolveInfo;
-import android.content.pm.crossprofile.ICrossProfileApps;
-import android.graphics.Rect;
 import android.os.Binder;
-import android.os.Bundle;
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.os.UserManager;
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index a43818a..cc448da 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -17,10 +17,12 @@
 package com.android.server.pm;
 
 import static android.content.pm.PackageManager.INSTALL_FAILED_ABORTED;
+import static android.content.pm.PackageManager.INSTALL_FAILED_BAD_DEX_METADATA;
 import static android.content.pm.PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
 import static android.content.pm.PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
 import static android.content.pm.PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
 import static android.content.pm.PackageManager.INSTALL_FAILED_INVALID_APK;
+import static android.content.pm.PackageParser.APK_FILE_EXTENSION;
 import static android.system.OsConstants.O_CREAT;
 import static android.system.OsConstants.O_RDONLY;
 import static android.system.OsConstants.O_WRONLY;
@@ -96,6 +98,7 @@
 import com.android.server.pm.Installer.InstallerException;
 import com.android.server.pm.PackageInstallerService.PackageInstallObserverAdapter;
 
+import android.content.pm.dex.DexMetadataHelper;
 import libcore.io.IoUtils;
 
 import org.xmlpull.v1.XmlPullParser;
@@ -259,6 +262,7 @@
             // entries like "lost+found".
             if (file.isDirectory()) return false;
             if (file.getName().endsWith(REMOVE_SPLIT_MARKER_EXTENSION)) return false;
+            if (DexMetadataHelper.isDexMetadataFile(file)) return false;
             return true;
         }
     };
@@ -939,6 +943,15 @@
                 mInstallerPackageName, mInstallerUid, user, mSigningDetails);
     }
 
+    private static void maybeRenameFile(File from, File to) throws PackageManagerException {
+        if (!from.equals(to)) {
+            if (!from.renameTo(to)) {
+                throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
+                        "Could not rename file " + from + " to " + to);
+            }
+        }
+    }
+
     /**
      * Validate install by confirming that all application packages are have
      * consistent package name, version code, and signing certificates.
@@ -983,6 +996,7 @@
         if (ArrayUtils.isEmpty(addedFiles) && removeSplitList.size() == 0) {
             throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, "No packages staged");
         }
+
         // Verify that all staged packages are internally consistent
         final ArraySet<String> stagedSplits = new ArraySet<>();
         for (File addedFile : addedFiles) {
@@ -1013,9 +1027,9 @@
             // Take this opportunity to enforce uniform naming
             final String targetName;
             if (apk.splitName == null) {
-                targetName = "base.apk";
+                targetName = "base" + APK_FILE_EXTENSION;
             } else {
-                targetName = "split_" + apk.splitName + ".apk";
+                targetName = "split_" + apk.splitName + APK_FILE_EXTENSION;
             }
             if (!FileUtils.isValidExtFilename(targetName)) {
                 throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
@@ -1023,9 +1037,7 @@
             }
 
             final File targetFile = new File(mResolvedStageDir, targetName);
-            if (!addedFile.equals(targetFile)) {
-                addedFile.renameTo(targetFile);
-            }
+            maybeRenameFile(addedFile, targetFile);
 
             // Base is coming from session
             if (apk.splitName == null) {
@@ -1033,6 +1045,18 @@
             }
 
             mResolvedStagedFiles.add(targetFile);
+
+            final File dexMetadataFile = DexMetadataHelper.findDexMetadataForFile(addedFile);
+            if (dexMetadataFile != null) {
+                if (!FileUtils.isValidExtFilename(dexMetadataFile.getName())) {
+                    throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
+                            "Invalid filename: " + dexMetadataFile);
+                }
+                final File targetDexMetadataFile = new File(mResolvedStageDir,
+                        DexMetadataHelper.buildDexMetadataPathForApk(targetName));
+                mResolvedStagedFiles.add(targetDexMetadataFile);
+                maybeRenameFile(dexMetadataFile, targetDexMetadataFile);
+            }
         }
 
         if (removeSplitList.size() > 0) {
@@ -1097,6 +1121,12 @@
             if (mResolvedBaseFile == null) {
                 mResolvedBaseFile = new File(appInfo.getBaseCodePath());
                 mResolvedInheritedFiles.add(mResolvedBaseFile);
+                // Inherit the dex metadata if present.
+                final File baseDexMetadataFile =
+                        DexMetadataHelper.findDexMetadataForFile(mResolvedBaseFile);
+                if (baseDexMetadataFile != null) {
+                    mResolvedInheritedFiles.add(baseDexMetadataFile);
+                }
             }
 
             // Inherit splits if not overridden
@@ -1107,6 +1137,12 @@
                     final boolean splitRemoved = removeSplitList.contains(splitName);
                     if (!stagedSplits.contains(splitName) && !splitRemoved) {
                         mResolvedInheritedFiles.add(splitFile);
+                        // Inherit the dex metadata if present.
+                        final File splitDexMetadataFile =
+                                DexMetadataHelper.findDexMetadataForFile(splitFile);
+                        if (splitDexMetadataFile != null) {
+                            mResolvedInheritedFiles.add(splitDexMetadataFile);
+                        }
                     }
                 }
             }
@@ -1163,43 +1199,6 @@
     }
 
     /**
-     * Calculate the final install footprint size, combining both staged and
-     * existing APKs together and including unpacked native code from both.
-     */
-    private long calculateInstalledSize() throws PackageManagerException {
-        Preconditions.checkNotNull(mResolvedBaseFile);
-
-        final ApkLite baseApk;
-        try {
-            baseApk = PackageParser.parseApkLite(mResolvedBaseFile, 0);
-        } catch (PackageParserException e) {
-            throw PackageManagerException.from(e);
-        }
-
-        final List<String> splitPaths = new ArrayList<>();
-        for (File file : mResolvedStagedFiles) {
-            if (mResolvedBaseFile.equals(file)) continue;
-            splitPaths.add(file.getAbsolutePath());
-        }
-        for (File file : mResolvedInheritedFiles) {
-            if (mResolvedBaseFile.equals(file)) continue;
-            splitPaths.add(file.getAbsolutePath());
-        }
-
-        // This is kind of hacky; we're creating a half-parsed package that is
-        // straddled between the inherited and staged APKs.
-        final PackageLite pkg = new PackageLite(null, baseApk, null, null, null, null,
-                splitPaths.toArray(new String[splitPaths.size()]), null);
-
-        try {
-            return PackageHelper.calculateInstalledSize(pkg, params.abiOverride);
-        } catch (IOException e) {
-            throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
-                    "Failed to calculate install size", e);
-        }
-    }
-
-    /**
      * Determine if creating hard links between source and destination is
      * possible. That is, do they all live on the same underlying device.
      */
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 711ea13..2585cf3 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -191,6 +191,7 @@
 import android.content.pm.VerifierDeviceIdentity;
 import android.content.pm.VerifierInfo;
 import android.content.pm.VersionedPackage;
+import android.content.pm.dex.DexMetadataHelper;
 import android.content.pm.dex.IArtManager;
 import android.content.res.Resources;
 import android.database.ContentObserver;
@@ -16486,6 +16487,7 @@
         final PackageParser.Package pkg;
         try {
             pkg = pp.parsePackage(tmpPackageFile, parseFlags);
+            DexMetadataHelper.validatePackageDexMetadata(pkg);
         } catch (PackageParserException e) {
             res.setError("Failed parse during installPackageLI", e);
             return;
@@ -18898,6 +18900,14 @@
         return Build.VERSION_CODES.CUR_DEVELOPMENT;
     }
 
+    private int getPackageTargetSdkVersionLockedLPr(String packageName) {
+        final PackageParser.Package p = mPackages.get(packageName);
+        if (p != null) {
+            return p.applicationInfo.targetSdkVersion;
+        }
+        return Build.VERSION_CODES.CUR_DEVELOPMENT;
+    }
+
     @Override
     public void addPreferredActivity(IntentFilter filter, int match,
             ComponentName[] set, ComponentName activity, int userId) {
@@ -23417,6 +23427,13 @@
         }
 
         @Override
+        public int getPackageTargetSdkVersion(String packageName) {
+            synchronized (mPackages) {
+                return getPackageTargetSdkVersionLockedLPr(packageName);
+            }
+        }
+
+        @Override
         public boolean canAccessInstantApps(int callingUid, int userId) {
             return PackageManagerService.this.canViewInstantApps(callingUid, userId);
         }
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 11b8041..a33f071 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -47,6 +47,7 @@
 import android.content.pm.ResolveInfo;
 import android.content.pm.UserInfo;
 import android.content.pm.VersionedPackage;
+import android.content.pm.dex.DexMetadataHelper;
 import android.content.res.AssetManager;
 import android.content.res.Resources;
 import android.net.Uri;
@@ -80,7 +81,6 @@
 
 import libcore.io.IoUtils;
 
-import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -2258,6 +2258,14 @@
             session = new PackageInstaller.Session(
                     mInterface.getPackageInstaller().openSession(sessionId));
 
+            // Sanity check that all .dm files match an apk.
+            // (The installer does not support standalone .dm files and will not process them.)
+            try {
+                DexMetadataHelper.validateDexPaths(session.getNames());
+            } catch (IllegalStateException | IOException e) {
+                pw.println("Warning [Could not validate the dex paths: " + e.getMessage() + "]");
+            }
+
             final LocalIntentReceiver receiver = new LocalIntentReceiver();
             session.commit(receiver.getIntentSender());
 
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 88e4270..6344997 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -850,7 +850,7 @@
                     dispatchMediaKeyRepeatWithWakeLock((KeyEvent)msg.obj);
                     break;
                 case MSG_DISPATCH_SHOW_RECENTS:
-                    showRecentApps(false, msg.arg1 != 0);
+                    showRecentApps(false);
                     break;
                 case MSG_DISPATCH_SHOW_GLOBAL_ACTIONS:
                     showGlobalActionsInternal();
@@ -3817,7 +3817,7 @@
                 final int shiftlessModifiers = event.getModifiers() & ~KeyEvent.META_SHIFT_MASK;
                 if (KeyEvent.metaStateHasModifiers(shiftlessModifiers, KeyEvent.META_ALT_ON)) {
                     mRecentAppsHeldModifiers = shiftlessModifiers;
-                    showRecentApps(true, false);
+                    showRecentApps(true);
                     return -1;
                 }
             }
@@ -4164,16 +4164,16 @@
     }
 
     @Override
-    public void showRecentApps(boolean fromHome) {
+    public void showRecentApps() {
         mHandler.removeMessages(MSG_DISPATCH_SHOW_RECENTS);
-        mHandler.obtainMessage(MSG_DISPATCH_SHOW_RECENTS, fromHome ? 1 : 0, 0).sendToTarget();
+        mHandler.obtainMessage(MSG_DISPATCH_SHOW_RECENTS).sendToTarget();
     }
 
-    private void showRecentApps(boolean triggeredFromAltTab, boolean fromHome) {
+    private void showRecentApps(boolean triggeredFromAltTab) {
         mPreloadedRecentApps = false; // preloading no longer needs to be canceled
         StatusBarManagerInternal statusbar = getStatusBarManagerInternal();
         if (statusbar != null) {
-            statusbar.showRecentApps(triggeredFromAltTab, fromHome);
+            statusbar.showRecentApps(triggeredFromAltTab);
         }
     }
 
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index c05dd2a..e9c4c5c 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -1571,7 +1571,7 @@
      * Show the recents task list app.
      * @hide
      */
-    public void showRecentApps(boolean fromHome);
+    public void showRecentApps();
 
     /**
      * Show the global actions dialog.
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
index 3792bc6..b5d0c60 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
@@ -30,7 +30,7 @@
 
     void cancelPreloadRecentApps();
 
-    void showRecentApps(boolean triggeredFromAltTab, boolean fromHome);
+    void showRecentApps(boolean triggeredFromAltTab);
 
     void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey);
 
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index c7c03b4..79d3dbb 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -282,10 +282,10 @@
         }
 
         @Override
-        public void showRecentApps(boolean triggeredFromAltTab, boolean fromHome) {
+        public void showRecentApps(boolean triggeredFromAltTab) {
             if (mBar != null) {
                 try {
-                    mBar.showRecentApps(triggeredFromAltTab, fromHome);
+                    mBar.showRecentApps(triggeredFromAltTab);
                 } catch (RemoteException ex) {}
             }
         }
diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java
index de723c6..d84fbc5 100644
--- a/services/core/java/com/android/server/vr/VrManagerService.java
+++ b/services/core/java/com/android/server/vr/VrManagerService.java
@@ -185,6 +185,14 @@
             ComponentName component = null;
             synchronized (mLock) {
                 component = ((mCurrentVrService == null) ? null : mCurrentVrService.getComponent());
+
+                // If the VrCore main service was disconnected or the binding died we'll rebind
+                // automatically. Call focusedActivityChanged() once we rebind.
+                if (component != null && component.equals(event.component) &&
+                        (event.event == LogEvent.EVENT_DISCONNECTED ||
+                         event.event == LogEvent.EVENT_BINDING_DIED)) {
+                    callFocusedActivityChangedLocked();
+                }
             }
 
             // If not on an AIO device and we permanently stopped trying to connect to the
@@ -980,16 +988,7 @@
                     oldVrServicePackage, oldUserId);
 
             if (mCurrentVrService != null && sendUpdatedCaller) {
-                final ComponentName c = mCurrentVrModeComponent;
-                final boolean b = running2dInVr;
-                final int pid = processId;
-                mCurrentVrService.sendEvent(new PendingEvent() {
-                    @Override
-                    public void runEvent(IInterface service) throws RemoteException {
-                        IVrListener l = (IVrListener) service;
-                        l.focusedActivityChanged(c, b, pid);
-                    }
-                });
+                callFocusedActivityChangedLocked();
             }
 
             if (!nothingChanged) {
@@ -1002,6 +1001,23 @@
         }
     }
 
+    private void callFocusedActivityChangedLocked() {
+        final ComponentName c = mCurrentVrModeComponent;
+        final boolean b = mRunning2dInVr;
+        final int pid = mVrAppProcessId;
+        mCurrentVrService.sendEvent(new PendingEvent() {
+            @Override
+            public void runEvent(IInterface service) throws RemoteException {
+                // Under specific (and unlikely) timing scenarios, when VrCore
+                // crashes and is rebound, focusedActivityChanged() may be
+                // called a 2nd time with the same arguments. IVrListeners
+                // should make sure to handle that scenario gracefully.
+                IVrListener l = (IVrListener) service;
+                l.focusedActivityChanged(c, b, pid);
+            }
+        });
+    }
+
     private boolean isDefaultAllowed(String packageName) {
         PackageManager pm = mContext.getPackageManager();
 
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 261065f..b474c62 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -517,15 +517,25 @@
     }
 
     WindowState findMainWindow() {
+        return findMainWindow(true);
+    }
+
+    /**
+     * Finds the main window that either has type base application or application starting if
+     * requested.
+     *
+     * @param includeStartingApp Allow to search application-starting windows to also be returned.
+     * @return The main window of type base application or application starting if requested.
+     */
+    WindowState findMainWindow(boolean includeStartingApp) {
         WindowState candidate = null;
-        int j = mChildren.size();
-        while (j > 0) {
-            j--;
+        for (int j = mChildren.size() - 1; j >= 0; --j) {
             final WindowState win = mChildren.get(j);
             final int type = win.mAttrs.type;
             // No need to loop through child window as base application and starting types can't be
             // child windows.
-            if (type == TYPE_BASE_APPLICATION || type == TYPE_APPLICATION_STARTING) {
+            if (type == TYPE_BASE_APPLICATION
+                    || (includeStartingApp && type == TYPE_APPLICATION_STARTING)) {
                 // In cases where there are multiple windows, we prefer the non-exiting window. This
                 // happens for example when replacing windows during an activity relaunch. When
                 // constructing the animation, we want the new window, not the exiting one.
@@ -1373,8 +1383,11 @@
 
         if (mLastTransactionSequence != mService.mTransactionSequence) {
             mLastTransactionSequence = mService.mTransactionSequence;
-            mNumInterestingWindows = mNumDrawnWindows = 0;
+            mNumDrawnWindows = 0;
             startingDisplayed = false;
+
+            // There is the main base application window, even if it is exiting, wait for it
+            mNumInterestingWindows = findMainWindow(false /* includeStartingApp */) != null ? 1 : 0;
         }
 
         final WindowStateAnimator winAnimator = w.mWinAnimator;
@@ -1396,7 +1409,10 @@
 
             if (w != startingWindow) {
                 if (w.isInteresting()) {
-                    mNumInterestingWindows++;
+                    // Add non-main window as interesting since the main app has already been added
+                    if (findMainWindow(false /* includeStartingApp */) != w) {
+                        mNumInterestingWindows++;
+                    }
                     if (w.isDrawnLw()) {
                         mNumDrawnWindows++;
 
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index ef48661..6dc384a 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -49,6 +49,7 @@
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
 import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
+import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
 import static android.view.WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION;
 import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
@@ -134,6 +135,7 @@
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.os.Trace;
+import android.util.ArraySet;
 import android.util.DisplayMetrics;
 import android.util.MutableBoolean;
 import android.util.Slog;
@@ -330,6 +332,8 @@
     final PinnedStackController mPinnedStackControllerLocked;
 
     final ArrayList<WindowState> mTapExcludedWindows = new ArrayList<>();
+    /** A collection of windows that provide tap exclude regions inside of them. */
+    final ArraySet<WindowState> mTapExcludeProvidingWindows = new ArraySet<>();
 
     private boolean mHaveBootMsg = false;
     private boolean mHaveApp = false;
@@ -1866,10 +1870,14 @@
             }
         }
         for (int i = mTapExcludedWindows.size() - 1; i >= 0; i--) {
-            WindowState win = mTapExcludedWindows.get(i);
+            final WindowState win = mTapExcludedWindows.get(i);
             win.getTouchableRegion(mTmpRegion);
             mTouchExcludeRegion.op(mTmpRegion, Region.Op.UNION);
         }
+        for (int i = mTapExcludeProvidingWindows.size() - 1; i >= 0; i--) {
+            final WindowState win = mTapExcludeProvidingWindows.valueAt(i);
+            win.amendTapExcludeRegion(mTouchExcludeRegion);
+        }
         // TODO(multi-display): Support docked stacks on secondary displays.
         if (mDisplayId == DEFAULT_DISPLAY && getSplitScreenPrimaryStack() != null) {
             mDividerControllerLocked.getTouchRegion(mTmpRect);
@@ -3173,6 +3181,21 @@
          */
         SurfaceControl mAppAnimationLayer = null;
 
+        /**
+         * Given that the split-screen divider does not have an AppWindowToken, it
+         * will have to live inside of a "NonAppWindowContainer", in particular
+         * {@link DisplayContent#mAboveAppWindowsContainers}. However, in visual Z order
+         * it will need to be interleaved with some of our children, appearing on top of
+         * both docked stacks but underneath any assistant stacks.
+         *
+         * To solve this problem we have this anchor control, which will always exist so
+         * we can always assign it the correct value in our {@link #assignChildLayers}.
+         * Likewise since it always exists, {@link AboveAppWindowContainers} can always
+         * assign the divider a layer relative to it. This way we prevent linking lifecycle
+         * events between the two containers.
+         */
+        SurfaceControl mSplitScreenDividerAnchor = null;
+
         // Cached reference to some special stacks we tend to get a lot so we don't need to loop
         // through the list to find them.
         private TaskStack mHomeStack = null;
@@ -3489,37 +3512,39 @@
 
         @Override
         void assignChildLayers(SurfaceControl.Transaction t) {
+
+            final int HOME_STACK_STATE = 0;
+            final int NORMAL_STACK_STATE = 1;
+            final int ALWAYS_ON_TOP_STATE = 2;
+
             int layer = 0;
-
-            // We allow stacks to change visual order from the AM specified order due to
-            // Z-boosting during animations. However we must take care to ensure TaskStacks
-            // which are marked as alwaysOnTop remain that way.
-            for (int i = 0; i < mChildren.size(); i++) {
-                final TaskStack s = mChildren.get(i);
-                s.assignChildLayers();
-                if (!s.needsZBoost() && !s.isAlwaysOnTop()) {
-                    s.assignLayer(t, layer++);
+            for (int state = 0; state <= ALWAYS_ON_TOP_STATE; state++) {
+                for (int i = 0; i < mChildren.size(); i++) {
+                    final TaskStack s = mChildren.get(i);
+                    if (state == HOME_STACK_STATE && s.isActivityTypeHome()) {
+                        s.assignLayer(t, layer++);
+                    } else if (state == NORMAL_STACK_STATE && !s.isActivityTypeHome()
+                            && !s.isAlwaysOnTop()) {
+                        s.assignLayer(t, layer++);
+                        if (s.inSplitScreenWindowingMode() && mSplitScreenDividerAnchor != null) {
+                            t.setLayer(mSplitScreenDividerAnchor, layer++);
+                        }
+                    } else if (state == ALWAYS_ON_TOP_STATE && s.isAlwaysOnTop()) {
+                        s.assignLayer(t, layer++);
+                    }
+                }
+                // The appropriate place for App-Transitions to occur is right
+                // above all other animations but still below things in the Picture-and-Picture
+                // windowing mode.
+                if (state == NORMAL_STACK_STATE && mAppAnimationLayer != null) {
+                    t.setLayer(mAppAnimationLayer, layer++);
                 }
             }
             for (int i = 0; i < mChildren.size(); i++) {
                 final TaskStack s = mChildren.get(i);
-                if (s.needsZBoost() && !s.isAlwaysOnTop()) {
-                    s.assignLayer(t, layer++);
-                }
-            }
-            for (int i = 0; i < mChildren.size(); i++) {
-                final TaskStack s = mChildren.get(i);
-                if (s.isAlwaysOnTop()) {
-                    s.assignLayer(t, layer++);
-                }
+                s.assignChildLayers(t);
             }
 
-            // The appropriate place for App-Transitions to occur is right
-            // above all other animations but still below things in the Picture-and-Picture
-            // windowing mode.
-            if (mAppAnimationLayer != null) {
-                t.setLayer(mAppAnimationLayer, layer++);
-            }
         }
 
         @Override
@@ -3527,6 +3552,10 @@
             return mAppAnimationLayer;
         }
 
+        SurfaceControl getSplitScreenDividerAnchor() {
+            return mSplitScreenDividerAnchor;
+        }
+
         @Override
         void onParentSet() {
             super.onParentSet();
@@ -3534,11 +3563,18 @@
                 mAppAnimationLayer = makeChildSurface(null)
                         .setName("animationLayer")
                         .build();
-                getPendingTransaction().show(mAppAnimationLayer);
+                mSplitScreenDividerAnchor = makeChildSurface(null)
+                        .setName("splitScreenDividerAnchor")
+                        .build();
+                getPendingTransaction()
+                        .show(mAppAnimationLayer)
+                        .show(mSplitScreenDividerAnchor);
                 scheduleAnimation();
             } else {
                 mAppAnimationLayer.destroy();
                 mAppAnimationLayer = null;
+                mSplitScreenDividerAnchor.destroy();
+                mSplitScreenDividerAnchor = null;
             }
         }
     }
@@ -3553,6 +3589,12 @@
                     && imeContainer.getSurfaceControl() != null;
             for (int j = 0; j < mChildren.size(); ++j) {
                 final WindowToken wt = mChildren.get(j);
+
+                // See {@link mSplitScreenDividerAnchor}
+                if (wt.windowType == TYPE_DOCK_DIVIDER) {
+                    wt.assignRelativeLayer(t, mTaskStackContainers.getSplitScreenDividerAnchor(), 1);
+                    continue;
+                }
                 wt.assignLayer(t, j);
                 wt.assignChildLayers(t);
 
@@ -3690,6 +3732,13 @@
             .setParent(mOverlayLayer);
     }
 
+    /**
+     * Reparents the given surface to mOverlayLayer.
+     */
+    void reparentToOverlay(Transaction transaction, SurfaceControl surface) {
+        transaction.reparent(surface, mOverlayLayer.getHandle());
+    }
+
     void applyMagnificationSpec(MagnificationSpec spec) {
         applyMagnificationSpec(getPendingTransaction(), spec);
         getPendingTransaction().apply();
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index 0cf8d2f..7ae1f24 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -454,8 +454,11 @@
                 inputMethodManagerInternal.hideCurrentInputMethod();
                 mImeHideRequested = true;
             }
+
+            // If a primary stack was just created, it will not have access to display content at
+            // this point so pass it from here to get a valid dock side.
             final TaskStack stack = mDisplayContent.getSplitScreenPrimaryStackIgnoringVisibility();
-            mOriginalDockedSide = stack.getDockSide();
+            mOriginalDockedSide = stack.getDockSideForDisplay(mDisplayContent);
             return;
         }
         mOriginalDockedSide = DOCKED_INVALID;
@@ -604,7 +607,7 @@
         if (wasMinimized && mMinimizedDock && containsAppInDockedStack(openingApps)
                 && appTransition != TRANSIT_NONE &&
                 !AppTransition.isKeyguardGoingAwayTransit(appTransition)) {
-            mService.showRecentApps(true /* fromHome */);
+            mService.showRecentApps();
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/DragDropController.java b/services/core/java/com/android/server/wm/DragDropController.java
index 0171b56..d55a649 100644
--- a/services/core/java/com/android/server/wm/DragDropController.java
+++ b/services/core/java/com/android/server/wm/DragDropController.java
@@ -18,12 +18,10 @@
 
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DRAG;
 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
-import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 
 import android.annotation.NonNull;
 import android.content.ClipData;
-import android.graphics.PixelFormat;
 import android.os.Binder;
 import android.os.Handler;
 import android.os.IBinder;
@@ -32,8 +30,8 @@
 import android.util.Slog;
 import android.view.Display;
 import android.view.IWindow;
-import android.view.Surface;
 import android.view.SurfaceControl;
+import android.view.SurfaceControl.Transaction;
 import android.view.SurfaceSession;
 import android.view.View;
 
@@ -50,10 +48,9 @@
     private static final long DRAG_TIMEOUT_MS = 5000;
 
     // Messages for Handler.
-    private static final int MSG_DRAG_START_TIMEOUT = 0;
-    static final int MSG_DRAG_END_TIMEOUT = 1;
-    static final int MSG_TEAR_DOWN_DRAG_AND_DROP_INPUT = 2;
-    static final int MSG_ANIMATION_END = 3;
+    static final int MSG_DRAG_END_TIMEOUT = 0;
+    static final int MSG_TEAR_DOWN_DRAG_AND_DROP_INPUT = 1;
+    static final int MSG_ANIMATION_END = 2;
 
     /**
      * Drag state per operation.
@@ -95,87 +92,35 @@
         mDragState.sendDragStartedIfNeededLocked(window);
     }
 
-    IBinder prepareDrag(SurfaceSession session, int callerPid,
-            int callerUid, IWindow window, int flags, int width, int height, Surface outSurface) {
+    IBinder performDrag(SurfaceSession session, int callerPid, int callerUid, IWindow window,
+            int flags, SurfaceControl surface, int touchSource, float touchX, float touchY,
+            float thumbCenterX, float thumbCenterY, ClipData data) {
         if (DEBUG_DRAG) {
-            Slog.d(TAG_WM, "prepare drag surface: w=" + width + " h=" + height
-                    + " flags=" + Integer.toHexString(flags) + " win=" + window
-                    + " asbinder=" + window.asBinder());
+            Slog.d(TAG_WM, "perform drag: win=" + window + " surface=" + surface + " flags=" +
+                            Integer.toHexString(flags) + " data=" + data);
         }
 
-        if (width <= 0 || height <= 0) {
-            Slog.w(TAG_WM, "width and height of drag shadow must be positive");
-            return null;
-        }
-
-        synchronized (mService.mWindowMap) {
-            if (dragDropActiveLocked()) {
-                Slog.w(TAG_WM, "Drag already in progress");
-                return null;
-            }
-
-            // TODO(multi-display): support other displays
-            final DisplayContent displayContent =
-                    mService.getDefaultDisplayContentLocked();
-            final Display display = displayContent.getDisplay();
-
-            final SurfaceControl surface = new SurfaceControl.Builder(session)
-                    .setName("drag surface")
-                    .setSize(width, height)
-                    .setFormat(PixelFormat.TRANSLUCENT)
-                    .build();
-            surface.setLayerStack(display.getLayerStack());
-            float alpha = 1;
-            if ((flags & View.DRAG_FLAG_OPAQUE) == 0) {
-                alpha = DRAG_SHADOW_ALPHA_TRANSPARENT;
-            }
-            surface.setAlpha(alpha);
-
-            if (SHOW_TRANSACTIONS)
-                Slog.i(TAG_WM, "  DRAG " + surface + ": CREATE");
-            outSurface.copyFrom(surface);
-            final IBinder winBinder = window.asBinder();
-            IBinder token = new Binder();
-            mDragState = new DragState(mService, this, token, surface, flags, winBinder);
-            mDragState.mPid = callerPid;
-            mDragState.mUid = callerUid;
-            mDragState.mOriginalAlpha = alpha;
-            token = mDragState.mToken = new Binder();
-
-            // 5 second timeout for this window to actually begin the drag
-            sendTimeoutMessage(MSG_DRAG_START_TIMEOUT, winBinder);
-            return token;
-        }
-    }
-
-    boolean performDrag(IWindow window, IBinder dragToken,
-            int touchSource, float touchX, float touchY, float thumbCenterX, float thumbCenterY,
-            ClipData data) {
-        if (DEBUG_DRAG) {
-            Slog.d(TAG_WM, "perform drag: win=" + window + " data=" + data);
-        }
-
+        final IBinder dragToken = new Binder();
         final boolean callbackResult = mCallback.get().prePerformDrag(window, dragToken,
                 touchSource, touchX, touchY, thumbCenterX, thumbCenterY, data);
         try {
             synchronized (mService.mWindowMap) {
-                mHandler.removeMessages(MSG_DRAG_START_TIMEOUT, window.asBinder());
                 try {
                     if (!callbackResult) {
-                        return false;
+                        Slog.w(TAG_WM, "IDragDropCallback rejects the performDrag request");
+                        return null;
                     }
 
-                    Preconditions.checkState(
-                            mDragState != null, "performDrag() without prepareDrag()");
-                    Preconditions.checkState(
-                            mDragState.mToken == dragToken,
-                            "performDrag() does not match prepareDrag()");
+                    if (dragDropActiveLocked()) {
+                        Slog.w(TAG_WM, "Drag already in progress");
+                        return null;
+                    }
 
                     final WindowState callingWin = mService.windowForClientLocked(
                             null, window, false);
                     if (callingWin == null) {
                         Slog.w(TAG_WM, "Bad requesting window " + window);
-                        return false;  // !!! TODO: throw here?
+                        return null;  // !!! TODO: throw here?
                     }
 
                     // !!! TODO: if input is not still focused on the initiating window, fail
@@ -188,18 +133,31 @@
                     // !!! FIXME: put all this heavy stuff onto the mHandler looper, as well as
                     // the actual drag event dispatch stuff in the dragstate
 
+                    // !!! TODO(multi-display): support other displays
+
                     final DisplayContent displayContent = callingWin.getDisplayContent();
                     if (displayContent == null) {
                         Slog.w(TAG_WM, "display content is null");
-                        return false;
+                        return null;
                     }
 
+                    final float alpha = (flags & View.DRAG_FLAG_OPAQUE) == 0 ?
+                            DRAG_SHADOW_ALPHA_TRANSPARENT : 1;
+                    final IBinder winBinder = window.asBinder();
+                    IBinder token = new Binder();
+                    mDragState = new DragState(mService, this, token, surface, flags, winBinder);
+                    surface = null;
+                    mDragState.mPid = callerPid;
+                    mDragState.mUid = callerUid;
+                    mDragState.mOriginalAlpha = alpha;
+                    mDragState.mToken = dragToken;
+
                     final Display display = displayContent.getDisplay();
                     mDragState.register(display);
                     if (!mService.mInputManager.transferTouchFocus(callingWin.mInputChannel,
                             mDragState.getInputChannel())) {
                         Slog.e(TAG_WM, "Unable to transfer touch focus");
-                        return false;
+                        return null;
                     }
 
                     mDragState.mDisplayContent = displayContent;
@@ -213,28 +171,31 @@
                     // Make the surface visible at the proper location
                     final SurfaceControl surfaceControl = mDragState.mSurfaceControl;
                     if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM, ">>> OPEN TRANSACTION performDrag");
-                    mService.openSurfaceTransaction();
-                    try {
-                        surfaceControl.setPosition(touchX - thumbCenterX,
-                                touchY - thumbCenterY);
-                        surfaceControl.setLayer(mDragState.getDragLayerLocked());
-                        surfaceControl.setLayerStack(display.getLayerStack());
-                        surfaceControl.show();
-                    } finally {
-                        mService.closeSurfaceTransaction("performDrag");
-                        if (SHOW_LIGHT_TRANSACTIONS) {
-                            Slog.i(TAG_WM, "<<< CLOSE TRANSACTION performDrag");
-                        }
+
+                    final SurfaceControl.Transaction transaction =
+                            callingWin.getPendingTransaction();
+                    transaction.setAlpha(surfaceControl, mDragState.mOriginalAlpha);
+                    transaction.setPosition(
+                            surfaceControl, touchX - thumbCenterX, touchY - thumbCenterY);
+                    transaction.show(surfaceControl);
+                    displayContent.reparentToOverlay(transaction, surfaceControl);
+                    callingWin.scheduleAnimation();
+
+                    if (SHOW_LIGHT_TRANSACTIONS) {
+                        Slog.i(TAG_WM, "<<< CLOSE TRANSACTION performDrag");
                     }
 
                     mDragState.notifyLocationLocked(touchX, touchY);
                 } finally {
+                    if (surface != null) {
+                        surface.release();
+                    }
                     if (mDragState != null && !mDragState.isInProgress()) {
                         mDragState.closeLocked();
                     }
                 }
             }
-            return true;    // success!
+            return dragToken;    // success!
         } finally {
             mCallback.get().postPerformDrag();
         }
@@ -385,21 +346,6 @@
         @Override
         public void handleMessage(Message msg) {
             switch (msg.what) {
-                case MSG_DRAG_START_TIMEOUT: {
-                    IBinder win = (IBinder) msg.obj;
-                    if (DEBUG_DRAG) {
-                        Slog.w(TAG_WM, "Timeout starting drag by win " + win);
-                    }
-
-                    synchronized (mService.mWindowMap) {
-                        // !!! TODO: ANR the app that has failed to start the drag in time
-                        if (mDragState != null) {
-                            mDragState.closeLocked();
-                        }
-                    }
-                    break;
-                }
-
                 case MSG_DRAG_END_TIMEOUT: {
                     final IBinder win = (IBinder) msg.obj;
                     if (DEBUG_DRAG) {
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 192d6c8..04ae38e 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -51,6 +51,7 @@
 import android.view.IWindowSessionCallback;
 import android.view.InputChannel;
 import android.view.Surface;
+import android.view.SurfaceControl;
 import android.view.SurfaceSession;
 import android.view.WindowManager;
 
@@ -308,30 +309,22 @@
     }
 
     /* Drag/drop */
+
     @Override
-    public IBinder prepareDrag(IWindow window, int flags, int width, int height,
-            Surface outSurface) {
+    public IBinder performDrag(IWindow window, int flags, SurfaceControl surface, int touchSource,
+            float touchX, float touchY, float thumbCenterX, float thumbCenterY, ClipData data) {
         final int callerPid = Binder.getCallingPid();
         final int callerUid = Binder.getCallingUid();
         final long ident = Binder.clearCallingIdentity();
         try {
-            return mDragDropController.prepareDrag(
-                    mSurfaceSession, callerPid, callerUid, window, flags, width, height,
-                    outSurface);
+            return mDragDropController.performDrag(mSurfaceSession, callerPid, callerUid, window,
+                    flags, surface, touchSource, touchX, touchY, thumbCenterX, thumbCenterY, data);
         } finally {
             Binder.restoreCallingIdentity(ident);
         }
     }
 
     @Override
-    public boolean performDrag(IWindow window, IBinder dragToken,
-            int touchSource, float touchX, float touchY, float thumbCenterX, float thumbCenterY,
-            ClipData data) {
-        return mDragDropController.performDrag(window, dragToken, touchSource,
-                touchX, touchY, thumbCenterX, thumbCenterY, data);
-    }
-
-    @Override
     public void reportDropResult(IWindow window, boolean consumed) {
         final long ident = Binder.clearCallingIdentity();
         try {
@@ -467,6 +460,17 @@
         }
     }
 
+    @Override
+    public void updateTapExcludeRegion(IWindow window, int regionId, int left, int top, int width,
+            int height) {
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            mService.updateTapExcludeRegion(window, regionId, left, top, width, height);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
     void windowAddedLocked(String packageName) {
         mPackageName = packageName;
         mRelayoutTag = "relayoutWindow: " + mPackageName;
diff --git a/services/core/java/com/android/server/wm/TapExcludeRegionHolder.java b/services/core/java/com/android/server/wm/TapExcludeRegionHolder.java
new file mode 100644
index 0000000..cbc936f
--- /dev/null
+++ b/services/core/java/com/android/server/wm/TapExcludeRegionHolder.java
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+package com.android.server.wm;
+
+import android.graphics.Rect;
+import android.graphics.Region;
+import android.util.SparseArray;
+
+/**
+ * A holder that contains a collection of rectangular areas identified by int id. Each individual
+ * region can be updated separately.
+ */
+class TapExcludeRegionHolder {
+    private SparseArray<Rect> mTapExcludeRects = new SparseArray<>();
+
+    /** Update the specified region with provided position and size. */
+    void updateRegion(int regionId, int left, int top, int width, int height) {
+        if (width <= 0 || height <= 0) {
+            // A region became empty - remove it.
+            mTapExcludeRects.remove(regionId);
+            return;
+        }
+
+        Rect region = mTapExcludeRects.get(regionId);
+        if (region == null) {
+            region = new Rect();
+        }
+        region.set(left, top, left + width, top + height);
+        mTapExcludeRects.put(regionId, region);
+    }
+
+    /**
+     * Union the provided region with current region formed by this container.
+     */
+    void amendRegion(Region region, Rect boundingRegion) {
+        for (int i = mTapExcludeRects.size() - 1; i>= 0 ; --i) {
+            final Rect rect = mTapExcludeRects.valueAt(i);
+            rect.intersect(boundingRegion);
+            region.union(rect);
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java
index fa7ea2f..26c87b7 100644
--- a/services/core/java/com/android/server/wm/TaskPositioner.java
+++ b/services/core/java/com/android/server/wm/TaskPositioner.java
@@ -59,6 +59,8 @@
     private static final String TAG_LOCAL = "TaskPositioner";
     private static final String TAG = TAG_WITH_CLASS_NAME ? TAG_LOCAL : TAG_WM;
 
+    private static Factory sFactory;
+
     // The margin the pointer position has to be within the side of the screen to be
     // considered at the side of the screen.
     static final int SIDE_MARGIN_DIP = 100;
@@ -214,6 +216,7 @@
         }
     }
 
+    /** Use {@link #create(WindowManagerService)} instead **/
     TaskPositioner(WindowManagerService service) {
         mService = service;
     }
@@ -622,4 +625,22 @@
     public String toShortString() {
         return TAG;
     }
+
+    static void setFactory(Factory factory) {
+        sFactory = factory;
+    }
+
+    static TaskPositioner create(WindowManagerService service) {
+        if (sFactory == null) {
+            sFactory = new Factory() {};
+        }
+
+        return sFactory.create(service);
+    }
+
+    interface Factory {
+        default TaskPositioner create(WindowManagerService service) {
+            return new TaskPositioner(service);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/wm/TaskPositioningController.java b/services/core/java/com/android/server/wm/TaskPositioningController.java
index 4dfe290..a3f4ee8 100644
--- a/services/core/java/com/android/server/wm/TaskPositioningController.java
+++ b/services/core/java/com/android/server/wm/TaskPositioningController.java
@@ -126,7 +126,7 @@
         }
 
         Display display = displayContent.getDisplay();
-        mTaskPositioner = new TaskPositioner(mService);
+        mTaskPositioner = TaskPositioner.create(mService);
         mTaskPositioner.register(displayContent);
         mInputMonitor.updateInputWindowsLw(true /*force*/);
 
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 8a36226..bc0f9ad 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -1397,15 +1397,23 @@
         return getDockSide(getRawBounds());
     }
 
+    int getDockSideForDisplay(DisplayContent dc) {
+        return getDockSide(dc, getRawBounds());
+    }
+
     private int getDockSide(Rect bounds) {
-        if (!inSplitScreenWindowingMode()) {
-            return DOCKED_INVALID;
-        }
         if (mDisplayContent == null) {
             return DOCKED_INVALID;
         }
-        mDisplayContent.getBounds(mTmpRect);
-        final int orientation = mDisplayContent.getConfiguration().orientation;
+        return getDockSide(mDisplayContent, bounds);
+    }
+
+    private int getDockSide(DisplayContent dc, Rect bounds) {
+        if (!inSplitScreenWindowingMode()) {
+            return DOCKED_INVALID;
+        }
+        dc.getBounds(mTmpRect);
+        final int orientation = dc.getConfiguration().orientation;
         return getDockSideUnchecked(bounds, mTmpRect, orientation);
     }
 
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 0fedc79..de1e7ec 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -5967,8 +5967,8 @@
         mPolicy.lockNow(options);
     }
 
-    public void showRecentApps(boolean fromHome) {
-        mPolicy.showRecentApps(fromHome);
+    public void showRecentApps() {
+        mPolicy.showRecentApps();
     }
 
     @Override
@@ -6613,7 +6613,7 @@
     public void onOverlayChanged() {
         synchronized (mWindowMap) {
             mPolicy.onOverlayChangedLw();
-            mDisplayManagerInternal.onOverlayChanged();
+            getDefaultDisplayContentLocked().updateDisplayInfo();
             requestTraversal();
         }
     }
@@ -6922,6 +6922,23 @@
         }
     }
 
+    /**
+     * Update a tap exclude region with a rectangular area in the window identified by the provided
+     * id. Touches on this region will not switch focus to this window. Passing an empty rect will
+     * remove the area from the exclude region of this window.
+     */
+    void updateTapExcludeRegion(IWindow client, int regionId, int left, int top, int width,
+            int height) {
+        synchronized (mWindowMap) {
+            final WindowState callingWin = windowForClientLocked(null, client, false);
+            if (callingWin == null) {
+                Slog.w(TAG_WM, "Bad requesting window " + client);
+                return;
+            }
+            callingWin.updateTapExcludeRegion(regionId, left, top, width, height);
+        }
+    }
+
     @Override
     public void registerShortcutKey(long shortcutCode, IShortcutService shortcutKeyReceiver)
             throws RemoteException {
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index db30db0..477dd2b 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -630,6 +630,11 @@
     private final Point mSurfacePosition = new Point();
 
     /**
+     * A region inside of this window to be excluded from touch-related focus switches.
+     */
+    private TapExcludeRegionHolder mTapExcludeRegionHolder;
+
+    /**
      * Compares two window sub-layers and returns -1 if the first is lesser than the second in terms
      * of z-order and 1 otherwise.
      */
@@ -1870,6 +1875,11 @@
         if (WindowManagerService.excludeWindowTypeFromTapOutTask(type)) {
             dc.mTapExcludedWindows.remove(this);
         }
+        if (mTapExcludeRegionHolder != null) {
+            // If a tap exclude region container was initialized for this window, then it should've
+            // also been registered in display.
+            dc.mTapExcludeProvidingWindows.remove(this);
+        }
         mPolicy.removeWindowLw(this);
 
         disposeInputChannel();
@@ -4620,6 +4630,37 @@
         }
     }
 
+    /**
+     * Update a tap exclude region with a rectangular area identified by provided id. The requested
+     * area will be clipped to the window bounds.
+     */
+    void updateTapExcludeRegion(int regionId, int left, int top, int width, int height) {
+        final DisplayContent currentDisplay = getDisplayContent();
+        if (currentDisplay == null) {
+            throw new IllegalStateException("Trying to update window not attached to any display.");
+        }
+
+        if (mTapExcludeRegionHolder == null) {
+            mTapExcludeRegionHolder = new TapExcludeRegionHolder();
+
+            // Make sure that this window is registered as one that provides a tap exclude region
+            // for its containing display.
+            currentDisplay.mTapExcludeProvidingWindows.add(this);
+        }
+
+        mTapExcludeRegionHolder.updateRegion(regionId, left, top, width, height);
+        // Trigger touch exclude region update on current display.
+        final boolean isAppFocusedOnDisplay = mService.mFocusedApp != null
+                && mService.mFocusedApp.getDisplayContent() == currentDisplay;
+        currentDisplay.setTouchExcludeRegion(isAppFocusedOnDisplay ? mService.mFocusedApp.getTask()
+                : null);
+    }
+
+    /** Union the region with current tap exclude region that this window provides. */
+    void amendTapExcludeRegion(Region region) {
+        mTapExcludeRegionHolder.amendRegion(region, getBounds());
+    }
+
     private final class MoveAnimationSpec implements AnimationSpec {
 
         private final long mDuration;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
index 384b416..99275e8 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
@@ -126,4 +126,19 @@
     public String getEndUserSessionMessage(ComponentName admin) {
         return null;
     }
+
+    @Override
+    public void setPrintingEnabled(ComponentName admin, boolean enabled) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean isPrintingEnabled() {
+        return true;
+    }
+
+    @Override
+    public CharSequence getPrintingDisabledReason() {
+        return null;
+    }
 }
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index cb4f5c1..77b87b6 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -74,6 +74,7 @@
 import android.app.Activity;
 import android.app.ActivityManager;
 import android.app.ActivityManagerInternal;
+import android.app.ActivityThread;
 import android.app.AlarmManager;
 import android.app.AppGlobals;
 import android.app.IActivityManager;
@@ -285,6 +286,8 @@
 
     private static final String TAG_PASSWORD_VALIDITY = "password-validity";
 
+    private static final String TAG_PRINTING_ENABLED = "printing-enabled";
+
     private static final int REQUEST_EXPIRE_PASSWORD = 5571;
 
     private static final long MS_PER_DAY = TimeUnit.DAYS.toMillis(1);
@@ -589,6 +592,8 @@
 
         long mPasswordTokenHandle = 0;
 
+        boolean mPrintingEnabled = true;
+
         public DevicePolicyData(int userHandle) {
             mUserHandle = userHandle;
         }
@@ -648,14 +653,14 @@
             }
 
             if (Intent.ACTION_USER_ADDED.equals(action)) {
-                sendUserAddedOrRemovedCommand(DeviceAdminReceiver.ACTION_USER_ADDED, userHandle);
+                sendDeviceOwnerUserCommand(DeviceAdminReceiver.ACTION_USER_ADDED, userHandle);
                 synchronized (DevicePolicyManagerService.this) {
                     // It might take a while for the user to become affiliated. Make security
                     // and network logging unavailable in the meantime.
                     maybePauseDeviceWideLoggingLocked();
                 }
             } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
-                sendUserAddedOrRemovedCommand(DeviceAdminReceiver.ACTION_USER_REMOVED, userHandle);
+                sendDeviceOwnerUserCommand(DeviceAdminReceiver.ACTION_USER_REMOVED, userHandle);
                 synchronized (DevicePolicyManagerService.this) {
                     // Check whether the user is affiliated, *before* removing its data.
                     boolean isRemovedUserAffiliated = isUserAffiliatedWithDeviceLocked(userHandle);
@@ -669,12 +674,17 @@
                     }
                 }
             } else if (Intent.ACTION_USER_STARTED.equals(action)) {
+                sendDeviceOwnerUserCommand(DeviceAdminReceiver.ACTION_USER_STARTED, userHandle);
                 synchronized (DevicePolicyManagerService.this) {
                     maybeSendAdminEnabledBroadcastLocked(userHandle);
                     // Reset the policy data
                     mUserData.remove(userHandle);
                 }
                 handlePackagesChanged(null /* check all admins */, userHandle);
+            } else if (Intent.ACTION_USER_STOPPED.equals(action)) {
+                sendDeviceOwnerUserCommand(DeviceAdminReceiver.ACTION_USER_STOPPED, userHandle);
+            } else if (Intent.ACTION_USER_SWITCHED.equals(action)) {
+                sendDeviceOwnerUserCommand(DeviceAdminReceiver.ACTION_USER_SWITCHED, userHandle);
             } else if (Intent.ACTION_USER_UNLOCKED.equals(action)) {
                 synchronized (DevicePolicyManagerService.this) {
                     maybeSendAdminEnabledBroadcastLocked(userHandle);
@@ -683,7 +693,7 @@
                 handlePackagesChanged(null /* check all admins */, userHandle);
             } else if (Intent.ACTION_PACKAGE_CHANGED.equals(action)
                     || (Intent.ACTION_PACKAGE_ADDED.equals(action)
-                            && intent.getBooleanExtra(Intent.EXTRA_REPLACING, false))) {
+                    && intent.getBooleanExtra(Intent.EXTRA_REPLACING, false))) {
                 handlePackagesChanged(intent.getData().getSchemeSpecificPart(), userHandle);
             } else if (Intent.ACTION_PACKAGE_REMOVED.equals(action)
                     && !intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
@@ -693,7 +703,7 @@
             }
         }
 
-        private void sendUserAddedOrRemovedCommand(String action, int userHandle) {
+        private void sendDeviceOwnerUserCommand(String action, int userHandle) {
             synchronized (DevicePolicyManagerService.this) {
                 ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked();
                 if (deviceOwner != null) {
@@ -2041,6 +2051,8 @@
         filter.addAction(Intent.ACTION_USER_ADDED);
         filter.addAction(Intent.ACTION_USER_REMOVED);
         filter.addAction(Intent.ACTION_USER_STARTED);
+        filter.addAction(Intent.ACTION_USER_STOPPED);
+        filter.addAction(Intent.ACTION_USER_SWITCHED);
         filter.addAction(Intent.ACTION_USER_UNLOCKED);
         filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
         mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, mHandler);
@@ -2880,6 +2892,12 @@
                 out.endTag(null, TAG_CURRENT_INPUT_METHOD_SET);
             }
 
+            if (!policy.mPrintingEnabled) {
+                out.startTag(null, TAG_PRINTING_ENABLED);
+                out.attribute(null, ATTR_VALUE, Boolean.toString(policy.mPrintingEnabled));
+                out.endTag(null, TAG_PRINTING_ENABLED);
+            }
+
             for (final String cert : policy.mOwnerInstalledCaCerts) {
                 out.startTag(null, TAG_OWNER_INSTALLED_CA_CERT);
                 out.attribute(null, ATTR_ALIAS, cert);
@@ -3098,6 +3116,9 @@
                     policy.mCurrentInputMethodSet = true;
                 } else if (TAG_OWNER_INSTALLED_CA_CERT.equals(tag)) {
                     policy.mOwnerInstalledCaCerts.add(parser.getAttributeValue(null, ATTR_ALIAS));
+                } else if (TAG_PRINTING_ENABLED.equals(tag)) {
+                    String enabled = parser.getAttributeValue(null, ATTR_VALUE);
+                    policy.mPrintingEnabled = Boolean.toString(true).equals(enabled);
                 } else {
                     Slog.w(LOG_TAG, "Unknown tag: " + tag);
                     XmlUtils.skipCurrentTag(parser);
@@ -12274,4 +12295,93 @@
             return deviceOwner.endUserSessionMessage;
         }
     }
+
+    private boolean hasPrinting() {
+        return mInjector.getPackageManager().hasSystemFeature(PackageManager.FEATURE_PRINTING);
+    }
+
+    @Override
+    public void setPrintingEnabled(ComponentName admin, boolean enabled) {
+        if (!mHasFeature || !hasPrinting()) {
+            return;
+        }
+        Preconditions.checkNotNull(admin, "Admin cannot be null.");
+        enforceProfileOrDeviceOwner(admin);
+        synchronized (this) {
+            final int userHandle = mInjector.userHandleGetCallingUserId();
+            DevicePolicyData policy = getUserData(userHandle);
+            if (policy.mPrintingEnabled != enabled) {
+                policy.mPrintingEnabled = enabled;
+                saveSettingsLocked(userHandle);
+            }
+        }
+    }
+
+    /**
+     * Returns whether printing is enabled for current user.
+     * @hide
+     */
+    @Override
+    public boolean isPrintingEnabled() {
+        if (!hasPrinting()) {
+            return false;
+        }
+        if (!mHasFeature) {
+            return true;
+        }
+        synchronized (this) {
+            final int userHandle = mInjector.userHandleGetCallingUserId();
+            DevicePolicyData policy = getUserData(userHandle);
+            return policy.mPrintingEnabled;
+        }
+    }
+
+    /**
+     * Returns text of error message if printing is disabled.
+     * Only to be called by Print Service.
+     * @hide
+     */
+    @Override
+    public CharSequence getPrintingDisabledReason() {
+        if (!hasPrinting() || !mHasFeature) {
+            Log.e(LOG_TAG, "no printing or no management");
+            return null;
+        }
+        synchronized (this) {
+            final int userHandle = mInjector.userHandleGetCallingUserId();
+            DevicePolicyData policy = getUserData(userHandle);
+            if (policy.mPrintingEnabled) {
+                Log.e(LOG_TAG, "printing is enabled");
+                return null;
+            }
+            String ownerPackage = mOwners.getProfileOwnerPackage(userHandle);
+            if (ownerPackage == null) {
+                ownerPackage = mOwners.getDeviceOwnerPackageName();
+            }
+            PackageManager pm = mInjector.getPackageManager();
+            PackageInfo packageInfo;
+            try {
+                packageInfo = pm.getPackageInfo(ownerPackage, 0);
+            } catch (NameNotFoundException e) {
+                Log.e(LOG_TAG, "getPackageInfo error", e);
+                return null;
+            }
+            if (packageInfo == null) {
+                Log.e(LOG_TAG, "packageInfo is inexplicably null");
+                return null;
+            }
+            ApplicationInfo appInfo = packageInfo.applicationInfo;
+            if (appInfo == null) {
+                Log.e(LOG_TAG, "appInfo is inexplicably null");
+                return null;
+            }
+            CharSequence appLabel = pm.getApplicationLabel(appInfo);
+            if (appLabel == null) {
+                Log.e(LOG_TAG, "appLabel is inexplicably null");
+                return null;
+            }
+            return ((Context) ActivityThread.currentActivityThread().getSystemUiContext())
+                    .getResources().getString(R.string.printing_disabled_by, appLabel);
+        }
+    }
 }
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 3199bfa..e660c50 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -46,10 +46,10 @@
 import android.os.Trace;
 import android.os.UserHandle;
 import android.os.storage.IStorageManager;
-import android.util.TimingsTraceLog;
 import android.util.DisplayMetrics;
 import android.util.EventLog;
 import android.util.Slog;
+import android.util.TimingsTraceLog;
 import android.view.WindowManager;
 
 import com.android.internal.R;
@@ -57,20 +57,21 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.notification.SystemNotificationChannels;
 import com.android.internal.os.BinderInternal;
-import com.android.internal.util.EmergencyAffordanceManager;
 import com.android.internal.util.ConcurrentUtils;
+import com.android.internal.util.EmergencyAffordanceManager;
 import com.android.internal.widget.ILockSettings;
 import com.android.server.accessibility.AccessibilityManagerService;
 import com.android.server.am.ActivityManagerService;
 import com.android.server.audio.AudioService;
+import com.android.server.broadcastradio.BroadcastRadioService;
 import com.android.server.camera.CameraServiceProxy;
 import com.android.server.car.CarServiceHelperService;
 import com.android.server.clipboard.ClipboardService;
 import com.android.server.connectivity.IpConnectivityMetrics;
 import com.android.server.coverage.CoverageService;
 import com.android.server.devicepolicy.DevicePolicyManagerService;
-import com.android.server.display.DisplayManagerService;
 import com.android.server.display.ColorDisplayService;
+import com.android.server.display.DisplayManagerService;
 import com.android.server.dreams.DreamManagerService;
 import com.android.server.emergency.EmergencyAffordanceService;
 import com.android.server.fingerprint.FingerprintService;
@@ -92,17 +93,16 @@
 import com.android.server.os.DeviceIdentifiersPolicyService;
 import com.android.server.os.SchedulingPolicyService;
 import com.android.server.pm.BackgroundDexOptService;
+import com.android.server.pm.CrossProfileAppsService;
 import com.android.server.pm.Installer;
 import com.android.server.pm.LauncherAppsService;
 import com.android.server.pm.OtaDexoptService;
 import com.android.server.pm.PackageManagerService;
 import com.android.server.pm.ShortcutService;
 import com.android.server.pm.UserManagerService;
-import com.android.server.pm.crossprofile.CrossProfileAppsService;
 import com.android.server.policy.PhoneWindowManager;
 import com.android.server.power.PowerManagerService;
 import com.android.server.power.ShutdownThread;
-import com.android.server.broadcastradio.BroadcastRadioService;
 import com.android.server.restrictions.RestrictionsManagerService;
 import com.android.server.security.KeyAttestationApplicationIdProviderService;
 import com.android.server.security.KeyChainSystemService;
diff --git a/services/print/java/com/android/server/print/PrintManagerService.java b/services/print/java/com/android/server/print/PrintManagerService.java
index cd4e8f9..89a5fe1 100644
--- a/services/print/java/com/android/server/print/PrintManagerService.java
+++ b/services/print/java/com/android/server/print/PrintManagerService.java
@@ -21,6 +21,7 @@
 
 import android.annotation.NonNull;
 import android.app.ActivityManager;
+import android.app.admin.DevicePolicyManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -32,6 +33,7 @@
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Bundle;
+import android.os.Looper;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.UserHandle;
@@ -54,6 +56,7 @@
 import android.util.Log;
 import android.util.SparseArray;
 import android.util.proto.ProtoOutputStream;
+import android.widget.Toast;
 
 import com.android.internal.content.PackageMonitor;
 import com.android.internal.os.BackgroundThread;
@@ -110,9 +113,12 @@
 
         private final SparseArray<UserState> mUserStates = new SparseArray<>();
 
+        private final DevicePolicyManager mDpc;
+
         PrintManagerImpl(Context context) {
             mContext = context;
             mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
+            mDpc = (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
             registerContentObservers();
             registerBroadcastReceivers();
         }
@@ -120,8 +126,26 @@
         @Override
         public Bundle print(String printJobName, IPrintDocumentAdapter adapter,
                 PrintAttributes attributes, String packageName, int appId, int userId) {
-            printJobName = Preconditions.checkStringNotEmpty(printJobName);
             adapter = Preconditions.checkNotNull(adapter);
+            if (!isPrintingEnabled()) {
+                final CharSequence disabledMessage = mDpc.getPrintingDisabledReason();
+                if (disabledMessage != null) {
+                    Toast.makeText(mContext, Looper.getMainLooper(), disabledMessage,
+                            Toast.LENGTH_LONG).show();
+                }
+                try {
+                    adapter.start();
+                } catch (RemoteException re) {
+                    Log.e(LOG_TAG, "Error calling IPrintDocumentAdapter.start()");
+                }
+                try {
+                    adapter.finish();
+                } catch (RemoteException re) {
+                    Log.e(LOG_TAG, "Error calling IPrintDocumentAdapter.finish()");
+                }
+                return null;
+            }
+            printJobName = Preconditions.checkStringNotEmpty(printJobName);
             packageName = Preconditions.checkStringNotEmpty(packageName);
 
             final int resolvedUserId = resolveCallingUserEnforcingPermissions(userId);
@@ -240,7 +264,8 @@
 
         @Override
         public void restartPrintJob(PrintJobId printJobId, int appId, int userId) {
-            if (printJobId == null) {
+            if (printJobId == null || !isPrintingEnabled()) {
+                // if printing is disabled the state just remains "failed".
                 return;
             }
 
@@ -685,6 +710,10 @@
             }
         }
 
+        private boolean isPrintingEnabled() {
+            return mDpc == null || mDpc.isPrintingEnabled();
+        }
+
         private void dump(@NonNull DualDumpOutputStream dumpStream,
                 @NonNull ArrayList<UserState> userStatesToDump) {
             final int userStateCount = userStatesToDump.size();
diff --git a/services/robotests/src/com/android/server/backup/TransportManagerTest.java b/services/robotests/src/com/android/server/backup/TransportManagerTest.java
index cf0bc23..068fe81 100644
--- a/services/robotests/src/com/android/server/backup/TransportManagerTest.java
+++ b/services/robotests/src/com/android/server/backup/TransportManagerTest.java
@@ -19,9 +19,13 @@
 import static com.android.server.backup.testing.TransportData.genericTransport;
 import static com.android.server.backup.testing.TransportTestUtils.mockTransport;
 import static com.android.server.backup.testing.TransportTestUtils.setUpTransportsForTransportManager;
-
 import static com.google.common.truth.Truth.assertThat;
-
+import static java.util.Arrays.asList;
+import static java.util.Collections.emptyList;
+import static java.util.Collections.singletonList;
+import static java.util.stream.Collectors.toList;
+import static java.util.stream.Collectors.toSet;
+import static java.util.stream.Stream.concat;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.never;
@@ -31,23 +35,15 @@
 import static org.robolectric.shadow.api.Shadow.extract;
 import static org.testng.Assert.expectThrows;
 
-import static java.util.Arrays.asList;
-import static java.util.Collections.emptyList;
-import static java.util.Collections.singletonList;
-import static java.util.stream.Collectors.toList;
-import static java.util.stream.Collectors.toSet;
-import static java.util.stream.Stream.concat;
-
 import android.annotation.Nullable;
+import android.app.backup.BackupManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.platform.test.annotations.Presubmit;
-
 import com.android.server.backup.testing.ShadowContextImplForBackup;
-import com.android.server.testing.shadows.FrameworkShadowPackageManager;
 import com.android.server.backup.testing.TransportData;
 import com.android.server.backup.testing.TransportTestUtils.TransportMock;
 import com.android.server.backup.transport.OnTransportRegisteredListener;
@@ -57,7 +53,12 @@
 import com.android.server.testing.FrameworkRobolectricTestRunner;
 import com.android.server.testing.SystemLoaderClasses;
 import com.android.server.testing.shadows.FrameworkShadowContextImpl;
-
+import com.android.server.testing.shadows.FrameworkShadowPackageManager;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Stream;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -68,12 +69,6 @@
 import org.robolectric.annotation.Config;
 import org.robolectric.shadows.ShadowPackageManager;
 
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Objects;
-import java.util.Set;
-import java.util.stream.Stream;
-
 @RunWith(FrameworkRobolectricTestRunner.class)
 @Config(
     manifest = Config.NONE,
@@ -308,6 +303,43 @@
     }
 
     @Test
+    public void testRegisterAndSelectTransport_whenTransportRegistered() throws Exception {
+        setUpPackage(PACKAGE_A, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
+        setUpTransports(mTransportA1);
+        TransportManager transportManager = createTransportManager(null, mTransportA1);
+        transportManager.registerTransports();
+        ComponentName transportComponent = mTransportA1.getTransportComponent();
+
+        int result = transportManager.registerAndSelectTransport(transportComponent);
+
+        assertThat(result).isEqualTo(BackupManager.SUCCESS);
+        assertThat(transportManager.getRegisteredTransportComponents())
+                .asList()
+                .contains(transportComponent);
+        assertThat(transportManager.getCurrentTransportName())
+                .isEqualTo(mTransportA1.transportName);
+    }
+
+    @Test
+    public void testRegisterAndSelectTransport_whenTransportNotRegistered() throws Exception {
+        setUpPackage(PACKAGE_A, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
+        setUpTransports(mTransportA1);
+        TransportManager transportManager = createTransportManager(null, mTransportA1);
+        ComponentName transportComponent = mTransportA1.getTransportComponent();
+
+        int result = transportManager.registerAndSelectTransport(transportComponent);
+
+        assertThat(result).isEqualTo(BackupManager.SUCCESS);
+        assertThat(transportManager.getRegisteredTransportComponents())
+                .asList()
+                .contains(transportComponent);
+        assertThat(transportManager.getTransportDirName(mTransportA1.transportName))
+                .isEqualTo(mTransportA1.transportDirName);
+        assertThat(transportManager.getCurrentTransportName())
+                .isEqualTo(mTransportA1.transportName);
+    }
+
+    @Test
     public void testGetCurrentTransportName_whenSelectTransportNotCalled_returnsDefaultTransport()
             throws Exception {
         setUpPackage(PACKAGE_A, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
@@ -500,6 +532,46 @@
                 () -> transportManager.getTransportDirName(mTransportA2.transportName));
     }
 
+    @Test
+    public void testGetRegisteredTransportNames() throws Exception {
+        setUpPackage(PACKAGE_A, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
+        setUpPackage(PACKAGE_B, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
+        TransportData[] transportsData = {mTransportA1, mTransportA2, mTransportB1};
+        setUpTransports(transportsData);
+        TransportManager transportManager =
+                createTransportManager(mTransportA1, mTransportA2, mTransportB1);
+        transportManager.registerTransports();
+
+        String[] transportNames = transportManager.getRegisteredTransportNames();
+
+        assertThat(transportNames)
+                .asList()
+                .containsExactlyElementsIn(
+                        Stream.of(transportsData)
+                                .map(transportData -> transportData.transportName)
+                                .collect(toList()));
+    }
+
+    @Test
+    public void testGetRegisteredTransportComponents() throws Exception {
+        setUpPackage(PACKAGE_A, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
+        setUpPackage(PACKAGE_B, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
+        TransportData[] transportsData = {mTransportA1, mTransportA2, mTransportB1};
+        setUpTransports(transportsData);
+        TransportManager transportManager =
+                createTransportManager(mTransportA1, mTransportA2, mTransportB1);
+        transportManager.registerTransports();
+
+        ComponentName[] transportNames = transportManager.getRegisteredTransportComponents();
+
+        assertThat(transportNames)
+                .asList()
+                .containsExactlyElementsIn(
+                        Stream.of(transportsData)
+                                .map(TransportData::getTransportComponent)
+                                .collect(toList()));
+    }
+
     private List<TransportMock> setUpTransports(TransportData... transports) throws Exception {
         setUpTransportsForTransportManager(mShadowPackageManager, transports);
         List<TransportMock> transportMocks = new ArrayList<>(transports.length);
diff --git a/services/tests/servicestests/assets/NetworkWatchlistTest/watchlist_config_test1.xml b/services/tests/servicestests/assets/NetworkWatchlistTest/watchlist_config_test1.xml
new file mode 100644
index 0000000..e31fad8
--- /dev/null
+++ b/services/tests/servicestests/assets/NetworkWatchlistTest/watchlist_config_test1.xml
@@ -0,0 +1,27 @@
+<?xml version='1.0'?>
+<watchlist-config>
+    <sha256-domain>
+        <!-- test-cc-domain.com -->
+        <hash>8E7DCD2AEB4F364358242BB3F403263E61E3B4AECE4E2500FF28BF32E52FF0F1</hash>
+        <!-- test-cc-match-sha256-only.com -->
+        <hash>F0905DA7549614957B449034C281EF7BDEFDBC2B6E050AD1E78D6DE18FBD0D5F</hash>
+    </sha256-domain>
+    <sha256-ip>
+        <!-- 127.0.0.2 -->
+        <hash>1EDD62868F2767A1FFF68DF0A4CB3C23448E45100715768DB9310B5E719536A1</hash>
+        <!-- 127.0.0.3, match in sha256 only -->
+        <hash>18DD41C9F2E8E4879A1575FB780514EF33CF6E1F66578C4AE7CCA31F49B9F2ED</hash>
+    </sha256-ip>
+    <crc32-domain>
+        <!-- test-cc-domain.com -->
+        <hash>6C67059D</hash>
+        <!-- test-cc-match-crc32-only.com -->
+        <hash>3DC775F8</hash>
+    </crc32-domain>
+    <crc32-ip>
+        <!-- 127.0.0.2 -->
+        <hash>4EBEB612</hash>
+        <!-- 127.0.0.4, match in crc32 only -->
+        <hash>A7DD1327</hash>
+    </crc32-ip>
+</watchlist-config>
diff --git a/services/tests/servicestests/assets/NetworkWatchlistTest/watchlist_settings_test1.xml b/services/tests/servicestests/assets/NetworkWatchlistTest/watchlist_settings_test1.xml
index bb97e94..5349a13 100644
--- a/services/tests/servicestests/assets/NetworkWatchlistTest/watchlist_settings_test1.xml
+++ b/services/tests/servicestests/assets/NetworkWatchlistTest/watchlist_settings_test1.xml
@@ -1,27 +1,4 @@
 <?xml version='1.0'?>
-<watchlist-settings>
-    <sha256-domain>
-        <!-- test-cc-domain.com -->
-        <hash>8E7DCD2AEB4F364358242BB3F403263E61E3B4AECE4E2500FF28BF32E52FF0F1</hash>
-        <!-- test-cc-match-sha256-only.com -->
-        <hash>F0905DA7549614957B449034C281EF7BDEFDBC2B6E050AD1E78D6DE18FBD0D5F</hash>
-    </sha256-domain>
-    <sha256-ip>
-        <!-- 127.0.0.2 -->
-        <hash>1EDD62868F2767A1FFF68DF0A4CB3C23448E45100715768DB9310B5E719536A1</hash>
-        <!-- 127.0.0.3, match in sha256 only -->
-        <hash>18DD41C9F2E8E4879A1575FB780514EF33CF6E1F66578C4AE7CCA31F49B9F2ED</hash>
-    </sha256-ip>
-    <crc32-domain>
-        <!-- test-cc-domain.com -->
-        <hash>6C67059D</hash>
-        <!-- test-cc-match-crc32-only.com -->
-        <hash>3DC775F8</hash>
-    </crc32-domain>
-    <crc32-ip>
-        <!-- 127.0.0.2 -->
-        <hash>4EBEB612</hash>
-        <!-- 127.0.0.4, match in crc32 only -->
-        <hash>A7DD1327</hash>
-    </crc32-ip>
-</watchlist-settings>
+<network-watchlist-settings>
+    <secret-key>1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF</secret-key>
+</network-watchlist-settings>
diff --git a/services/tests/servicestests/assets/NetworkWatchlistTest/watchlist_settings_test2.xml b/services/tests/servicestests/assets/NetworkWatchlistTest/watchlist_settings_test2.xml
new file mode 100644
index 0000000..3e65bc0
--- /dev/null
+++ b/services/tests/servicestests/assets/NetworkWatchlistTest/watchlist_settings_test2.xml
@@ -0,0 +1,4 @@
+<?xml version='1.0'?>
+<network-watchlist-settings>
+
+</network-watchlist-settings>
diff --git a/services/tests/servicestests/src/com/android/server/ForceAppStandbyTrackerTest.java b/services/tests/servicestests/src/com/android/server/ForceAppStandbyTrackerTest.java
index 6a21931..429dd8f 100644
--- a/services/tests/servicestests/src/com/android/server/ForceAppStandbyTrackerTest.java
+++ b/services/tests/servicestests/src/com/android/server/ForceAppStandbyTrackerTest.java
@@ -42,7 +42,6 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.os.BatteryManager;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.PowerManager.ServiceType;
@@ -52,7 +51,6 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.provider.Settings;
-import android.provider.Settings.Global;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 import android.test.mock.MockContentResolver;
@@ -107,9 +105,6 @@
         PowerManagerInternal injectPowerManagerInternal() {
             return mMockPowerManagerInternal;
         }
-
-        @Override
-        boolean isSmallBatteryDevice() { return mIsSmallBatteryDevice; };
     }
 
     private static final int UID_1 = Process.FIRST_APPLICATION_UID + 1;
@@ -149,7 +144,6 @@
     private FakeSettingsProvider mFakeSettingsProvider;
 
     private boolean mPowerSaveMode;
-    private boolean mIsSmallBatteryDevice;
 
     private final ArraySet<Pair<Integer, String>> mRestrictedPackages = new ArraySet();
 
@@ -186,12 +180,13 @@
     }
 
     private void callStart(ForceAppStandbyTrackerTestable instance) throws RemoteException {
+
         // Set up functions that start() calls.
         when(mMockPowerManagerInternal.getLowPowerState(eq(ServiceType.FORCE_ALL_APPS_STANDBY)))
                 .thenAnswer(inv -> getPowerSaveState());
         when(mMockAppOpsManager.getPackagesForOps(
                 any(int[].class)
-        )).thenAnswer(inv -> new ArrayList<AppOpsManager.PackageOps>());
+                )).thenAnswer(inv -> new ArrayList<AppOpsManager.PackageOps>());
 
         mMockContentResolver = new MockContentResolver();
         mFakeSettingsProvider = new FakeSettingsProvider();
@@ -224,6 +219,7 @@
         verify(mMockPowerManagerInternal).registerLowPowerModeObserver(
                 eq(ServiceType.FORCE_ALL_APPS_STANDBY),
                 powerSaveObserverCaptor.capture());
+
         verify(mMockContext).registerReceiver(
                 receiverCaptor.capture(), any(IntentFilter.class));
 
@@ -236,7 +232,6 @@
         assertNotNull(mAppOpsCallback);
         assertNotNull(mPowerSaveObserver);
         assertNotNull(mReceiver);
-        assertNotNull(instance.mFlagsObserver);
     }
 
     private void setAppOps(int uid, String packageName, boolean restrict) throws RemoteException {
@@ -511,8 +506,8 @@
         verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
         reset(l);
 
-        // Power save on.
-        mPowerSaveMode = true;
+        // Updating to the same state should not fire listener
+        mPowerSaveMode = false;
         mPowerSaveObserver.accept(getPowerSaveState());
 
         assertNoCallbacks(l);
@@ -550,14 +545,14 @@
 
         verify(l, times(0)).unblockAllUnrestrictedAlarms();
         verify(l, times(0)).unblockAlarmsForUid(anyInt());
-        verify(l, times(0)).unblockAlarmsForUidPackage(eq(UID_10_2), eq(PACKAGE_2));
+        verify(l, times(1)).unblockAlarmsForUidPackage(eq(UID_10_2), eq(PACKAGE_2));
         reset(l);
 
         setAppOps(UID_10_2, PACKAGE_2, false);
 
         verify(l, times(0)).updateAllJobs();
         verify(l, times(0)).updateJobsForUid(anyInt());
-        verify(l, times(1)).updateJobsForUidPackage(eq(UID_10_2), eq(PACKAGE_2));
+        verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
 
         verify(l, times(0)).unblockAllUnrestrictedAlarms();
         verify(l, times(0)).unblockAlarmsForUid(anyInt());
@@ -650,10 +645,20 @@
         mPowerSaveMode = true;
         mPowerSaveObserver.accept(getPowerSaveState());
 
+        verify(l, times(1)).updateAllJobs();
+        verify(l, times(0)).updateJobsForUid(anyInt());
+        verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
+
+        verify(l, times(0)).unblockAllUnrestrictedAlarms();
+        verify(l, times(0)).unblockAlarmsForUid(anyInt());
+        verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
+        reset(l);
+
         instance.setPowerSaveWhitelistAppIds(new int[] {UID_1, UID_2}, new int[] {});
 
         waitUntilMainHandlerDrain();
-        verify(l, times(1)).updateAllJobs();
+        // Called once for updating all whitelist and once for updating temp whitelist
+        verify(l, times(2)).updateAllJobs();
         verify(l, times(0)).updateJobsForUid(anyInt());
         verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
 
@@ -715,7 +720,7 @@
         verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
 
         verify(l, times(0)).unblockAllUnrestrictedAlarms();
-        verify(l, times(0)).unblockAlarmsForUid(anyInt());
+        verify(l, times(1)).unblockAlarmsForUid(eq(UID_10_1));
         verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
         reset(l);
 
@@ -739,7 +744,7 @@
         verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
 
         verify(l, times(0)).unblockAllUnrestrictedAlarms();
-        verify(l, times(0)).unblockAlarmsForUid(anyInt());
+        verify(l, times(1)).unblockAlarmsForUid(eq(UID_10_1));
         verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
         reset(l);
 
@@ -759,6 +764,15 @@
         mPowerSaveMode = false;
         mPowerSaveObserver.accept(getPowerSaveState());
 
+        verify(l, times(1)).updateAllJobs();
+        verify(l, times(0)).updateJobsForUid(eq(UID_10_1));
+        verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
+
+        verify(l, times(1)).unblockAllUnrestrictedAlarms();
+        verify(l, times(0)).unblockAlarmsForUid(anyInt());
+        verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
+        reset(l);
+
         mIUidObserver.onUidActive(UID_10_1);
 
         waitUntilMainHandlerDrain();
@@ -767,7 +781,7 @@
         verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
 
         verify(l, times(0)).unblockAllUnrestrictedAlarms();
-        verify(l, times(0)).unblockAlarmsForUid(anyInt());
+        verify(l, times(1)).unblockAlarmsForUid(eq(UID_10_1));
         verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
         reset(l);
 
@@ -791,7 +805,7 @@
         verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString());
 
         verify(l, times(0)).unblockAllUnrestrictedAlarms();
-        verify(l, times(0)).unblockAlarmsForUid(anyInt());
+        verify(l, times(1)).unblockAlarmsForUid(eq(UID_10_1));
         verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString());
         reset(l);
 
@@ -838,33 +852,6 @@
         assertTrue(instance.isRunAnyInBackgroundAppOpsAllowed(UID_10_2, PACKAGE_2));
     }
 
-    @Test
-    public void testSmallBatteryAndCharging() throws Exception {
-        // This is a small battery device
-        mIsSmallBatteryDevice = true;
-
-        final ForceAppStandbyTrackerTestable instance = newInstance();
-        callStart(instance);
-        assertFalse(instance.isForceAllAppsStandbyEnabled());
-
-        // Setting/experiment for all app standby for small battery is enabled
-        Global.putInt(mMockContentResolver, Global.FORCED_APP_STANDBY_FOR_SMALL_BATTERY_ENABLED, 1);
-        instance.mFlagsObserver.onChange(true,
-                Global.getUriFor(Global.FORCED_APP_STANDBY_FOR_SMALL_BATTERY_ENABLED));
-        assertTrue(instance.isForceAllAppsStandbyEnabled());
-
-        // When battery is charging, force app standby is disabled
-        Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED);
-        intent.putExtra(BatteryManager.EXTRA_STATUS, BatteryManager.BATTERY_STATUS_CHARGING);
-        mReceiver.onReceive(mMockContext, intent);
-        assertFalse(instance.isForceAllAppsStandbyEnabled());
-
-        // When battery stops charging, force app standby is enabled
-        intent.putExtra(BatteryManager.EXTRA_STATUS, BatteryManager.BATTERY_STATUS_DISCHARGING);
-        mReceiver.onReceive(mMockContext, intent);
-        assertTrue(instance.isForceAllAppsStandbyEnabled());
-    }
-
     static int[] array(int... appIds) {
         Arrays.sort(appIds);
         return appIds;
diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
index fbcccf0..7c3082f 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
@@ -18,6 +18,7 @@
 
 import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
 import static android.net.ConnectivityManager.TYPE_WIFI;
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
 import static android.net.NetworkPolicy.LIMIT_DISABLED;
 import static android.net.NetworkPolicy.SNOOZE_NEVER;
 import static android.net.NetworkPolicy.WARNING_DISABLED;
@@ -34,6 +35,7 @@
 import static android.telephony.CarrierConfigManager.KEY_DATA_LIMIT_THRESHOLD_BYTES_LONG;
 import static android.telephony.CarrierConfigManager.KEY_DATA_WARNING_THRESHOLD_BYTES_LONG;
 import static android.telephony.CarrierConfigManager.KEY_MONTHLY_DATA_CYCLE_DAY_INT;
+import static android.telephony.SubscriptionPlan.LIMIT_BEHAVIOR_THROTTLED;
 import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
 import static android.text.format.Time.TIMEZONE_UTC;
 
@@ -62,6 +64,7 @@
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -86,13 +89,16 @@
 import android.net.INetworkPolicyListener;
 import android.net.INetworkStatsService;
 import android.net.LinkProperties;
+import android.net.Network;
 import android.net.NetworkCapabilities;
 import android.net.NetworkInfo;
 import android.net.NetworkInfo.DetailedState;
 import android.net.NetworkPolicy;
 import android.net.NetworkState;
 import android.net.NetworkStats;
+import android.net.NetworkStatsHistory;
 import android.net.NetworkTemplate;
+import android.net.StringNetworkSpecifier;
 import android.os.Binder;
 import android.os.INetworkManagementService;
 import android.os.PersistableBundle;
@@ -105,9 +111,11 @@
 import android.support.test.runner.AndroidJUnit4;
 import android.telephony.CarrierConfigManager;
 import android.telephony.SubscriptionManager;
+import android.telephony.SubscriptionPlan;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 import android.text.format.Time;
+import android.util.DataUnit;
 import android.util.Log;
 import android.util.Pair;
 import android.util.RecurrenceRule;
@@ -186,6 +194,7 @@
     private static final long TEST_START = 1194220800000L;
     private static final String TEST_IFACE = "test0";
     private static final String TEST_SSID = "AndroidAP";
+    private static final String TEST_IMSI = "310210";
 
     private static NetworkTemplate sTemplateWifi = NetworkTemplate.buildTemplateWifi(TEST_SSID);
 
@@ -309,6 +318,11 @@
                         return super.getSystemService(name);
                 }
             }
+
+            @Override
+            public void enforceCallingOrSelfPermission(String permission, String message) {
+                // Assume that we're AID_SYSTEM
+            }
         };
 
         setNetpolicyXml(context);
@@ -1065,6 +1079,67 @@
     }
 
     @Test
+    public void testRapidNotification() throws Exception {
+        // Create a place to store fake usage
+        final NetworkStatsHistory history = new NetworkStatsHistory(TimeUnit.HOURS.toMillis(1));
+        when(mStatsService.getNetworkTotalBytes(any(), anyLong(), anyLong()))
+                .thenAnswer(new Answer<Long>() {
+                    @Override
+                    public Long answer(InvocationOnMock invocation) throws Throwable {
+                        final NetworkStatsHistory.Entry entry = history.getValues(
+                                invocation.getArgument(1), invocation.getArgument(2), null);
+                        return entry.rxBytes + entry.txBytes;
+                    }
+                });
+
+        // Define simple data plan which gives us effectively 60MB/day
+        final SubscriptionPlan plan = SubscriptionPlan.Builder
+                .createRecurringMonthly(ZonedDateTime.parse("2015-11-01T00:00:00.00Z"))
+                .setDataLimit(DataUnit.MEGABYTES.toBytes(1800), LIMIT_BEHAVIOR_THROTTLED)
+                .build();
+        mService.setSubscriptionPlans(42, new SubscriptionPlan[] { plan },
+                mServiceContext.getOpPackageName());
+
+        // And get that active network in place
+        when(mConnManager.getAllNetworkState()).thenReturn(new NetworkState[] {
+                new NetworkState(null, new LinkProperties(),
+                        new NetworkCapabilities().addTransportType(TRANSPORT_CELLULAR)
+                                .setNetworkSpecifier(new StringNetworkSpecifier("42")),
+                        new Network(42), TEST_IMSI, null)
+        });
+        mService.updateNetworks();
+
+        // We're 20% through the month (6 days)
+        final long start = parseTime("2015-11-01T00:00Z");
+        final long end = parseTime("2015-11-07T00:00Z");
+        setCurrentTimeMillis(end);
+
+        // Using 20% of data in 20% is normal
+        {
+            history.removeBucketsBefore(Long.MAX_VALUE);
+            history.recordData(start, end,
+                    new NetworkStats.Entry(DataUnit.MEGABYTES.toBytes(360), 0L, 0L, 0L, 0));
+
+            reset(mNotifManager);
+            mService.updateNotifications();
+            verify(mNotifManager, never()).enqueueNotificationWithTag(any(), any(), any(),
+                    anyInt(), any(), anyInt());
+        }
+
+        // Using 80% data in 20% time is alarming
+        {
+            history.removeBucketsBefore(Long.MAX_VALUE);
+            history.recordData(start, end,
+                    new NetworkStats.Entry(DataUnit.MEGABYTES.toBytes(1440), 0L, 0L, 0L, 0));
+
+            reset(mNotifManager);
+            mService.updateNotifications();
+            verify(mNotifManager, atLeastOnce()).enqueueNotificationWithTag(any(), any(), any(),
+                    anyInt(), any(), anyInt());
+        }
+    }
+
+    @Test
     public void testMeteredNetworkWithoutLimit() throws Exception {
         NetworkState[] state = null;
         NetworkStats stats = null;
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/GlobalActionPerformerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/GlobalActionPerformerTest.java
index 1213e81..e72e460 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/GlobalActionPerformerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/GlobalActionPerformerTest.java
@@ -16,13 +16,18 @@
 
 package com.android.server.accessibility;
 
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.accessibilityservice.AccessibilityService;
 import android.app.StatusBarManager;
 import android.content.Context;
+import android.os.Handler;
 
+import com.android.internal.util.ScreenshotHelper;
 import com.android.server.wm.WindowManagerInternal;
 
 import org.junit.Before;
@@ -39,6 +44,7 @@
     @Mock Context mMockContext;
     @Mock WindowManagerInternal mMockWindowManagerInternal;
     @Mock StatusBarManager mMockStatusBarManager;
+    @Mock ScreenshotHelper mMockScreenshotHelper;
 
     @Before
     public void setup() {
@@ -48,7 +54,8 @@
                 .thenReturn(mMockStatusBarManager);
 
         mGlobalActionPerformer =
-                new GlobalActionPerformer(mMockContext, mMockWindowManagerInternal);
+                new GlobalActionPerformer(mMockContext, mMockWindowManagerInternal,
+                        () -> mMockScreenshotHelper);
     }
 
     @Test
@@ -70,4 +77,13 @@
         mGlobalActionPerformer.performGlobalAction(AccessibilityService.GLOBAL_ACTION_POWER_DIALOG);
         verify(mMockWindowManagerInternal).showGlobalActions();
     }
+
+    @Test
+    public void testScreenshot_requestsFromScreenshotHelper() {
+        mGlobalActionPerformer.performGlobalAction(
+                AccessibilityService.GLOBAL_ACTION_TAKE_SCREENSHOT);
+        verify(mMockScreenshotHelper).takeScreenshot(
+                eq(android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN), anyBoolean(),
+                anyBoolean(), any(Handler.class));
+    }
 }
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 d8e3be9..43d026d 100644
--- a/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java
+++ b/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java
@@ -6,12 +6,17 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
 import android.app.job.JobInfo;
 import android.app.job.JobInfo.Builder;
 import android.content.ComponentName;
 import android.content.Context;
+import android.content.pm.PackageManagerInternal;
 import android.net.NetworkRequest;
+import android.os.Build;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.PersistableBundle;
@@ -24,6 +29,7 @@
 
 import com.android.internal.util.HexDump;
 import com.android.server.IoThread;
+import com.android.server.LocalServices;
 import com.android.server.job.JobStore.JobSet;
 import com.android.server.job.controllers.JobStatus;
 
@@ -65,6 +71,13 @@
                 JobStore.initAndGetForTesting(mTestContext, mTestContext.getFilesDir());
         mComponent = new ComponentName(getContext().getPackageName(), StubClass.class.getName());
 
+        // Assume all packages are current SDK
+        final PackageManagerInternal pm = mock(PackageManagerInternal.class);
+        when(pm.getPackageTargetSdkVersion(anyString()))
+                .thenReturn(Build.VERSION_CODES.CUR_DEVELOPMENT);
+        LocalServices.removeServiceForTest(PackageManagerInternal.class);
+        LocalServices.addService(PackageManagerInternal.class, pm);
+
         // Freeze the clocks at this moment in time
         JobSchedulerService.sSystemClock =
                 Clock.fixed(Clock.systemUTC().instant(), ZoneOffset.UTC);
diff --git a/services/tests/servicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java b/services/tests/servicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java
new file mode 100644
index 0000000..f6a749d
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java
@@ -0,0 +1,169 @@
+/*
+ * 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.job.controllers;
+
+import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.app.job.JobInfo;
+import android.content.ComponentName;
+import android.content.pm.PackageManagerInternal;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.os.Build;
+import android.os.SystemClock;
+import android.support.test.runner.AndroidJUnit4;
+import android.util.DataUnit;
+
+import com.android.server.LocalServices;
+import com.android.server.job.JobSchedulerService;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.time.Clock;
+import java.time.ZoneOffset;
+
+@RunWith(AndroidJUnit4.class)
+public class ConnectivityControllerTest {
+    @Before
+    public void setUp() throws Exception {
+        // Assume all packages are current SDK
+        final PackageManagerInternal pm = mock(PackageManagerInternal.class);
+        when(pm.getPackageTargetSdkVersion(anyString()))
+                .thenReturn(Build.VERSION_CODES.CUR_DEVELOPMENT);
+        LocalServices.removeServiceForTest(PackageManagerInternal.class);
+        LocalServices.addService(PackageManagerInternal.class, pm);
+
+        // Freeze the clocks at this moment in time
+        JobSchedulerService.sSystemClock =
+                Clock.fixed(Clock.systemUTC().instant(), ZoneOffset.UTC);
+        JobSchedulerService.sUptimeMillisClock =
+                Clock.fixed(SystemClock.uptimeMillisClock().instant(), ZoneOffset.UTC);
+        JobSchedulerService.sElapsedRealtimeClock =
+                Clock.fixed(SystemClock.elapsedRealtimeClock().instant(), ZoneOffset.UTC);
+    }
+
+    @Test
+    public void testInsane() throws Exception {
+        final Network network = new Network(101);
+        final JobInfo.Builder job = createJob()
+                .setEstimatedNetworkBytes(DataUnit.MEBIBYTES.toBytes(1))
+                .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY);
+
+        // Slow network is too slow
+        assertFalse(ConnectivityController.isSatisfied(createJobStatus(job), network,
+                createCapabilities().setLinkUpstreamBandwidthKbps(1)
+                        .setLinkDownstreamBandwidthKbps(1)));
+        // Fast network looks great
+        assertTrue(ConnectivityController.isSatisfied(createJobStatus(job), network,
+                createCapabilities().setLinkUpstreamBandwidthKbps(1024)
+                        .setLinkDownstreamBandwidthKbps(1024)));
+    }
+
+    @Test
+    public void testCongestion() throws Exception {
+        final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
+        final JobInfo.Builder job = createJob()
+                .setEstimatedNetworkBytes(DataUnit.MEBIBYTES.toBytes(1))
+                .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY);
+        final JobStatus early = createJobStatus(job, now - 1000, now + 2000);
+        final JobStatus late = createJobStatus(job, now - 2000, now + 1000);
+
+        // Uncongested network is whenever
+        {
+            final Network network = new Network(101);
+            final NetworkCapabilities capabilities = createCapabilities()
+                    .addCapability(NET_CAPABILITY_NOT_CONGESTED);
+            assertTrue(ConnectivityController.isSatisfied(early, network, capabilities));
+            assertTrue(ConnectivityController.isSatisfied(late, network, capabilities));
+        }
+
+        // Congested network is more selective
+        {
+            final Network network = new Network(101);
+            final NetworkCapabilities capabilities = createCapabilities();
+            assertFalse(ConnectivityController.isSatisfied(early, network, capabilities));
+            assertTrue(ConnectivityController.isSatisfied(late, network, capabilities));
+        }
+    }
+
+    @Test
+    public void testRelaxed() throws Exception {
+        final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
+        final JobInfo.Builder job = createJob()
+                .setEstimatedNetworkBytes(DataUnit.MEBIBYTES.toBytes(1))
+                .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED);
+        final JobStatus early = createJobStatus(job, now - 1000, now + 2000);
+        final JobStatus late = createJobStatus(job, now - 2000, now + 1000);
+
+        job.setIsPrefetch(true);
+        final JobStatus earlyPrefetch = createJobStatus(job, now - 1000, now + 2000);
+        final JobStatus latePrefetch = createJobStatus(job, now - 2000, now + 1000);
+
+        // Unmetered network is whenever
+        {
+            final Network network = new Network(101);
+            final NetworkCapabilities capabilities = createCapabilities()
+                    .addCapability(NET_CAPABILITY_NOT_CONGESTED)
+                    .addCapability(NET_CAPABILITY_NOT_METERED);
+            assertTrue(ConnectivityController.isSatisfied(early, network, capabilities));
+            assertTrue(ConnectivityController.isSatisfied(late, network, capabilities));
+            assertTrue(ConnectivityController.isSatisfied(earlyPrefetch, network, capabilities));
+            assertTrue(ConnectivityController.isSatisfied(latePrefetch, network, capabilities));
+        }
+
+        // Metered network is only when prefetching and late
+        {
+            final Network network = new Network(101);
+            final NetworkCapabilities capabilities = createCapabilities()
+                    .addCapability(NET_CAPABILITY_NOT_CONGESTED);
+            assertFalse(ConnectivityController.isSatisfied(early, network, capabilities));
+            assertFalse(ConnectivityController.isSatisfied(late, network, capabilities));
+            assertFalse(ConnectivityController.isSatisfied(earlyPrefetch, network, capabilities));
+            assertTrue(ConnectivityController.isSatisfied(latePrefetch, network, capabilities));
+        }
+    }
+
+    private static NetworkCapabilities createCapabilities() {
+        return new NetworkCapabilities().addCapability(NET_CAPABILITY_INTERNET)
+                .addCapability(NET_CAPABILITY_VALIDATED);
+    }
+
+    private static JobInfo.Builder createJob() {
+        return new JobInfo.Builder(101, new ComponentName("foo", "bar"));
+    }
+
+    private static JobStatus createJobStatus(JobInfo.Builder job) {
+        return createJobStatus(job, 0, Long.MAX_VALUE);
+    }
+
+    private static JobStatus createJobStatus(JobInfo.Builder job, long earliestRunTimeElapsedMillis,
+            long latestRunTimeElapsedMillis) {
+        return new JobStatus(job.build(), 0, null, -1, 0, 0, null, earliestRunTimeElapsedMillis,
+                latestRunTimeElapsedMillis, 0, 0, null);
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/job/controllers/JobStatusTest.java b/services/tests/servicestests/src/com/android/server/job/controllers/JobStatusTest.java
new file mode 100644
index 0000000..15c24ac
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/job/controllers/JobStatusTest.java
@@ -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
+ */
+
+package com.android.server.job.controllers;
+
+import static org.junit.Assert.assertEquals;
+
+import android.app.job.JobInfo;
+import android.content.ComponentName;
+import android.os.SystemClock;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.server.job.JobSchedulerService;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.time.Clock;
+import java.time.ZoneOffset;
+
+@RunWith(AndroidJUnit4.class)
+public class JobStatusTest {
+    private static final double DELTA = 0.00001;
+
+    @Before
+    public void setUp() throws Exception {
+        // Freeze the clocks at this moment in time
+        JobSchedulerService.sSystemClock =
+                Clock.fixed(Clock.systemUTC().instant(), ZoneOffset.UTC);
+        JobSchedulerService.sUptimeMillisClock =
+                Clock.fixed(SystemClock.uptimeMillisClock().instant(), ZoneOffset.UTC);
+        JobSchedulerService.sElapsedRealtimeClock =
+                Clock.fixed(SystemClock.elapsedRealtimeClock().instant(), ZoneOffset.UTC);
+    }
+
+    @Test
+    public void testFraction() throws Exception {
+        final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
+
+        assertEquals(1, createJobStatus(0, Long.MAX_VALUE).getFractionRunTime(), DELTA);
+
+        assertEquals(1, createJobStatus(0, now - 1000).getFractionRunTime(), DELTA);
+        assertEquals(0, createJobStatus(0, now + 1000).getFractionRunTime(), DELTA);
+
+        assertEquals(1, createJobStatus(now - 1000, Long.MAX_VALUE).getFractionRunTime(), DELTA);
+        assertEquals(0, createJobStatus(now + 1000, Long.MAX_VALUE).getFractionRunTime(), DELTA);
+
+        assertEquals(0, createJobStatus(now, now + 2000).getFractionRunTime(), DELTA);
+        assertEquals(0.25, createJobStatus(now - 500, now + 1500).getFractionRunTime(), DELTA);
+        assertEquals(0.5, createJobStatus(now - 1000, now + 1000).getFractionRunTime(), DELTA);
+        assertEquals(0.75, createJobStatus(now - 1500, now + 500).getFractionRunTime(), DELTA);
+        assertEquals(1, createJobStatus(now - 2000, now).getFractionRunTime(), DELTA);
+    }
+
+    private static JobStatus createJobStatus(long earliestRunTimeElapsedMillis,
+            long latestRunTimeElapsedMillis) {
+        final JobInfo job = new JobInfo.Builder(101, new ComponentName("foo", "bar"))
+                .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY).build();
+        return new JobStatus(job, 0, null, -1, 0, 0, null, earliestRunTimeElapsedMillis,
+                latestRunTimeElapsedMillis, 0, 0, null);
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java
index c6fc675..7eec4fe 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java
@@ -78,7 +78,7 @@
     private static final int TEST_RECOVERY_AGENT_UID = 10009;
     private static final int TEST_RECOVERY_AGENT_UID2 = 10010;
     private static final byte[] TEST_VAULT_HANDLE =
-            new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 14, 15, 16, 17};
+            new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
     private static final String TEST_APP_KEY_ALIAS = "rcleaver";
     private static final int TEST_GENERATION_ID = 2;
     private static final int TEST_CREDENTIAL_TYPE = CREDENTIAL_TYPE_PASSWORD;
@@ -278,9 +278,13 @@
     public void run_sendsEncryptedKeysIfAvailableToSync() throws Exception {
         mRecoverableKeyStoreDb.setRecoveryServicePublicKey(
                 TEST_USER_ID, TEST_RECOVERY_AGENT_UID, mKeyPair.getPublic());
+
+        mRecoverableKeyStoreDb.setServerParams(
+                TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_VAULT_HANDLE);
         when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID)).thenReturn(true);
         SecretKey applicationKey =
                 addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS);
+
         mKeySyncTask.run();
 
         KeychainSnapshot keychainSnapshot = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID);
@@ -293,6 +297,7 @@
                 KeyDerivationParams.getSalt(),
                 TEST_CREDENTIAL);
         Long counterId = mRecoverableKeyStoreDb.getCounterId(TEST_USER_ID, TEST_RECOVERY_AGENT_UID);
+        counterId = 1L; // TODO: use value from the database.
         assertThat(counterId).isNotNull();
         byte[] recoveryKey = decryptThmEncryptedKey(
                 lockScreenHash,
@@ -304,6 +309,11 @@
                         TEST_VAULT_HANDLE));
         List<WrappedApplicationKey> applicationKeys = keychainSnapshot.getWrappedApplicationKeys();
         assertThat(applicationKeys).hasSize(1);
+        assertThat(keychainSnapshot.getCounterId()).isEqualTo(counterId);
+        assertThat(keychainSnapshot.getMaxAttempts()).isEqualTo(10);
+        assertThat(keychainSnapshot.getTrustedHardwarePublicKey())
+                .isEqualTo(SecureBox.encodePublicKey(mKeyPair.getPublic()));
+        assertThat(keychainSnapshot.getServerParams()).isEqualTo(TEST_VAULT_HANDLE);
         WrappedApplicationKey keyData = applicationKeys.get(0);
         assertEquals(TEST_APP_KEY_ALIAS, keyData.getAlias());
         assertThat(keyData.getAlias()).isEqualTo(keyData.getAlias());
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncUtilsTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncUtilsTest.java
index ba6b274..a251c9d 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncUtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncUtilsTest.java
@@ -51,7 +51,7 @@
     private static final int THM_KF_HASH_SIZE = 256;
     private static final int KEY_CLAIMANT_LENGTH_BYTES = 16;
     private static final byte[] TEST_VAULT_HANDLE =
-            new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 14, 15, 16, 17};
+            new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17};
     private static final String SHA_256_ALGORITHM = "SHA-256";
     private static final String APPLICATION_KEY_ALGORITHM = "AES";
     private static final byte[] LOCK_SCREEN_HASH_1 =
@@ -417,8 +417,7 @@
         byteBuffer.position(PUBLIC_KEY_LENGTH_BYTES + Long.BYTES + Integer.BYTES);
         byte[] vaultHandle = new byte[VAULT_HANDLE_LENGTH_BYTES];
         byteBuffer.get(vaultHandle);
-        // TODO: Fix this once we fix the code in the KeySyncUtils class
-        assertArrayEquals(new byte[VAULT_HANDLE_LENGTH_BYTES], vaultHandle);
+        assertArrayEquals(TEST_VAULT_HANDLE, vaultHandle);
     }
 
     private static byte[] randomBytes(int n) {
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
index 402a37c..970bc33 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
@@ -330,7 +330,7 @@
                     TEST_VAULT_CHALLENGE,
                     ImmutableList.of());
             fail("should have thrown");
-        } catch (ServiceSpecificException e) {
+        } catch (UnsupportedOperationException e) {
             assertThat(e.getMessage()).startsWith(
                     "Only a single KeychainProtectionParams is supported");
         }
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbTest.java
index 5cb7b67..f0254c6 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbTest.java
@@ -28,8 +28,7 @@
 import org.junit.runner.RunWith;
 
 import android.content.Context;
-import android.content.SharedPreferences;
-import android.security.keystore.RecoveryManager;
+import android.security.keystore.RecoveryController;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
@@ -283,7 +282,7 @@
 
         Map<String, Integer> statuses = mRecoverableKeyStoreDb.getStatusForAllKeys(uid);
         assertThat(statuses).hasSize(3);
-        assertThat(statuses).containsEntry(alias, RecoveryManager.RECOVERY_STATUS_SYNC_IN_PROGRESS);
+        assertThat(statuses).containsEntry(alias, RecoveryController.RECOVERY_STATUS_SYNC_IN_PROGRESS);
         assertThat(statuses).containsEntry(alias2, status);
         assertThat(statuses).containsEntry(alias3, status);
 
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverySessionStorageTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverySessionStorageTest.java
index 0f95748..bb0474e 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverySessionStorageTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverySessionStorageTest.java
@@ -125,7 +125,7 @@
 
         storage.remove(TEST_USER_ID, TEST_SESSION_ID);
 
-        assertNotNull(storage.get(TEST_USER_ID, TEST_SESSION_ID));
+        assertNotNull(storage.get(TEST_USER_ID, otherSessionId));
     }
 
     @Test
diff --git a/services/tests/servicestests/src/com/android/server/net/watchlist/PrivacyUtilsTests.java b/services/tests/servicestests/src/com/android/server/net/watchlist/PrivacyUtilsTests.java
new file mode 100644
index 0000000..a31b46c
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/net/watchlist/PrivacyUtilsTests.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.net.watchlist;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.privacy.DifferentialPrivacyEncoder;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * runtest frameworks-services -c com.android.server.net.watchlist.PrivacyUtilsTests
+ */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class PrivacyUtilsTests {
+
+    private static final List<String> TEST_DIGEST_LIST = Arrays.asList(
+            "B86F9D37425340B635F43D6BC2506630761ADA71F5E6BBDBCA4651C479F9FB43",
+            "E86F9D37425340B635F43D6BC2506630761ADA71F5E6BBDBCA4651C479F9FB45",
+            "C86F9D37425340B635F43D6BC2506630761ADA71F5E6BBDBCA4651C479F9FB44",
+            "C86F9D37425340B635F43D6BC2506630761ADA71F5E6BBDBCA4651C479F9FB47",
+            "C86F9D37425340B635F43D6BC2506630761ADA71F5E6BBDBCA4651C479F9FB48",
+            "C86F9D37425340B635F43D6BC2506630761ADA71F5E6BBDBCA4651C479F9FB49");
+
+    private static final WatchlistReportDbHelper.AggregatedResult TEST_AGGREGATED_RESULT1 =
+            new WatchlistReportDbHelper.AggregatedResult(new HashSet<>(Arrays.asList(
+                    "B86F9D37425340B635F43D6BC2506630761ADA71F5E6BBDBCA4651C479F9FB43",
+                    "C86F9D37425340B635F43D6BC2506630761ADA71F5E6BBDBCA4651C479F9FB48",
+                    "E86F9D37425340B635F43D6BC2506630761ADA71F5E6BBDBCA4651C479F9FB45")), null,
+                    new HashMap<>());
+
+    private static final byte[] TEST_SECRET = new byte[]{
+            (byte) 0xD7, (byte) 0x68, (byte) 0x99, (byte) 0x93,
+            (byte) 0x94, (byte) 0x13, (byte) 0x53, (byte) 0x54,
+            (byte) 0xFE, (byte) 0xD0, (byte) 0x7E, (byte) 0x54,
+            (byte) 0xFE, (byte) 0xD0, (byte) 0x7E, (byte) 0x54,
+            (byte) 0xD7, (byte) 0x68, (byte) 0x99, (byte) 0x93,
+            (byte) 0x94, (byte) 0x13, (byte) 0x53, (byte) 0x54,
+            (byte) 0xFE, (byte) 0xD0, (byte) 0x7E, (byte) 0x54,
+            (byte) 0xFE, (byte) 0xD0, (byte) 0x7E, (byte) 0x54,
+            (byte) 0xD7, (byte) 0x68, (byte) 0x99, (byte) 0x93,
+            (byte) 0x94, (byte) 0x13, (byte) 0x53, (byte) 0x54,
+            (byte) 0xFE, (byte) 0xD0, (byte) 0x7E, (byte) 0x54,
+            (byte) 0xFE, (byte) 0xD0, (byte) 0x7E, (byte) 0x54
+    };
+
+    @Test
+    public void testPrivacyUtils_encodeReport() throws Exception {
+        Map<String, Boolean> result = PrivacyUtils.createDpEncodedReportMap(false, null,
+                TEST_DIGEST_LIST, TEST_AGGREGATED_RESULT1);
+        assertEquals(6, result.size());
+        assertTrue(result.get("C86F9D37425340B635F43D6BC2506630761ADA71F5E6BBDBCA4651C479F9FB48"));
+        assertTrue(result.get("C86F9D37425340B635F43D6BC2506630761ADA71F5E6BBDBCA4651C479F9FB49"));
+        assertFalse(result.get("C86F9D37425340B635F43D6BC2506630761ADA71F5E6BBDBCA4651C479F9FB47"));
+        assertTrue(result.get("E86F9D37425340B635F43D6BC2506630761ADA71F5E6BBDBCA4651C479F9FB45"));
+        assertFalse(result.get("C86F9D37425340B635F43D6BC2506630761ADA71F5E6BBDBCA4651C479F9FB44"));
+        assertTrue(result.get("B86F9D37425340B635F43D6BC2506630761ADA71F5E6BBDBCA4651C479F9FB43"));
+    }
+
+    @Test
+    public void testPrivacyUtils_createInsecureDPEncoderForTest() throws Exception {
+        DifferentialPrivacyEncoder encoder = PrivacyUtils.createInsecureDPEncoderForTest("foo");
+        assertEquals(
+                "EncoderId: watchlist_encoder:foo, ProbabilityF: 0.400, ProbabilityP: 0.250, "
+                        + "ProbabilityQ: 1.000",
+                encoder.getConfig().toString());
+        assertTrue(encoder.isInsecureEncoderForTest());
+    }
+
+    @Test
+    public void testPrivacyUtils_createSecureDPEncoderTest() throws Exception {
+        DifferentialPrivacyEncoder encoder = PrivacyUtils.createSecureDPEncoder(TEST_SECRET, "foo");
+        assertEquals(
+                "EncoderId: watchlist_encoder:foo, ProbabilityF: 0.400, ProbabilityP: 0.250, "
+                        + "ProbabilityQ: 1.000",
+                encoder.getConfig().toString());
+        assertFalse(encoder.isInsecureEncoderForTest());
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/net/watchlist/ReportUtilsTests.java b/services/tests/servicestests/src/com/android/server/net/watchlist/ReportUtilsTests.java
new file mode 100644
index 0000000..395969e
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/net/watchlist/ReportUtilsTests.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.net.watchlist;
+
+import static org.junit.Assert.assertArrayEquals;
+
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.internal.util.HexDump;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.HashMap;
+
+/**
+ * runtest frameworks-services -c com.android.server.net.watchlist.ReportUtilsTests
+ */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class ReportUtilsTests {
+
+    private static final String TEST_XML_1 = "NetworkWatchlistTest/watchlist_config_test1.xml";
+    private static final String TEST_XML_1_HASH =
+            "C99F27A08B1FDB15B101098E12BB2A0AA0D474E23C50F24920A52AB2322BFD94";
+    private static final String REPORT_HEADER_MAGIC = "8D370AAC";
+    private static final String REPORT_HEADER_VERSION = "0001";
+
+    private Context mContext;
+    private File mTestXmlFile;
+
+    @Before
+    public void setUp() throws Exception {
+        mContext = InstrumentationRegistry.getContext();
+        mTestXmlFile =  new File(mContext.getFilesDir(), "test_watchlist_config.xml");
+        mTestXmlFile.delete();
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        mTestXmlFile.delete();
+    }
+
+    @Test
+    public void testReportUtils_serializeReport() throws Exception {
+        final byte[] expectedResult = HexDump.hexStringToByteArray(
+                REPORT_HEADER_MAGIC + REPORT_HEADER_VERSION + TEST_XML_1_HASH
+                        + "B86F9D37425340B635F43D6BC2506630761ADA71F5E6BBDBCA4651C479F9FB43" + "01"
+                        + "C86F9D37425340B635F43D6BC2506630761ADA71F5E6BBDBCA4651C479F9FB44" + "00"
+                        + "D86F9D37425340B635F43D6BC2506630761ADA71F5E6BBDBCA4651C479F9FB45" + "00"
+                        + "E86F9D37425340B635F43D6BC2506630761ADA71F5E6BBDBCA4651C479F9FB46" + "01"
+                        + "F86F9D37425340B635F43D6BC2506630761ADA71F5E6BBDBCA4651C479F9FB47" + "01"
+        );
+        HashMap<String, Boolean> input = new HashMap<>();
+        input.put("C86F9D37425340B635F43D6BC2506630761ADA71F5E6BBDBCA4651C479F9FB44", false);
+        input.put("B86F9D37425340B635F43D6BC2506630761ADA71F5E6BBDBCA4651C479F9FB43", true);
+        input.put("D86F9D37425340B635F43D6BC2506630761ADA71F5E6BBDBCA4651C479F9FB45", false);
+        input.put("E86F9D37425340B635F43D6BC2506630761ADA71F5E6BBDBCA4651C479F9FB46", true);
+        input.put("F86F9D37425340B635F43D6BC2506630761ADA71F5E6BBDBCA4651C479F9FB47", true);
+
+        copyWatchlistConfigXml(mContext, TEST_XML_1, mTestXmlFile);
+        WatchlistConfig config = new WatchlistConfig(mTestXmlFile);
+
+        byte[] result = ReportEncoder.serializeReport(config, input);
+        assertArrayEquals(expectedResult, result);
+    }
+
+    private static void copyWatchlistConfigXml(Context context, String xmlAsset, File outFile)
+            throws IOException {
+        writeToFile(outFile, readAsset(context, xmlAsset));
+    }
+
+    private static String readAsset(Context context, String assetPath) throws IOException {
+        final StringBuilder sb = new StringBuilder();
+        try (BufferedReader br = new BufferedReader(
+                new InputStreamReader(
+                        context.getResources().getAssets().open(assetPath)))) {
+            String line;
+            while ((line = br.readLine()) != null) {
+                sb.append(line);
+                sb.append(System.lineSeparator());
+            }
+        }
+        return sb.toString();
+    }
+
+    private static void writeToFile(File path, String content)
+            throws IOException {
+        path.getParentFile().mkdirs();
+
+        try (FileWriter writer = new FileWriter(path)) {
+            writer.write(content);
+        }
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/net/watchlist/WatchlistConfigTests.java b/services/tests/servicestests/src/com/android/server/net/watchlist/WatchlistConfigTests.java
new file mode 100644
index 0000000..851d2c6
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/net/watchlist/WatchlistConfigTests.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.net.watchlist;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.internal.util.HexDump;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.Arrays;
+
+/**
+ * runtest frameworks-services -c com.android.server.net.watchlist.WatchlistConfigTests
+ */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class WatchlistConfigTests {
+
+    private static final String TEST_XML_1 = "NetworkWatchlistTest/watchlist_config_test1.xml";
+    private static final String TEST_XML_1_HASH =
+            "C99F27A08B1FDB15B101098E12BB2A0AA0D474E23C50F24920A52AB2322BFD94";
+    private static final String TEST_CC_DOMAIN = "test-cc-domain.com";
+    private static final String TEST_CC_IP = "127.0.0.2";
+    private static final String TEST_NOT_EXIST_CC_DOMAIN = "test-not-exist-cc-domain.com";
+    private static final String TEST_NOT_EXIST_CC_IP = "1.2.3.4";
+    private static final String TEST_SHA256_ONLY_DOMAIN = "test-cc-match-sha256-only.com";
+    private static final String TEST_SHA256_ONLY_IP = "127.0.0.3";
+    private static final String TEST_CRC32_ONLY_DOMAIN = "test-cc-match-crc32-only.com";
+    private static final String TEST_CRC32_ONLY_IP = "127.0.0.4";
+
+    private static final String TEST_NEW_CC_DOMAIN = "test-new-cc-domain.com";
+    private static final byte[] TEST_NEW_CC_DOMAIN_SHA256 = HexDump.hexStringToByteArray(
+            "B86F9D37425340B635F43D6BC2506630761ADA71F5E6BBDBCA4651C479F9FB43");
+    private static final byte[] TEST_NEW_CC_DOMAIN_CRC32 = HexDump.hexStringToByteArray("76795BD3");
+
+    private static final String TEST_NEW_CC_IP = "1.1.1.2";
+    private static final byte[] TEST_NEW_CC_IP_SHA256 = HexDump.hexStringToByteArray(
+            "721BAB5E313CF0CC76B10F9592F18B9D1B8996497501A3306A55B3AE9F1CC87C");
+    private static final byte[] TEST_NEW_CC_IP_CRC32 = HexDump.hexStringToByteArray("940B8BEE");
+
+    private Context mContext;
+    private File mTestXmlFile;
+
+    @Before
+    public void setUp() throws Exception {
+        mContext = InstrumentationRegistry.getContext();
+        mTestXmlFile =  new File(mContext.getFilesDir(), "test_watchlist_config.xml");
+        mTestXmlFile.delete();
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        mTestXmlFile.delete();
+    }
+
+    @Test
+    public void testWatchlistConfig_parsing() throws Exception {
+        copyWatchlistConfigXml(mContext, TEST_XML_1, mTestXmlFile);
+        WatchlistConfig config = new WatchlistConfig(mTestXmlFile);
+        assertTrue(config.containsDomain(TEST_CC_DOMAIN));
+        assertTrue(config.containsIp(TEST_CC_IP));
+        assertFalse(config.containsDomain(TEST_NOT_EXIST_CC_DOMAIN));
+        assertFalse(config.containsIp(TEST_NOT_EXIST_CC_IP));
+        assertFalse(config.containsDomain(TEST_SHA256_ONLY_DOMAIN));
+        assertFalse(config.containsIp(TEST_SHA256_ONLY_IP));
+        assertFalse(config.containsDomain(TEST_CRC32_ONLY_DOMAIN));
+        assertFalse(config.containsIp(TEST_CRC32_ONLY_IP));
+    }
+
+    @Test
+    public void testWatchlistConfig_noXml() throws Exception {
+        WatchlistConfig config = new WatchlistConfig(mTestXmlFile);
+        assertFalse(config.containsDomain(TEST_CC_DOMAIN));
+        assertFalse(config.containsIp(TEST_CC_IP));
+        assertFalse(config.containsDomain(TEST_NOT_EXIST_CC_DOMAIN));
+        assertFalse(config.containsIp(TEST_NOT_EXIST_CC_IP));
+        assertFalse(config.containsDomain(TEST_SHA256_ONLY_DOMAIN));
+        assertFalse(config.containsIp(TEST_SHA256_ONLY_IP));
+        assertFalse(config.containsDomain(TEST_CRC32_ONLY_DOMAIN));
+        assertFalse(config.containsIp(TEST_CRC32_ONLY_IP));
+    }
+
+    @Test
+    public void testWatchlistConfig_getWatchlistConfigHash() throws Exception {
+        copyWatchlistConfigXml(mContext, TEST_XML_1, mTestXmlFile);
+        WatchlistConfig config = new WatchlistConfig(mTestXmlFile);
+        assertEquals(TEST_XML_1_HASH, HexDump.toHexString(config.getWatchlistConfigHash()));
+    }
+
+    private static void copyWatchlistConfigXml(Context context, String xmlAsset, File outFile)
+            throws IOException {
+        writeToFile(outFile, readAsset(context, xmlAsset));
+    }
+
+    private static String readAsset(Context context, String assetPath) throws IOException {
+        final StringBuilder sb = new StringBuilder();
+        try (BufferedReader br = new BufferedReader(
+                new InputStreamReader(
+                        context.getResources().getAssets().open(assetPath)))) {
+            String line;
+            while ((line = br.readLine()) != null) {
+                sb.append(line);
+                sb.append(System.lineSeparator());
+            }
+        }
+        return sb.toString();
+    }
+
+    private static void writeToFile(File path, String content)
+            throws IOException {
+        path.getParentFile().mkdirs();
+
+        try (FileWriter writer = new FileWriter(path)) {
+            writer.write(content);
+        }
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/net/watchlist/WatchlistLoggingHandlerTests.java b/services/tests/servicestests/src/com/android/server/net/watchlist/WatchlistLoggingHandlerTests.java
index e356b13..070de5b 100644
--- a/services/tests/servicestests/src/com/android/server/net/watchlist/WatchlistLoggingHandlerTests.java
+++ b/services/tests/servicestests/src/com/android/server/net/watchlist/WatchlistLoggingHandlerTests.java
@@ -36,14 +36,6 @@
 @SmallTest
 public class WatchlistLoggingHandlerTests {
 
-    @Before
-    public void setUp() throws Exception {
-    }
-
-    @After
-    public void tearDown() throws Exception {
-    }
-
     @Test
     public void testWatchlistLoggingHandler_getAllSubDomains() throws Exception {
         String[] subDomains = WatchlistLoggingHandler.getAllSubDomains("abc.def.gh.i.jkl.mm");
diff --git a/services/tests/servicestests/src/com/android/server/net/watchlist/WatchlistSettingsTests.java b/services/tests/servicestests/src/com/android/server/net/watchlist/WatchlistSettingsTests.java
index 212d25d..07158af 100644
--- a/services/tests/servicestests/src/com/android/server/net/watchlist/WatchlistSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/net/watchlist/WatchlistSettingsTests.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright 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.
@@ -16,8 +16,8 @@
 
 package com.android.server.net.watchlist;
 
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
 
 import android.content.Context;
 import android.support.test.InstrumentationRegistry;
@@ -36,7 +36,6 @@
 import java.io.FileWriter;
 import java.io.IOException;
 import java.io.InputStreamReader;
-import java.util.Arrays;
 
 /**
  * runtest frameworks-services -c com.android.server.net.watchlist.WatchlistSettingsTests
@@ -46,24 +45,9 @@
 public class WatchlistSettingsTests {
 
     private static final String TEST_XML_1 = "NetworkWatchlistTest/watchlist_settings_test1.xml";
-    private static final String TEST_CC_DOMAIN = "test-cc-domain.com";
-    private static final String TEST_CC_IP = "127.0.0.2";
-    private static final String TEST_NOT_EXIST_CC_DOMAIN = "test-not-exist-cc-domain.com";
-    private static final String TEST_NOT_EXIST_CC_IP = "1.2.3.4";
-    private static final String TEST_SHA256_ONLY_DOMAIN = "test-cc-match-sha256-only.com";
-    private static final String TEST_SHA256_ONLY_IP = "127.0.0.3";
-    private static final String TEST_CRC32_ONLY_DOMAIN = "test-cc-match-crc32-only.com";
-    private static final String TEST_CRC32_ONLY_IP = "127.0.0.4";
-
-    private static final String TEST_NEW_CC_DOMAIN = "test-new-cc-domain.com";
-    private static final byte[] TEST_NEW_CC_DOMAIN_SHA256 = HexDump.hexStringToByteArray(
-            "B86F9D37425340B635F43D6BC2506630761ADA71F5E6BBDBCA4651C479F9FB43");
-    private static final byte[] TEST_NEW_CC_DOMAIN_CRC32 = HexDump.hexStringToByteArray("76795BD3");
-
-    private static final String TEST_NEW_CC_IP = "1.1.1.2";
-    private static final byte[] TEST_NEW_CC_IP_SHA256 = HexDump.hexStringToByteArray(
-            "721BAB5E313CF0CC76B10F9592F18B9D1B8996497501A3306A55B3AE9F1CC87C");
-    private static final byte[] TEST_NEW_CC_IP_CRC32 = HexDump.hexStringToByteArray("940B8BEE");
+    private static final String TEST_XML_2 = "NetworkWatchlistTest/watchlist_settings_test2.xml";
+    private static final String HARD_CODED_SECRET_KEY = "1234567890ABCDEF1234567890ABCDEF"
+            + "1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF";
 
     private Context mContext;
     private File mTestXmlFile;
@@ -71,7 +55,7 @@
     @Before
     public void setUp() throws Exception {
         mContext = InstrumentationRegistry.getContext();
-        mTestXmlFile =  new File(mContext.getFilesDir(), "test_watchlist_settings.xml");
+        mTestXmlFile = new File(mContext.getFilesDir(), "test_settings_config.xml");
         mTestXmlFile.delete();
     }
 
@@ -84,55 +68,48 @@
     public void testWatchlistSettings_parsing() throws Exception {
         copyWatchlistSettingsXml(mContext, TEST_XML_1, mTestXmlFile);
         WatchlistSettings settings = new WatchlistSettings(mTestXmlFile);
-        assertTrue(settings.containsDomain(TEST_CC_DOMAIN));
-        assertTrue(settings.containsIp(TEST_CC_IP));
-        assertFalse(settings.containsDomain(TEST_NOT_EXIST_CC_DOMAIN));
-        assertFalse(settings.containsIp(TEST_NOT_EXIST_CC_IP));
-        assertFalse(settings.containsDomain(TEST_SHA256_ONLY_DOMAIN));
-        assertFalse(settings.containsIp(TEST_SHA256_ONLY_IP));
-        assertFalse(settings.containsDomain(TEST_CRC32_ONLY_DOMAIN));
-        assertFalse(settings.containsIp(TEST_CRC32_ONLY_IP));
+        assertEquals(HARD_CODED_SECRET_KEY, HexDump.toHexString(settings.getPrivacySecretKey()));
+        // Try again.
+        assertEquals(HARD_CODED_SECRET_KEY, HexDump.toHexString(settings.getPrivacySecretKey()));
     }
 
     @Test
-    public void testWatchlistSettings_writeSettingsToMemory() throws Exception {
-        copyWatchlistSettingsXml(mContext, TEST_XML_1, mTestXmlFile);
+    public void testWatchlistSettings_parsingWithoutKey() throws Exception {
+        copyWatchlistSettingsXml(mContext, TEST_XML_2, mTestXmlFile);
         WatchlistSettings settings = new WatchlistSettings(mTestXmlFile);
-        settings.writeSettingsToMemory(Arrays.asList(TEST_NEW_CC_DOMAIN_CRC32),
-                Arrays.asList(TEST_NEW_CC_DOMAIN_SHA256), Arrays.asList(TEST_NEW_CC_IP_CRC32),
-                Arrays.asList(TEST_NEW_CC_IP_SHA256));
-        // Ensure old watchlist is not in memory
-        assertFalse(settings.containsDomain(TEST_CC_DOMAIN));
-        assertFalse(settings.containsIp(TEST_CC_IP));
-        assertFalse(settings.containsDomain(TEST_NOT_EXIST_CC_DOMAIN));
-        assertFalse(settings.containsIp(TEST_NOT_EXIST_CC_IP));
-        assertFalse(settings.containsDomain(TEST_SHA256_ONLY_DOMAIN));
-        assertFalse(settings.containsIp(TEST_SHA256_ONLY_IP));
-        assertFalse(settings.containsDomain(TEST_CRC32_ONLY_DOMAIN));
-        assertFalse(settings.containsIp(TEST_CRC32_ONLY_IP));
-        // Ensure new watchlist is in memory
-        assertTrue(settings.containsDomain(TEST_NEW_CC_DOMAIN));
-        assertTrue(settings.containsIp(TEST_NEW_CC_IP));
-        // Reload settings from disk and test again
+        final String tmpKey1 = HexDump.toHexString(settings.getPrivacySecretKey());
+        assertNotEquals(HARD_CODED_SECRET_KEY, tmpKey1);
+        assertEquals(96, tmpKey1.length());
+        // Try again to make sure it's the same.
+        assertEquals(tmpKey1, HexDump.toHexString(settings.getPrivacySecretKey()));
+        // Create new settings object again to make sure it can get the new saved key.
         settings = new WatchlistSettings(mTestXmlFile);
-        // Ensure old watchlist is in memory
-        assertTrue(settings.containsDomain(TEST_CC_DOMAIN));
-        assertTrue(settings.containsIp(TEST_CC_IP));
-        assertFalse(settings.containsDomain(TEST_NOT_EXIST_CC_DOMAIN));
-        assertFalse(settings.containsIp(TEST_NOT_EXIST_CC_IP));
-        assertFalse(settings.containsDomain(TEST_SHA256_ONLY_DOMAIN));
-        assertFalse(settings.containsIp(TEST_SHA256_ONLY_IP));
-        assertFalse(settings.containsDomain(TEST_CRC32_ONLY_DOMAIN));
-        assertFalse(settings.containsIp(TEST_CRC32_ONLY_IP));
-        // Ensure new watchlist is not in memory
-        assertFalse(settings.containsDomain(TEST_NEW_CC_DOMAIN));
-        assertFalse(settings.containsIp(TEST_NEW_CC_IP));;
+        assertEquals(tmpKey1, HexDump.toHexString(settings.getPrivacySecretKey()));
+    }
+
+    @Test
+    public void testWatchlistSettings_noExistingXml() throws Exception {
+        WatchlistSettings settings = new WatchlistSettings(mTestXmlFile);
+        final String tmpKey1 = HexDump.toHexString(settings.getPrivacySecretKey());
+        assertNotEquals(HARD_CODED_SECRET_KEY, tmpKey1);
+        assertEquals(96, tmpKey1.length());
+        // Try again to make sure it's the same.
+        assertEquals(tmpKey1, HexDump.toHexString(settings.getPrivacySecretKey()));
+        // Create new settings object again to make sure it can get the new saved key.
+        settings = new WatchlistSettings(mTestXmlFile);
+        assertEquals(tmpKey1, HexDump.toHexString(settings.getPrivacySecretKey()));
+        // Delete xml and generate key again, to make sure key is randomly generated.
+        mTestXmlFile.delete();
+        settings = new WatchlistSettings(mTestXmlFile);
+        final String tmpKey2 = HexDump.toHexString(settings.getPrivacySecretKey());
+        assertNotEquals(HARD_CODED_SECRET_KEY, tmpKey2);
+        assertNotEquals(tmpKey1, tmpKey2);
+        assertEquals(96, tmpKey2.length());
     }
 
     private static void copyWatchlistSettingsXml(Context context, String xmlAsset, File outFile)
             throws IOException {
         writeToFile(outFile, readAsset(context, xmlAsset));
-
     }
 
     private static String readAsset(Context context, String assetPath) throws IOException {
diff --git a/services/tests/servicestests/src/com/android/server/pm/crossprofile/CrossProfileAppsServiceImplTest.java b/services/tests/servicestests/src/com/android/server/pm/CrossProfileAppsServiceImplTest.java
similarity index 98%
rename from services/tests/servicestests/src/com/android/server/pm/crossprofile/CrossProfileAppsServiceImplTest.java
rename to services/tests/servicestests/src/com/android/server/pm/CrossProfileAppsServiceImplTest.java
index ff55a2b..c69437dc 100644
--- a/services/tests/servicestests/src/com/android/server/pm/crossprofile/CrossProfileAppsServiceImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/CrossProfileAppsServiceImplTest.java
@@ -1,9 +1,7 @@
-package com.android.server.pm.crossprofile;
+package com.android.server.pm;
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static junit.framework.Assert.assertEquals;
-
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyString;
@@ -34,7 +32,6 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.junit.MockitoJUnitRunner;
 
@@ -44,7 +41,7 @@
 
 /**
  * Build/Install/Run:
- * bit FrameworksServicesTests:com.android.server.pm.crossprofile.CrossProfileAppsServiceImplTest
+ * atest FrameworksServicesTests:com.android.server.pm.CrossProfileAppsServiceImplTest
  */
 @Presubmit
 @RunWith(MockitoJUnitRunner.class)
diff --git a/services/tests/servicestests/src/com/android/server/wm/DragDropControllerTests.java b/services/tests/servicestests/src/com/android/server/wm/DragDropControllerTests.java
index ac29163..57da6a3 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DragDropControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DragDropControllerTests.java
@@ -20,7 +20,6 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
 import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.mock;
@@ -28,6 +27,7 @@
 import static org.mockito.Mockito.when;
 
 import android.content.ClipData;
+import android.graphics.PixelFormat;
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.UserHandle;
@@ -36,7 +36,7 @@
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 import android.view.InputChannel;
-import android.view.Surface;
+import android.view.SurfaceControl;
 import android.view.SurfaceSession;
 import android.view.View;
 import com.android.internal.annotations.GuardedBy;
@@ -146,14 +146,6 @@
     }
 
     @Test
-    public void testPrepareDrag_ZeroSizeSurface() throws Exception {
-        final Surface surface = new Surface();
-        mToken = mTarget.prepareDrag(
-                new SurfaceSession(), 0, 0, mWindow.mClient, 0, 0, 0, surface);
-        assertNull(mToken);
-    }
-
-    @Test
     public void testPerformDrag_NullDataWithGrantUri() throws Exception {
         dragFlow(View.DRAG_FLAG_GLOBAL | View.DRAG_FLAG_GLOBAL_URI_READ, null, 0, 0);
     }
@@ -169,16 +161,24 @@
     }
 
     private void dragFlow(int flag, ClipData data, float dropX, float dropY) {
-        final Surface surface = new Surface();
-        mToken = mTarget.prepareDrag(
-                new SurfaceSession(), 0, 0, mWindow.mClient, flag, 100, 100, surface);
-        assertNotNull(mToken);
+        final SurfaceSession appSession = new SurfaceSession();
+        try {
+            final SurfaceControl surface = new SurfaceControl.Builder(appSession)
+                    .setName("drag surface")
+                    .setSize(100, 100)
+                    .setFormat(PixelFormat.TRANSLUCENT)
+                    .build();
 
-        assertTrue(sWm.mInputManager.transferTouchFocus(null, null));
-        assertTrue(mTarget.performDrag(
-                mWindow.mClient, mToken, 0, 0, 0, 0, 0, data));
+            assertTrue(sWm.mInputManager.transferTouchFocus(null, null));
+            mToken = mTarget.performDrag(
+                    new SurfaceSession(), 0, 0, mWindow.mClient, flag, surface, 0, 0, 0, 0, 0,
+                    data);
+            assertNotNull(mToken);
 
-        mTarget.handleMotionEvent(false, dropX, dropY);
-        mToken = mWindow.mClient.asBinder();
+            mTarget.handleMotionEvent(false, dropX, dropY);
+            mToken = mWindow.mClient.asBinder();
+        } finally {
+            appSession.kill();
+        }
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/wm/TaskPositionerTests.java b/services/tests/servicestests/src/com/android/server/wm/TaskPositionerTests.java
index 873a01b..7bf7dd7 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TaskPositionerTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TaskPositionerTests.java
@@ -33,6 +33,7 @@
 import static com.android.server.wm.WindowState.MINIMUM_VISIBLE_HEIGHT_IN_DP;
 import static com.android.server.wm.WindowState.MINIMUM_VISIBLE_WIDTH_IN_DP;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
 /**
@@ -57,6 +58,9 @@
     @Before
     public void setUp() throws Exception {
         super.setUp();
+
+        TaskPositioner.setFactory(null);
+
         final Display display = mDisplayContent.getDisplay();
         final DisplayMetrics dm = new DisplayMetrics();
         display.getMetrics(dm);
@@ -65,10 +69,26 @@
         mMinVisibleWidth = dipToPixel(MINIMUM_VISIBLE_WIDTH_IN_DP, dm);
         mMinVisibleHeight = dipToPixel(MINIMUM_VISIBLE_HEIGHT_IN_DP, dm);
 
-        mPositioner = new TaskPositioner(sWm);
+        mPositioner = TaskPositioner.create(sWm);
         mPositioner.register(mDisplayContent);
     }
 
+    @Test
+    public void testOverrideFactory() throws Exception {
+        final boolean[] created = new boolean[1];
+        created[0] = false;
+        TaskPositioner.setFactory(new TaskPositioner.Factory() {
+            @Override
+            public TaskPositioner create(WindowManagerService service) {
+                created[0] = true;
+                return null;
+            }
+        });
+
+        assertNull(TaskPositioner.create(sWm));
+        assertTrue(created[0]);
+    }
+
     /**
      * This tests that free resizing will allow to change the orientation as well
      * as does some basic tests (e.g. dragging in Y only will keep X stable).
diff --git a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
index 5ed17cc..35ca493 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
@@ -539,7 +539,7 @@
     }
 
     @Override
-    public void showRecentApps(boolean fromHome) {
+    public void showRecentApps() {
 
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/wm/ZOrderingTests.java b/services/tests/servicestests/src/com/android/server/wm/ZOrderingTests.java
index 6468763..5f44fb6 100644
--- a/services/tests/servicestests/src/com/android/server/wm/ZOrderingTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/ZOrderingTests.java
@@ -17,14 +17,17 @@
 package com.android.server.wm;
 
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
+import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL;
 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL;
@@ -74,11 +77,11 @@
             return super.setRelativeLayer(sc, relativeTo, layer);
         }
 
-        int getLayer(SurfaceControl sc) {
+        private int getLayer(SurfaceControl sc) {
             return mLayersForControl.getOrDefault(sc, 0);
         }
 
-        SurfaceControl getRelativeLayer(SurfaceControl sc) {
+        private SurfaceControl getRelativeLayer(SurfaceControl sc) {
             return mRelativeLayersForControl.get(sc);
         }
     };
@@ -146,8 +149,9 @@
         return p;
     }
 
-    void assertZOrderGreaterThan(LayerRecordingTransaction t,
-            SurfaceControl left, SurfaceControl right) throws Exception {
+
+    void assertZOrderGreaterThan(LayerRecordingTransaction t, SurfaceControl left,
+            SurfaceControl right) throws Exception {
         final LinkedList<SurfaceControl> leftParentChain = getAncestors(t, left);
         final LinkedList<SurfaceControl> rightParentChain = getAncestors(t, right);
 
@@ -171,9 +175,12 @@
         }
     }
 
-    void assertWindowLayerGreaterThan(LayerRecordingTransaction t,
-            WindowState left, WindowState right) throws Exception {
-        assertZOrderGreaterThan(t, left.getSurfaceControl(), right.getSurfaceControl());
+    void assertWindowHigher(WindowState left, WindowState right) throws Exception {
+        assertZOrderGreaterThan(mTransaction, left.getSurfaceControl(), right.getSurfaceControl());
+    }
+
+    WindowState createWindow(String name) {
+        return createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, name);
     }
 
     @Test
@@ -184,38 +191,37 @@
         // The Ime has an higher base layer than app windows and lower base layer than system
         // windows, so it should be above app windows and below system windows if there isn't an IME
         // target.
-        assertWindowLayerGreaterThan(mTransaction, mImeWindow, mChildAppWindowAbove);
-        assertWindowLayerGreaterThan(mTransaction, mImeWindow, mAppWindow);
-        assertWindowLayerGreaterThan(mTransaction, mNavBarWindow, mImeWindow);
-        assertWindowLayerGreaterThan(mTransaction, mStatusBarWindow, mImeWindow);
+        assertWindowHigher(mImeWindow, mChildAppWindowAbove);
+        assertWindowHigher(mImeWindow, mAppWindow);
+        assertWindowHigher(mNavBarWindow, mImeWindow);
+        assertWindowHigher(mStatusBarWindow, mImeWindow);
 
         // And, IME dialogs should always have an higher layer than the IME.
-        assertWindowLayerGreaterThan(mTransaction, mImeDialogWindow, mImeWindow);
+        assertWindowHigher(mImeDialogWindow, mImeWindow);
     }
 
     @Test
     public void testAssignWindowLayers_ForImeWithAppTarget() throws Exception {
-        final WindowState imeAppTarget =
-                createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "imeAppTarget");
+        final WindowState imeAppTarget = createWindow("imeAppTarget");
         sWm.mInputMethodTarget = imeAppTarget;
+
         mDisplayContent.assignChildLayers(mTransaction);
 
         // Ime should be above all app windows and below system windows if it is targeting an app
         // window.
-        assertWindowLayerGreaterThan(mTransaction, mImeWindow, imeAppTarget);
-        assertWindowLayerGreaterThan(mTransaction, mImeWindow, mChildAppWindowAbove);
-        assertWindowLayerGreaterThan(mTransaction, mImeWindow, mAppWindow);
-        assertWindowLayerGreaterThan(mTransaction, mNavBarWindow, mImeWindow);
-        assertWindowLayerGreaterThan(mTransaction, mStatusBarWindow, mImeWindow);
+        assertWindowHigher(mImeWindow, imeAppTarget);
+        assertWindowHigher(mImeWindow, mChildAppWindowAbove);
+        assertWindowHigher(mImeWindow, mAppWindow);
+        assertWindowHigher(mNavBarWindow, mImeWindow);
+        assertWindowHigher(mStatusBarWindow, mImeWindow);
 
         // And, IME dialogs should always have an higher layer than the IME.
-        assertWindowLayerGreaterThan(mTransaction, mImeDialogWindow, mImeWindow);
+        assertWindowHigher(mImeDialogWindow, mImeWindow);
     }
 
     @Test
     public void testAssignWindowLayers_ForImeWithAppTargetWithChildWindows() throws Exception {
-        final WindowState imeAppTarget =
-                createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "imeAppTarget");
+        final WindowState imeAppTarget = createWindow("imeAppTarget");
         final WindowState imeAppTargetChildAboveWindow = createWindow(imeAppTarget,
                 TYPE_APPLICATION_ATTACHED_DIALOG, imeAppTarget.mToken,
                 "imeAppTargetChildAboveWindow");
@@ -228,41 +234,38 @@
 
         // Ime should be above all app windows except for child windows that are z-ordered above it
         // and below system windows if it is targeting an app window.
-        assertWindowLayerGreaterThan(mTransaction, mImeWindow, imeAppTarget);
-        assertWindowLayerGreaterThan(mTransaction, imeAppTargetChildAboveWindow, mImeWindow);
-        assertWindowLayerGreaterThan(mTransaction, mImeWindow, mChildAppWindowAbove);
-        assertWindowLayerGreaterThan(mTransaction, mImeWindow, mAppWindow);
-        assertWindowLayerGreaterThan(mTransaction, mNavBarWindow, mImeWindow);
-        assertWindowLayerGreaterThan(mTransaction, mStatusBarWindow, mImeWindow);
+        assertWindowHigher(mImeWindow, imeAppTarget);
+        assertWindowHigher(imeAppTargetChildAboveWindow, mImeWindow);
+        assertWindowHigher(mImeWindow, mChildAppWindowAbove);
+        assertWindowHigher(mImeWindow, mAppWindow);
+        assertWindowHigher(mNavBarWindow, mImeWindow);
+        assertWindowHigher(mStatusBarWindow, mImeWindow);
 
         // And, IME dialogs should always have an higher layer than the IME.
-        assertWindowLayerGreaterThan(mTransaction, mImeDialogWindow, mImeWindow);
+        assertWindowHigher(mImeDialogWindow, mImeWindow);
     }
 
     @Test
     public void testAssignWindowLayers_ForImeWithAppTargetAndAppAbove() throws Exception {
-        final WindowState appBelowImeTarget =
-                createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "appBelowImeTarget");
-        final WindowState imeAppTarget =
-                createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "imeAppTarget");
-        final WindowState appAboveImeTarget =
-                createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "appAboveImeTarget");
+        final WindowState appBelowImeTarget = createWindow("appBelowImeTarget");
+        final WindowState imeAppTarget = createWindow("imeAppTarget");
+        final WindowState appAboveImeTarget = createWindow("appAboveImeTarget");
 
         sWm.mInputMethodTarget = imeAppTarget;
         mDisplayContent.assignChildLayers(mTransaction);
 
         // Ime should be above all app windows except for non-fullscreen app window above it and
         // below system windows if it is targeting an app window.
-        assertWindowLayerGreaterThan(mTransaction, mImeWindow, imeAppTarget);
-        assertWindowLayerGreaterThan(mTransaction, mImeWindow, appBelowImeTarget);
-        assertWindowLayerGreaterThan(mTransaction, appAboveImeTarget, mImeWindow);
-        assertWindowLayerGreaterThan(mTransaction, mImeWindow, mChildAppWindowAbove);
-        assertWindowLayerGreaterThan(mTransaction, mImeWindow, mAppWindow);
-        assertWindowLayerGreaterThan(mTransaction, mNavBarWindow, mImeWindow);
-        assertWindowLayerGreaterThan(mTransaction, mStatusBarWindow, mImeWindow);
+        assertWindowHigher(mImeWindow, imeAppTarget);
+        assertWindowHigher(mImeWindow, appBelowImeTarget);
+        assertWindowHigher(appAboveImeTarget, mImeWindow);
+        assertWindowHigher(mImeWindow, mChildAppWindowAbove);
+        assertWindowHigher(mImeWindow, mAppWindow);
+        assertWindowHigher(mNavBarWindow, mImeWindow);
+        assertWindowHigher(mStatusBarWindow, mImeWindow);
 
         // And, IME dialogs should always have an higher layer than the IME.
-        assertWindowLayerGreaterThan(mTransaction, mImeDialogWindow, mImeWindow);
+        assertWindowHigher(mImeDialogWindow, mImeWindow);
     }
 
     @Test
@@ -276,20 +279,20 @@
 
         // The IME target base layer is higher than all window except for the nav bar window, so the
         // IME should be above all windows except for the nav bar.
-        assertWindowLayerGreaterThan(mTransaction, mImeWindow, imeSystemOverlayTarget);
-        assertWindowLayerGreaterThan(mTransaction, mImeWindow, mChildAppWindowAbove);
-        assertWindowLayerGreaterThan(mTransaction, mImeWindow, mAppWindow);
-        assertWindowLayerGreaterThan(mTransaction, mImeWindow, mDockedDividerWindow);
+        assertWindowHigher(mImeWindow, imeSystemOverlayTarget);
+        assertWindowHigher(mImeWindow, mChildAppWindowAbove);
+        assertWindowHigher(mImeWindow, mAppWindow);
+        assertWindowHigher(mImeWindow, mDockedDividerWindow);
 
         // The IME has a higher base layer than the status bar so we may expect it to go
         // above the status bar once they are both in the Non-App layer, as past versions of this
         // test enforced. However this seems like the wrong behavior unless the status bar is the
         // IME target.
-        assertWindowLayerGreaterThan(mTransaction, mNavBarWindow, mImeWindow);
-        assertWindowLayerGreaterThan(mTransaction, mStatusBarWindow, mImeWindow);
+        assertWindowHigher(mNavBarWindow, mImeWindow);
+        assertWindowHigher(mStatusBarWindow, mImeWindow);
 
         // And, IME dialogs should always have an higher layer than the IME.
-        assertWindowLayerGreaterThan(mTransaction, mImeDialogWindow, mImeWindow);
+        assertWindowHigher(mImeDialogWindow, mImeWindow);
     }
 
     @Test
@@ -297,17 +300,18 @@
         sWm.mInputMethodTarget = mStatusBarWindow;
         mDisplayContent.assignChildLayers(mTransaction);
 
-        assertWindowLayerGreaterThan(mTransaction, mImeWindow, mChildAppWindowAbove);
-        assertWindowLayerGreaterThan(mTransaction, mImeWindow, mAppWindow);
-        assertWindowLayerGreaterThan(mTransaction, mImeWindow, mDockedDividerWindow);
-        assertWindowLayerGreaterThan(mTransaction, mImeWindow, mStatusBarWindow);
+        assertWindowHigher(mImeWindow, mChildAppWindowAbove);
+        assertWindowHigher(mImeWindow, mAppWindow);
+        assertWindowHigher(mImeWindow, mDockedDividerWindow);
+        assertWindowHigher(mImeWindow, mStatusBarWindow);
 
         // And, IME dialogs should always have an higher layer than the IME.
-        assertWindowLayerGreaterThan(mTransaction, mImeDialogWindow, mImeWindow);
+        assertWindowHigher(mImeDialogWindow, mImeWindow);
     }
 
     @Test
     public void testStackLayers() throws Exception {
+        final WindowState anyWindow1 = createWindow("anyWindow");
         final WindowState pinnedStackWindow = createWindowOnStack(null, WINDOWING_MODE_PINNED,
                 ACTIVITY_TYPE_STANDARD, TYPE_BASE_APPLICATION, mDisplayContent,
                 "pinnedStackWindow");
@@ -317,12 +321,22 @@
         final WindowState assistantStackWindow = createWindowOnStack(null, WINDOWING_MODE_FULLSCREEN,
                 ACTIVITY_TYPE_ASSISTANT, TYPE_BASE_APPLICATION,
                 mDisplayContent, "assistantStackWindow");
+        final WindowState homeActivityWindow = createWindowOnStack(null, WINDOWING_MODE_FULLSCREEN,
+                ACTIVITY_TYPE_HOME, TYPE_BASE_APPLICATION,
+                mDisplayContent, "homeActivityWindow");
+        final WindowState anyWindow2 = createWindow("anyWindow2");
 
         mDisplayContent.assignChildLayers(mTransaction);
 
-        assertWindowLayerGreaterThan(mTransaction, dockedStackWindow, mAppWindow);
-        assertWindowLayerGreaterThan(mTransaction, assistantStackWindow, dockedStackWindow);
-        assertWindowLayerGreaterThan(mTransaction, pinnedStackWindow, assistantStackWindow);
+        assertWindowHigher(dockedStackWindow, homeActivityWindow);
+        assertWindowHigher(assistantStackWindow, homeActivityWindow);
+        assertWindowHigher(pinnedStackWindow, homeActivityWindow);
+        assertWindowHigher(anyWindow1, homeActivityWindow);
+        assertWindowHigher(anyWindow2, homeActivityWindow);
+        assertWindowHigher(pinnedStackWindow, anyWindow1);
+        assertWindowHigher(pinnedStackWindow, anyWindow2);
+        assertWindowHigher(pinnedStackWindow, dockedStackWindow);
+        assertWindowHigher(pinnedStackWindow, assistantStackWindow);
     }
 
     @Test
@@ -337,9 +351,9 @@
 
         // Ime should be above all app windows and below system windows if it is targeting an app
         // window.
-        assertWindowLayerGreaterThan(mTransaction, navBarPanel, mNavBarWindow);
-        assertWindowLayerGreaterThan(mTransaction, statusBarPanel, mStatusBarWindow);
-        assertWindowLayerGreaterThan(mTransaction, statusBarSubPanel, statusBarPanel);
+        assertWindowHigher(navBarPanel, mNavBarWindow);
+        assertWindowHigher(statusBarPanel, mStatusBarWindow);
+        assertWindowHigher(statusBarSubPanel, statusBarPanel);
     }
 
     @Test
@@ -347,8 +361,7 @@
         // TODO(b/70040778): We should aim to eliminate the last user of TYPE_APPLICATION_MEDIA
         // then we can drop all negative layering on the windowing side.
 
-        final WindowState anyWindow =
-                createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "anyWindow");
+        final WindowState anyWindow = createWindow("anyWindow");
         final WindowState child = createWindow(anyWindow, TYPE_APPLICATION_MEDIA, mDisplayContent,
                 "TypeApplicationMediaChild");
         final WindowState mediaOverlayChild = createWindow(anyWindow, TYPE_APPLICATION_MEDIA_OVERLAY,
@@ -356,7 +369,29 @@
 
         mDisplayContent.assignChildLayers(mTransaction);
 
-        assertWindowLayerGreaterThan(mTransaction, anyWindow, mediaOverlayChild);
-        assertWindowLayerGreaterThan(mTransaction, mediaOverlayChild, child);
+        assertWindowHigher(anyWindow, mediaOverlayChild);
+        assertWindowHigher(mediaOverlayChild, child);
+    }
+
+    @Test
+    public void testDockedDividerPosition() throws Exception {
+        final WindowState pinnedStackWindow = createWindowOnStack(null, WINDOWING_MODE_PINNED,
+                ACTIVITY_TYPE_STANDARD, TYPE_BASE_APPLICATION, mDisplayContent,
+                "pinnedStackWindow");
+        final WindowState splitScreenWindow = createWindowOnStack(null,
+                WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD, TYPE_BASE_APPLICATION,
+                mDisplayContent, "splitScreenWindow");
+        final WindowState splitScreenSecondaryWindow = createWindowOnStack(null,
+                WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD,
+                TYPE_BASE_APPLICATION, mDisplayContent, "splitScreenSecondaryWindow");
+        final WindowState assistantStackWindow = createWindowOnStack(null, WINDOWING_MODE_FULLSCREEN,
+                ACTIVITY_TYPE_ASSISTANT, TYPE_BASE_APPLICATION,
+                mDisplayContent, "assistantStackWindow");
+
+        mDisplayContent.assignChildLayers(mTransaction);
+
+        assertWindowHigher(mDockedDividerWindow, splitScreenWindow);
+        assertWindowHigher(mDockedDividerWindow, splitScreenSecondaryWindow);
+        assertWindowHigher(pinnedStackWindow, mDockedDividerWindow);
     }
 }
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationComparatorTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationComparatorTest.java
index 3dcd5b9..30fae01 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationComparatorTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationComparatorTest.java
@@ -78,6 +78,8 @@
     private NotificationRecord mRecordCheater;
     private NotificationRecord mRecordCheaterColorized;
     private NotificationRecord mNoMediaSessionMedia;
+    private NotificationRecord mRecordColorized;
+    private NotificationRecord mRecordColorizedCall;
 
     @Before
     public void setUp() {
@@ -113,7 +115,6 @@
         Notification n2 = new Notification.Builder(mContext, TEST_CHANNEL_ID)
                 .setCategory(Notification.CATEGORY_CALL)
                 .setFlag(Notification.FLAG_FOREGROUND_SERVICE, true)
-                .setColorized(true /* colorized */)
                 .build();
         mRecordHighCall = new NotificationRecord(mContext, new StatusBarNotification(callPkg,
                 callPkg, 1, "highcall", callUid, callUid, n2,
@@ -200,13 +201,34 @@
                 pkg2, pkg2, 1, "cheater", uid2, uid2, n12, new UserHandle(userId),
                 "", 9258), getDefaultChannel());
         mNoMediaSessionMedia.setUserImportance(NotificationManager.IMPORTANCE_DEFAULT);
+
+        Notification n13 = new Notification.Builder(mContext, TEST_CHANNEL_ID)
+                .setFlag(Notification.FLAG_FOREGROUND_SERVICE, true)
+                .setColorized(true /* colorized */)
+                .build();
+        mRecordColorized = new NotificationRecord(mContext, new StatusBarNotification(pkg2,
+                pkg2, 1, "colorized", uid2, uid2, n13,
+                new UserHandle(userId), "", 1999), getDefaultChannel());
+        mRecordHighCall.setUserImportance(NotificationManager.IMPORTANCE_HIGH);
+
+        Notification n14 = new Notification.Builder(mContext, TEST_CHANNEL_ID)
+                .setCategory(Notification.CATEGORY_CALL)
+                .setColorized(true)
+                .setFlag(Notification.FLAG_FOREGROUND_SERVICE, true)
+                .build();
+        mRecordColorizedCall = new NotificationRecord(mContext, new StatusBarNotification(callPkg,
+                callPkg, 1, "colorizedCall", callUid, callUid, n14,
+                new UserHandle(userId), "", 1999), getDefaultChannel());
+        mRecordColorizedCall.setUserImportance(NotificationManager.IMPORTANCE_HIGH);
     }
 
     @Test
     public void testOrdering() throws Exception {
         final List<NotificationRecord> expected = new ArrayList<>();
-        expected.add(mRecordHighCall);
+        expected.add(mRecordColorizedCall);
         expected.add(mRecordDefaultMedia);
+        expected.add(mRecordColorized);
+        expected.add(mRecordHighCall);
         expected.add(mRecordInlineReply);
         expected.add(mRecordSms);
         expected.add(mRecordStarredContact);
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 423dc80..1406093 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -16,6 +16,10 @@
 
 package android.telephony;
 
+import static android.net.NetworkPolicyManager.OVERRIDE_CONGESTED;
+import static android.net.NetworkPolicyManager.OVERRIDE_UNMETERED;
+
+import android.annotation.DurationMillisLong;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
@@ -30,6 +34,7 @@
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.net.INetworkPolicyManager;
+import android.net.NetworkCapabilities;
 import android.net.Uri;
 import android.os.Handler;
 import android.os.Looper;
@@ -38,7 +43,6 @@
 import android.os.ServiceManager;
 import android.os.ServiceManager.ServiceNotFoundException;
 import android.util.DisplayMetrics;
-import android.util.Log;
 
 import com.android.internal.telephony.IOnSubscriptionsChangedListener;
 import com.android.internal.telephony.ISub;
@@ -1738,6 +1742,75 @@
     }
 
     /**
+     * Temporarily override the billing relationship plan between a carrier and
+     * a specific subscriber to be considered unmetered. This will be reflected
+     * to apps via {@link NetworkCapabilities#NET_CAPABILITY_NOT_METERED}.
+     * <p>
+     * This method is only accessible to the following narrow set of apps:
+     * <ul>
+     * <li>The carrier app for this subscriberId, as determined by
+     * {@link TelephonyManager#hasCarrierPrivileges()}.
+     * <li>The carrier app explicitly delegated access through
+     * {@link CarrierConfigManager#KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING}.
+     * </ul>
+     *
+     * @param subId the subscriber this override applies to.
+     * @param overrideUnmetered set if the billing relationship should be
+     *            considered unmetered.
+     * @param timeoutMillis the timeout after which the requested override will
+     *            be automatically cleared, or {@code 0} to leave in the
+     *            requested state until explicitly cleared, or the next reboot,
+     *            whichever happens first.
+     * @hide
+     */
+    @SystemApi
+    public void setSubscriptionOverrideUnmetered(int subId, boolean overrideUnmetered,
+            @DurationMillisLong long timeoutMillis) {
+        try {
+            final int overrideValue = overrideUnmetered ? OVERRIDE_UNMETERED : 0;
+            mNetworkPolicy.setSubscriptionOverride(subId, OVERRIDE_UNMETERED, overrideValue,
+                    timeoutMillis, mContext.getOpPackageName());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Temporarily override the billing relationship plan between a carrier and
+     * a specific subscriber to be considered congested. This will cause the
+     * device to delay certain network requests when possible, such as developer
+     * jobs that are willing to run in a flexible time window.
+     * <p>
+     * This method is only accessible to the following narrow set of apps:
+     * <ul>
+     * <li>The carrier app for this subscriberId, as determined by
+     * {@link TelephonyManager#hasCarrierPrivileges()}.
+     * <li>The carrier app explicitly delegated access through
+     * {@link CarrierConfigManager#KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING}.
+     * </ul>
+     *
+     * @param subId the subscriber this override applies to.
+     * @param overrideCongested set if the subscription should be considered
+     *            congested.
+     * @param timeoutMillis the timeout after which the requested override will
+     *            be automatically cleared, or {@code 0} to leave in the
+     *            requested state until explicitly cleared, or the next reboot,
+     *            whichever happens first.
+     * @hide
+     */
+    @SystemApi
+    public void setSubscriptionOverrideCongested(int subId, boolean overrideCongested,
+            @DurationMillisLong long timeoutMillis) {
+        try {
+            final int overrideValue = overrideCongested ? OVERRIDE_CONGESTED : 0;
+            mNetworkPolicy.setSubscriptionOverride(subId, OVERRIDE_CONGESTED, overrideValue,
+                    timeoutMillis, mContext.getOpPackageName());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Create an {@link Intent} that can be launched towards the carrier app
      * that is currently defining the billing relationship plan through
      * {@link #setSubscriptionPlans(int, List)}.
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 8edc8b1..de9e691 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -2122,6 +2122,27 @@
      * carrier restrictions.
      */
     public static final int SIM_STATE_CARD_RESTRICTED = 9;
+    /**
+     * SIM card state: Loaded: SIM card applications have been loaded
+     * @hide
+     */
+    @SystemApi
+    public static final int SIM_STATE_LOADED = 10;
+    /**
+     * SIM card state: SIM Card is present
+     * @hide
+     */
+    @SystemApi
+    public static final int SIM_STATE_PRESENT = 11;
+
+    /**
+     * Extra included in {@link Intent.ACTION_SIM_CARD_STATE_CHANGED} and
+     * {@link Intent.ACTION_SIM_APPLICATION_STATE_CHANGED} to indicate the card/application state.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final String EXTRA_SIM_STATE = "android.telephony.extra.SIM_STATE";
 
     /**
      * @return true if a ICC card is present
@@ -2168,6 +2189,14 @@
      * @see #SIM_STATE_CARD_RESTRICTED
      */
     public int getSimState() {
+        int simState = getSimStateIncludingLoaded();
+        if (simState == SIM_STATE_LOADED) {
+            simState = SIM_STATE_READY;
+        }
+        return simState;
+    }
+
+    private int getSimStateIncludingLoaded() {
         int slotIndex = getSlotIndex();
         // slotIndex may be invalid due to sim being absent. In that case query all slots to get
         // sim state
@@ -2186,7 +2215,63 @@
                     "state as absent");
             return SIM_STATE_ABSENT;
         }
-        return getSimState(slotIndex);
+        return SubscriptionManager.getSimStateForSlotIndex(slotIndex);
+    }
+
+    /**
+     * Returns a constant indicating the state of the default SIM card.
+     *
+     * @see #SIM_STATE_UNKNOWN
+     * @see #SIM_STATE_ABSENT
+     * @see #SIM_STATE_CARD_IO_ERROR
+     * @see #SIM_STATE_CARD_RESTRICTED
+     * @see #SIM_STATE_PRESENT
+     *
+     * @hide
+     */
+    @SystemApi
+    public int getSimCardState() {
+        int simCardState = getSimState();
+        switch (simCardState) {
+            case SIM_STATE_UNKNOWN:
+            case SIM_STATE_ABSENT:
+            case SIM_STATE_CARD_IO_ERROR:
+            case SIM_STATE_CARD_RESTRICTED:
+                return simCardState;
+            default:
+                return SIM_STATE_PRESENT;
+        }
+    }
+
+    /**
+     * Returns a constant indicating the state of the card applications on the default SIM card.
+     *
+     * @see #SIM_STATE_UNKNOWN
+     * @see #SIM_STATE_PIN_REQUIRED
+     * @see #SIM_STATE_PUK_REQUIRED
+     * @see #SIM_STATE_NETWORK_LOCKED
+     * @see #SIM_STATE_NOT_READY
+     * @see #SIM_STATE_PERM_DISABLED
+     * @see #SIM_STATE_LOADED
+     *
+     * @hide
+     */
+    @SystemApi
+    public int getSimApplicationState() {
+        int simApplicationState = getSimStateIncludingLoaded();
+        switch (simApplicationState) {
+            case SIM_STATE_UNKNOWN:
+            case SIM_STATE_ABSENT:
+            case SIM_STATE_CARD_IO_ERROR:
+            case SIM_STATE_CARD_RESTRICTED:
+                return SIM_STATE_UNKNOWN;
+            case SIM_STATE_READY:
+                // Ready is not a valid state anymore. The state that is broadcast goes from
+                // NOT_READY to either LOCKED or LOADED.
+                return SIM_STATE_NOT_READY;
+            default:
+                return simApplicationState;
+        }
     }
 
     /**
@@ -2207,6 +2292,9 @@
      */
     public int getSimState(int slotIndex) {
         int simState = SubscriptionManager.getSimStateForSlotIndex(slotIndex);
+        if (simState == SIM_STATE_LOADED) {
+            simState = SIM_STATE_READY;
+        }
         return simState;
     }
 
diff --git a/telephony/java/android/telephony/ims/feature/MMTelFeature.java b/telephony/java/android/telephony/ims/feature/MMTelFeature.java
index 4e095e3a..5197107 100644
--- a/telephony/java/android/telephony/ims/feature/MMTelFeature.java
+++ b/telephony/java/android/telephony/ims/feature/MMTelFeature.java
@@ -19,6 +19,7 @@
 import android.app.PendingIntent;
 import android.os.Message;
 import android.os.RemoteException;
+import android.telephony.ims.internal.stub.SmsImplBase;
 
 import com.android.ims.ImsCallProfile;
 import com.android.ims.internal.IImsCallSession;
@@ -28,6 +29,7 @@
 import com.android.ims.internal.IImsMMTelFeature;
 import com.android.ims.internal.IImsMultiEndpoint;
 import com.android.ims.internal.IImsRegistrationListener;
+import com.android.ims.internal.IImsSmsListener;
 import com.android.ims.internal.IImsUt;
 import com.android.ims.internal.ImsCallSession;
 
@@ -171,6 +173,42 @@
                 return MMTelFeature.this.getMultiEndpointInterface();
             }
         }
+
+        @Override
+        public void setSmsListener(IImsSmsListener l) throws RemoteException {
+            synchronized (mLock) {
+                MMTelFeature.this.setSmsListener(l);
+            }
+        }
+
+        @Override
+        public void sendSms(int token, int messageRef, String format, String smsc, boolean retry,
+                byte[] pdu) {
+            synchronized (mLock) {
+                MMTelFeature.this.sendSms(token, messageRef, format, smsc, retry, pdu);
+            }
+        }
+
+        @Override
+        public void acknowledgeSms(int token, int messageRef, int result) {
+            synchronized (mLock) {
+                MMTelFeature.this.acknowledgeSms(token, messageRef, result);
+            }
+        }
+
+        @Override
+        public void acknowledgeSmsReport(int token, int messageRef, int result) {
+            synchronized (mLock) {
+                MMTelFeature.this.acknowledgeSmsReport(token, messageRef, result);
+            }
+        }
+
+        @Override
+        public String getSmsFormat() {
+            synchronized (mLock) {
+                return MMTelFeature.this.getSmsFormat();
+            }
+        }
     };
 
     /**
@@ -346,6 +384,39 @@
         return null;
     }
 
+    public void setSmsListener(IImsSmsListener listener) {
+        getSmsImplementation().registerSmsListener(listener);
+    }
+
+    public void sendSms(int token, int messageRef, String format, String smsc, boolean isRetry,
+            byte[] pdu) {
+        getSmsImplementation().sendSms(token, messageRef, format, smsc, isRetry, pdu);
+    }
+
+    public void acknowledgeSms(int token, int messageRef,
+            @SmsImplBase.DeliverStatusResult int result) {
+        getSmsImplementation().acknowledgeSms(token, messageRef, result);
+    }
+
+    public void acknowledgeSmsReport(int token, int messageRef,
+            @SmsImplBase.StatusReportResult int result) {
+        getSmsImplementation().acknowledgeSmsReport(token, messageRef, result);
+    }
+
+    /**
+     * Must be overridden by IMS Provider to be able to support SMS over IMS. Otherwise a default
+     * non-functional implementation is returned.
+     *
+     * @return an instance of {@link SmsImplBase} which should be implemented by the IMS Provider.
+     */
+    protected SmsImplBase getSmsImplementation() {
+        return new SmsImplBase();
+    }
+
+    public String getSmsFormat() {
+        return getSmsImplementation().getSmsFormat();
+    }
+
     @Override
     public void onFeatureReady() {
 
diff --git a/telephony/java/android/telephony/ims/internal/SmsImplBase.java b/telephony/java/android/telephony/ims/internal/SmsImplBase.java
index eb805a8..33b23d9 100644
--- a/telephony/java/android/telephony/ims/internal/SmsImplBase.java
+++ b/telephony/java/android/telephony/ims/internal/SmsImplBase.java
@@ -17,7 +17,6 @@
 package android.telephony.ims.internal;
 
 import android.annotation.IntDef;
-import android.annotation.SystemApi;
 import android.os.RemoteException;
 import android.telephony.SmsManager;
 import android.telephony.SmsMessage;
@@ -37,6 +36,7 @@
 public class SmsImplBase {
   private static final String LOG_TAG = "SmsImplBase";
 
+  /** @hide */
   @IntDef({
           SEND_STATUS_OK,
           SEND_STATUS_ERROR,
@@ -68,6 +68,7 @@
    */
   public static final int SEND_STATUS_ERROR_FALLBACK = 4;
 
+  /** @hide */
   @IntDef({
           DELIVER_STATUS_OK,
           DELIVER_STATUS_ERROR
@@ -84,6 +85,7 @@
    */
   public static final int DELIVER_STATUS_ERROR = 2;
 
+  /** @hide */
   @IntDef({
           STATUS_REPORT_STATUS_OK,
           STATUS_REPORT_STATUS_ERROR
@@ -114,9 +116,9 @@
    * @hide
    */
   public final void registerSmsListener(IImsSmsListener listener) {
-    synchronized (mLock) {
-      mListener = listener;
-    }
+      synchronized (mLock) {
+          mListener = listener;
+      }
   }
 
   /**
@@ -128,8 +130,8 @@
    *             callbacks for this specific message.
    * @param messageRef the message reference.
    * @param format the format of the message. Valid values are {@link SmsMessage#FORMAT_3GPP} and
+   *               {@link SmsMessage#FORMAT_3GPP2}.
    * @param smsc the Short Message Service Center address.
-   * {@link SmsMessage#FORMAT_3GPP2}.
    * @param isRetry whether it is a retry of an already attempted message or not.
    * @param pdu PDUs representing the contents of the message.
    */
@@ -154,7 +156,7 @@
    * @param messageRef the message reference
    */
   public void acknowledgeSms(int token, int messageRef, @DeliverStatusResult int result) {
-
+    Log.e(LOG_TAG, "acknowledgeSms() not implemented.");
   }
 
   /**
@@ -168,7 +170,7 @@
    * @param messageRef the message reference
    */
   public void acknowledgeSmsReport(int token, int messageRef, @StatusReportResult int result) {
-
+    Log.e(LOG_TAG, "acknowledgeSmsReport() not implemented.");
   }
 
   /**
@@ -193,7 +195,6 @@
       }
       try {
         mListener.onSmsReceived(token, format, pdu);
-        acknowledgeSms(token, 0, DELIVER_STATUS_OK);
       } catch (RemoteException e) {
         Log.e(LOG_TAG, "Can not deliver sms: " + e.getMessage());
         acknowledgeSms(token, 0, DELIVER_STATUS_ERROR);
diff --git a/telephony/java/android/telephony/ims/internal/stub/SmsImplBase.java b/telephony/java/android/telephony/ims/internal/stub/SmsImplBase.java
new file mode 100644
index 0000000..113dad4
--- /dev/null
+++ b/telephony/java/android/telephony/ims/internal/stub/SmsImplBase.java
@@ -0,0 +1,271 @@
+/*
+ * 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.telephony.ims.internal.stub;
+
+import android.annotation.IntDef;
+import android.os.RemoteException;
+import android.telephony.SmsManager;
+import android.telephony.SmsMessage;
+import android.telephony.ims.internal.feature.MmTelFeature;
+import android.util.Log;
+
+import com.android.ims.internal.IImsSmsListener;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Base implementation for SMS over IMS.
+ *
+ * Any service wishing to provide SMS over IMS should extend this class and implement all methods
+ * that the service supports.
+ * @hide
+ */
+public class SmsImplBase {
+    private static final String LOG_TAG = "SmsImplBase";
+
+    @IntDef({
+            SEND_STATUS_OK,
+            SEND_STATUS_ERROR,
+            SEND_STATUS_ERROR_RETRY,
+            SEND_STATUS_ERROR_FALLBACK
+        })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface SendStatusResult {}
+    /**
+     * Message was sent successfully.
+     */
+    public static final int SEND_STATUS_OK = 1;
+
+    /**
+     * IMS provider failed to send the message and platform should not retry falling back to sending
+     * the message using the radio.
+     */
+    public static final int SEND_STATUS_ERROR = 2;
+
+    /**
+     * IMS provider failed to send the message and platform should retry again after setting TP-RD bit
+     * to high.
+     */
+    public static final int SEND_STATUS_ERROR_RETRY = 3;
+
+    /**
+     * IMS provider failed to send the message and platform should retry falling back to sending
+     * the message using the radio.
+     */
+    public static final int SEND_STATUS_ERROR_FALLBACK = 4;
+
+    @IntDef({
+            DELIVER_STATUS_OK,
+            DELIVER_STATUS_ERROR
+        })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface DeliverStatusResult {}
+    /**
+     * Message was delivered successfully.
+     */
+    public static final int DELIVER_STATUS_OK = 1;
+
+    /**
+     * Message was not delivered.
+     */
+    public static final int DELIVER_STATUS_ERROR = 2;
+
+    @IntDef({
+            STATUS_REPORT_STATUS_OK,
+            STATUS_REPORT_STATUS_ERROR
+        })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface StatusReportResult {}
+
+    /**
+     * Status Report was set successfully.
+     */
+    public static final int STATUS_REPORT_STATUS_OK = 1;
+
+    /**
+     * Error while setting status report.
+     */
+    public static final int STATUS_REPORT_STATUS_ERROR = 2;
+
+
+    // Lock for feature synchronization
+    private final Object mLock = new Object();
+    private IImsSmsListener mListener;
+
+    /**
+     * Registers a listener responsible for handling tasks like delivering messages.
+     *
+     * @param listener listener to register.
+     *
+     * @hide
+     */
+    public final void registerSmsListener(IImsSmsListener listener) {
+        synchronized (mLock) {
+            mListener = listener;
+        }
+    }
+
+    /**
+     * This method will be triggered by the platform when the user attempts to send an SMS. This
+     * method should be implemented by the IMS providers to provide implementation of sending an SMS
+     * over IMS.
+     *
+     * @param token unique token generated by the platform that should be used when triggering
+     *             callbacks for this specific message.
+     * @param messageRef the message reference.
+     * @param format the format of the message. Valid values are {@link SmsMessage#FORMAT_3GPP} and
+     *               {@link SmsMessage#FORMAT_3GPP2}.
+     * @param smsc the Short Message Service Center address.
+     * @param isRetry whether it is a retry of an already attempted message or not.
+     * @param pdu PDUs representing the contents of the message.
+     */
+    public void sendSms(int token, int messageRef, String format, String smsc, boolean isRetry,
+            byte[] pdu) {
+        // Base implementation returns error. Should be overridden.
+        try {
+            onSendSmsResult(token, messageRef, SEND_STATUS_ERROR,
+                    SmsManager.RESULT_ERROR_GENERIC_FAILURE);
+        } catch (RemoteException e) {
+            Log.e(LOG_TAG, "Can not send sms: " + e.getMessage());
+        }
+    }
+
+    /**
+     * This method will be triggered by the platform after {@link #onSmsReceived(int, String, byte[])}
+     * has been called to deliver the result to the IMS provider.
+     *
+     * @param token token provided in {@link #onSmsReceived(int, String, byte[])}
+     * @param result result of delivering the message. Valid values are defined in
+     * {@link DeliverStatusResult}
+     * @param messageRef the message reference
+     */
+    public void acknowledgeSms(int token, int messageRef, @DeliverStatusResult int result) {
+        Log.e(LOG_TAG, "acknowledgeSms() not implemented.");
+    }
+
+    /**
+     * This method will be triggered by the platform after
+     * {@link #onSmsStatusReportReceived(int, int, String, byte[])} has been called to provide the
+     * result to the IMS provider.
+     *
+     * @param token token provided in {@link #sendSms(int, int, String, String, boolean, byte[])}
+     * @param result result of delivering the message. Valid values are defined in
+     * {@link StatusReportResult}
+     * @param messageRef the message reference
+     */
+    public void acknowledgeSmsReport(int token, int messageRef, @StatusReportResult int result) {
+        Log.e(LOG_TAG, "acknowledgeSmsReport() not implemented.");
+    }
+
+    /**
+     * This method should be triggered by the IMS providers when there is an incoming message. The
+     * platform will deliver the message to the messages database and notify the IMS provider of the
+     * result by calling {@link #acknowledgeSms(int, int, int)}.
+     *
+     * This method must not be called before {@link MmTelFeature#onFeatureReady()} is called.
+     *
+     * @param token unique token generated by IMS providers that the platform will use to trigger
+     *              callbacks for this message.
+     * @param format the format of the message. Valid values are {@link SmsMessage#FORMAT_3GPP} and
+     * {@link SmsMessage#FORMAT_3GPP2}.
+     * @param pdu PDUs representing the contents of the message.
+     * @throws IllegalStateException if called before {@link MmTelFeature#onFeatureReady()}
+     */
+    public final void onSmsReceived(int token, String format, byte[] pdu)
+            throws IllegalStateException {
+        synchronized (mLock) {
+            if (mListener == null) {
+                throw new IllegalStateException("Feature not ready.");
+            }
+            try {
+                mListener.onSmsReceived(token, format, pdu);
+            } catch (RemoteException e) {
+                Log.e(LOG_TAG, "Can not deliver sms: " + e.getMessage());
+                acknowledgeSms(token, 0, DELIVER_STATUS_ERROR);
+            }
+        }
+    }
+
+    /**
+     * This method should be triggered by the IMS providers to pass the result of the sent message
+     * to the platform.
+     *
+     * This method must not be called before {@link MmTelFeature#onFeatureReady()} is called.
+     *
+     * @param token token provided in {@link #sendSms(int, int, String, String, boolean, byte[])}
+     * @param messageRef the message reference. Should be between 0 and 255 per TS.123.040
+     * @param status result of sending the SMS. Valid values are defined in {@link SendStatusResult}
+     * @param reason reason in case status is failure. Valid values are:
+     *  {@link SmsManager#RESULT_ERROR_NONE},
+     *  {@link SmsManager#RESULT_ERROR_GENERIC_FAILURE},
+     *  {@link SmsManager#RESULT_ERROR_RADIO_OFF},
+     *  {@link SmsManager#RESULT_ERROR_NULL_PDU},
+     *  {@link SmsManager#RESULT_ERROR_NO_SERVICE},
+     *  {@link SmsManager#RESULT_ERROR_LIMIT_EXCEEDED},
+     *  {@link SmsManager#RESULT_ERROR_SHORT_CODE_NOT_ALLOWED},
+     *  {@link SmsManager#RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED}
+     * @throws IllegalStateException if called before {@link MmTelFeature#onFeatureReady()}
+     * @throws RemoteException if the connection to the framework is not available. If this happens
+     *  attempting to send the SMS should be aborted.
+     */
+    public final void onSendSmsResult(int token, int messageRef, @SendStatusResult int status,
+            int reason) throws IllegalStateException, RemoteException {
+        synchronized (mLock) {
+            if (mListener == null) {
+                throw new IllegalStateException("Feature not ready.");
+            }
+            mListener.onSendSmsResult(token, messageRef, status, reason);
+        }
+    }
+
+    /**
+     * Sets the status report of the sent message.
+     *
+     * @param token token provided in {@link #sendSms(int, int, String, String, boolean, byte[])}
+     * @param messageRef the message reference.
+     * @param format the format of the message. Valid values are {@link SmsMessage#FORMAT_3GPP} and
+     * {@link SmsMessage#FORMAT_3GPP2}.
+     * @param pdu PDUs representing the content of the status report.
+     * @throws IllegalStateException if called before {@link MmTelFeature#onFeatureReady()}
+     */
+    public final void onSmsStatusReportReceived(int token, int messageRef, String format,
+            byte[] pdu) {
+        synchronized (mLock) {
+            if (mListener == null) {
+                throw new IllegalStateException("Feature not ready.");
+            }
+            try {
+                mListener.onSmsStatusReportReceived(token, messageRef, format, pdu);
+            } catch (RemoteException e) {
+                Log.e(LOG_TAG, "Can not process sms status report: " + e.getMessage());
+                acknowledgeSmsReport(token, messageRef, STATUS_REPORT_STATUS_ERROR);
+            }
+        }
+    }
+
+    /**
+     * Returns the SMS format. Default is {@link SmsMessage#FORMAT_3GPP} unless overridden by IMS
+     * Provider.
+     *
+     * @return  the format of the message. Valid values are {@link SmsMessage#FORMAT_3GPP} and
+     * {@link SmsMessage#FORMAT_3GPP2}.
+     */
+    public String getSmsFormat() {
+      return SmsMessage.FORMAT_3GPP;
+    }
+}
diff --git a/telephony/java/com/android/ims/internal/IImsMMTelFeature.aidl b/telephony/java/com/android/ims/internal/IImsMMTelFeature.aidl
index 52b3853..cce39f4 100644
--- a/telephony/java/com/android/ims/internal/IImsMMTelFeature.aidl
+++ b/telephony/java/com/android/ims/internal/IImsMMTelFeature.aidl
@@ -25,6 +25,7 @@
 import com.android.ims.internal.IImsEcbm;
 import com.android.ims.internal.IImsMultiEndpoint;
 import com.android.ims.internal.IImsRegistrationListener;
+import com.android.ims.internal.IImsSmsListener;
 import com.android.ims.internal.IImsUt;
 
 import android.os.Message;
@@ -53,4 +54,11 @@
     IImsEcbm getEcbmInterface();
     void setUiTTYMode(int uiTtyMode, in Message onComplete);
     IImsMultiEndpoint getMultiEndpointInterface();
+    // SMS APIs
+    void setSmsListener(IImsSmsListener l);
+    oneway void sendSms(in int token, int messageRef, String format, String smsc, boolean retry,
+            in byte[] pdu);
+    oneway void acknowledgeSms(int token, int messageRef, int result);
+    oneway void acknowledgeSmsReport(int token, int messageRef, int result);
+    String getSmsFormat();
 }
diff --git a/telephony/java/com/android/ims/internal/IImsSmsListener.aidl b/telephony/java/com/android/ims/internal/IImsSmsListener.aidl
new file mode 100644
index 0000000..5a4b7e4
--- /dev/null
+++ b/telephony/java/com/android/ims/internal/IImsSmsListener.aidl
@@ -0,0 +1,28 @@
+/*
+ * 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.ims.internal;
+
+/**
+ * See SmsImplBase for more information.
+ * {@hide}
+ */
+interface IImsSmsListener {
+    void onSendSmsResult(int token, int messageRef, int status, int reason);
+    void onSmsStatusReportReceived(int token, int messageRef, in String format,
+            in byte[] pdu);
+    void onSmsReceived(int token, in String format, in byte[] pdu);
+}
\ No newline at end of file
diff --git a/telephony/java/com/android/internal/telephony/IccCardConstants.java b/telephony/java/com/android/internal/telephony/IccCardConstants.java
index f3d9335..d57f9af 100644
--- a/telephony/java/com/android/internal/telephony/IccCardConstants.java
+++ b/telephony/java/com/android/internal/telephony/IccCardConstants.java
@@ -30,16 +30,14 @@
     public static final String INTENT_VALUE_ICC_NOT_READY = "NOT_READY";
     /* ABSENT means ICC is missing */
     public static final String INTENT_VALUE_ICC_ABSENT = "ABSENT";
+    /* PRESENT means ICC is present */
+    public static final String INTENT_VALUE_ICC_PRESENT = "PRESENT";
     /* CARD_IO_ERROR means for three consecutive times there was SIM IO error */
     static public final String INTENT_VALUE_ICC_CARD_IO_ERROR = "CARD_IO_ERROR";
     /* CARD_RESTRICTED means card is present but not usable due to carrier restrictions */
     static public final String INTENT_VALUE_ICC_CARD_RESTRICTED = "CARD_RESTRICTED";
     /* LOCKED means ICC is locked by pin or by network */
     public static final String INTENT_VALUE_ICC_LOCKED = "LOCKED";
-    //TODO: we can remove this state in the future if Bug 18489776 analysis
-    //#42's first race condition is resolved
-    /* INTERNAL LOCKED means ICC is locked by pin or by network */
-    public static final String INTENT_VALUE_ICC_INTERNAL_LOCKED = "INTERNAL_LOCKED";
     /* READY means ICC is ready to access */
     public static final String INTENT_VALUE_ICC_READY = "READY";
     /* IMSI means ICC IMSI is ready in property */
@@ -77,7 +75,8 @@
         NOT_READY,      /** ordinal(6) == {@See TelephonyManager#SIM_STATE_NOT_READY} */
         PERM_DISABLED,  /** ordinal(7) == {@See TelephonyManager#SIM_STATE_PERM_DISABLED} */
         CARD_IO_ERROR,  /** ordinal(8) == {@See TelephonyManager#SIM_STATE_CARD_IO_ERROR} */
-        CARD_RESTRICTED;/** ordinal(9) == {@See TelephonyManager#SIM_STATE_CARD_RESTRICTED} */
+        CARD_RESTRICTED,/** ordinal(9) == {@See TelephonyManager#SIM_STATE_CARD_RESTRICTED} */
+        LOADED;         /** ordinal(9) == {@See TelephonyManager#SIM_STATE_LOADED} */
 
         public boolean isPinLocked() {
             return ((this == PIN_REQUIRED) || (this == PUK_REQUIRED));
@@ -85,9 +84,9 @@
 
         public boolean iccCardExist() {
             return ((this == PIN_REQUIRED) || (this == PUK_REQUIRED)
-                    || (this == NETWORK_LOCKED) || (this == READY)
+                    || (this == NETWORK_LOCKED) || (this == READY) || (this == NOT_READY)
                     || (this == PERM_DISABLED) || (this == CARD_IO_ERROR)
-                    || (this == CARD_RESTRICTED));
+                    || (this == CARD_RESTRICTED) || (this == LOADED));
         }
 
         public static State intToState(int state) throws IllegalArgumentException {
@@ -102,6 +101,7 @@
                 case 7: return PERM_DISABLED;
                 case 8: return CARD_IO_ERROR;
                 case 9: return CARD_RESTRICTED;
+                case 10: return LOADED;
                 default:
                     throw new IllegalArgumentException();
             }
diff --git a/tests/UiBench/src/com/android/test/uibench/leanback/BrowseFragment.java b/tests/UiBench/src/com/android/test/uibench/leanback/BrowseFragment.java
index 11ea361..4ab38a6 100644
--- a/tests/UiBench/src/com/android/test/uibench/leanback/BrowseFragment.java
+++ b/tests/UiBench/src/com/android/test/uibench/leanback/BrowseFragment.java
@@ -24,6 +24,7 @@
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
+        TestHelper.initHeaderState(this);
         super.onCreate(savedInstanceState);
         BitmapLoader.clear();
         TestHelper.initBackground(getActivity());
diff --git a/tests/UiBench/src/com/android/test/uibench/leanback/TestHelper.java b/tests/UiBench/src/com/android/test/uibench/leanback/TestHelper.java
index 2bf3885..bf408f7 100644
--- a/tests/UiBench/src/com/android/test/uibench/leanback/TestHelper.java
+++ b/tests/UiBench/src/com/android/test/uibench/leanback/TestHelper.java
@@ -40,6 +40,7 @@
     public static final String EXTRA_CARD_ROUND_RECT = "extra_card_round_rect";
     public static final String EXTRA_ENTRANCE_TRANSITION = "extra_entrance_transition";
     public static final String EXTRA_BITMAP_UPLOAD = "extra_bitmap_upload";
+    public static final String EXTRA_SHOW_FAST_LANE = "extra_show_fast_lane";
 
     /**
      * Dont change the default values, they gave baseline for measuring the performance
@@ -53,6 +54,7 @@
     static final boolean DEFAULT_CARD_SHADOW = true;
     static final boolean DEFAULT_CARD_ROUND_RECT = true;
     static final boolean DEFAULT_BITMAP_UPLOAD = true;
+    static final boolean DEFAULT_SHOW_FAST_LANE = true;
 
     static long sCardIdSeed = 0;
     static long sRowIdSeed = 0;
@@ -235,4 +237,11 @@
             manager.setBitmap(bitmap);
         }
     }
+
+    public static void initHeaderState(BrowseFragment fragment) {
+        if (!fragment.getActivity().getIntent()
+                .getBooleanExtra(EXTRA_SHOW_FAST_LANE, DEFAULT_SHOW_FAST_LANE)) {
+            fragment.setHeadersState(BrowseFragment.HEADERS_HIDDEN);
+        }
+    }
 }
diff --git a/tests/net/java/android/net/NetworkStatsTest.java b/tests/net/java/android/net/NetworkStatsTest.java
index 25289ba..035a4cd7 100644
--- a/tests/net/java/android/net/NetworkStatsTest.java
+++ b/tests/net/java/android/net/NetworkStatsTest.java
@@ -16,6 +16,9 @@
 
 package android.net;
 
+import static android.net.NetworkStats.DEFAULT_NETWORK_ALL;
+import static android.net.NetworkStats.DEFAULT_NETWORK_NO;
+import static android.net.NetworkStats.DEFAULT_NETWORK_YES;
 import static android.net.NetworkStats.METERED_ALL;
 import static android.net.NetworkStats.METERED_NO;
 import static android.net.NetworkStats.METERED_YES;
@@ -56,71 +59,75 @@
     @Test
     public void testFindIndex() throws Exception {
         final NetworkStats stats = new NetworkStats(TEST_START, 5)
-                .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 1024L,
-                        8L, 0L, 0L, 10)
-                .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 0L, 0L,
-                        1024L, 8L, 11)
-                .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO, 0L, 0L,
-                        1024L, 8L, 11)
-                .addValues(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 1024L,
-                        8L, 1024L, 8L, 12)
-                .addValues(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_YES, 1024L,
-                        8L, 1024L, 8L, 12);
+                .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+                        DEFAULT_NETWORK_YES, 1024L, 8L, 0L, 0L, 10)
+                .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+                        DEFAULT_NETWORK_NO, 0L, 0L, 1024L, 8L, 11)
+                .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO,
+                        DEFAULT_NETWORK_YES, 0L, 0L, 1024L, 8L, 11)
+                .addValues(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+                        DEFAULT_NETWORK_NO, 1024L, 8L, 1024L, 8L, 12)
+                .addValues(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_YES,
+                        DEFAULT_NETWORK_YES, 1024L, 8L, 1024L, 8L, 12);
 
         assertEquals(4, stats.findIndex(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, METERED_YES,
-                ROAMING_YES));
+                ROAMING_YES, DEFAULT_NETWORK_YES));
         assertEquals(3, stats.findIndex(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, METERED_NO,
-                ROAMING_NO));
+                ROAMING_NO, DEFAULT_NETWORK_NO));
         assertEquals(2, stats.findIndex(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES,
-                ROAMING_NO));
+                ROAMING_NO, DEFAULT_NETWORK_YES));
         assertEquals(1, stats.findIndex(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO,
-                ROAMING_NO));
+                ROAMING_NO, DEFAULT_NETWORK_NO));
         assertEquals(0, stats.findIndex(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO,
-                ROAMING_NO));
+                ROAMING_NO, DEFAULT_NETWORK_YES));
         assertEquals(-1, stats.findIndex(TEST_IFACE, 6, SET_DEFAULT, TAG_NONE, METERED_NO,
-                ROAMING_NO));
+                ROAMING_NO, DEFAULT_NETWORK_NO));
+        assertEquals(-1, stats.findIndex(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO,
+                ROAMING_NO, DEFAULT_NETWORK_NO));
     }
 
     @Test
     public void testFindIndexHinted() {
         final NetworkStats stats = new NetworkStats(TEST_START, 3)
-                .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 1024L,
-                        8L, 0L, 0L, 10)
-                .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 0L, 0L,
-                        1024L, 8L, 11)
-                .addValues(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 1024L,
-                        8L, 1024L, 8L, 12)
+                .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+                        DEFAULT_NETWORK_YES, 1024L, 8L, 0L, 0L, 10)
+                .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+                        DEFAULT_NETWORK_NO, 0L, 0L, 1024L, 8L, 11)
+                .addValues(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+                        DEFAULT_NETWORK_YES, 1024L, 8L, 1024L, 8L, 12)
                 .addValues(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
-                        1024L, 8L, 0L, 0L, 10)
-                .addValues(TEST_IFACE2, 101, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO, 0L, 0L,
-                        1024L, 8L, 11)
-                .addValues(TEST_IFACE2, 101, SET_DEFAULT, 0xF00D, METERED_YES, ROAMING_NO, 0L, 0L,
-                        1024L, 8L, 11)
-                .addValues(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 1024L,
-                        8L, 1024L, 8L, 12)
-                .addValues(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_YES, 1024L,
-                        8L, 1024L, 8L, 12);
+                        DEFAULT_NETWORK_NO, 1024L, 8L, 0L, 0L, 10)
+                .addValues(TEST_IFACE2, 101, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO,
+                        DEFAULT_NETWORK_YES, 0L, 0L, 1024L, 8L, 11)
+                .addValues(TEST_IFACE2, 101, SET_DEFAULT, 0xF00D, METERED_YES, ROAMING_NO,
+                        DEFAULT_NETWORK_NO, 0L, 0L, 1024L, 8L, 11)
+                .addValues(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+                        DEFAULT_NETWORK_YES, 1024L, 8L, 1024L, 8L, 12)
+                .addValues(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_YES,
+                        DEFAULT_NETWORK_NO, 1024L, 8L, 1024L, 8L, 12);
 
         // verify that we correctly find across regardless of hinting
         for (int hint = 0; hint < stats.size(); hint++) {
             assertEquals(0, stats.findIndexHinted(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE,
-                    METERED_NO, ROAMING_NO, hint));
+                    METERED_NO, ROAMING_NO, DEFAULT_NETWORK_YES, hint));
             assertEquals(1, stats.findIndexHinted(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE,
-                    METERED_NO, ROAMING_NO, hint));
+                    METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, hint));
             assertEquals(2, stats.findIndexHinted(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE,
-                    METERED_NO, ROAMING_NO, hint));
+                    METERED_NO, ROAMING_NO, DEFAULT_NETWORK_YES, hint));
             assertEquals(3, stats.findIndexHinted(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE,
-                    METERED_NO, ROAMING_NO, hint));
+                    METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, hint));
             assertEquals(4, stats.findIndexHinted(TEST_IFACE2, 101, SET_DEFAULT, 0xF00D,
-                    METERED_NO, ROAMING_NO, hint));
+                    METERED_NO, ROAMING_NO, DEFAULT_NETWORK_YES, hint));
             assertEquals(5, stats.findIndexHinted(TEST_IFACE2, 101, SET_DEFAULT, 0xF00D,
-                    METERED_YES, ROAMING_NO, hint));
+                    METERED_YES, ROAMING_NO, DEFAULT_NETWORK_NO, hint));
             assertEquals(6, stats.findIndexHinted(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE,
-                    METERED_NO, ROAMING_NO, hint));
+                    METERED_NO, ROAMING_NO, DEFAULT_NETWORK_YES, hint));
             assertEquals(7, stats.findIndexHinted(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE,
-                    METERED_YES, ROAMING_YES, hint));
+                    METERED_YES, ROAMING_YES, DEFAULT_NETWORK_NO, hint));
             assertEquals(-1, stats.findIndexHinted(TEST_IFACE, 6, SET_DEFAULT, TAG_NONE,
-                    METERED_NO, ROAMING_NO, hint));
+                    METERED_NO, ROAMING_NO, DEFAULT_NETWORK_YES, hint));
+            assertEquals(-1, stats.findIndexHinted(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE,
+                    METERED_YES, ROAMING_YES, DEFAULT_NETWORK_YES, hint));
         }
     }
 
@@ -131,50 +138,50 @@
         assertEquals(0, stats.size());
         assertEquals(4, stats.internalSize());
 
-        stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 1L, 1L,
-                2L, 2L, 3);
-        stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 2L, 2L,
-                2L, 2L, 4);
-        stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES, 3L,
-                3L, 2L, 2L, 5);
-        stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_YES, 3L,
-                3L, 2L, 2L, 5);
+        stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+                DEFAULT_NETWORK_YES, 1L, 1L, 2L, 2L, 3);
+        stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+                DEFAULT_NETWORK_NO, 2L, 2L, 2L, 2L, 4);
+        stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES,
+                DEFAULT_NETWORK_YES, 3L, 3L, 2L, 2L, 5);
+        stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_YES,
+                DEFAULT_NETWORK_NO, 3L, 3L, 2L, 2L, 5);
 
         assertEquals(4, stats.size());
         assertEquals(4, stats.internalSize());
 
-        stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 4L,
-                40L, 4L, 40L, 7);
-        stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 5L,
-                50L, 4L, 40L, 8);
-        stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 6L,
-                60L, 5L, 50L, 10);
-        stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES, 7L,
-                70L, 5L, 50L, 11);
-        stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_YES, 7L,
-                70L, 5L, 50L, 11);
+        stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+                DEFAULT_NETWORK_NO, 4L, 40L, 4L, 40L, 7);
+        stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+                DEFAULT_NETWORK_YES, 5L, 50L, 4L, 40L, 8);
+        stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+                DEFAULT_NETWORK_NO, 6L, 60L, 5L, 50L, 10);
+        stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES,
+                DEFAULT_NETWORK_YES, 7L, 70L, 5L, 50L, 11);
+        stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_YES,
+                DEFAULT_NETWORK_NO, 7L, 70L, 5L, 50L, 11);
 
         assertEquals(9, stats.size());
         assertTrue(stats.internalSize() >= 9);
 
         assertValues(stats, 0, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
-                1L, 1L, 2L, 2L, 3);
+                DEFAULT_NETWORK_YES, 1L, 1L, 2L, 2L, 3);
         assertValues(stats, 1, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
-                2L, 2L, 2L, 2L, 4);
+                DEFAULT_NETWORK_NO, 2L, 2L, 2L, 2L, 4);
         assertValues(stats, 2, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES,
-                3L, 3L, 2L, 2L, 5);
+                DEFAULT_NETWORK_YES, 3L, 3L, 2L, 2L, 5);
         assertValues(stats, 3, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_YES,
-                ROAMING_YES, 3L, 3L, 2L, 2L, 5);
+                ROAMING_YES, DEFAULT_NETWORK_NO, 3L, 3L, 2L, 2L, 5);
         assertValues(stats, 4, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
-                4L, 40L, 4L, 40L, 7);
+                DEFAULT_NETWORK_NO, 4L, 40L, 4L, 40L, 7);
         assertValues(stats, 5, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
-                5L, 50L, 4L, 40L, 8);
+                DEFAULT_NETWORK_YES, 5L, 50L, 4L, 40L, 8);
         assertValues(stats, 6, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
-                6L, 60L, 5L, 50L, 10);
+                DEFAULT_NETWORK_NO, 6L, 60L, 5L, 50L, 10);
         assertValues(stats, 7, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES,
-                7L, 70L, 5L, 50L, 11);
+                DEFAULT_NETWORK_YES, 7L, 70L, 5L, 50L, 11);
         assertValues(stats, 8, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, METERED_YES,
-                ROAMING_YES, 7L, 70L, 5L, 50L, 11);
+                ROAMING_YES, DEFAULT_NETWORK_NO, 7L, 70L, 5L, 50L, 11);
     }
 
     @Test
@@ -187,17 +194,17 @@
                 -128L, -1L, -1);
 
         assertValues(stats, 0, TEST_IFACE, 1001, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
-                384L, 3L, 128L, 1L, 9);
-        assertValues(stats, 1, TEST_IFACE, 1001, SET_DEFAULT, 0xff, METERED_NO, ROAMING_NO, 128L,
-                1L, 128L, 1L, 2);
+                DEFAULT_NETWORK_NO, 384L, 3L, 128L, 1L, 9);
+        assertValues(stats, 1, TEST_IFACE, 1001, SET_DEFAULT, 0xff, METERED_NO, ROAMING_NO,
+                DEFAULT_NETWORK_NO, 128L, 1L, 128L, 1L, 2);
 
         // now try combining that should create row
         stats.combineValues(TEST_IFACE, 5005, SET_DEFAULT, TAG_NONE, 128L, 1L, 128L, 1L, 3);
         assertValues(stats, 2, TEST_IFACE, 5005, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
-                128L, 1L, 128L, 1L, 3);
+                DEFAULT_NETWORK_NO, 128L, 1L, 128L, 1L, 3);
         stats.combineValues(TEST_IFACE, 5005, SET_DEFAULT, TAG_NONE, 128L, 1L, 128L, 1L, 3);
         assertValues(stats, 2, TEST_IFACE, 5005, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
-                256L, 2L, 256L, 2L, 6);
+                DEFAULT_NETWORK_NO, 256L, 2L, 256L, 2L, 6);
     }
 
     @Test
@@ -213,10 +220,10 @@
         final NetworkStats result = after.subtract(before);
 
         // identical data should result in zero delta
-        assertValues(result, 0, TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 0L,
-                0L, 0L, 0L, 0);
-        assertValues(result, 1, TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 0L,
-                0L, 0L, 0L, 0);
+        assertValues(result, 0, TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+                DEFAULT_NETWORK_NO, 0L, 0L, 0L, 0L, 0);
+        assertValues(result, 1, TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+                DEFAULT_NETWORK_NO, 0L, 0L, 0L, 0L, 0);
     }
 
     @Test
@@ -232,10 +239,10 @@
         final NetworkStats result = after.subtract(before);
 
         // expect delta between measurements
-        assertValues(result, 0, TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 1L,
-                1L, 2L, 1L, 4);
-        assertValues(result, 1, TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 3L,
-                1L, 4L, 1L, 8);
+        assertValues(result, 0, TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+                DEFAULT_NETWORK_NO, 1L, 1L, 2L, 1L, 4);
+        assertValues(result, 1, TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+                DEFAULT_NETWORK_NO, 3L, 1L, 4L, 1L, 8);
     }
 
     @Test
@@ -252,12 +259,12 @@
         final NetworkStats result = after.subtract(before);
 
         // its okay to have new rows
-        assertValues(result, 0, TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 0L,
-                0L, 0L, 0L, 0);
-        assertValues(result, 1, TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 0L,
-                0L, 0L, 0L, 0);
+        assertValues(result, 0, TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+                DEFAULT_NETWORK_NO, 0L, 0L, 0L, 0L, 0);
+        assertValues(result, 1, TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+                DEFAULT_NETWORK_NO, 0L, 0L, 0L, 0L, 0);
         assertValues(result, 2, TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
-                1024L, 8L, 1024L, 8L, 20);
+                DEFAULT_NETWORK_NO, 1024L, 8L, 1024L, 8L, 20);
     }
 
     @Test
@@ -274,7 +281,7 @@
         // should silently drop omitted rows
         assertEquals(1, result.size());
         assertValues(result, 0, TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, METERED_NO,
-                ROAMING_NO, 1L, 2L, 3L, 4L, 0);
+                ROAMING_NO, DEFAULT_NETWORK_NO, 1L, 2L, 3L, 4L, 0);
         assertEquals(4L, result.getTotalBytes());
     }
 
@@ -301,21 +308,21 @@
         assertEquals(64L, uidTag.getTotalBytes());
 
         final NetworkStats uidMetered = new NetworkStats(TEST_START, 3)
-                .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 32L, 0L,
-                        0L, 0L, 0L)
-                .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO, 32L, 0L,
-                        0L, 0L, 0L)
-                .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO, 32L, 0L,
-                        0L, 0L, 0L);
+                .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+                        DEFAULT_NETWORK_YES, 32L, 0L, 0L, 0L, 0L)
+                .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO,
+                        DEFAULT_NETWORK_NO, 32L, 0L, 0L, 0L, 0L)
+                .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO,
+                        DEFAULT_NETWORK_YES, 32L, 0L, 0L, 0L, 0L);
         assertEquals(96L, uidMetered.getTotalBytes());
 
         final NetworkStats uidRoaming = new NetworkStats(TEST_START, 3)
-                .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 32L, 0L,
-                        0L, 0L, 0L)
-                .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO, 32L, 0L,
-                        0L, 0L, 0L)
-                .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES, 32L, 0L,
-                        0L, 0L, 0L);
+                .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+                        DEFAULT_NETWORK_YES, 32L, 0L, 0L, 0L, 0L)
+                .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO,
+                        DEFAULT_NETWORK_NO, 32L, 0L, 0L, 0L, 0L)
+                .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES,
+                        DEFAULT_NETWORK_YES, 32L, 0L, 0L, 0L, 0L);
         assertEquals(96L, uidRoaming.getTotalBytes());
     }
 
@@ -331,38 +338,38 @@
     @Test
     public void testGroupedByIfaceAll() throws Exception {
         final NetworkStats uidStats = new NetworkStats(TEST_START, 3)
-                .addValues(IFACE_ALL, 100, SET_ALL, TAG_NONE, METERED_NO, ROAMING_NO, 128L, 8L, 0L,
-                        2L, 20L)
-                .addValues(IFACE_ALL, 101, SET_FOREGROUND, TAG_NONE, METERED_YES, ROAMING_NO, 128L,
-                        8L, 0L, 2L, 20L)
-                .addValues(IFACE_ALL, 101, SET_ALL, TAG_NONE, METERED_NO, ROAMING_YES, 128L, 8L, 0L,
-                        2L, 20L);
+                .addValues(IFACE_ALL, 100, SET_ALL, TAG_NONE, METERED_NO, ROAMING_NO,
+                        DEFAULT_NETWORK_YES, 128L, 8L, 0L, 2L, 20L)
+                .addValues(IFACE_ALL, 101, SET_FOREGROUND, TAG_NONE, METERED_YES, ROAMING_NO,
+                        DEFAULT_NETWORK_NO, 128L, 8L, 0L, 2L, 20L)
+                .addValues(IFACE_ALL, 101, SET_ALL, TAG_NONE, METERED_NO, ROAMING_YES,
+                        DEFAULT_NETWORK_YES, 128L, 8L, 0L, 2L, 20L);
         final NetworkStats grouped = uidStats.groupedByIface();
 
         assertEquals(3, uidStats.size());
         assertEquals(1, grouped.size());
 
         assertValues(grouped, 0, IFACE_ALL, UID_ALL, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL,
-                384L, 24L, 0L, 6L, 0L);
+                DEFAULT_NETWORK_ALL, 384L, 24L, 0L, 6L, 0L);
     }
 
     @Test
     public void testGroupedByIface() throws Exception {
         final NetworkStats uidStats = new NetworkStats(TEST_START, 7)
-                .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 128L, 8L,
-                        0L, 2L, 20L)
-                .addValues(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 512L,
-                        32L, 0L, 0L, 0L)
-                .addValues(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO, 64L, 4L,
-                        0L, 0L, 0L)
-                .addValues(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, 512L,
-                        32L, 0L, 0L, 0L)
-                .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 128L, 8L,
-                        0L, 0L, 0L)
-                .addValues(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, METERED_YES, ROAMING_NO, 128L, 8L,
-                        0L, 0L, 0L)
-                .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES, 128L,
-                        8L, 0L, 0L, 0L);
+                .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+                        DEFAULT_NETWORK_YES, 128L, 8L, 0L, 2L, 20L)
+                .addValues(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+                        DEFAULT_NETWORK_NO, 512L, 32L, 0L, 0L, 0L)
+                .addValues(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO,
+                        DEFAULT_NETWORK_YES, 64L, 4L, 0L, 0L, 0L)
+                .addValues(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
+                        DEFAULT_NETWORK_NO, 512L, 32L, 0L, 0L, 0L)
+                .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+                        DEFAULT_NETWORK_YES, 128L, 8L, 0L, 0L, 0L)
+                .addValues(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, METERED_YES, ROAMING_NO,
+                        DEFAULT_NETWORK_NO, 128L, 8L, 0L, 0L, 0L)
+                .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES,
+                        DEFAULT_NETWORK_YES, 128L, 8L, 0L, 0L, 0L);
 
         final NetworkStats grouped = uidStats.groupedByIface();
 
@@ -370,59 +377,59 @@
 
         assertEquals(2, grouped.size());
         assertValues(grouped, 0, TEST_IFACE, UID_ALL, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL,
-                384L, 24L, 0L, 2L, 0L);
+                DEFAULT_NETWORK_ALL, 384L, 24L, 0L, 2L, 0L);
         assertValues(grouped, 1, TEST_IFACE2, UID_ALL, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL,
-                1024L, 64L, 0L, 0L, 0L);
+                DEFAULT_NETWORK_ALL, 1024L, 64L, 0L, 0L, 0L);
     }
 
     @Test
     public void testAddAllValues() {
         final NetworkStats first = new NetworkStats(TEST_START, 5)
-                .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO, 32L, 0L,
-                        0L, 0L, 0L)
-                .addValues(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, 32L,
-                        0L, 0L, 0L, 0L)
-                .addValues(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, METERED_YES, ROAMING_YES, 32L,
-                        0L, 0L, 0L, 0L);
+                .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO,
+                        DEFAULT_NETWORK_YES, 32L, 0L, 0L, 0L, 0L)
+                .addValues(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
+                        DEFAULT_NETWORK_NO, 32L, 0L, 0L, 0L, 0L)
+                .addValues(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, METERED_YES, ROAMING_YES,
+                        DEFAULT_NETWORK_YES, 32L, 0L, 0L, 0L, 0L);
 
         final NetworkStats second = new NetworkStats(TEST_START, 2)
-                .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO, 32L, 0L,
-                        0L, 0L, 0L)
-                .addValues(TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 32L,
-                        0L, 0L, 0L, 0L)
-                .addValues(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, METERED_YES, ROAMING_YES, 32L,
-                        0L, 0L, 0L, 0L);
+                .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO,
+                        DEFAULT_NETWORK_YES, 32L, 0L, 0L, 0L, 0L)
+                .addValues(TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+                        DEFAULT_NETWORK_NO, 32L, 0L, 0L, 0L, 0L)
+                .addValues(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, METERED_YES, ROAMING_YES,
+                        DEFAULT_NETWORK_YES, 32L, 0L, 0L, 0L, 0L);
 
         first.combineAllValues(second);
 
         assertEquals(4, first.size());
-        assertValues(first, 0, TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO, 64L,
-                0L, 0L, 0L, 0L);
+        assertValues(first, 0, TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO,
+                DEFAULT_NETWORK_YES, 64L, 0L, 0L, 0L, 0L);
         assertValues(first, 1, TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
-                32L, 0L, 0L, 0L, 0L);
+                DEFAULT_NETWORK_NO, 32L, 0L, 0L, 0L, 0L);
         assertValues(first, 2, TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, METERED_YES, ROAMING_YES,
-                64L, 0L, 0L, 0L, 0L);
+                DEFAULT_NETWORK_YES, 64L, 0L, 0L, 0L, 0L);
         assertValues(first, 3, TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
-                32L, 0L, 0L, 0L, 0L);
+                DEFAULT_NETWORK_NO, 32L, 0L, 0L, 0L, 0L);
     }
 
     @Test
     public void testGetTotal() {
         final NetworkStats stats = new NetworkStats(TEST_START, 7)
-                .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 128L, 8L,
-                        0L, 2L, 20L)
-                .addValues(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 512L,
-                        32L, 0L, 0L, 0L)
-                .addValues(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO, 64L, 4L,
-                        0L, 0L, 0L)
-                .addValues(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, 512L,
-                        32L, 0L, 0L, 0L)
-                .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO, 128L,
-                        8L, 0L, 0L, 0L)
-                .addValues(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO, 128L, 8L,
-                        0L, 0L, 0L)
-                .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES, 128L,
-                        8L, 0L, 0L, 0L);
+                .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+                        DEFAULT_NETWORK_YES, 128L, 8L, 0L, 2L, 20L)
+                .addValues(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+                        DEFAULT_NETWORK_NO, 512L, 32L, 0L, 0L, 0L)
+                .addValues(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO,
+                        DEFAULT_NETWORK_YES, 64L, 4L, 0L, 0L, 0L)
+                .addValues(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
+                        DEFAULT_NETWORK_NO, 512L,32L, 0L, 0L, 0L)
+                .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO,
+                        DEFAULT_NETWORK_YES, 128L, 8L, 0L, 0L, 0L)
+                .addValues(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO,
+                        DEFAULT_NETWORK_NO, 128L, 8L, 0L, 0L, 0L)
+                .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_YES,
+                        DEFAULT_NETWORK_NO, 128L, 8L, 0L, 0L, 0L);
 
         assertValues(stats.getTotal(null), 1408L, 88L, 0L, 2L, 20L);
         assertValues(stats.getTotal(null, 100), 1280L, 80L, 0L, 2L, 20L);
@@ -449,9 +456,9 @@
         assertEquals(6, before.size());
         assertEquals(2, after.size());
         assertValues(after, 0, TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
-                128L, 8L, 0L, 0L, 0L);
-        assertValues(after, 1, TEST_IFACE, 101, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO, 128L,
-                8L, 0L, 0L, 0L);
+                DEFAULT_NETWORK_NO, 128L, 8L, 0L, 0L, 0L);
+        assertValues(after, 1, TEST_IFACE, 101, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO,
+                DEFAULT_NETWORK_NO, 128L, 8L, 0L, 0L, 0L);
     }
 
     @Test
@@ -489,90 +496,90 @@
         final String underlyingIface = "wlan0";
         final int testTag1 = 8888;
         NetworkStats delta = new NetworkStats(TEST_START, 17)
-            .addValues(tunIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 39605L, 46L,
-                    12259L, 55L, 0L)
-            .addValues(tunIface, 10100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, 0L, 0L,
-                    0L, 0L, 0L)
-            .addValues(tunIface, 10120, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 72667L, 197L,
-                    43909L, 241L, 0L)
-            .addValues(tunIface, 10120, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, 9297L,
-                    17L, 4128L, 21L, 0L)
+            .addValues(tunIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+                    DEFAULT_NETWORK_NO, 39605L, 46L, 12259L, 55L, 0L)
+            .addValues(tunIface, 10100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
+                    DEFAULT_NETWORK_NO, 0L, 0L, 0L, 0L, 0L)
+            .addValues(tunIface, 10120, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+                    DEFAULT_NETWORK_NO, 72667L, 197L, 43909L, 241L, 0L)
+            .addValues(tunIface, 10120, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
+                    DEFAULT_NETWORK_NO, 9297L, 17L, 4128L, 21L, 0L)
             // VPN package also uses some traffic through unprotected network.
-            .addValues(tunIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 4983L, 10L,
-                    1801L, 12L, 0L)
-            .addValues(tunIface, tunUid, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, 0L, 0L,
-                    0L, 0L, 0L)
+            .addValues(tunIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+                    DEFAULT_NETWORK_NO, 4983L, 10L, 1801L, 12L, 0L)
+            .addValues(tunIface, tunUid, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
+                    DEFAULT_NETWORK_NO, 0L, 0L, 0L, 0L, 0L)
             // Tag entries
-            .addValues(tunIface, 10120, SET_DEFAULT, testTag1, METERED_NO, ROAMING_NO, 21691L, 41L,
-                    13820L, 51L, 0L)
-            .addValues(tunIface, 10120, SET_FOREGROUND, testTag1, METERED_NO, ROAMING_NO, 1281L, 2L,
-                    665L, 2L, 0L)
+            .addValues(tunIface, 10120, SET_DEFAULT, testTag1, METERED_NO, ROAMING_NO,
+                    DEFAULT_NETWORK_NO, 21691L, 41L, 13820L, 51L, 0L)
+            .addValues(tunIface, 10120, SET_FOREGROUND, testTag1, METERED_NO, ROAMING_NO,
+                    DEFAULT_NETWORK_NO, 1281L, 2L, 665L, 2L, 0L)
             // Irrelevant entries
-            .addValues(TEST_IFACE, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 1685L, 5L,
-                    2070L, 6L, 0L)
+            .addValues(TEST_IFACE, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+                    DEFAULT_NETWORK_NO, 1685L, 5L, 2070L, 6L, 0L)
             // Underlying Iface entries
-            .addValues(underlyingIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 5178L,
-                    8L, 2139L, 11L, 0L)
-            .addValues(underlyingIface, 10100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO, 0L,
-                    0L, 0L, 0L, 0L)
+            .addValues(underlyingIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+                    DEFAULT_NETWORK_NO, 5178L, 8L, 2139L, 11L, 0L)
+            .addValues(underlyingIface, 10100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
+                    DEFAULT_NETWORK_NO, 0L, 0L, 0L, 0L, 0L)
             .addValues(underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
-                    149873L, 287L, 59217L /* smaller than sum(tun0) */,
+                    DEFAULT_NETWORK_NO, 149873L, 287L, 59217L /* smaller than sum(tun0) */,
                     299L /* smaller than sum(tun0) */, 0L)
             .addValues(underlyingIface, tunUid, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
-                    0L, 0L, 0L, 0L, 0L);
+                    DEFAULT_NETWORK_NO, 0L, 0L, 0L, 0L, 0L);
 
-        assertTrue(delta.migrateTun(tunUid, tunIface, underlyingIface));
+        assertTrue(delta.toString(), delta.migrateTun(tunUid, tunIface, underlyingIface));
         assertEquals(20, delta.size());
 
         // tunIface and TEST_IFACE entries are not changed.
         assertValues(delta, 0, tunIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
-                39605L, 46L, 12259L, 55L, 0L);
+                DEFAULT_NETWORK_NO, 39605L, 46L, 12259L, 55L, 0L);
         assertValues(delta, 1, tunIface, 10100, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
-                0L, 0L, 0L, 0L, 0L);
+                DEFAULT_NETWORK_NO, 0L, 0L, 0L, 0L, 0L);
         assertValues(delta, 2, tunIface, 10120, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
-                72667L, 197L, 43909L, 241L, 0L);
+                DEFAULT_NETWORK_NO, 72667L, 197L, 43909L, 241L, 0L);
         assertValues(delta, 3, tunIface, 10120, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
-                9297L, 17L, 4128L, 21L, 0L);
+                DEFAULT_NETWORK_NO, 9297L, 17L, 4128L, 21L, 0L);
         assertValues(delta, 4, tunIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
-                4983L, 10L, 1801L, 12L, 0L);
+                DEFAULT_NETWORK_NO, 4983L, 10L, 1801L, 12L, 0L);
         assertValues(delta, 5, tunIface, tunUid, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
-                0L, 0L, 0L, 0L, 0L);
+                DEFAULT_NETWORK_NO, 0L, 0L, 0L, 0L, 0L);
         assertValues(delta, 6, tunIface, 10120, SET_DEFAULT, testTag1, METERED_NO, ROAMING_NO,
-                21691L, 41L, 13820L, 51L, 0L);
+                DEFAULT_NETWORK_NO, 21691L, 41L, 13820L, 51L, 0L);
         assertValues(delta, 7, tunIface, 10120, SET_FOREGROUND, testTag1, METERED_NO, ROAMING_NO,
-                1281L, 2L, 665L, 2L, 0L);
+                DEFAULT_NETWORK_NO, 1281L, 2L, 665L, 2L, 0L);
         assertValues(delta, 8, TEST_IFACE, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
-                1685L, 5L, 2070L, 6L, 0L);
+                DEFAULT_NETWORK_NO, 1685L, 5L, 2070L, 6L, 0L);
 
         // Existing underlying Iface entries are updated
         assertValues(delta, 9, underlyingIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO,
-                ROAMING_NO, 44783L, 54L, 14178L, 62L, 0L);
+                ROAMING_NO, DEFAULT_NETWORK_NO, 44783L, 54L, 14178L, 62L, 0L);
         assertValues(delta, 10, underlyingIface, 10100, SET_FOREGROUND, TAG_NONE, METERED_NO,
-                ROAMING_NO, 0L, 0L, 0L, 0L, 0L);
+                ROAMING_NO, DEFAULT_NETWORK_NO, 0L, 0L, 0L, 0L, 0L);
 
         // VPN underlying Iface entries are updated
         assertValues(delta, 11, underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO,
-                ROAMING_NO, 28304L, 27L, 1L, 2L, 0L);
+                ROAMING_NO, DEFAULT_NETWORK_NO, 28304L, 27L, 1L, 2L, 0L);
         assertValues(delta, 12, underlyingIface, tunUid, SET_FOREGROUND, TAG_NONE, METERED_NO,
-                ROAMING_NO, 0L, 0L, 0L, 0L, 0L);
+                ROAMING_NO, DEFAULT_NETWORK_NO, 0L, 0L, 0L, 0L, 0L);
 
         // New entries are added for new application's underlying Iface traffic
         assertContains(delta, underlyingIface, 10120, SET_DEFAULT, TAG_NONE, METERED_NO,
-                ROAMING_NO, 72667L, 197L, 43123L, 227L, 0L);
+                ROAMING_NO, DEFAULT_NETWORK_NO, 72667L, 197L, 43123L, 227L, 0L);
         assertContains(delta, underlyingIface, 10120, SET_FOREGROUND, TAG_NONE, METERED_NO,
-                ROAMING_NO, 9297L, 17L, 4054, 19L, 0L);
+                ROAMING_NO, DEFAULT_NETWORK_NO, 9297L, 17L, 4054, 19L, 0L);
         assertContains(delta, underlyingIface, 10120, SET_DEFAULT, testTag1, METERED_NO,
-                ROAMING_NO, 21691L, 41L, 13572L, 48L, 0L);
+                ROAMING_NO, DEFAULT_NETWORK_NO, 21691L, 41L, 13572L, 48L, 0L);
         assertContains(delta, underlyingIface, 10120, SET_FOREGROUND, testTag1, METERED_NO,
-                ROAMING_NO, 1281L, 2L, 653L, 1L, 0L);
+                ROAMING_NO, DEFAULT_NETWORK_NO, 1281L, 2L, 653L, 1L, 0L);
 
         // New entries are added for debug purpose
         assertContains(delta, underlyingIface, 10100, SET_DBG_VPN_IN, TAG_NONE, METERED_NO,
-                ROAMING_NO, 39605L, 46L, 12039, 51, 0);
+                ROAMING_NO, DEFAULT_NETWORK_NO, 39605L, 46L, 12039, 51, 0);
         assertContains(delta, underlyingIface, 10120, SET_DBG_VPN_IN, TAG_NONE, METERED_NO,
-                ROAMING_NO, 81964, 214, 47177, 246, 0);
+                ROAMING_NO, DEFAULT_NETWORK_NO, 81964, 214, 47177, 246, 0);
         assertContains(delta, underlyingIface, tunUid, SET_DBG_VPN_OUT, TAG_NONE, METERED_ALL,
-                ROAMING_ALL, 121569, 260, 59216, 297, 0);
+                ROAMING_ALL, DEFAULT_NETWORK_ALL, 121569, 260, 59216, 297, 0);
 
     }
 
@@ -587,79 +594,80 @@
         final String underlyingIface = "wlan0";
         NetworkStats delta = new NetworkStats(TEST_START, 9)
             // 2 different apps sent/receive data via tun0.
-            .addValues(tunIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 50000L, 25L,
-                    100000L, 50L, 0L)
-            .addValues(tunIface, 20100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 500L, 2L,
-                    200L, 5L, 0L)
+            .addValues(tunIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+                    DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L)
+            .addValues(tunIface, 20100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+                    DEFAULT_NETWORK_NO, 500L, 2L, 200L, 5L, 0L)
             // VPN package resends data through the tunnel (with exaggerated overhead)
-            .addValues(tunIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 240000,
-                    100L, 120000L, 60L, 0L)
+            .addValues(tunIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+                    DEFAULT_NETWORK_NO, 240000, 100L, 120000L, 60L, 0L)
             // 1 app already has some traffic on the underlying interface, the other doesn't yet
-            .addValues(underlyingIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 1000L,
-                    10L, 2000L, 20L, 0L)
+            .addValues(underlyingIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+                    DEFAULT_NETWORK_NO, 1000L, 10L, 2000L, 20L, 0L)
             // Traffic through the underlying interface via the vpn app.
             // This test should redistribute this data correctly.
             .addValues(underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
-                    75500L, 37L, 130000L, 70L, 0L);
+                    DEFAULT_NETWORK_NO,  75500L, 37L, 130000L, 70L, 0L);
 
         assertTrue(delta.migrateTun(tunUid, tunIface, underlyingIface));
         assertEquals(9, delta.size());
 
         // tunIface entries should not be changed.
         assertValues(delta, 0, tunIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
-                50000L, 25L, 100000L, 50L, 0L);
+                DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
         assertValues(delta, 1, tunIface, 20100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
-                500L, 2L, 200L, 5L, 0L);
+                DEFAULT_NETWORK_NO, 500L, 2L, 200L, 5L, 0L);
         assertValues(delta, 2, tunIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
-                240000L, 100L, 120000L, 60L, 0L);
+                DEFAULT_NETWORK_NO, 240000L, 100L, 120000L, 60L, 0L);
 
         // Existing underlying Iface entries are updated
         assertValues(delta, 3, underlyingIface, 10100, SET_DEFAULT, TAG_NONE, METERED_NO,
-                ROAMING_NO, 51000L, 35L, 102000L, 70L, 0L);
+                ROAMING_NO, DEFAULT_NETWORK_NO, 51000L, 35L, 102000L, 70L, 0L);
 
         // VPN underlying Iface entries are updated
         assertValues(delta, 4, underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO,
-                ROAMING_NO, 25000L, 10L, 29800L, 15L, 0L);
+                ROAMING_NO, DEFAULT_NETWORK_NO, 25000L, 10L, 29800L, 15L, 0L);
 
         // New entries are added for new application's underlying Iface traffic
         assertContains(delta, underlyingIface, 20100, SET_DEFAULT, TAG_NONE, METERED_NO,
-                ROAMING_NO, 500L, 2L, 200L, 5L, 0L);
+                ROAMING_NO, DEFAULT_NETWORK_NO, 500L, 2L, 200L, 5L, 0L);
 
         // New entries are added for debug purpose
         assertContains(delta, underlyingIface, 10100, SET_DBG_VPN_IN, TAG_NONE, METERED_NO,
-                ROAMING_NO, 50000L, 25L, 100000L, 50L, 0L);
+                ROAMING_NO, DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
         assertContains(delta, underlyingIface, 20100, SET_DBG_VPN_IN, TAG_NONE, METERED_NO,
-                ROAMING_NO, 500, 2L, 200L, 5L, 0L);
+                ROAMING_NO, DEFAULT_NETWORK_NO, 500, 2L, 200L, 5L, 0L);
         assertContains(delta, underlyingIface, tunUid, SET_DBG_VPN_OUT, TAG_NONE, METERED_ALL,
-                ROAMING_ALL, 50500L, 27L, 100200L, 55, 0);
+                ROAMING_ALL, DEFAULT_NETWORK_ALL, 50500L, 27L, 100200L, 55, 0);
     }
 
     private static void assertContains(NetworkStats stats,  String iface, int uid, int set,
-            int tag, int metered, int roaming, long rxBytes, long rxPackets, long txBytes,
-            long txPackets, long operations) {
-        int index = stats.findIndex(iface, uid, set, tag, metered, roaming);
+            int tag, int metered, int roaming, int defaultNetwork, long rxBytes, long rxPackets,
+            long txBytes, long txPackets, long operations) {
+        int index = stats.findIndex(iface, uid, set, tag, metered, roaming, defaultNetwork);
         assertTrue(index != -1);
-        assertValues(stats, index, iface, uid, set, tag, metered, roaming,
+        assertValues(stats, index, iface, uid, set, tag, metered, roaming, defaultNetwork,
                 rxBytes, rxPackets, txBytes, txPackets, operations);
     }
 
     private static void assertValues(NetworkStats stats, int index, String iface, int uid, int set,
-            int tag, int metered, int roaming, long rxBytes, long rxPackets, long txBytes,
-            long txPackets, long operations) {
+            int tag, int metered, int roaming, int defaultNetwork, long rxBytes, long rxPackets,
+            long txBytes, long txPackets, long operations) {
         final NetworkStats.Entry entry = stats.getValues(index, null);
-        assertValues(entry, iface, uid, set, tag, metered, roaming);
+        assertValues(entry, iface, uid, set, tag, metered, roaming, defaultNetwork);
         assertValues(entry, rxBytes, rxPackets, txBytes, txPackets, operations);
     }
 
     private static void assertValues(
             NetworkStats.Entry entry, String iface, int uid, int set, int tag, int metered,
-            int roaming) {
+            int roaming, int defaultNetwork) {
         assertEquals(iface, entry.iface);
         assertEquals(uid, entry.uid);
         assertEquals(set, entry.set);
         assertEquals(tag, entry.tag);
         assertEquals(metered, entry.metered);
         assertEquals(roaming, entry.roaming);
+        assertEquals(defaultNetwork, entry.defaultNetwork);
     }
 
     private static void assertValues(NetworkStats.Entry entry, long rxBytes, long rxPackets,
diff --git a/tests/net/java/com/android/internal/net/NetworkStatsFactoryTest.java b/tests/net/java/com/android/internal/net/NetworkStatsFactoryTest.java
index fb2bd79..56b8e60 100644
--- a/tests/net/java/com/android/internal/net/NetworkStatsFactoryTest.java
+++ b/tests/net/java/com/android/internal/net/NetworkStatsFactoryTest.java
@@ -16,6 +16,7 @@
 
 package com.android.internal.net;
 
+import static android.net.NetworkStats.DEFAULT_NETWORK_NO;
 import static android.net.NetworkStats.METERED_NO;
 import static android.net.NetworkStats.ROAMING_NO;
 import static android.net.NetworkStats.SET_ALL;
@@ -240,7 +241,8 @@
 
     private static void assertStatsEntry(NetworkStats stats, String iface, int uid, int set,
             int tag, long rxBytes, long txBytes) {
-        final int i = stats.findIndex(iface, uid, set, tag, METERED_NO, ROAMING_NO);
+        final int i = stats.findIndex(iface, uid, set, tag, METERED_NO, ROAMING_NO,
+                DEFAULT_NETWORK_NO);
         if (i < 0) {
             fail(String.format("no NetworkStats for (iface: %s, uid: %d, set: %d, tag: %d)",
                     iface, uid, set, tag));
@@ -252,7 +254,8 @@
 
     private static void assertStatsEntry(NetworkStats stats, String iface, int uid, int set,
             int tag, long rxBytes, long rxPackets, long txBytes, long txPackets) {
-        final int i = stats.findIndex(iface, uid, set, tag, METERED_NO, ROAMING_NO);
+        final int i = stats.findIndex(iface, uid, set, tag, METERED_NO, ROAMING_NO,
+                DEFAULT_NETWORK_NO);
         if (i < 0) {
             fail(String.format("no NetworkStats for (iface: %s, uid: %d, set: %d, tag: %d)",
                     iface, uid, set, tag));
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index b8e37f3..70cacb3 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -3501,34 +3501,50 @@
     @Test
     public void testStatsIfacesChanged() throws Exception {
         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+
+        Network[] onlyCell = new Network[]{mCellNetworkAgent.getNetwork()};
+        Network[] onlyWifi = new Network[]{mWiFiNetworkAgent.getNetwork()};
 
         // Simple connection should have updated ifaces
         mCellNetworkAgent.connect(false);
         waitForIdle();
-        verify(mStatsService, atLeastOnce()).forceUpdateIfaces();
+        verify(mStatsService, atLeastOnce()).forceUpdateIfaces(onlyCell);
+        reset(mStatsService);
+
+        // Default network switch should update ifaces.
+        mWiFiNetworkAgent.connect(false);
+        waitForIdle();
+        verify(mStatsService, atLeastOnce()).forceUpdateIfaces(onlyWifi);
+        reset(mStatsService);
+
+        // Disconnect should update ifaces.
+        mWiFiNetworkAgent.disconnect();
+        waitForIdle();
+        verify(mStatsService, atLeastOnce()).forceUpdateIfaces(onlyCell);
         reset(mStatsService);
 
         // Metered change should update ifaces
         mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
         waitForIdle();
-        verify(mStatsService, atLeastOnce()).forceUpdateIfaces();
+        verify(mStatsService, atLeastOnce()).forceUpdateIfaces(onlyCell);
         reset(mStatsService);
 
         mCellNetworkAgent.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
         waitForIdle();
-        verify(mStatsService, atLeastOnce()).forceUpdateIfaces();
+        verify(mStatsService, atLeastOnce()).forceUpdateIfaces(onlyCell);
         reset(mStatsService);
 
         // Captive portal change shouldn't update ifaces
         mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL);
         waitForIdle();
-        verify(mStatsService, never()).forceUpdateIfaces();
+        verify(mStatsService, never()).forceUpdateIfaces(onlyCell);
         reset(mStatsService);
 
         // Roaming change should update ifaces
         mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
         waitForIdle();
-        verify(mStatsService, atLeastOnce()).forceUpdateIfaces();
+        verify(mStatsService, atLeastOnce()).forceUpdateIfaces(onlyCell);
         reset(mStatsService);
     }
 
diff --git a/tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java b/tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java
index dbaf8e6..6f14332 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java
@@ -210,7 +210,7 @@
         final NetworkStats.Entry entry = new NetworkStats.Entry();
         final NetworkIdentitySet identSet = new NetworkIdentitySet();
         identSet.add(new NetworkIdentity(TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN,
-                TEST_IMSI, null, false, true));
+                TEST_IMSI, null, false, true, true));
 
         int myUid = Process.myUid();
         int otherUidInSameUser = Process.myUid() + 1;
@@ -465,7 +465,7 @@
         final NetworkStatsCollection large = new NetworkStatsCollection(HOUR_IN_MILLIS);
         final NetworkIdentitySet ident = new NetworkIdentitySet();
         ident.add(new NetworkIdentity(ConnectivityManager.TYPE_MOBILE, -1, TEST_IMSI, null,
-                false, true));
+                false, true, true));
         large.recordData(ident, UID_ALL, SET_ALL, TAG_NONE, TIME_A, TIME_B,
                 new NetworkStats.Entry(12_730_893_164L, 1, 0, 0, 0));
 
diff --git a/tests/net/java/com/android/server/net/NetworkStatsObserversTest.java b/tests/net/java/com/android/server/net/NetworkStatsObserversTest.java
index 2be5dae..185c3eb 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsObserversTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsObserversTest.java
@@ -18,6 +18,8 @@
 
 import static android.net.ConnectivityManager.TYPE_MOBILE;
 import static android.net.ConnectivityManager.TYPE_WIFI;
+import static android.net.NetworkStats.DEFAULT_NETWORK_NO;
+import static android.net.NetworkStats.DEFAULT_NETWORK_YES;
 import static android.net.NetworkStats.METERED_NO;
 import static android.net.NetworkStats.ROAMING_NO;
 import static android.net.NetworkStats.SET_DEFAULT;
@@ -224,6 +226,15 @@
         Mockito.verifyZeroInteractions(mockBinder);
     }
 
+    private NetworkIdentitySet makeTestIdentSet() {
+        NetworkIdentitySet identSet = new NetworkIdentitySet();
+        identSet.add(new NetworkIdentity(
+                TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN,
+                IMSI_1, null /* networkId */, false /* roaming */, true /* metered */,
+                true /* defaultNetwork */));
+        return identSet;
+    }
+
     @Test
     public void testUpdateStats_initialSample_doesNotNotify() throws Exception {
         DataUsageRequest inputRequest = new DataUsageRequest(
@@ -235,10 +246,7 @@
         assertTrue(Objects.equals(sTemplateImsi1, request.template));
         assertEquals(THRESHOLD_BYTES, request.thresholdInBytes);
 
-        NetworkIdentitySet identSet = new NetworkIdentitySet();
-        identSet.add(new NetworkIdentity(
-                TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN,
-                IMSI_1, null /* networkId */, false /* roaming */, true /* metered */));
+        NetworkIdentitySet identSet = makeTestIdentSet();
         mActiveIfaces.put(TEST_IFACE, identSet);
 
         // Baseline
@@ -263,10 +271,7 @@
         assertTrue(Objects.equals(sTemplateImsi1, request.template));
         assertEquals(THRESHOLD_BYTES, request.thresholdInBytes);
 
-        NetworkIdentitySet identSet = new NetworkIdentitySet();
-        identSet.add(new NetworkIdentity(
-                TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN,
-                IMSI_1, null /* networkId */, false /* roaming */, true /* metered */));
+        NetworkIdentitySet identSet = makeTestIdentSet();
         mActiveIfaces.put(TEST_IFACE, identSet);
 
         // Baseline
@@ -298,10 +303,7 @@
         assertTrue(Objects.equals(sTemplateImsi1, request.template));
         assertEquals(THRESHOLD_BYTES, request.thresholdInBytes);
 
-        NetworkIdentitySet identSet = new NetworkIdentitySet();
-        identSet.add(new NetworkIdentity(
-                TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN,
-                IMSI_1, null /* networkId */, false /* roaming */, true /* metered */));
+        NetworkIdentitySet identSet = makeTestIdentSet();
         mActiveIfaces.put(TEST_IFACE, identSet);
 
         // Baseline
@@ -334,17 +336,14 @@
         assertTrue(Objects.equals(sTemplateImsi1, request.template));
         assertEquals(THRESHOLD_BYTES, request.thresholdInBytes);
 
-        NetworkIdentitySet identSet = new NetworkIdentitySet();
-        identSet.add(new NetworkIdentity(
-                TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN,
-                IMSI_1, null /* networkId */, false /* roaming */, true /* metered */));
+        NetworkIdentitySet identSet = makeTestIdentSet();
         mActiveUidIfaces.put(TEST_IFACE, identSet);
 
         // Baseline
         NetworkStats xtSnapshot = null;
         NetworkStats uidSnapshot = new NetworkStats(TEST_START, 2 /* initialSize */)
                 .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
-                        BASE_BYTES, 2L, BASE_BYTES, 2L, 0L);
+                        DEFAULT_NETWORK_YES, BASE_BYTES, 2L, BASE_BYTES, 2L, 0L);
         mStatsObservers.updateStats(
                 xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces,
                 VPN_INFO, TEST_START);
@@ -352,7 +351,8 @@
         // Delta
         uidSnapshot = new NetworkStats(TEST_START + 2 * MINUTE_IN_MILLIS, 2 /* initialSize */)
                 .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
-                        BASE_BYTES + THRESHOLD_BYTES, 2L, BASE_BYTES + THRESHOLD_BYTES, 2L, 0L);
+                        DEFAULT_NETWORK_NO, BASE_BYTES + THRESHOLD_BYTES, 2L,
+                        BASE_BYTES + THRESHOLD_BYTES, 2L, 0L);
         mStatsObservers.updateStats(
                 xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces,
                 VPN_INFO, TEST_START);
@@ -371,17 +371,14 @@
         assertTrue(Objects.equals(sTemplateImsi1, request.template));
         assertEquals(THRESHOLD_BYTES, request.thresholdInBytes);
 
-        NetworkIdentitySet identSet = new NetworkIdentitySet();
-        identSet.add(new NetworkIdentity(
-                TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN,
-                IMSI_1, null /* networkId */, false /* roaming */, true /* metered */));
+        NetworkIdentitySet identSet = makeTestIdentSet();
         mActiveUidIfaces.put(TEST_IFACE, identSet);
 
         // Baseline
         NetworkStats xtSnapshot = null;
         NetworkStats uidSnapshot = new NetworkStats(TEST_START, 2 /* initialSize */)
                 .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
-                        BASE_BYTES, 2L, BASE_BYTES, 2L, 0L);
+                        DEFAULT_NETWORK_NO, BASE_BYTES, 2L, BASE_BYTES, 2L, 0L);
         mStatsObservers.updateStats(
                 xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces,
                 VPN_INFO, TEST_START);
@@ -389,7 +386,8 @@
         // Delta
         uidSnapshot = new NetworkStats(TEST_START + 2 * MINUTE_IN_MILLIS, 2 /* initialSize */)
                 .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
-                        BASE_BYTES + THRESHOLD_BYTES, 2L, BASE_BYTES + THRESHOLD_BYTES, 2L, 0L);
+                        DEFAULT_NETWORK_NO, BASE_BYTES + THRESHOLD_BYTES, 2L,
+                        BASE_BYTES + THRESHOLD_BYTES, 2L, 0L);
         mStatsObservers.updateStats(
                 xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces,
                 VPN_INFO, TEST_START);
@@ -407,17 +405,14 @@
         assertTrue(Objects.equals(sTemplateImsi1, request.template));
         assertEquals(THRESHOLD_BYTES, request.thresholdInBytes);
 
-        NetworkIdentitySet identSet = new NetworkIdentitySet();
-        identSet.add(new NetworkIdentity(
-                TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN,
-                IMSI_1, null /* networkId */, false /* roaming */, true /* metered */));
+        NetworkIdentitySet identSet = makeTestIdentSet();
         mActiveUidIfaces.put(TEST_IFACE, identSet);
 
         // Baseline
         NetworkStats xtSnapshot = null;
         NetworkStats uidSnapshot = new NetworkStats(TEST_START, 2 /* initialSize */)
                 .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
-                        BASE_BYTES, 2L, BASE_BYTES, 2L, 0L);
+                        DEFAULT_NETWORK_YES, BASE_BYTES, 2L, BASE_BYTES, 2L, 0L);
         mStatsObservers.updateStats(
                 xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces,
                 VPN_INFO, TEST_START);
@@ -425,7 +420,8 @@
         // Delta
         uidSnapshot = new NetworkStats(TEST_START + 2 * MINUTE_IN_MILLIS, 2 /* initialSize */)
                 .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
-                        BASE_BYTES + THRESHOLD_BYTES, 2L, BASE_BYTES + THRESHOLD_BYTES, 2L, 0L);
+                        DEFAULT_NETWORK_YES, BASE_BYTES + THRESHOLD_BYTES, 2L,
+                        BASE_BYTES + THRESHOLD_BYTES, 2L, 0L);
         mStatsObservers.updateStats(
                 xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces,
                 VPN_INFO, TEST_START);
@@ -444,17 +440,14 @@
         assertTrue(Objects.equals(sTemplateImsi1, request.template));
         assertEquals(THRESHOLD_BYTES, request.thresholdInBytes);
 
-        NetworkIdentitySet identSet = new NetworkIdentitySet();
-        identSet.add(new NetworkIdentity(
-                TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN,
-                IMSI_1, null /* networkId */, false /* roaming */, true /* metered */));
+        NetworkIdentitySet identSet = makeTestIdentSet();
         mActiveUidIfaces.put(TEST_IFACE, identSet);
 
         // Baseline
         NetworkStats xtSnapshot = null;
         NetworkStats uidSnapshot = new NetworkStats(TEST_START, 2 /* initialSize */)
                 .addValues(TEST_IFACE, UID_ANOTHER_USER, SET_DEFAULT, TAG_NONE, METERED_NO,
-                        ROAMING_NO, BASE_BYTES, 2L, BASE_BYTES, 2L, 0L);
+                        ROAMING_NO, DEFAULT_NETWORK_YES, BASE_BYTES, 2L, BASE_BYTES, 2L, 0L);
         mStatsObservers.updateStats(
                 xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces,
                 VPN_INFO, TEST_START);
@@ -462,8 +455,8 @@
         // Delta
         uidSnapshot = new NetworkStats(TEST_START + 2 * MINUTE_IN_MILLIS, 2 /* initialSize */)
                 .addValues(TEST_IFACE, UID_ANOTHER_USER, SET_DEFAULT, TAG_NONE, METERED_NO,
-                        ROAMING_NO, BASE_BYTES + THRESHOLD_BYTES, 2L, BASE_BYTES + THRESHOLD_BYTES,
-                        2L, 0L);
+                        ROAMING_NO, DEFAULT_NETWORK_NO, BASE_BYTES + THRESHOLD_BYTES, 2L,
+                        BASE_BYTES + THRESHOLD_BYTES, 2L, 0L);
         mStatsObservers.updateStats(
                 xtSnapshot, uidSnapshot, mActiveIfaces, mActiveUidIfaces,
                 VPN_INFO, TEST_START);
diff --git a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
index 65be5ff..0f26edb 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
@@ -21,6 +21,9 @@
 import static android.net.ConnectivityManager.TYPE_MOBILE;
 import static android.net.ConnectivityManager.TYPE_WIFI;
 import static android.net.ConnectivityManager.TYPE_WIMAX;
+import static android.net.NetworkStats.DEFAULT_NETWORK_ALL;
+import static android.net.NetworkStats.DEFAULT_NETWORK_NO;
+import static android.net.NetworkStats.DEFAULT_NETWORK_YES;
 import static android.net.NetworkStats.IFACE_ALL;
 import static android.net.NetworkStats.METERED_ALL;
 import static android.net.NetworkStats.METERED_NO;
@@ -67,6 +70,7 @@
 import android.net.INetworkManagementEventObserver;
 import android.net.INetworkStatsSession;
 import android.net.LinkProperties;
+import android.net.Network;
 import android.net.NetworkCapabilities;
 import android.net.NetworkInfo;
 import android.net.NetworkInfo.DetailedState;
@@ -136,6 +140,12 @@
     private static final int UID_BLUE = 1002;
     private static final int UID_GREEN = 1003;
 
+
+    private static final Network WIFI_NETWORK =  new Network(100);
+    private static final Network MOBILE_NETWORK =  new Network(101);
+    private static final Network[] NETWORKS_WIFI = new Network[]{ WIFI_NETWORK };
+    private static final Network[] NETWORKS_MOBILE = new Network[]{ MOBILE_NETWORK };
+
     private static final long WAIT_TIMEOUT = 2 * 1000;  // 2 secs
     private static final int INVALID_TYPE = -1;
 
@@ -230,7 +240,7 @@
         expectNetworkStatsUidDetail(buildEmptyStats());
         expectBandwidthControlCheck();
 
-        mService.forceUpdateIfaces();
+        mService.forceUpdateIfaces(NETWORKS_WIFI);
 
         // verify service has empty history for wifi
         assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0);
@@ -277,7 +287,7 @@
         expectNetworkStatsUidDetail(buildEmptyStats());
         expectBandwidthControlCheck();
 
-        mService.forceUpdateIfaces();
+        mService.forceUpdateIfaces(NETWORKS_WIFI);
 
         // verify service has empty history for wifi
         assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0);
@@ -305,10 +315,10 @@
         // verify service recorded history
         assertNetworkTotal(sTemplateWifi, 1024L, 8L, 2048L, 16L, 0);
         assertUidTotal(sTemplateWifi, UID_RED, 1024L, 8L, 512L, 4L, 10);
-        assertUidTotal(sTemplateWifi, UID_RED, SET_DEFAULT, METERED_NO, ROAMING_NO, 512L, 4L, 256L,
-                2L, 4);
-        assertUidTotal(sTemplateWifi, UID_RED, SET_FOREGROUND, METERED_NO, ROAMING_NO, 512L, 4L,
-                256L, 2L, 6);
+        assertUidTotal(sTemplateWifi, UID_RED, SET_DEFAULT, METERED_NO, ROAMING_NO,
+                DEFAULT_NETWORK_YES, 512L, 4L, 256L, 2L, 4);
+        assertUidTotal(sTemplateWifi, UID_RED, SET_FOREGROUND, METERED_NO, ROAMING_NO,
+                DEFAULT_NETWORK_YES, 512L, 4L, 256L, 2L, 6);
         assertUidTotal(sTemplateWifi, UID_BLUE, 128L, 1L, 128L, 1L, 0);
 
 
@@ -330,10 +340,10 @@
         // after systemReady(), we should have historical stats loaded again
         assertNetworkTotal(sTemplateWifi, 1024L, 8L, 2048L, 16L, 0);
         assertUidTotal(sTemplateWifi, UID_RED, 1024L, 8L, 512L, 4L, 10);
-        assertUidTotal(sTemplateWifi, UID_RED, SET_DEFAULT, METERED_NO, ROAMING_NO, 512L, 4L, 256L,
-                2L, 4);
-        assertUidTotal(sTemplateWifi, UID_RED, SET_FOREGROUND, METERED_NO, ROAMING_NO, 512L, 4L,
-                256L, 2L, 6);
+        assertUidTotal(sTemplateWifi, UID_RED, SET_DEFAULT, METERED_NO, ROAMING_NO,
+                DEFAULT_NETWORK_YES, 512L, 4L, 256L, 2L, 4);
+        assertUidTotal(sTemplateWifi, UID_RED, SET_FOREGROUND, METERED_NO, ROAMING_NO,
+                DEFAULT_NETWORK_YES, 512L, 4L, 256L, 2L, 6);
         assertUidTotal(sTemplateWifi, UID_BLUE, 128L, 1L, 128L, 1L, 0);
 
     }
@@ -355,7 +365,7 @@
         expectNetworkStatsUidDetail(buildEmptyStats());
         expectBandwidthControlCheck();
 
-        mService.forceUpdateIfaces();
+        mService.forceUpdateIfaces(NETWORKS_WIFI);
 
 
         // modify some number on wifi, and trigger poll event
@@ -400,7 +410,7 @@
         expectNetworkStatsUidDetail(buildEmptyStats());
         expectBandwidthControlCheck();
 
-        mService.forceUpdateIfaces();
+        mService.forceUpdateIfaces(NETWORKS_MOBILE);
 
 
         // create some traffic on first network
@@ -438,7 +448,7 @@
                 .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 512L, 4L, 0L, 0L, 0L));
         expectBandwidthControlCheck();
 
-        mService.forceUpdateIfaces();
+        mService.forceUpdateIfaces(NETWORKS_MOBILE);
         forcePollAndWaitForIdle();
 
 
@@ -480,7 +490,7 @@
         expectNetworkStatsUidDetail(buildEmptyStats());
         expectBandwidthControlCheck();
 
-        mService.forceUpdateIfaces();
+        mService.forceUpdateIfaces(NETWORKS_WIFI);
 
 
         // create some traffic
@@ -542,7 +552,7 @@
         expectNetworkStatsUidDetail(buildEmptyStats());
         expectBandwidthControlCheck();
 
-        mService.forceUpdateIfaces();
+        mService.forceUpdateIfaces(NETWORKS_MOBILE);
 
 
         // create some traffic
@@ -572,7 +582,7 @@
                 .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L));
         expectBandwidthControlCheck();
 
-        mService.forceUpdateIfaces();
+        mService.forceUpdateIfaces(NETWORKS_MOBILE);
         forcePollAndWaitForIdle();
 
 
@@ -604,7 +614,7 @@
         expectNetworkStatsUidDetail(buildEmptyStats());
         expectBandwidthControlCheck();
 
-        mService.forceUpdateIfaces();
+        mService.forceUpdateIfaces(NETWORKS_WIFI);
 
 
         // create some traffic for two apps
@@ -640,12 +650,12 @@
         NetworkStats stats = mSession.getSummaryForAllUid(
                 sTemplateWifi, Long.MIN_VALUE, Long.MAX_VALUE, true);
         assertEquals(3, stats.size());
-        assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 50L,
-                5L, 50L, 5L, 1);
-        assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO, 10L,
-                1L, 10L, 1L, 1);
+        assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+                DEFAULT_NETWORK_YES, 50L, 5L, 50L, 5L, 1);
+        assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO,
+                DEFAULT_NETWORK_YES, 10L, 1L, 10L, 1L, 1);
         assertValues(stats, IFACE_ALL, UID_BLUE, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
-                2048L, 16L, 1024L, 8L, 0);
+                DEFAULT_NETWORK_YES, 2048L, 16L, 1024L, 8L, 0);
 
         // now verify that recent history only contains one uid
         final long currentTime = currentTimeMillis();
@@ -653,7 +663,7 @@
                 sTemplateWifi, currentTime - HOUR_IN_MILLIS, currentTime, true);
         assertEquals(1, stats.size());
         assertValues(stats, IFACE_ALL, UID_BLUE, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
-                1024L, 8L, 512L, 4L, 0);
+                DEFAULT_NETWORK_YES, 1024L, 8L, 512L, 4L, 0);
     }
 
     @Test
@@ -666,7 +676,7 @@
         expectNetworkStatsUidDetail(buildEmptyStats());
         expectBandwidthControlCheck();
 
-        mService.forceUpdateIfaces();
+        mService.forceUpdateIfaces(NETWORKS_WIFI);
 
 
         // create some initial traffic
@@ -707,14 +717,14 @@
         final NetworkStats stats = mSession.getSummaryForAllUid(
                 sTemplateWifi, Long.MIN_VALUE, Long.MAX_VALUE, true);
         assertEquals(4, stats.size());
-        assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 128L,
-                2L, 128L, 2L, 1);
-        assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO, 64L,
-                1L, 64L, 1L, 1);
+        assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+                DEFAULT_NETWORK_YES, 128L, 2L, 128L, 2L, 1);
+        assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO,
+                DEFAULT_NETWORK_YES, 64L, 1L, 64L, 1L, 1);
         assertValues(stats, IFACE_ALL, UID_RED, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
-                32L, 2L, 32L, 2L, 1);
-        assertValues(stats, IFACE_ALL, UID_RED, SET_FOREGROUND, 0xFAAD, METERED_NO, ROAMING_NO, 1L,
-                1L, 1L, 1L, 1);
+                DEFAULT_NETWORK_YES, 32L, 2L, 32L, 2L, 1);
+        assertValues(stats, IFACE_ALL, UID_RED, SET_FOREGROUND, 0xFAAD, METERED_NO, ROAMING_NO,
+                DEFAULT_NETWORK_YES, 1L, 1L, 1L, 1L, 1);
     }
 
     @Test
@@ -727,7 +737,7 @@
         expectNetworkStatsUidDetail(buildEmptyStats());
         expectBandwidthControlCheck();
 
-        mService.forceUpdateIfaces();
+        mService.forceUpdateIfaces(NETWORKS_WIFI);
 
 
         // create some initial traffic
@@ -735,14 +745,14 @@
         expectCurrentTime();
         expectDefaultSettings();
         expectNetworkStatsSummary(buildEmptyStats());
-        // Note that all traffic from NetworkManagementService is tagged as METERED_NO and
-        // ROAMING_NO, because metered and roaming isn't tracked at that layer. We layer it
-        // on top by inspecting the iface properties.
+        // Note that all traffic from NetworkManagementService is tagged as METERED_NO, ROAMING_NO
+        // and DEFAULT_NETWORK_YES, because these three properties aren't tracked at that layer.
+        // We layer them on top by inspecting the iface properties.
         expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
-                .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO, 128L,
-                        2L, 128L, 2L, 0L)
-                .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO, 64L,
-                        1L, 64L, 1L, 0L));
+                .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+                        DEFAULT_NETWORK_YES, 128L, 2L, 128L, 2L, 0L)
+                .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, METERED_NO, ROAMING_NO,
+                        DEFAULT_NETWORK_YES, 64L, 1L, 64L, 1L, 0L));
         mService.incrementOperationCount(UID_RED, 0xF00D, 1);
 
         forcePollAndWaitForIdle();
@@ -754,9 +764,9 @@
                 sTemplateWifi, Long.MIN_VALUE, Long.MAX_VALUE, true);
         assertEquals(2, stats.size());
         assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, METERED_YES, ROAMING_NO,
-                128L, 2L, 128L, 2L, 1);
-        assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, 0xF00D, METERED_YES, ROAMING_NO, 64L,
-                1L, 64L, 1L, 1);
+                DEFAULT_NETWORK_YES,  128L, 2L, 128L, 2L, 1);
+        assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, 0xF00D, METERED_YES, ROAMING_NO,
+                DEFAULT_NETWORK_YES, 64L, 1L, 64L, 1L, 1);
     }
 
     @Test
@@ -769,7 +779,7 @@
         expectNetworkStatsUidDetail(buildEmptyStats());
         expectBandwidthControlCheck();
 
-        mService.forceUpdateIfaces();
+        mService.forceUpdateIfaces(NETWORKS_MOBILE);
 
 
         // Create some traffic
@@ -782,9 +792,9 @@
         // on top by inspecting the iface properties.
         expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1)
                 .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, METERED_ALL, ROAMING_NO,
-                        128L, 2L, 128L, 2L, 0L)
-                .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, METERED_ALL, ROAMING_NO, 64L,
-                        1L, 64L, 1L, 0L));
+                        DEFAULT_NETWORK_YES,  128L, 2L, 128L, 2L, 0L)
+                .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, METERED_ALL, ROAMING_NO,
+                        DEFAULT_NETWORK_YES, 64L, 1L, 64L, 1L, 0L));
         forcePollAndWaitForIdle();
 
         // verify service recorded history
@@ -795,9 +805,9 @@
                 sTemplateImsi1, Long.MIN_VALUE, Long.MAX_VALUE, true);
         assertEquals(2, stats.size());
         assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, METERED_ALL, ROAMING_YES,
-                128L, 2L, 128L, 2L, 0);
-        assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, 0xF00D, METERED_ALL, ROAMING_YES, 64L,
-                1L, 64L, 1L, 0);
+                DEFAULT_NETWORK_YES, 128L, 2L, 128L, 2L, 0);
+        assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, 0xF00D, METERED_ALL, ROAMING_YES,
+                DEFAULT_NETWORK_YES, 64L, 1L, 64L, 1L, 0);
     }
 
     @Test
@@ -810,7 +820,7 @@
         expectNetworkStatsUidDetail(buildEmptyStats());
         expectBandwidthControlCheck();
 
-        mService.forceUpdateIfaces();
+        mService.forceUpdateIfaces(NETWORKS_MOBILE);
 
 
         // create some tethering traffic
@@ -855,7 +865,7 @@
         expectNetworkStatsUidDetail(buildEmptyStats());
         expectBandwidthControlCheck();
 
-        mService.forceUpdateIfaces();
+        mService.forceUpdateIfaces(NETWORKS_WIFI);
 
         // verify service has empty history for wifi
         assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0);
@@ -976,18 +986,18 @@
         // verify summary API
         final NetworkStats stats = mSession.getSummaryForNetwork(template, start, end);
         assertValues(stats, IFACE_ALL, UID_ALL, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL,
-                rxBytes, rxPackets, txBytes, txPackets, operations);
+                DEFAULT_NETWORK_ALL,  rxBytes, rxPackets, txBytes, txPackets, operations);
     }
 
     private void assertUidTotal(NetworkTemplate template, int uid, long rxBytes, long rxPackets,
             long txBytes, long txPackets, int operations) throws Exception {
-        assertUidTotal(template, uid, SET_ALL, METERED_ALL, ROAMING_ALL, rxBytes, rxPackets,
-                txBytes, txPackets, operations);
+        assertUidTotal(template, uid, SET_ALL, METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL,
+                rxBytes, rxPackets, txBytes, txPackets, operations);
     }
 
     private void assertUidTotal(NetworkTemplate template, int uid, int set, int metered,
-            int roaming, long rxBytes, long rxPackets, long txBytes, long txPackets, int operations)
-            throws Exception {
+            int roaming, int defaultNetwork, long rxBytes, long rxPackets, long txBytes,
+            long txPackets, int operations) throws Exception {
         // verify history API
         final NetworkStatsHistory history = mSession.getHistoryForUid(
                 template, uid, set, TAG_NONE, FIELD_ALL);
@@ -997,8 +1007,8 @@
         // verify summary API
         final NetworkStats stats = mSession.getSummaryForAllUid(
                 template, Long.MIN_VALUE, Long.MAX_VALUE, false);
-        assertValues(stats, IFACE_ALL, uid, set, TAG_NONE, metered, roaming, rxBytes, rxPackets,
-                txBytes, txPackets, operations);
+        assertValues(stats, IFACE_ALL, uid, set, TAG_NONE, metered, roaming, defaultNetwork,
+                rxBytes, rxPackets, txBytes, txPackets, operations);
     }
 
     private void expectSystemReady() throws Exception {
@@ -1096,8 +1106,8 @@
     }
 
     private static void assertValues(NetworkStats stats, String iface, int uid, int set,
-            int tag, int metered, int roaming, long rxBytes, long rxPackets, long txBytes,
-            long txPackets, int operations) {
+            int tag, int metered, int roaming, int defaultNetwork, long rxBytes, long rxPackets,
+            long txBytes, long txPackets, int operations) {
         final NetworkStats.Entry entry = new NetworkStats.Entry();
         final int[] sets;
         if (set == SET_ALL) {
@@ -1120,12 +1130,22 @@
             meterings = new int[] { metered };
         }
 
+        final int[] defaultNetworks;
+        if (defaultNetwork == DEFAULT_NETWORK_ALL) {
+            defaultNetworks = new int[] { DEFAULT_NETWORK_ALL, DEFAULT_NETWORK_YES,
+                    DEFAULT_NETWORK_NO };
+        } else {
+            defaultNetworks = new int[] { defaultNetwork };
+        }
+
         for (int s : sets) {
             for (int r : roamings) {
                 for (int m : meterings) {
-                    final int i = stats.findIndex(iface, uid, s, tag, m, r);
-                    if (i != -1) {
-                        entry.add(stats.getValues(i, null));
+                    for (int d : defaultNetworks) {
+                        final int i = stats.findIndex(iface, uid, s, tag, m, r, d);
+                        if (i != -1) {
+                            entry.add(stats.getValues(i, null));
+                        }
                     }
                 }
             }
@@ -1160,7 +1180,7 @@
         final NetworkCapabilities capabilities = new NetworkCapabilities();
         capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED, !isMetered);
         capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING, true);
-        return new NetworkState(info, prop, capabilities, null, null, TEST_SSID);
+        return new NetworkState(info, prop, capabilities, WIFI_NETWORK, null, TEST_SSID);
     }
 
     private static NetworkState buildMobile3gState(String subscriberId) {
@@ -1177,7 +1197,7 @@
         final NetworkCapabilities capabilities = new NetworkCapabilities();
         capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED, false);
         capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING, !isRoaming);
-        return new NetworkState(info, prop, capabilities, null, subscriberId, null);
+        return new NetworkState(info, prop, capabilities, MOBILE_NETWORK, subscriberId, null);
     }
 
     private static NetworkState buildMobile4gState(String iface) {
@@ -1188,7 +1208,7 @@
         final NetworkCapabilities capabilities = new NetworkCapabilities();
         capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED, false);
         capabilities.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING, true);
-        return new NetworkState(info, prop, capabilities, null, null, null);
+        return new NetworkState(info, prop, capabilities, MOBILE_NETWORK, null, null);
     }
 
     private NetworkStats buildEmptyStats() {
diff --git a/tests/permission/src/com/android/framework/permission/tests/ServiceManagerPermissionTests.java b/tests/permission/src/com/android/framework/permission/tests/ServiceManagerPermissionTests.java
index 4098b98..0504c79 100644
--- a/tests/permission/src/com/android/framework/permission/tests/ServiceManagerPermissionTests.java
+++ b/tests/permission/src/com/android/framework/permission/tests/ServiceManagerPermissionTests.java
@@ -62,6 +62,11 @@
                 public boolean isRuntimePermission(String permission) {
                     return false;
                 }
+
+                @Override
+                public int getPackageUid(String packageName, int flags) {
+                    return -1;
+                }
             };
             ServiceManagerNative.asInterface(BinderInternal.getContextObject())
                     .setPermissionController(pc);
diff --git a/tools/aapt2/ResourceTable.cpp b/tools/aapt2/ResourceTable.cpp
index 9905f82..95bf921 100644
--- a/tools/aapt2/ResourceTable.cpp
+++ b/tools/aapt2/ResourceTable.cpp
@@ -47,6 +47,13 @@
   return lhs->name.compare(0, lhs->name.size(), rhs.data(), rhs.size()) < 0;
 }
 
+template <typename T>
+static bool less_than_struct_with_name_and_id(const std::unique_ptr<T>& lhs,
+                                              const std::pair<StringPiece, Maybe<uint8_t>>& rhs) {
+  int name_cmp = lhs->name.compare(0, lhs->name.size(), rhs.first.data(), rhs.first.size());
+  return name_cmp < 0 || (name_cmp == 0 && lhs->id < rhs.second);
+}
+
 ResourceTablePackage* ResourceTable::FindPackage(const StringPiece& name) const {
   const auto last = packages.end();
   auto iter = std::lower_bound(packages.begin(), last, name,
@@ -79,6 +86,22 @@
   return package;
 }
 
+ResourceTablePackage* ResourceTable::CreatePackageAllowingDuplicateNames(const StringPiece& name,
+                                                                         const Maybe<uint8_t> id) {
+  const auto last = packages.end();
+  auto iter = std::lower_bound(packages.begin(), last, std::make_pair(name, id),
+                               less_than_struct_with_name_and_id<ResourceTablePackage>);
+
+  if (iter != last && name == (*iter)->name && id == (*iter)->id) {
+    return iter->get();
+  }
+
+  std::unique_ptr<ResourceTablePackage> new_package = util::make_unique<ResourceTablePackage>();
+  new_package->name = name.to_string();
+  new_package->id = id;
+  return packages.emplace(iter, std::move(new_package))->get();
+}
+
 ResourceTablePackage* ResourceTable::FindOrCreatePackage(const StringPiece& name) {
   const auto last = packages.end();
   auto iter = std::lower_bound(packages.begin(), last, name,
diff --git a/tools/aapt2/ResourceTable.h b/tools/aapt2/ResourceTable.h
index 95e30c4..374fe1e 100644
--- a/tools/aapt2/ResourceTable.h
+++ b/tools/aapt2/ResourceTable.h
@@ -229,6 +229,11 @@
 
   ResourceTablePackage* CreatePackage(const android::StringPiece& name, Maybe<uint8_t> id = {});
 
+  // Attempts to find a package having the specified name and ID. If not found, a new package
+  // of the specified parameters is created and returned.
+  ResourceTablePackage* CreatePackageAllowingDuplicateNames(const android::StringPiece& name,
+                                                            const Maybe<uint8_t> id);
+
   std::unique_ptr<ResourceTable> Clone() const;
 
   // The string pool used by this resource table. Values that reference strings must use
@@ -239,7 +244,8 @@
   // destroyed.
   StringPool string_pool;
 
-  // The list of packages in this table, sorted alphabetically by package name.
+  // The list of packages in this table, sorted alphabetically by package name and increasing
+  // package ID (missing ID being the lowest).
   std::vector<std::unique_ptr<ResourceTablePackage>> packages;
 
   // Set of dynamic packages that this table may reference. Their package names get encoded
diff --git a/tools/aapt2/Resources.proto b/tools/aapt2/Resources.proto
index 8552195..069360e 100644
--- a/tools/aapt2/Resources.proto
+++ b/tools/aapt2/Resources.proto
@@ -306,10 +306,25 @@
 }
 
 // A value that represents a primitive data type (float, int, boolean, etc.).
-// Corresponds to the fields (type/data) of the C struct android::Res_value.
 message Primitive {
-  uint32 type = 1;
-  uint32 data = 2;
+  message NullType {
+  }
+  message EmptyType {
+  }
+  oneof oneof_value {
+    NullType null_value = 1;
+    EmptyType empty_value = 2;
+    float float_value = 3;
+    float dimension_value = 4;
+    float fraction_value = 5;
+    int32 int_decimal_value = 6;
+    uint32 int_hexidecimal_value = 7;
+    bool boolean_value = 8;
+    uint32 color_argb8_value = 9;
+    uint32 color_rgb8_value = 10;
+    uint32 color_argb4_value = 11;
+    uint32 color_rgb4_value = 12;
+  }
 }
 
 // A value that represents an XML attribute and what values it accepts.
diff --git a/tools/aapt2/format/proto/ProtoDeserialize.cpp b/tools/aapt2/format/proto/ProtoDeserialize.cpp
index d8635a9..81bc2c8 100644
--- a/tools/aapt2/format/proto/ProtoDeserialize.cpp
+++ b/tools/aapt2/format/proto/ProtoDeserialize.cpp
@@ -23,6 +23,7 @@
 #include "Locale.h"
 #include "ResourceTable.h"
 #include "ResourceUtils.h"
+#include "ResourceValues.h"
 #include "ValueVisitor.h"
 
 using ::android::ResStringPool;
@@ -380,7 +381,8 @@
 
   std::map<ResourceId, ResourceNameRef> id_index;
 
-  ResourceTablePackage* pkg = out_table->CreatePackage(pb_package.package_name(), id);
+  ResourceTablePackage* pkg =
+      out_table->CreatePackageAllowingDuplicateNames(pb_package.package_name(), id);
   for (const pb::Type& pb_type : pb_package.type()) {
     const ResourceType* res_type = ParseResourceType(pb_type.name());
     if (res_type == nullptr) {
@@ -761,8 +763,66 @@
 
     case pb::Item::kPrim: {
       const pb::Primitive& pb_prim = pb_item.prim();
-      return util::make_unique<BinaryPrimitive>(static_cast<uint8_t>(pb_prim.type()),
-                                                pb_prim.data());
+      android::Res_value val = {};
+      switch (pb_prim.oneof_value_case()) {
+        case pb::Primitive::kNullValue: {
+          val.dataType = android::Res_value::TYPE_NULL;
+          val.data = android::Res_value::DATA_NULL_UNDEFINED;
+        } break;
+        case pb::Primitive::kEmptyValue: {
+          val.dataType = android::Res_value::TYPE_NULL;
+          val.data = android::Res_value::DATA_NULL_EMPTY;
+        } break;
+        case pb::Primitive::kFloatValue: {
+          val.dataType = android::Res_value::TYPE_FLOAT;
+          float float_val = pb_prim.float_value();
+          val.data = *(uint32_t*)&float_val;
+        } break;
+        case pb::Primitive::kDimensionValue: {
+          val.dataType = android::Res_value::TYPE_DIMENSION;
+          float dimen_val = pb_prim.dimension_value();
+          val.data = *(uint32_t*)&dimen_val;
+        } break;
+        case pb::Primitive::kFractionValue: {
+          val.dataType = android::Res_value::TYPE_FRACTION;
+          float fraction_val = pb_prim.fraction_value();
+          val.data = *(uint32_t*)&fraction_val;
+        } break;
+        case pb::Primitive::kIntDecimalValue: {
+          val.dataType = android::Res_value::TYPE_INT_DEC;
+          val.data = static_cast<uint32_t>(pb_prim.int_decimal_value());
+        } break;
+        case pb::Primitive::kIntHexidecimalValue: {
+          val.dataType = android::Res_value::TYPE_INT_HEX;
+          val.data = pb_prim.int_hexidecimal_value();
+        } break;
+        case pb::Primitive::kBooleanValue: {
+          val.dataType = android::Res_value::TYPE_INT_BOOLEAN;
+          val.data = pb_prim.boolean_value() ? 0xFFFFFFFF : 0x0;
+        } break;
+        case pb::Primitive::kColorArgb8Value: {
+          val.dataType = android::Res_value::TYPE_INT_COLOR_ARGB8;
+          val.data = pb_prim.color_argb8_value();
+        } break;
+        case pb::Primitive::kColorRgb8Value: {
+          val.dataType = android::Res_value::TYPE_INT_COLOR_RGB8;
+          val.data = pb_prim.color_rgb8_value();
+        } break;
+        case pb::Primitive::kColorArgb4Value: {
+          val.dataType = android::Res_value::TYPE_INT_COLOR_ARGB4;
+          val.data = pb_prim.color_argb4_value();
+        } break;
+        case pb::Primitive::kColorRgb4Value: {
+          val.dataType = android::Res_value::TYPE_INT_COLOR_RGB4;
+          val.data = pb_prim.color_rgb4_value();
+        } break;
+        default: {
+          LOG(FATAL) << "Unexpected Primitive type: "
+                     << static_cast<uint32_t>(pb_prim.oneof_value_case());
+          return {};
+        } break;
+      }
+      return util::make_unique<BinaryPrimitive>(val);
     } break;
 
     case pb::Item::kId: {
diff --git a/tools/aapt2/format/proto/ProtoSerialize.cpp b/tools/aapt2/format/proto/ProtoSerialize.cpp
index 78f1281..e9622f5 100644
--- a/tools/aapt2/format/proto/ProtoSerialize.cpp
+++ b/tools/aapt2/format/proto/ProtoSerialize.cpp
@@ -436,8 +436,51 @@
     prim->Flatten(&val);
 
     pb::Primitive* pb_prim = out_value_->mutable_item()->mutable_prim();
-    pb_prim->set_type(val.dataType);
-    pb_prim->set_data(val.data);
+
+    switch (val.dataType) {
+      case android::Res_value::TYPE_NULL: {
+        if (val.data == android::Res_value::DATA_NULL_UNDEFINED) {
+          pb_prim->set_allocated_null_value(new pb::Primitive_NullType());
+        } else if (val.data == android::Res_value::DATA_NULL_EMPTY) {
+          pb_prim->set_allocated_empty_value(new pb::Primitive_EmptyType());
+        } else {
+          LOG(FATAL) << "Unexpected data value for TYPE_NULL BinaryPrimitive: " << val.data;
+        }
+      } break;
+      case android::Res_value::TYPE_FLOAT: {
+        pb_prim->set_float_value(*(float*)&val.data);
+      } break;
+      case android::Res_value::TYPE_DIMENSION: {
+        pb_prim->set_dimension_value(*(float*)&val.data);
+      } break;
+      case android::Res_value::TYPE_FRACTION: {
+        pb_prim->set_fraction_value(*(float*)&val.data);
+      } break;
+      case android::Res_value::TYPE_INT_DEC: {
+        pb_prim->set_int_decimal_value(static_cast<int32_t>(val.data));
+      } break;
+      case android::Res_value::TYPE_INT_HEX: {
+        pb_prim->set_int_hexidecimal_value(val.data);
+      } break;
+      case android::Res_value::TYPE_INT_BOOLEAN: {
+        pb_prim->set_boolean_value(static_cast<bool>(val.data));
+      } break;
+      case android::Res_value::TYPE_INT_COLOR_ARGB8: {
+        pb_prim->set_color_argb8_value(val.data);
+      } break;
+      case android::Res_value::TYPE_INT_COLOR_RGB8: {
+        pb_prim->set_color_rgb8_value(val.data);
+      } break;
+      case android::Res_value::TYPE_INT_COLOR_ARGB4: {
+        pb_prim->set_color_argb4_value(val.data);
+      } break;
+      case android::Res_value::TYPE_INT_COLOR_RGB4: {
+        pb_prim->set_color_rgb4_value(val.data);
+      } break;
+      default:
+        LOG(FATAL) << "Unexpected BinaryPrimitive type: " << val.dataType;
+        break;
+    }
   }
 
   void Visit(const Attribute* attr) override {
diff --git a/tools/aapt2/format/proto/ProtoSerialize_test.cpp b/tools/aapt2/format/proto/ProtoSerialize_test.cpp
index ccba5c6..9081ab6 100644
--- a/tools/aapt2/format/proto/ProtoSerialize_test.cpp
+++ b/tools/aapt2/format/proto/ProtoSerialize_test.cpp
@@ -254,6 +254,111 @@
   EXPECT_THAT(child_text->text, StrEq("woah there"));
 }
 
+TEST(ProtoSerializeTest, SerializeAndDeserializePrimitives) {
+  std::unique_ptr<ResourceTable> table =
+      test::ResourceTableBuilder()
+          .AddValue("android:bool/boolean_true",
+                    test::BuildPrimitive(android::Res_value::TYPE_INT_BOOLEAN, true))
+          .AddValue("android:bool/boolean_false",
+                    test::BuildPrimitive(android::Res_value::TYPE_INT_BOOLEAN, false))
+          .AddValue("android:color/color_rgb8", ResourceUtils::TryParseColor("#AABBCC"))
+          .AddValue("android:color/color_argb8", ResourceUtils::TryParseColor("#11223344"))
+          .AddValue("android:color/color_rgb4", ResourceUtils::TryParseColor("#DEF"))
+          .AddValue("android:color/color_argb4", ResourceUtils::TryParseColor("#5678"))
+          .AddValue("android:integer/integer_444", ResourceUtils::TryParseInt("444"))
+          .AddValue("android:integer/integer_neg_333", ResourceUtils::TryParseInt("-333"))
+          .AddValue("android:integer/hex_int_abcd", ResourceUtils::TryParseInt("0xABCD"))
+          .AddValue("android:dimen/dimen_1.39mm", ResourceUtils::TryParseFloat("1.39mm"))
+          .AddValue("android:fraction/fraction_27", ResourceUtils::TryParseFloat("27%"))
+          .AddValue("android:integer/null", ResourceUtils::MakeEmpty())
+          .Build();
+
+  pb::ResourceTable pb_table;
+  SerializeTableToPb(*table, &pb_table);
+
+  test::TestFile file_a("res/layout/main.xml");
+  MockFileCollection files;
+  EXPECT_CALL(files, FindFile(Eq("res/layout/main.xml")))
+      .WillRepeatedly(::testing::Return(&file_a));
+
+  ResourceTable new_table;
+  std::string error;
+  ASSERT_TRUE(DeserializeTableFromPb(pb_table, &files, &new_table, &error));
+  EXPECT_THAT(error, IsEmpty());
+
+  BinaryPrimitive* bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(
+      &new_table, "android:bool/boolean_true", ConfigDescription::DefaultConfig(), "");
+  ASSERT_THAT(bp, NotNull());
+  EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_INT_BOOLEAN));
+  EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseBool("true")->value.data));
+
+  bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(&new_table, "android:bool/boolean_false",
+                                                          ConfigDescription::DefaultConfig(), "");
+  ASSERT_THAT(bp, NotNull());
+  EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_INT_BOOLEAN));
+  EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseBool("false")->value.data));
+
+  bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(&new_table, "android:color/color_rgb8",
+                                                          ConfigDescription::DefaultConfig(), "");
+  ASSERT_THAT(bp, NotNull());
+  EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_INT_COLOR_RGB8));
+  EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseColor("#AABBCC")->value.data));
+
+  bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(&new_table, "android:color/color_argb8",
+                                                          ConfigDescription::DefaultConfig(), "");
+  ASSERT_THAT(bp, NotNull());
+  EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_INT_COLOR_ARGB8));
+  EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseColor("#11223344")->value.data));
+
+  bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(&new_table, "android:color/color_rgb4",
+                                                          ConfigDescription::DefaultConfig(), "");
+  ASSERT_THAT(bp, NotNull());
+  EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_INT_COLOR_RGB4));
+  EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseColor("#DEF")->value.data));
+
+  bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(&new_table, "android:color/color_argb4",
+                                                          ConfigDescription::DefaultConfig(), "");
+  ASSERT_THAT(bp, NotNull());
+  EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_INT_COLOR_ARGB4));
+  EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseColor("#5678")->value.data));
+
+  bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(&new_table, "android:integer/integer_444",
+                                                          ConfigDescription::DefaultConfig(), "");
+  ASSERT_THAT(bp, NotNull());
+  EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_INT_DEC));
+  EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseInt("444")->value.data));
+
+  bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(
+      &new_table, "android:integer/integer_neg_333", ConfigDescription::DefaultConfig(), "");
+  ASSERT_THAT(bp, NotNull());
+  EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_INT_DEC));
+  EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseInt("-333")->value.data));
+
+  bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(
+      &new_table, "android:integer/hex_int_abcd", ConfigDescription::DefaultConfig(), "");
+  ASSERT_THAT(bp, NotNull());
+  EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_INT_HEX));
+  EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseInt("0xABCD")->value.data));
+
+  bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(&new_table, "android:dimen/dimen_1.39mm",
+                                                          ConfigDescription::DefaultConfig(), "");
+  ASSERT_THAT(bp, NotNull());
+  EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_DIMENSION));
+  EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseFloat("1.39mm")->value.data));
+
+  bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(
+      &new_table, "android:fraction/fraction_27", ConfigDescription::DefaultConfig(), "");
+  ASSERT_THAT(bp, NotNull());
+  EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_FRACTION));
+  EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseFloat("27%")->value.data));
+
+  bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(&new_table, "android:integer/null",
+                                                          ConfigDescription::DefaultConfig(), "");
+  ASSERT_THAT(bp, NotNull());
+  EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_NULL));
+  EXPECT_THAT(bp->value.data, Eq(ResourceUtils::MakeEmpty()->value.data));
+}
+
 static void ExpectConfigSerializes(const StringPiece& config_str) {
   const ConfigDescription expected_config = test::ParseConfigOrDie(config_str);
   pb::Configuration pb_config;
diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp
index ccc3470..713db5b 100644
--- a/tools/aapt2/link/ManifestFixer.cpp
+++ b/tools/aapt2/link/ManifestFixer.cpp
@@ -319,6 +319,7 @@
   manifest_action["original-package"];
   manifest_action["overlay"];
   manifest_action["protected-broadcast"];
+  manifest_action["adopt-permissions"];
   manifest_action["uses-permission"];
   manifest_action["uses-permission-sdk-23"];
   manifest_action["permission"];
diff --git a/tools/fonts/fontchain_linter.py b/tools/fonts/fontchain_linter.py
index 15d39fd..ec40a222 100755
--- a/tools/fonts/fontchain_linter.py
+++ b/tools/fonts/fontchain_linter.py
@@ -270,6 +270,9 @@
             if index:
                 index = int(index)
 
+            if not path.exists(path.join(_fonts_dir, font_file)):
+                continue # Missing font is a valid case. Just ignore the missing font files.
+
             record = FontRecord(
                 name,
                 frozenset(scripts),
diff --git a/wifi/java/android/net/wifi/ISoftApCallback.aidl b/wifi/java/android/net/wifi/ISoftApCallback.aidl
new file mode 100644
index 0000000..b8d2971
--- /dev/null
+++ b/wifi/java/android/net/wifi/ISoftApCallback.aidl
@@ -0,0 +1,44 @@
+/*
+ * 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.wifi;
+
+/**
+ * Interface for Soft AP callback.
+ *
+ * @hide
+ */
+oneway interface ISoftApCallback
+{
+    /**
+     * Service to manager callback providing current soft AP state. The possible
+     * parameter values listed are defined in WifiManager.java
+     *
+     * @param state new AP state. One of WIFI_AP_STATE_DISABLED,
+     *        WIFI_AP_STATE_DISABLING, WIFI_AP_STATE_ENABLED,
+     *        WIFI_AP_STATE_ENABLING, WIFI_AP_STATE_FAILED
+     * @param failureReason reason when in failed state. One of
+     *        SAP_START_FAILURE_GENERAL, SAP_START_FAILURE_NO_CHANNEL
+     */
+    void onStateChanged(int state, int failureReason);
+
+    /**
+     * Service to manager callback providing number of connected clients.
+     *
+     * @param numClients number of connected clients
+     */
+    void onNumClientsChanged(int numClients);
+}
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 70d6ce4..e9e61a5 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -23,15 +23,15 @@
 import android.net.wifi.hotspot2.PasspointConfiguration;
 import android.net.wifi.hotspot2.IProvisioningCallback;
 
+import android.net.DhcpInfo;
+import android.net.Network;
+import android.net.wifi.ISoftApCallback;
+import android.net.wifi.PasspointManagementObjectDefinition;
+import android.net.wifi.ScanResult;
+import android.net.wifi.ScanSettings;
+import android.net.wifi.WifiActivityEnergyInfo;
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiInfo;
-import android.net.wifi.ScanSettings;
-import android.net.wifi.ScanResult;
-import android.net.wifi.PasspointManagementObjectDefinition;
-import android.net.wifi.WifiActivityEnergyInfo;
-import android.net.Network;
-
-import android.net.DhcpInfo;
 
 import android.os.Messenger;
 import android.os.ResultReceiver;
@@ -178,5 +178,9 @@
     void restoreSupplicantBackupData(in byte[] supplicantData, in byte[] ipConfigData);
 
     void startSubscriptionProvisioning(in OsuProvider provider, in IProvisioningCallback callback);
+
+    void registerSoftApCallback(in IBinder binder, in ISoftApCallback callback, int callbackIdentifier);
+
+    void unregisterSoftApCallback(int callbackIdentifier);
 }
 
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 6438631..2c60118 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -267,8 +267,15 @@
     public static final int AP_BAND_5GHZ = 1;
 
     /**
+     * Device is allowed to choose the optimal band (2Ghz or 5Ghz) based on device capability,
+     * operating country code and current radio conditions.
+     * @hide
+     */
+    public static final int AP_BAND_ANY = -1;
+
+    /**
      * The band which AP resides on
-     * 0-2G  1-5G
+     * -1:Any 0:2G 1:5G
      * By default, 2G is chosen
      * @hide
      */
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index aa75a07..99080d6 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -16,6 +16,7 @@
 
 package android.net.wifi;
 
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
@@ -55,6 +56,8 @@
 
 import dalvik.system.CloseGuard;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.lang.ref.WeakReference;
 import java.net.InetAddress;
 import java.util.Collections;
@@ -432,6 +435,17 @@
      */
     public static final String EXTRA_WIFI_AP_MODE = "wifi_ap_mode";
 
+    /** @hide */
+    @IntDef(flag = false, prefix = { "WIFI_AP_STATE_" }, value = {
+        WIFI_AP_STATE_DISABLING,
+        WIFI_AP_STATE_DISABLED,
+        WIFI_AP_STATE_ENABLING,
+        WIFI_AP_STATE_ENABLED,
+        WIFI_AP_STATE_FAILED,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface WifiApState {}
+
     /**
      * Wi-Fi AP is currently being disabled. The state will change to
      * {@link #WIFI_AP_STATE_DISABLED} if it finishes successfully.
@@ -486,6 +500,14 @@
     @SystemApi
     public static final int WIFI_AP_STATE_FAILED = 14;
 
+    /** @hide */
+    @IntDef(flag = false, prefix = { "SAP_START_FAILURE_" }, value = {
+        SAP_START_FAILURE_GENERAL,
+        SAP_START_FAILURE_NO_CHANNEL,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface SapStartFailure {}
+
     /**
      *  If WIFI AP start failed, this reason code means there is no legal channel exists on
      *  user selected band by regulatory
@@ -2324,6 +2346,119 @@
     }
 
     /**
+     * Base class for soft AP callback. Should be extended by applications and set when calling
+     * {@link WifiManager#registerSoftApCallback(SoftApCallback, Handler)}.
+     *
+     * @hide
+     */
+    public interface SoftApCallback {
+        /**
+         * Called when soft AP state changes.
+         *
+         * @param state new new AP state. One of {@link #WIFI_AP_STATE_DISABLED},
+         *        {@link #WIFI_AP_STATE_DISABLING}, {@link #WIFI_AP_STATE_ENABLED},
+         *        {@link #WIFI_AP_STATE_ENABLING}, {@link #WIFI_AP_STATE_FAILED}
+         * @param failureReason reason when in failed state. One of
+         *        {@link #SAP_START_FAILURE_GENERAL}, {@link #SAP_START_FAILURE_NO_CHANNEL}
+         */
+        public abstract void onStateChanged(@WifiApState int state,
+                @SapStartFailure int failureReason);
+
+        /**
+         * Called when number of connected clients to soft AP changes.
+         *
+         * @param numClients number of connected clients
+         */
+        public abstract void onNumClientsChanged(int numClients);
+    }
+
+    /**
+     * Callback proxy for SoftApCallback objects.
+     *
+     * @hide
+     */
+    private static class SoftApCallbackProxy extends ISoftApCallback.Stub {
+        private final Handler mHandler;
+        private final SoftApCallback mCallback;
+
+        SoftApCallbackProxy(Looper looper, SoftApCallback callback) {
+            mHandler = new Handler(looper);
+            mCallback = callback;
+        }
+
+        @Override
+        public void onStateChanged(int state, int failureReason) throws RemoteException {
+            Log.v(TAG, "SoftApCallbackProxy: onStateChanged: state=" + state + ", failureReason=" +
+                    failureReason);
+            mHandler.post(() -> {
+                mCallback.onStateChanged(state, failureReason);
+            });
+        }
+
+        @Override
+        public void onNumClientsChanged(int numClients) throws RemoteException {
+            Log.v(TAG, "SoftApCallbackProxy: onNumClientsChanged: numClients=" + numClients);
+            mHandler.post(() -> {
+                mCallback.onNumClientsChanged(numClients);
+            });
+        }
+    }
+
+    /**
+     * Registers a callback for Soft AP. See {@link SoftApCallback}. Caller will receive the current
+     * soft AP state and number of connected devices immediately after a successful call to this API
+     * via callback. Note that receiving an immediate WIFI_AP_STATE_FAILED value for soft AP state
+     * indicates that the latest attempt to start soft AP has failed. Caller can unregister a
+     * previously registered callback using {@link unregisterSoftApCallback}
+     * <p>
+     * Applications should have the
+     * {@link android.Manifest.permission#NETWORK_SETTINGS NETWORK_SETTINGS} permission. Callers
+     * without the permission will trigger a {@link java.lang.SecurityException}.
+     * <p>
+     *
+     * @param callback Callback for soft AP events
+     * @param handler  The Handler on whose thread to execute the callbacks of the {@code callback}
+     *                 object. If null, then the application's main thread will be used.
+     *
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
+    public void registerSoftApCallback(@NonNull SoftApCallback callback,
+                                       @Nullable Handler handler) {
+        if (callback == null) throw new IllegalArgumentException("callback cannot be null");
+        Log.v(TAG, "registerSoftApCallback: callback=" + callback + ", handler=" + handler);
+
+        Looper looper = (handler == null) ? mContext.getMainLooper() : handler.getLooper();
+        Binder binder = new Binder();
+        try {
+            mService.registerSoftApCallback(binder, new SoftApCallbackProxy(looper, callback),
+                    callback.hashCode());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Allow callers to unregister a previously registered callback. After calling this method,
+     * applications will no longer receive soft AP events.
+     *
+     * @param callback Callback to unregister for soft AP events
+     *
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
+    public void unregisterSoftApCallback(@NonNull SoftApCallback callback) {
+        if (callback == null) throw new IllegalArgumentException("callback cannot be null");
+        Log.v(TAG, "unregisterSoftApCallback: callback=" + callback);
+
+        try {
+            mService.unregisterSoftApCallback(callback.hashCode());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * LocalOnlyHotspotReservation that contains the {@link WifiConfiguration} for the active
      * LocalOnlyHotspot request.
      * <p>
diff --git a/wifi/tests/src/android/net/wifi/WifiManagerTest.java b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
index 0df5615..4b5f645 100644
--- a/wifi/tests/src/android/net/wifi/WifiManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
@@ -24,11 +24,19 @@
 import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_NO_CHANNEL;
 import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_TETHERING_DISALLOWED;
 import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.REQUEST_REGISTERED;
+import static android.net.wifi.WifiManager.SAP_START_FAILURE_GENERAL;
+import static android.net.wifi.WifiManager.SAP_START_FAILURE_NO_CHANNEL;
+import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLED;
+import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLING;
+import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLED;
+import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLING;
+import static android.net.wifi.WifiManager.WIFI_AP_STATE_FAILED;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 import static org.mockito.Mockito.*;
 
 import android.content.Context;
@@ -37,6 +45,7 @@
 import android.net.wifi.WifiManager.LocalOnlyHotspotObserver;
 import android.net.wifi.WifiManager.LocalOnlyHotspotReservation;
 import android.net.wifi.WifiManager.LocalOnlyHotspotSubscription;
+import android.net.wifi.WifiManager.SoftApCallback;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Message;
@@ -66,6 +75,7 @@
     @Mock ApplicationInfo mApplicationInfo;
     @Mock WifiConfiguration mApConfig;
     @Mock IBinder mAppBinder;
+    @Mock SoftApCallback mSoftApCallback;
 
     private Handler mHandler;
     private TestLooper mLooper;
@@ -632,6 +642,149 @@
     }
 
     /**
+     * Verify an IllegalArgumentException is thrown if callback is not provided.
+     */
+    @Test
+    public void registerSoftApCallbackThrowsIllegalArgumentExceptionOnNullArgumentForCallback() {
+        try {
+            mWifiManager.registerSoftApCallback(null, mHandler);
+            fail("expected IllegalArgumentException");
+        } catch (IllegalArgumentException expected) {
+        }
+    }
+
+    /**
+     * Verify an IllegalArgumentException is thrown if callback is not provided.
+     */
+    @Test
+    public void unregisterSoftApCallbackThrowsIllegalArgumentExceptionOnNullArgumentForCallback() {
+        try {
+            mWifiManager.unregisterSoftApCallback(null);
+            fail("expected IllegalArgumentException");
+        } catch (IllegalArgumentException expected) {
+        }
+    }
+
+    /**
+     * Verify main looper is used when handler is not provided.
+     */
+    @Test
+    public void registerSoftApCallbackUsesMainLooperOnNullArgumentForHandler() {
+        when(mContext.getMainLooper()).thenReturn(mLooper.getLooper());
+        mWifiManager.registerSoftApCallback(mSoftApCallback, null);
+        verify(mContext).getMainLooper();
+    }
+
+    /**
+     * Verify the call to registerSoftApCallback goes to WifiServiceImpl.
+     */
+    @Test
+    public void registerSoftApCallbackCallGoesToWifiServiceImpl() throws Exception {
+        mWifiManager.registerSoftApCallback(mSoftApCallback, mHandler);
+        verify(mWifiService).registerSoftApCallback(any(IBinder.class),
+                any(ISoftApCallback.Stub.class), anyInt());
+    }
+
+    /**
+     * Verify the call to unregisterSoftApCallback goes to WifiServiceImpl.
+     */
+    @Test
+    public void unregisterSoftApCallbackCallGoesToWifiServiceImpl() throws Exception {
+        ArgumentCaptor<Integer> callbackIdentifier = ArgumentCaptor.forClass(Integer.class);
+        mWifiManager.registerSoftApCallback(mSoftApCallback, mHandler);
+        verify(mWifiService).registerSoftApCallback(any(IBinder.class),
+                any(ISoftApCallback.Stub.class), callbackIdentifier.capture());
+
+        mWifiManager.unregisterSoftApCallback(mSoftApCallback);
+        verify(mWifiService).unregisterSoftApCallback(eq((int) callbackIdentifier.getValue()));
+    }
+
+    /*
+     * Verify client provided callback is being called through callback proxy
+     */
+    @Test
+    public void softApCallbackProxyCallsOnStateChanged() throws Exception {
+        ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
+                ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
+        mWifiManager.registerSoftApCallback(mSoftApCallback, mHandler);
+        verify(mWifiService).registerSoftApCallback(any(IBinder.class), callbackCaptor.capture(),
+                anyInt());
+
+        callbackCaptor.getValue().onStateChanged(WIFI_AP_STATE_ENABLED, 0);
+        mLooper.dispatchAll();
+        verify(mSoftApCallback).onStateChanged(WIFI_AP_STATE_ENABLED, 0);
+    }
+
+    /*
+     * Verify client provided callback is being called through callback proxy
+     */
+    @Test
+    public void softApCallbackProxyCallsOnNumClientsChanged() throws Exception {
+        ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
+                ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
+        mWifiManager.registerSoftApCallback(mSoftApCallback, mHandler);
+        verify(mWifiService).registerSoftApCallback(any(IBinder.class), callbackCaptor.capture(),
+                anyInt());
+
+        final int testNumClients = 3;
+        callbackCaptor.getValue().onNumClientsChanged(testNumClients);
+        mLooper.dispatchAll();
+        verify(mSoftApCallback).onNumClientsChanged(testNumClients);
+    }
+
+    /*
+     * Verify client provided callback is being called through callback proxy on multiple events
+     */
+    @Test
+    public void softApCallbackProxyCallsOnMultipleUpdates() throws Exception {
+        ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
+                ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
+        mWifiManager.registerSoftApCallback(mSoftApCallback, mHandler);
+        verify(mWifiService).registerSoftApCallback(any(IBinder.class), callbackCaptor.capture(),
+                anyInt());
+
+        final int testNumClients = 5;
+        callbackCaptor.getValue().onStateChanged(WIFI_AP_STATE_ENABLING, 0);
+        callbackCaptor.getValue().onNumClientsChanged(testNumClients);
+        callbackCaptor.getValue().onStateChanged(WIFI_AP_STATE_FAILED, SAP_START_FAILURE_GENERAL);
+
+        mLooper.dispatchAll();
+        verify(mSoftApCallback).onStateChanged(WIFI_AP_STATE_ENABLING, 0);
+        verify(mSoftApCallback).onNumClientsChanged(testNumClients);
+        verify(mSoftApCallback).onStateChanged(WIFI_AP_STATE_FAILED, SAP_START_FAILURE_GENERAL);
+    }
+
+    /*
+     * Verify client provided callback is being called on the correct thread
+     */
+    @Test
+    public void softApCallbackIsCalledOnCorrectThread() throws Exception {
+        ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
+                ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
+        TestLooper altLooper = new TestLooper();
+        Handler altHandler = new Handler(altLooper.getLooper());
+        mWifiManager.registerSoftApCallback(mSoftApCallback, altHandler);
+        verify(mWifiService).registerSoftApCallback(any(IBinder.class), callbackCaptor.capture(),
+                anyInt());
+
+        callbackCaptor.getValue().onStateChanged(WIFI_AP_STATE_ENABLED, 0);
+        altLooper.dispatchAll();
+        verify(mSoftApCallback).onStateChanged(WIFI_AP_STATE_ENABLED, 0);
+    }
+
+    /**
+     * Verify that the handler provided by the caller is used for registering soft AP callback.
+     */
+    @Test
+    public void testCorrectLooperIsUsedForSoftApCallbackHandler() throws Exception {
+        mWifiManager.registerSoftApCallback(mSoftApCallback, mHandler);
+        mLooper.dispatchAll();
+        verify(mWifiService).registerSoftApCallback(any(IBinder.class),
+                any(ISoftApCallback.Stub.class), anyInt());
+        verify(mContext, never()).getMainLooper();
+    }
+
+    /**
      * Verify that the handler provided by the caller is used for the observer.
      */
     @Test